]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/common/usc_impl.c
ICU-57132.0.1.tar.gz
[apple/icu.git] / icuSources / common / usc_impl.c
index 83b0727cec5c89551fd8aff96c77187e50c6af11..1769269378b26c13487d9e48c91f23c0f03c1e33 100644 (file)
@@ -1,6 +1,6 @@
 /*
 **********************************************************************
-*   Copyright (C) 1999-2002, International Business Machines
+*   Copyright (C) 1999-2016, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 **********************************************************************
 *
 #include "usc_impl.h"
 #include "cmemory.h"
 
-#define ARRAY_SIZE(array) (sizeof array  / sizeof array[0])
+#define PAREN_STACK_DEPTH 32
 
-#define PAREN_STACK_DEPTH 128
+#define MOD(sp) ((sp) % PAREN_STACK_DEPTH)
+#define LIMIT_INC(sp) (((sp) < PAREN_STACK_DEPTH)? (sp) + 1 : PAREN_STACK_DEPTH)
+#define INC(sp,count) (MOD((sp) + (count)))
+#define INC1(sp) (INC(sp, 1))
+#define DEC(sp,count) (MOD((sp) + PAREN_STACK_DEPTH - (count)))
+#define DEC1(sp) (DEC(sp, 1))
+#define STACK_IS_EMPTY(scriptRun) ((scriptRun)->pushCount <= 0)
+#define STACK_IS_NOT_EMPTY(scriptRun) (! STACK_IS_EMPTY(scriptRun))
+#define TOP(scriptRun) ((scriptRun)->parenStack[(scriptRun)->parenSP])
+#define SYNC_FIXUP(scriptRun) ((scriptRun)->fixupCount = 0)
 
 struct ParenStackEntry
 {
@@ -38,6 +47,8 @@ struct UScriptRun
 
     struct ParenStackEntry parenStack[PAREN_STACK_DEPTH];
     int32_t parenSP;
+    int32_t pushCount;
+    int32_t fixupCount;
 };
 
 static int8_t highBit(int32_t value);
@@ -62,6 +73,47 @@ static const UChar32 pairedChars[] = {
     0x301a, 0x301b
 };
 
+static void push(UScriptRun *scriptRun, int32_t pairIndex, UScriptCode scriptCode)
+{
+    scriptRun->pushCount  = LIMIT_INC(scriptRun->pushCount);
+    scriptRun->fixupCount = LIMIT_INC(scriptRun->fixupCount);
+    
+    scriptRun->parenSP = INC1(scriptRun->parenSP);
+    scriptRun->parenStack[scriptRun->parenSP].pairIndex  = pairIndex;
+    scriptRun->parenStack[scriptRun->parenSP].scriptCode = scriptCode;
+}
+
+static void pop(UScriptRun *scriptRun)
+{
+    if (STACK_IS_EMPTY(scriptRun)) {
+        return;
+    }
+    
+    if (scriptRun->fixupCount > 0) {
+        scriptRun->fixupCount -= 1;
+    }
+    
+    scriptRun->pushCount -= 1;
+    scriptRun->parenSP = DEC1(scriptRun->parenSP);
+    
+    /* If the stack is now empty, reset the stack
+       pointers to their initial values.
+     */
+    if (STACK_IS_EMPTY(scriptRun)) {
+        scriptRun->parenSP = -1;
+    }
+}
+
+static void fixup(UScriptRun *scriptRun, UScriptCode scriptCode)
+{
+    int32_t fixupSP = DEC(scriptRun->parenSP, scriptRun->fixupCount);
+    
+    while (scriptRun->fixupCount-- > 0) {
+        fixupSP = INC1(fixupSP);
+        scriptRun->parenStack[fixupSP].scriptCode = scriptCode;
+    }
+}
+
 static int8_t
 highBit(int32_t value)
 {
@@ -92,7 +144,7 @@ highBit(int32_t value)
     }
 
     if (value >= 1 << 1) {
-        value >>= 1;
+        //value >>= 1;
         bit += 1;
     }
 
