1ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* 2ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru********************************************************************** 3f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius* Copyright (C) 1999-2014, International Business Machines 4ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* Corporation and others. All Rights Reserved. 5ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru********************************************************************** 6ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* 7ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* File USC_IMPL.C 8ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* 9ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* Modification History: 10ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* 11ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* Date Name Description 12ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* 07/08/2002 Eric Mader Creation. 13ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru****************************************************************************** 14ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*/ 15ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 16ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/uscript.h" 17ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "usc_impl.h" 18ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "cmemory.h" 19ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 20ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define ARRAY_SIZE(array) (sizeof array / sizeof array[0]) 21ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 22ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define PAREN_STACK_DEPTH 32 23ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 24ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define MOD(sp) ((sp) % PAREN_STACK_DEPTH) 25ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define LIMIT_INC(sp) (((sp) < PAREN_STACK_DEPTH)? (sp) + 1 : PAREN_STACK_DEPTH) 26ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define INC(sp,count) (MOD((sp) + (count))) 27ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define INC1(sp) (INC(sp, 1)) 28ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define DEC(sp,count) (MOD((sp) + PAREN_STACK_DEPTH - (count))) 29ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define DEC1(sp) (DEC(sp, 1)) 30ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define STACK_IS_EMPTY(scriptRun) ((scriptRun)->pushCount <= 0) 31ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define STACK_IS_NOT_EMPTY(scriptRun) (! STACK_IS_EMPTY(scriptRun)) 32ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define TOP(scriptRun) ((scriptRun)->parenStack[(scriptRun)->parenSP]) 33ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define SYNC_FIXUP(scriptRun) ((scriptRun)->fixupCount = 0) 34ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 35ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustruct ParenStackEntry 36ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 37ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t pairIndex; 38ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UScriptCode scriptCode; 39ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}; 40ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 41ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustruct UScriptRun 42ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 43ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t textLength; 44ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru const UChar *textArray; 45ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 46ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t scriptStart; 47ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t scriptLimit; 48ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UScriptCode scriptCode; 49ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 50ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru struct ParenStackEntry parenStack[PAREN_STACK_DEPTH]; 51ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t parenSP; 52ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t pushCount; 53ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t fixupCount; 54ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}; 55ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 56ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic int8_t highBit(int32_t value); 57ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 58ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar32 pairedChars[] = { 59ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 0x0028, 0x0029, /* ascii paired punctuation */ 60ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 0x003c, 0x003e, 61ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 0x005b, 0x005d, 62ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 0x007b, 0x007d, 63ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 0x00ab, 0x00bb, /* guillemets */ 64ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 0x2018, 0x2019, /* general punctuation */ 65ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 0x201c, 0x201d, 66ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 0x2039, 0x203a, 67ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 0x3008, 0x3009, /* chinese paired punctuation */ 68ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 0x300a, 0x300b, 69ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 0x300c, 0x300d, 70ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 0x300e, 0x300f, 71ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 0x3010, 0x3011, 72ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 0x3014, 0x3015, 73ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 0x3016, 0x3017, 74ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 0x3018, 0x3019, 75ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 0x301a, 0x301b 76ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}; 77ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 78ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic void push(UScriptRun *scriptRun, int32_t pairIndex, UScriptCode scriptCode) 79ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 80ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru scriptRun->pushCount = LIMIT_INC(scriptRun->pushCount); 81ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru scriptRun->fixupCount = LIMIT_INC(scriptRun->fixupCount); 82ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 83ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru scriptRun->parenSP = INC1(scriptRun->parenSP); 84ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru scriptRun->parenStack[scriptRun->parenSP].pairIndex = pairIndex; 85ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru scriptRun->parenStack[scriptRun->parenSP].scriptCode = scriptCode; 86ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 87ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 88ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic void pop(UScriptRun *scriptRun) 89ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 90ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (STACK_IS_EMPTY(scriptRun)) { 91ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return; 92ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 93ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 94ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (scriptRun->fixupCount > 0) { 95ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru scriptRun->fixupCount -= 1; 96ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 97ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 98ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru scriptRun->pushCount -= 1; 99ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru scriptRun->parenSP = DEC1(scriptRun->parenSP); 100ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 101ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru /* If the stack is now empty, reset the stack 102ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru pointers to their initial values. 103ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 104ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (STACK_IS_EMPTY(scriptRun)) { 105ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru scriptRun->parenSP = -1; 106ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 107ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 108ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 109ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic void fixup(UScriptRun *scriptRun, UScriptCode scriptCode) 110ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 111ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t fixupSP = DEC(scriptRun->parenSP, scriptRun->fixupCount); 112ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 113ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru while (scriptRun->fixupCount-- > 0) { 114ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru fixupSP = INC1(fixupSP); 115ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru scriptRun->parenStack[fixupSP].scriptCode = scriptCode; 116ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 117ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 118ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 119ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic int8_t 120ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruhighBit(int32_t value) 121ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 122ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int8_t bit = 0; 123ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 124ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (value <= 0) { 125ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return -32; 126ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 127ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 128ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (value >= 1 << 16) { 129ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru value >>= 16; 130ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru bit += 16; 131ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 132ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 133ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (value >= 1 << 8) { 134ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru value >>= 8; 135ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru bit += 8; 136ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 137ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 138ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (value >= 1 << 4) { 139ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru value >>= 4; 140ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru bit += 4; 141ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 142ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 143ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (value >= 1 << 2) { 144ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru value >>= 2; 145ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru bit += 2; 146ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 147ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 148ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (value >= 1 << 1) { 149f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius //value >>= 1; 150ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru bit += 1; 151ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 152ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 153ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return bit; 154ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 155ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 156ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic int32_t 157ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QuerugetPairIndex(UChar32 ch) 158ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 159ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t pairedCharCount = ARRAY_SIZE(pairedChars); 160ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t pairedCharPower = 1 << highBit(pairedCharCount); 161ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t pairedCharExtra = pairedCharCount - pairedCharPower; 162ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 163ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t probe = pairedCharPower; 16485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho int32_t pairIndex = 0; 165ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 166ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (ch >= pairedChars[pairedCharExtra]) { 16785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho pairIndex = pairedCharExtra; 168ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 169ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 170ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru while (probe > (1 << 0)) { 171ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru probe >>= 1; 172ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 17385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if (ch >= pairedChars[pairIndex + probe]) { 17485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho pairIndex += probe; 175ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 176ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 177ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 17885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if (pairedChars[pairIndex] != ch) { 17985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho pairIndex = -1; 180ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 181ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 18285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return pairIndex; 183ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 184ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 185ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic UBool 186ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QuerusameScript(UScriptCode scriptOne, UScriptCode scriptTwo) 187ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 188ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return scriptOne <= USCRIPT_INHERITED || scriptTwo <= USCRIPT_INHERITED || scriptOne == scriptTwo; 189ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 190ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 191ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI UScriptRun * U_EXPORT2 192ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruuscript_openRun(const UChar *src, int32_t length, UErrorCode *pErrorCode) 193ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 194ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UScriptRun *result = NULL; 195ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 196ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (pErrorCode == NULL || U_FAILURE(*pErrorCode)) { 197ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return NULL; 198ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 199ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 200ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru result = uprv_malloc(sizeof (UScriptRun)); 201ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 202ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (result == NULL) { 203ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *pErrorCode = U_MEMORY_ALLOCATION_ERROR; 204ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return NULL; 205ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 206ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 207ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru uscript_setRunText(result, src, length, pErrorCode); 208ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 209ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru /* Release the UScriptRun if uscript_setRunText() returns an error */ 210ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(*pErrorCode)) { 211ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru uprv_free(result); 212ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru result = NULL; 213ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 214ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 215ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return result; 216ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 217ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 218ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI void U_EXPORT2 219ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruuscript_closeRun(UScriptRun *scriptRun) 220ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 221ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (scriptRun != NULL) { 222ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru uprv_free(scriptRun); 223ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 224ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 225ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 226ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI void U_EXPORT2 227ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruuscript_resetRun(UScriptRun *scriptRun) 228ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 229ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (scriptRun != NULL) { 230ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru scriptRun->scriptStart = 0; 231ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru scriptRun->scriptLimit = 0; 232ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru scriptRun->scriptCode = USCRIPT_INVALID_CODE; 233ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru scriptRun->parenSP = -1; 234ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru scriptRun->pushCount = 0; 235ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru scriptRun->fixupCount = 0; 236ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 237ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 238ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 239ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI void U_EXPORT2 240ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruuscript_setRunText(UScriptRun *scriptRun, const UChar *src, int32_t length, UErrorCode *pErrorCode) 241ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 242ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (pErrorCode == NULL || U_FAILURE(*pErrorCode)) { 243ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return; 244ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 245ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 246ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (scriptRun == NULL || length < 0 || ((src == NULL) != (length == 0))) { 247ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR; 248ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return; 249ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 250ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 251ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru scriptRun->textArray = src; 252ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru scriptRun->textLength = length; 253ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 254ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru uscript_resetRun(scriptRun); 255ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 256ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 257ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI UBool U_EXPORT2 258ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruuscript_nextRun(UScriptRun *scriptRun, int32_t *pRunStart, int32_t *pRunLimit, UScriptCode *pRunScript) 259ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 260ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UErrorCode error = U_ZERO_ERROR; 261ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 262ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru /* if we've fallen off the end of the text, we're done */ 263ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (scriptRun == NULL || scriptRun->scriptLimit >= scriptRun->textLength) { 264ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return FALSE; 265ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 266ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 267ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru SYNC_FIXUP(scriptRun); 268ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru scriptRun->scriptCode = USCRIPT_COMMON; 269ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 270ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru for (scriptRun->scriptStart = scriptRun->scriptLimit; scriptRun->scriptLimit < scriptRun->textLength; scriptRun->scriptLimit += 1) { 271ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UChar high = scriptRun->textArray[scriptRun->scriptLimit]; 272ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UChar32 ch = high; 273ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UScriptCode sc; 274ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t pairIndex; 275ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 276ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru /* 277ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * if the character is a high surrogate and it's not the last one 278ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * in the text, see if it's followed by a low surrogate 279ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 280ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (high >= 0xD800 && high <= 0xDBFF && scriptRun->scriptLimit < scriptRun->textLength - 1) { 281ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UChar low = scriptRun->textArray[scriptRun->scriptLimit + 1]; 282ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 283ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru /* 284ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * if it is followed by a low surrogate, 285ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * consume it and form the full character 286ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 287ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (low >= 0xDC00 && low <= 0xDFFF) { 288ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru ch = (high - 0xD800) * 0x0400 + low - 0xDC00 + 0x10000; 289ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru scriptRun->scriptLimit += 1; 290ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 291ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 292ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 293ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru sc = uscript_getScript(ch, &error); 294ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru pairIndex = getPairIndex(ch); 295ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 296ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru /* 297ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Paired character handling: 298ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 299ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * if it's an open character, push it onto the stack. 300ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * if it's a close character, find the matching open on the 301ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * stack, and use that script code. Any non-matching open 302ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * characters above it on the stack will be poped. 303ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 304ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (pairIndex >= 0) { 305ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if ((pairIndex & 1) == 0) { 306ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru push(scriptRun, pairIndex, scriptRun->scriptCode); 307ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else { 308ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru int32_t pi = pairIndex & ~1; 309ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 310ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru while (STACK_IS_NOT_EMPTY(scriptRun) && TOP(scriptRun).pairIndex != pi) { 311ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru pop(scriptRun); 312ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 313ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 314ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (STACK_IS_NOT_EMPTY(scriptRun)) { 315ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru sc = TOP(scriptRun).scriptCode; 316ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 317ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 318ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 319ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 320ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (sameScript(scriptRun->scriptCode, sc)) { 321ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (scriptRun->scriptCode <= USCRIPT_INHERITED && sc > USCRIPT_INHERITED) { 322ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru scriptRun->scriptCode = sc; 323ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 324ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru fixup(scriptRun, scriptRun->scriptCode); 325ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 326ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 327ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru /* 328ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * if this character is a close paired character, 329ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * pop the matching open character from the stack 330ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 331ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (pairIndex >= 0 && (pairIndex & 1) != 0) { 332ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru pop(scriptRun); 333ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 334ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else { 335ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru /* 336ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * if the run broke on a surrogate pair, 337ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * end it before the high surrogate 338ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 339ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (ch >= 0x10000) { 340ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru scriptRun->scriptLimit -= 1; 341ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 342ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 343ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru break; 344ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 345ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 346ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 347ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 348ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (pRunStart != NULL) { 349ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *pRunStart = scriptRun->scriptStart; 350ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 351ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 352ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (pRunLimit != NULL) { 353ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *pRunLimit = scriptRun->scriptLimit; 354ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 355ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 356ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (pRunScript != NULL) { 357ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *pRunScript = scriptRun->scriptCode; 358ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 359ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 360ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return TRUE; 361ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 362