| Index: third_party/sqlite/src/ext/icu/icu.c
|
| diff --git a/third_party/sqlite/src/ext/icu/icu.c b/third_party/sqlite/src/ext/icu/icu.c
|
| index da34f3b11a90b6ab8dd4bea509e30d36bb0353f3..7c37812d86aed44e6b975546b2b7f1a8e2a27e59 100644
|
| --- a/third_party/sqlite/src/ext/icu/icu.c
|
| +++ b/third_party/sqlite/src/ext/icu/icu.c
|
| @@ -61,6 +61,38 @@ static void xFree(void *p){
|
| }
|
|
|
| /*
|
| +** This lookup table is used to help decode the first byte of
|
| +** a multi-byte UTF8 character. It is copied here from SQLite source
|
| +** code file utf8.c.
|
| +*/
|
| +static const unsigned char icuUtf8Trans1[] = {
|
| + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
| + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
| + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
|
| + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
|
| + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
| + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
| + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
| + 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x00, 0x00,
|
| +};
|
| +
|
| +#define SQLITE_ICU_READ_UTF8(zIn, c) \
|
| + c = *(zIn++); \
|
| + if( c>=0xc0 ){ \
|
| + c = icuUtf8Trans1[c-0xc0]; \
|
| + while( (*zIn & 0xc0)==0x80 ){ \
|
| + c = (c<<6) + (0x3f & *(zIn++)); \
|
| + } \
|
| + }
|
| +
|
| +#define SQLITE_ICU_SKIP_UTF8(zIn) \
|
| + assert( *zIn ); \
|
| + if( *(zIn++)>=0xc0 ){ \
|
| + while( (*zIn & 0xc0)==0x80 ){zIn++;} \
|
| + }
|
| +
|
| +
|
| +/*
|
| ** Compare two UTF-8 strings for equality where the first string is
|
| ** a "LIKE" expression. Return true (1) if they are the same and
|
| ** false (0) if they are different.
|
| @@ -73,16 +105,14 @@ static int icuLikeCompare(
|
| static const int MATCH_ONE = (UChar32)'_';
|
| static const int MATCH_ALL = (UChar32)'%';
|
|
|
| - int iPattern = 0; /* Current byte index in zPattern */
|
| - int iString = 0; /* Current byte index in zString */
|
| -
|
| int prevEscape = 0; /* True if the previous character was uEsc */
|
|
|
| - while( zPattern[iPattern]!=0 ){
|
| + while( 1 ){
|
|
|
| /* Read (and consume) the next character from the input pattern. */
|
| UChar32 uPattern;
|
| - U8_NEXT_OR_FFFD(zPattern, iPattern, -1, uPattern);
|
| + SQLITE_ICU_READ_UTF8(zPattern, uPattern);
|
| + if( uPattern==0 ) break;
|
|
|
| /* There are now 4 possibilities:
|
| **
|
| @@ -99,28 +129,28 @@ static int icuLikeCompare(
|
| ** MATCH_ALL. For each MATCH_ONE, skip one character in the
|
| ** test string.
|
| */
|
| - while( (c=zPattern[iPattern]) == MATCH_ALL || c == MATCH_ONE ){
|
| + while( (c=*zPattern) == MATCH_ALL || c == MATCH_ONE ){
|
| if( c==MATCH_ONE ){
|
| - if( zString[iString]==0 ) return 0;
|
| - U8_FWD_1(zString, iString, -1);
|
| + if( *zString==0 ) return 0;
|
| + SQLITE_ICU_SKIP_UTF8(zString);
|
| }
|
| - iPattern++;
|
| + zPattern++;
|
| }
|
|
|
| - if( zPattern[iPattern]==0 ) return 1;
|
| + if( *zPattern==0 ) return 1;
|
|
|
| - while( zString[iString] ){
|
| - if( icuLikeCompare(&zPattern[iPattern], &zString[iString], uEsc) ){
|
| + while( *zString ){
|
| + if( icuLikeCompare(zPattern, zString, uEsc) ){
|
| return 1;
|
| }
|
| - U8_FWD_1(zString, iString, -1);
|
| + SQLITE_ICU_SKIP_UTF8(zString);
|
| }
|
| return 0;
|
|
|
| }else if( !prevEscape && uPattern==MATCH_ONE ){
|
| /* Case 2. */
|
| - if( zString[iString]==0 ) return 0;
|
| - U8_FWD_1(zString, iString, -1);
|
| + if( *zString==0 ) return 0;
|
| + SQLITE_ICU_SKIP_UTF8(zString);
|
|
|
| }else if( !prevEscape && uPattern==uEsc){
|
| /* Case 3. */
|
| @@ -129,7 +159,7 @@ static int icuLikeCompare(
|
| }else{
|
| /* Case 4. */
|
| UChar32 uString;
|
| - U8_NEXT_OR_FFFD(zString, iString, -1, uString);
|
| + SQLITE_ICU_READ_UTF8(zString, uString);
|
| uString = u_foldCase(uString, U_FOLD_CASE_DEFAULT);
|
| uPattern = u_foldCase(uPattern, U_FOLD_CASE_DEFAULT);
|
| if( uString!=uPattern ){
|
| @@ -139,7 +169,7 @@ static int icuLikeCompare(
|
| }
|
| }
|
|
|
| - return zString[iString]==0;
|
| + return *zString==0;
|
| }
|
|
|
| /*
|
| @@ -319,20 +349,22 @@ static void icuRegexpFunc(sqlite3_context *p, int nArg, sqlite3_value **apArg){
|
| ** of upper() or lower().
|
| **
|
| ** lower('I', 'en_us') -> 'i'
|
| -** lower('I', 'tr_tr') -> 'ı' (small dotless i)
|
| +** lower('I', 'tr_tr') -> '\u131' (small dotless i)
|
| **
|
| ** http://www.icu-project.org/userguide/posix.html#case_mappings
|
| */
|
| static void icuCaseFunc16(sqlite3_context *p, int nArg, sqlite3_value **apArg){
|
| - const UChar *zInput;
|
| - UChar *zOutput = 0;
|
| - int nInput;
|
| - int nOut;
|
| + const UChar *zInput; /* Pointer to input string */
|
| + UChar *zOutput = 0; /* Pointer to output buffer */
|
| + int nInput; /* Size of utf-16 input string in bytes */
|
| + int nOut; /* Size of output buffer in bytes */
|
| int cnt;
|
| + int bToUpper; /* True for toupper(), false for tolower() */
|
| UErrorCode status;
|
| const char *zLocale = 0;
|
|
|
| assert(nArg==1 || nArg==2);
|
| + bToUpper = (sqlite3_user_data(p)!=0);
|
| if( nArg==2 ){
|
| zLocale = (const char *)sqlite3_value_text(apArg[1]);
|
| }
|
| @@ -356,19 +388,23 @@ static void icuCaseFunc16(sqlite3_context *p, int nArg, sqlite3_value **apArg){
|
| }
|
| zOutput = zNew;
|
| status = U_ZERO_ERROR;
|
| - if( sqlite3_user_data(p) ){
|
| + if( bToUpper ){
|
| nOut = 2*u_strToUpper(zOutput,nOut/2,zInput,nInput/2,zLocale,&status);
|
| }else{
|
| nOut = 2*u_strToLower(zOutput,nOut/2,zInput,nInput/2,zLocale,&status);
|
| }
|
| - if( !U_SUCCESS(status) ){
|
| - if( status==U_BUFFER_OVERFLOW_ERROR ) continue;
|
| - icuFunctionError(p,
|
| - sqlite3_user_data(p) ? "u_strToUpper()" : "u_strToLower", status);
|
| - return;
|
| +
|
| + if( U_SUCCESS(status) ){
|
| + sqlite3_result_text16(p, zOutput, nOut, xFree);
|
| + }else if( status==U_BUFFER_OVERFLOW_ERROR ){
|
| + assert( cnt==0 );
|
| + continue;
|
| + }else{
|
| + icuFunctionError(p, bToUpper ? "u_strToUpper" : "u_strToLower", status);
|
| }
|
| + return;
|
| }
|
| - sqlite3_result_text16(p, zOutput, nOut, xFree);
|
| + assert( 0 ); /* Unreachable */
|
| }
|
|
|
| /*
|
| @@ -457,38 +493,36 @@ static void icuLoadCollation(
|
| ** Register the ICU extension functions with database db.
|
| */
|
| int sqlite3IcuInit(sqlite3 *db){
|
| - struct IcuScalar {
|
| + static const struct IcuScalar {
|
| const char *zName; /* Function name */
|
| - int nArg; /* Number of arguments */
|
| - int enc; /* Optimal text encoding */
|
| - void *pContext; /* sqlite3_user_data() context */
|
| + unsigned char nArg; /* Number of arguments */
|
| + unsigned short enc; /* Optimal text encoding */
|
| + unsigned char iContext; /* sqlite3_user_data() context */
|
| void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
|
| } scalars[] = {
|
| - {"regexp", 2, SQLITE_ANY, 0, icuRegexpFunc},
|
| -
|
| - {"lower", 1, SQLITE_UTF16, 0, icuCaseFunc16},
|
| - {"lower", 2, SQLITE_UTF16, 0, icuCaseFunc16},
|
| - {"upper", 1, SQLITE_UTF16, (void*)1, icuCaseFunc16},
|
| - {"upper", 2, SQLITE_UTF16, (void*)1, icuCaseFunc16},
|
| -
|
| - {"lower", 1, SQLITE_UTF8, 0, icuCaseFunc16},
|
| - {"lower", 2, SQLITE_UTF8, 0, icuCaseFunc16},
|
| - {"upper", 1, SQLITE_UTF8, (void*)1, icuCaseFunc16},
|
| - {"upper", 2, SQLITE_UTF8, (void*)1, icuCaseFunc16},
|
| -
|
| - {"like", 2, SQLITE_UTF8, 0, icuLikeFunc},
|
| - {"like", 3, SQLITE_UTF8, 0, icuLikeFunc},
|
| -
|
| - {"icu_load_collation", 2, SQLITE_UTF8, (void*)db, icuLoadCollation},
|
| + {"icu_load_collation", 2, SQLITE_UTF8, 1, icuLoadCollation},
|
| + {"regexp", 2, SQLITE_ANY|SQLITE_DETERMINISTIC, 0, icuRegexpFunc},
|
| + {"lower", 1, SQLITE_UTF16|SQLITE_DETERMINISTIC, 0, icuCaseFunc16},
|
| + {"lower", 2, SQLITE_UTF16|SQLITE_DETERMINISTIC, 0, icuCaseFunc16},
|
| + {"upper", 1, SQLITE_UTF16|SQLITE_DETERMINISTIC, 1, icuCaseFunc16},
|
| + {"upper", 2, SQLITE_UTF16|SQLITE_DETERMINISTIC, 1, icuCaseFunc16},
|
| + {"lower", 1, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuCaseFunc16},
|
| + {"lower", 2, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuCaseFunc16},
|
| + {"upper", 1, SQLITE_UTF8|SQLITE_DETERMINISTIC, 1, icuCaseFunc16},
|
| + {"upper", 2, SQLITE_UTF8|SQLITE_DETERMINISTIC, 1, icuCaseFunc16},
|
| + {"like", 2, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuLikeFunc},
|
| + {"like", 3, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuLikeFunc},
|
| };
|
| -
|
| int rc = SQLITE_OK;
|
| int i;
|
|
|
| +
|
| for(i=0; rc==SQLITE_OK && i<(int)(sizeof(scalars)/sizeof(scalars[0])); i++){
|
| - struct IcuScalar *p = &scalars[i];
|
| + const struct IcuScalar *p = &scalars[i];
|
| rc = sqlite3_create_function(
|
| - db, p->zName, p->nArg, p->enc, p->pContext, p->xFunc, 0, 0
|
| + db, p->zName, p->nArg, p->enc,
|
| + p->iContext ? (void*)db : (void*)0,
|
| + p->xFunc, 0, 0
|
| );
|
| }
|
|
|
|
|