@@ -102,30 +154,30 @@ highBit(int32_t value)
 static int32_t
 getPairIndex(UChar32 ch)
 {
-    int32_t pairedCharCount = ARRAY_SIZE(pairedChars);
+    int32_t pairedCharCount = UPRV_LENGTHOF(pairedChars);
     int32_t pairedCharPower = 1 << highBit(pairedCharCount);
     int32_t pairedCharExtra = pairedCharCount - pairedCharPower;
 
     int32_t probe = pairedCharPower;
-    int32_t index = 0;
+    int32_t pairIndex = 0;
 
     if (ch >= pairedChars[pairedCharExtra]) {
-        index = pairedCharExtra;
+        pairIndex = pairedCharExtra;
     }
 
     while (probe > (1 << 0)) {
         probe >>= 1;
 
-        if (ch >= pairedChars[index + probe]) {
-            index += probe;
+        if (ch >= pairedChars[pairIndex + probe]) {
+            pairIndex += probe;
         }
     }
 
-    if (pairedChars[index] != ch) {
-        index = -1;
+    if (pairedChars[pairIndex] != ch) {
+        pairIndex = -1;
     }
 
-    return index;
+    return pairIndex;
 }
 
 static UBool
@@ -177,6 +229,8 @@ uscript_resetRun(UScriptRun *scriptRun)
         scriptRun->scriptLimit = 0;
         scriptRun->scriptCode  = USCRIPT_INVALID_CODE;
         scriptRun->parenSP     = -1;
+        scriptRun->pushCount   =  0;
+        scriptRun->fixupCount  =  0;
     }
 }
 
@@ -201,7 +255,6 @@ uscript_setRunText(UScriptRun *scriptRun, const UChar *src, int32_t length, UErr
 U_CAPI UBool U_EXPORT2
 uscript_nextRun(UScriptRun *scriptRun, int32_t *pRunStart, int32_t *pRunLimit, UScriptCode *pRunScript)
 {
-    int32_t startSP  = -1;  /* used to find the first new open character */
     UErrorCode error = U_ZERO_ERROR;
 
     /* if we've fallen off the end of the text, we're done */
@@ -209,7 +262,7 @@ uscript_nextRun(UScriptRun *scriptRun, int32_t *pRunStart, int32_t *pRunLimit, U
         return FALSE;
     }
     
-    startSP = scriptRun->parenSP;
+    SYNC_FIXUP(scriptRun);
     scriptRun->scriptCode = USCRIPT_COMMON;
 
     for (scriptRun->scriptStart = scriptRun->scriptLimit; scriptRun->scriptLimit < scriptRun->textLength; scriptRun->scriptLimit += 1) {
@@ -248,33 +301,16 @@ uscript_nextRun(UScriptRun *scriptRun, int32_t *pRunStart, int32_t *pRunLimit, U
          */
         if (pairIndex >= 0) {
             if ((pairIndex & 1) == 0) {
-
-                /*
-                 * If the paren stack is full, empty it. This
-                 * means that deeply nested paired punctuation
-                 * characters will be ignored, but that's an unusual
-                 * case, and it's better to ignore them than to
-                 * write off the end of the stack...
-                 */
-                if (++scriptRun->parenSP >= PAREN_STACK_DEPTH) {
-                    scriptRun->parenSP = 0;
-                }
-
-                scriptRun->parenStack[scriptRun->parenSP].pairIndex = pairIndex;
-                scriptRun->parenStack[scriptRun->parenSP].scriptCode  = scriptRun->scriptCode;
-            } else if (scriptRun->parenSP >= 0) {
+                push(scriptRun, pairIndex, scriptRun->scriptCode);
+            } else {
                 int32_t pi = pairIndex & ~1;
 
-                while (scriptRun->parenSP >= 0 && scriptRun->parenStack[scriptRun->parenSP].pairIndex != pi) {
-                    scriptRun->parenSP -= 1;
+                while (STACK_IS_NOT_EMPTY(scriptRun) && TOP(scriptRun).pairIndex != pi) {
+                    pop(scriptRun);
                 }
 
-                if (scriptRun->parenSP < startSP) {
-                    startSP = scriptRun->parenSP;
-                }
-
-                if (scriptRun->parenSP >= 0) {
-                    sc = scriptRun->parenStack[scriptRun->parenSP].scriptCode;
+                if (STACK_IS_NOT_EMPTY(scriptRun)) {
+                    sc = TOP(scriptRun).scriptCode;
                 }
             }
         }
@@ -283,22 +319,15 @@ uscript_nextRun(UScriptRun *scriptRun, int32_t *pRunStart, int32_t *pRunLimit, U
             if (scriptRun->scriptCode <= USCRIPT_INHERITED && sc > USCRIPT_INHERITED) {
                 scriptRun->scriptCode = sc;
 
-                /*
-                 * now that we have a final script code, fix any open
-                 * characters we pushed before we knew the script code.
-                 */
-                while (startSP < scriptRun->parenSP) {
-                    scriptRun->parenStack[++startSP].scriptCode = scriptRun->scriptCode;
-                }
+                fixup(scriptRun, scriptRun->scriptCode);
             }
 
             /*
              * if this character is a close paired character,
-             * pop it from the stack
+             * pop the matching open character from the stack
              */
-            if (pairIndex >= 0 && (pairIndex & 1) != 0 && scriptRun->parenSP >= 0) {
-                scriptRun->parenSP -= 1;
-                startSP -= 1;
+            if (pairIndex >= 0 && (pairIndex & 1) != 0) {
+                pop(scriptRun);
             }
         } else {
             /*