From 4e5ffc5f8d727ef1bd8beca17476b529e584e7b1 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 31 Aug 2004 00:52:37 +0000 Subject: [PATCH] Combine the implementation of LIKE and GLOB into a single parameterized function. (CVS 1923) FossilOrigin-Name: 0a47c8f86d1649e9ae7edd4c49a6fe5f5272351e --- manifest | 18 +-- manifest.uuid | 2 +- src/func.c | 348 +++++++++++++++++------------------------------- src/sqliteInt.h | 6 +- src/utf.c | 81 +---------- src/util.c | 167 +---------------------- 6 files changed, 144 insertions(+), 478 deletions(-) diff --git a/manifest b/manifest index 5465488ce3..a43ef5f86e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Better\sdetection\sand\shandling\sof\scorrupt\sdatabase\sfiles.\s(CVS\s1922) -D 2004-08-30T16:52:18 +C Combine\sthe\simplementation\sof\sLIKE\sand\sGLOB\sinto\sa\ssingle\sparameterized\nfunction.\s(CVS\s1923) +D 2004-08-31T00:52:37 F Makefile.in 65a7c43fcaf9a710d62f120b11b6e435eeb4a450 F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd @@ -35,7 +35,7 @@ F src/date.c edff4aa851eeca8abbc737dc3933a2f0671156ce F src/delete.c 0ccc3424d72e5aaded165a8861b9d958c9d0afe6 F src/encode.c a876af473d1d636faa3dca51c7571f2e007eea37 F src/expr.c 3694386726ca140dddb839837ba24b58563d10af -F src/func.c 7e2eeebe219aa612ce7a04c74ae6d57379c6656b +F src/func.c ab1d6436edea1333f2a9398800a6404942661724 F src/hash.c a97721a55440b7bea31ffe471bb2f6b4123cddd5 F src/hash.h 1b0c445e1c89ff2aaad9b4605ba61375af001e84 F src/insert.c fc1ce65a0fe68f226143de9b43c3582164a92aff @@ -61,7 +61,7 @@ F src/random.c eff68e3f257e05e81eae6c4d50a51eb88beb4ff3 F src/select.c 400b2dcc8e05c0101a65a370f7ebb33c9c85f0b3 F src/shell.c 64932b37d79baffd34544172c14c99b2e08a11bb F src/sqlite.h.in b89ced1acc705bc9c79a2a4e725ac0eb64bd0614 -F src/sqliteInt.h c7ed161ecc40f9fd0f080fbcc00e34bd7d6735ee +F src/sqliteInt.h 89c1555ceba68d460ee13530eb8a51944e57fad2 F src/table.c 4521c278892f60e4d630788c0ea5cf4db1e75c49 F src/tclsqlite.c b7dd8b3531b70188d03354db530de0f2ffcac697 F src/test1.c 3670f318c473b5a81cae548d9cc42da3f6a6efee @@ -72,8 +72,8 @@ F src/test5.c b001fa7f1b9e2dc5c2331de62fc641b5ab2bd7a1 F src/tokenize.c 32171c3d576c7ec6acd6cf15e55c00ac0b314769 F src/trigger.c 8b147c6b8ae0bab3a13463a4ca9ab6ad61f1361d F src/update.c 151f1869ce532ed883f1ce26306f0b0fa7b2589a -F src/utf.c 3d8f7bffcbefcced69a436c9e0a1c7eb9e0bb4fa -F src/util.c e2c631849cc9e035f6fd387f507ad8886f77cedd +F src/utf.c 328890099db492dda5620ee5f924e244c6e57ff7 +F src/util.c d5aaf211543fb6e285654fada50252c857ac78aa F src/vacuum.c 9978a5760c2c430bc5b5e66505a02dad76f25813 F src/vdbe.c bc7717be599d23c463c029d13eb2eb46c94a5e6e F src/vdbe.h e081c72cd0f7c19d49b1927460aeefcf0fbc85ac @@ -246,7 +246,7 @@ F www/tclsqlite.tcl 560ecd6a916b320e59f2917317398f3d59b7cc25 F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9 F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0 F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4 -P 9322c439c5727f0d65548efdf4de4d7b89b4be66 -R 78b9eb3fdca60240e1b2bb671f0502fe +P 8f5b199e845fa7ae3444ef69bd840716d305cf73 +R 616cb374fb9c8575e09ed1273dacb01d U drh -Z b8b12d29336c5de9dba049e2bc96808c +Z 33bccfa82a63e9342b9c97917948d9a3 diff --git a/manifest.uuid b/manifest.uuid index 283fbb4b9d..7ccd0c432f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8f5b199e845fa7ae3444ef69bd840716d305cf73 \ No newline at end of file +0a47c8f86d1649e9ae7edd4c49a6fe5f5272351e \ No newline at end of file diff --git a/src/func.c b/src/func.c index bad96d2a17..33ebfc4e5a 100644 --- a/src/func.c +++ b/src/func.c @@ -16,7 +16,7 @@ ** sqliteRegisterBuildinFunctions() found at the bottom of the file. ** All other code has file scope. ** -** $Id: func.c,v 1.80 2004/08/08 20:22:18 drh Exp $ +** $Id: func.c,v 1.81 2004/08/31 00:52:37 drh Exp $ */ #include #include @@ -298,250 +298,145 @@ static void total_changes( sqlite3_result_int(context, sqlite3_total_changes(db)); } -#if 0 - /* -** A LIKE pattern compiles to an instance of the following structure. Refer -** to the comment for compileLike() function for details. +** A structure defining how to do GLOB-style comparisons. */ -struct LikePattern { - int nState; - struct LikeState { - int val; /* Unicode codepoint or -1 for any char i.e. '_' */ - int failstate; /* State to jump to if next char is not val */ - } aState[1]; +struct compareInfo { + u8 matchAll; + u8 matchOne; + u8 matchSet; + u8 noCase; }; -typedef struct LikePattern LikePattern; - -void deleteLike(void *pLike){ - sqliteFree(pLike); -} -/* #define TRACE_LIKE */ -#if defined(TRACE_LIKE) && !defined(NDEBUG) -char *dumpLike(LikePattern *pLike){ - int i; - int k = 0; - char *zBuf = (char *)sqliteMalloc(pLike->nState*40); - - k += sprintf(&zBuf[k], "%d states - ", pLike->nState); - for(i=0; inState; i++){ - k += sprintf(&zBuf[k], " %d:(%d, %d)", i, pLike->aState[i].val, - pLike->aState[i].failstate); - } - return zBuf; -} -#endif +static const struct compareInfo globInfo = { '*', '?', '[', 0 }; +static const struct compareInfo likeInfo = { '%', '_', 0, 1 }; /* -** This function compiles an SQL 'LIKE' pattern into a state machine, -** represented by a LikePattern structure. -** -** Each state of the state-machine has two attributes, 'val' and -** 'failstate'. The val attribute is either the value of a unicode -** codepoint, or -1, indicating a '_' wildcard (match any single -** character). The failstate is either the number of another state -** or -1, indicating jump to 'no match'. -** -** To see if a string matches a pattern the pattern is -** compiled to a state machine that is executed according to the algorithm -** below. The string is assumed to be terminated by a 'NUL' character -** (unicode codepoint 0). -** -** 1 S = 0 -** 2 DO -** 3 C = -** 4 IF( C matches ) -** 5 S = S+1 -** 6 ELSE IF( S != ) -** 7 S = -** 8 -** 9 WHILE( (C != NUL) AND (S != FAILED) ) -** 10 -** 11 IF( S == ) -** 12 RETURN MATCH -** 13 ELSE -** 14 RETURN NO-MATCH -** -** In practice there is a small optimization to avoid the -** operation in line 8 of the description above. -** -** For example, the following pattern, 'X%ABabc%_Y' is compiled to -** the state machine below. -** -** State Val FailState -** ------------------------------- -** 0 120 (x) -1 (NO MATCH) -** 1 97 (a) 1 -** 2 98 (b) 1 -** 3 97 (a) 1 -** 4 98 (b) 2 -** 5 99 (c) 3 -** 6 -1 (_) 6 -** 7 121 (y) 7 -** 8 0 (NUL) 7 -** -** The algorithms implemented to compile and execute the state machine were -** first presented in "Fast pattern matching in strings", Knuth, Morris and -** Pratt, 1977. -** +** X is a pointer to the first byte of a UTF-8 character. Increment +** X so that it points to the next character. This only works right +** if X points to a well-formed UTF-8 string. */ -LikePattern *compileLike(sqlite3_value *pPattern, u8 enc){ - LikePattern *pLike; - struct LikeState *aState; - int pc_state = -1; /* State number of previous '%' wild card */ - int n = 0; - int c; +#define sqliteNextChar(X) while( (0xc0&*++(X))==0x80 ){} +#define sqliteCharVal(X) sqlite3ReadUtf8(X) - int offset = 0; - const char *zLike; - - if( enc==SQLITE_UTF8 ){ - zLike = sqlite3_value_text(pPattern); - n = sqlite3_value_bytes(pPattern) + 1; - }else{ - zLike = sqlite3_value_text16(pPattern); - n = sqlite3_value_bytes16(pPattern)/2 + 1; - } - - pLike = (LikePattern *) - sqliteMalloc(sizeof(LikePattern)+n*sizeof(struct LikeState)); - aState = pLike->aState; - - n = 0; - do { - c = sqlite3ReadUniChar(zLike, &offset, &enc, 1); - if( c==95 ){ /* A '_' wildcard */ - aState[n].val = -1; - n++; - }else if( c==37 ){ /* A '%' wildcard */ - aState[n].failstate = n; - pc_state = n; - }else{ /* A regular character */ - aState[n].val = c; - - assert( pc_state<=n ); - if( pc_state<0 ){ - aState[n].failstate = -1; - }else if( pc_state==n ){ - if( c ){ - aState[n].failstate = pc_state; - }else{ - aState[n].failstate = -2; - } - }else{ - int k = pLike->aState[n-1].failstate; - while( k>pc_state && aState[k+1].val!=-1 && aState[k+1].val!=c ){ - k = aState[k].failstate; - } - if( k!=pc_state && aState[k+1].val==c ){ - assert( k==pc_state ); - k++; - } - aState[n].failstate = k; - } - n++; - } - }while( c ); - pLike->nState = n; -#if defined(TRACE_LIKE) && !defined(NDEBUG) - { - char *zCompiled = dumpLike(pLike); - printf("Pattern=\"%s\" Compiled=\"%s\"\n", zPattern, zCompiled); - sqliteFree(zCompiled); - } -#endif - return pLike; -} /* -** Implementation of the like() SQL function. This function implements -** the build-in LIKE operator. The first argument to the function is the -** pattern and the second argument is the string. So, the SQL statements: +** Compare two UTF-8 strings for equality where the first string can +** potentially be a "glob" expression. Return true (1) if they +** are the same and false (0) if they are different. ** -** A LIKE B +** Globbing rules: ** -** is implemented as like(B,A). +** '*' Matches any sequence of zero or more characters. ** -** If the pointer retrieved by via a call to sqlite3_user_data() is -** not NULL, then this function uses UTF-16. Otherwise UTF-8. +** '?' Matches exactly one character. +** +** [...] Matches one character from the enclosed list of +** characters. +** +** [^...] Matches one character not in the enclosed list. +** +** With the [...] and [^...] matching, a ']' character can be included +** in the list by making it the first character after '[' or '^'. A +** range of characters can be specified using '-'. Example: +** "[a-z]" matches any single lower-case letter. To match a '-', make +** it the last character in the list. +** +** This routine is usually quick, but can be N**2 in the worst case. +** +** Hints: to match '*' or '?', put them in "[]". Like this: +** +** abc[*]xyz Matches "abc*xyz" only */ -static void likeFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv +int patternCompare( + const u8 *zPattern, /* The glob pattern */ + const u8 *zString, /* The string to compare against the glob */ + const struct compareInfo *pInfo /* Information about how to do the compare */ ){ register int c; - u8 enc; - int offset = 0; - const unsigned char *zString; - LikePattern *pLike = sqlite3_get_auxdata(context, 0); - struct LikeState *aState; - register struct LikeState *pState; + int invert; + int seen; + int c2; + u8 matchOne = pInfo->matchOne; + u8 matchAll = pInfo->matchAll; + u8 matchSet = pInfo->matchSet; + u8 noCase = pInfo->noCase; - /* If either argument is NULL, the result is NULL */ - if( sqlite3_value_type(argv[1])==SQLITE_NULL || - sqlite3_value_type(argv[0])==SQLITE_NULL ){ - return; - } - - /* If the user-data pointer is NULL, use UTF-8. Otherwise UTF-16. */ - if( sqlite3_user_data(context) ){ - enc = SQLITE_UTF16NATIVE; - zString = (const unsigned char *)sqlite3_value_text16(argv[1]); - assert(0); - }else{ - enc = SQLITE_UTF8; - zString = sqlite3_value_text(argv[1]); - } - - /* If the LIKE pattern has not been compiled, compile it now. */ - if( !pLike ){ - pLike = compileLike(argv[0], enc); - if( !pLike ){ - sqlite3_result_error(context, "out of memory", -1); - return; - } - sqlite3_set_auxdata(context, 0, pLike, deleteLike); - } - aState = pLike->aState; - pState = aState; - - do { - if( enc==SQLITE_UTF8 ){ - c = zString[offset++]; - if( c&0x80 ){ - offset--; - c = sqlite3ReadUniChar(zString, &offset, &enc, 1); + while( (c = *zPattern)!=0 ){ + if( c==matchAll ){ + while( (c=zPattern[1]) == matchAll || c == matchOne ){ + if( c==matchOne ){ + if( *zString==0 ) return 0; + sqliteNextChar(zString); + } + zPattern++; } - }else{ - c = sqlite3ReadUniChar(zString, &offset, &enc, 1); - } - -skip_read: - -#if defined(TRACE_LIKE) && !defined(NDEBUG) - printf("State=%d:(%d, %d) Input=%d\n", - (aState - pState), pState->val, pState->failstate, c); -#endif - - if( pState->val==-1 || pState->val==c ){ - pState++; - }else{ - struct LikeState *pFailState = &aState[pState->failstate]; - if( pState!=pFailState ){ - pState = pFailState; - if( c && pState>=aState ) goto skip_read; + if( c==0 ) return 1; + if( c==matchSet ){ + while( *zString && patternCompare(&zPattern[1],zString,pInfo)==0 ){ + sqliteNextChar(zString); + } + return *zString!=0; + }else{ + while( (c2 = *zString)!=0 ){ + if( noCase ){ + c2 = sqlite3UpperToLower[c2]; + c = sqlite3UpperToLower[c]; + while( c2 != 0 && c2 != c ){ c2 = sqlite3UpperToLower[*++zString]; } + }else{ + while( c2 != 0 && c2 != c ){ c2 = *++zString; } + } + if( c2==0 ) return 0; + if( patternCompare(&zPattern[1],zString,pInfo) ) return 1; + sqliteNextChar(zString); + } + return 0; } + }else if( c==matchOne ){ + if( *zString==0 ) return 0; + sqliteNextChar(zString); + zPattern++; + }else if( c==matchSet ){ + int prior_c = 0; + seen = 0; + invert = 0; + c = sqliteCharVal(zString); + if( c==0 ) return 0; + c2 = *++zPattern; + if( c2=='^' ){ invert = 1; c2 = *++zPattern; } + if( c2==']' ){ + if( c==']' ) seen = 1; + c2 = *++zPattern; + } + while( (c2 = sqliteCharVal(zPattern))!=0 && c2!=']' ){ + if( c2=='-' && zPattern[1]!=']' && zPattern[1]!=0 && prior_c>0 ){ + zPattern++; + c2 = sqliteCharVal(zPattern); + if( c>=prior_c && c<=c2 ) seen = 1; + prior_c = 0; + }else if( c==c2 ){ + seen = 1; + prior_c = c2; + }else{ + prior_c = c2; + } + sqliteNextChar(zPattern); + } + if( c2==0 || (seen ^ invert)==0 ) return 0; + sqliteNextChar(zString); + zPattern++; + }else{ + if( noCase ){ + if( sqlite3UpperToLower[c] != sqlite3UpperToLower[*zString] ) return 0; + }else{ + if( c != *zString ) return 0; + } + zPattern++; + zString++; } - }while( c && pState>=aState ); - - if( (pState-aState)==pLike->nState || (pState-aState)<-1 ){ - sqlite3_result_int(context, 1); - }else{ - sqlite3_result_int(context, 0); } + return *zString==0; } -#endif + /* ** Implementation of the like() SQL function. This function implements @@ -563,7 +458,7 @@ static void likeFunc( const unsigned char *zA = sqlite3_value_text(argv[0]); const unsigned char *zB = sqlite3_value_text(argv[1]); if( zA && zB ){ - sqlite3_result_int(context, sqlite3utf8LikeCompare(zA, zB)); + sqlite3_result_int(context, patternCompare(zA, zB, &likeInfo)); } } @@ -580,7 +475,7 @@ static void globFunc(sqlite3_context *context, int arg, sqlite3_value **argv){ const unsigned char *zA = sqlite3_value_text(argv[0]); const unsigned char *zB = sqlite3_value_text(argv[1]); if( zA && zB ){ - sqlite3_result_int(context, sqlite3GlobCompare(zA, zB)); + sqlite3_result_int(context, patternCompare(zA, zB, &globInfo)); } } @@ -1016,6 +911,7 @@ static void minMaxFinalize(sqlite3_context *context){ sqlite3VdbeMemRelease(pRes); } + /* ** This function registered all of the above C functions as SQL ** functions. This should be the only routine in this file with diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 3881dfa435..a5d8ebc08b 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.316 2004/08/21 17:54:45 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.317 2004/08/31 00:52:37 drh Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ @@ -1270,7 +1270,6 @@ void sqlite3UnlinkAndDeleteIndex(sqlite*,int,const char*); void sqlite3UnlinkAndDeleteTrigger(sqlite*,int,const char*); void sqlite3Vacuum(Parse*, Token*); int sqlite3RunVacuum(char**, sqlite*); -int sqlite3GlobCompare(const unsigned char*,const unsigned char*); char *sqlite3NameFromToken(Token*); int sqlite3ExprCheck(Parse*, Expr*, int, int*); int sqlite3ExprCompare(Expr*, Expr*); @@ -1354,7 +1353,7 @@ int sqlite3GetInt32(const char *, int*); int sqlite3FitsIn64Bits(const char *); int sqlite3utf16ByteLen(const void *pData, int nChar); int sqlite3utf8CharLen(const char *pData, int nByte); -int sqlite3utf8LikeCompare(const unsigned char*, const unsigned char*); +int sqlite3ReadUtf8(const unsigned char *); int sqlite3PutVarint(unsigned char *, u64); int sqlite3GetVarint(const unsigned char *, u64 *); int sqlite3GetVarint32(const unsigned char *, u32 *); @@ -1388,5 +1387,6 @@ void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8, void(*)(void*)); void sqlite3ValueFree(sqlite3_value*); sqlite3_value *sqlite3ValueNew(); sqlite3_value *sqlite3GetTransientValue(sqlite *db); +extern const unsigned char sqlite3UpperToLower[]; #endif diff --git a/src/utf.c b/src/utf.c index 563df63478..033ed38a78 100644 --- a/src/utf.c +++ b/src/utf.c @@ -12,7 +12,7 @@ ** This file contains routines used to translate between UTF-8, ** UTF-16, UTF-16BE, and UTF-16LE. ** -** $Id: utf.c,v 1.27 2004/08/08 23:39:19 drh Exp $ +** $Id: utf.c,v 1.28 2004/08/31 00:52:37 drh Exp $ ** ** Notes on UTF-8: ** @@ -62,27 +62,6 @@ #include "sqliteInt.h" #include "vdbeInt.h" -/* -** The following macro, LOWERCASE(x), takes an integer representing a -** unicode code point. The value returned is the same code point folded to -** lower case, if applicable. SQLite currently understands the upper/lower -** case relationship between the 26 characters used in the English -** language only. -** -** This means that characters with umlauts etc. will not be folded -** correctly (unless they are encoded as composite characters, which would -** doubtless cause much trouble). -*/ -#define LOWERCASE(x) (x<91?(int)(UpperToLower[x]):x) -static unsigned char UpperToLower[91] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, - 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, - 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, - 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 97, 98, 99,100,101,102,103, - 104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121, - 122, -}; - /* ** This table maps from the first byte of a UTF-8 character to the number ** of trailing bytes expected. A value '255' indicates that the table key @@ -141,6 +120,11 @@ static const int xtra_utf8_bits[4] = { c -= xtra_utf8_bits[xtra]; \ } \ } +int sqlite3ReadUtf8(const unsigned char *z){ + int c; + READ_UTF8(z, c); + return c; +} #define SKIP_UTF8(zIn) { \ zIn += (xtra_utf8_bytes[*(u8 *)zIn] + 1); \ @@ -491,59 +475,6 @@ int sqlite3utf16ByteLen(const void *zIn, int nChar){ return (z-(char const *)zIn)-((c==0)?2:0); } -/* -** Compare two UTF-8 strings for equality using the "LIKE" operator of -** SQL. The '%' character matches any sequence of 0 or more -** characters and '_' matches any single character. Case is -** not significant. -*/ -int sqlite3utf8LikeCompare( - const unsigned char *zPattern, - const unsigned char *zString -){ - register int c; - int c2; - - while( (c = LOWERCASE(*zPattern))!=0 ){ - switch( c ){ - case '%': { - while( (c=zPattern[1]) == '%' || c == '_' ){ - if( c=='_' ){ - if( *zString==0 ) return 0; - SKIP_UTF8(zString); - } - zPattern++; - } - if( c==0 ) return 1; - c = LOWERCASE(c); - while( (c2=LOWERCASE(*zString))!=0 ){ - while( c2 != 0 && c2 != c ){ - zString++; - c2 = LOWERCASE(*zString); - } - if( c2==0 ) return 0; - if( sqlite3utf8LikeCompare(&zPattern[1],zString) ) return 1; - SKIP_UTF8(zString); - } - return 0; - } - case '_': { - if( *zString==0 ) return 0; - SKIP_UTF8(zString); - zPattern++; - break; - } - default: { - if( c != LOWERCASE(*zString) ) return 0; - zPattern++; - zString++; - break; - } - } - } - return *zString==0; -} - /* ** UTF-16 implementation of the substr() */ diff --git a/src/util.c b/src/util.c index 8c7985d464..f31359620f 100644 --- a/src/util.c +++ b/src/util.c @@ -14,7 +14,7 @@ ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** -** $Id: util.c,v 1.113 2004/08/18 02:10:15 drh Exp $ +** $Id: util.c,v 1.114 2004/08/31 00:52:37 drh Exp $ */ #include "sqliteInt.h" #include @@ -533,7 +533,7 @@ void sqlite3Dequote(char *z){ /* An array to map all upper-case characters into their corresponding ** lower-case character. */ -static unsigned char UpperToLower[] = { +const unsigned char sqlite3UpperToLower[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, @@ -550,6 +550,7 @@ static unsigned char UpperToLower[] = { 234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251, 252,253,254,255 }; +#define UpperToLower sqlite3UpperToLower /* ** This function computes a hash on the name of a keyword. @@ -762,168 +763,6 @@ int sqlite3FitsIn64Bits(const char *zNum){ return i<19 || (i==19 && memcmp(zNum,"9223372036854775807",19)<=0); } -#if 1 /* We are now always UTF-8 */ -/* -** X is a pointer to the first byte of a UTF-8 character. Increment -** X so that it points to the next character. This only works right -** if X points to a well-formed UTF-8 string. -*/ -#define sqliteNextChar(X) while( (0xc0&*++(X))==0x80 ){} -#define sqliteCharVal(X) sqlite3ReadUtf8(X) - -#else /* !defined(SQLITE_UTF8) */ -/* -** For iso8859 encoding, the next character is just the next byte. -*/ -#define sqliteNextChar(X) (++(X)); -#define sqliteCharVal(X) ((int)*(X)) - -#endif /* defined(SQLITE_UTF8) */ - - -#if 1 /* We are now always UTF-8 */ -/* -** Convert the UTF-8 character to which z points into a 31-bit -** UCS character. This only works right if z points to a well-formed -** UTF-8 string. -*/ -int sqlite3ReadUtf8(const unsigned char *z){ - int c; - static const char initVal[] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, - 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, - 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, - 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, - 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, - 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, - 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, - 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, - 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, - 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, - 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, - 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 0, 1, 2, - 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, - 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 0, - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 0, 1, 254, - 255, - }; - c = initVal[*(z++)]; - while( (0xc0&*z)==0x80 ){ - c = (c<<6) | (0x3f&*(z++)); - } - return c; -} -#endif - -/* -** Compare two UTF-8 strings for equality where the first string can -** potentially be a "glob" expression. Return true (1) if they -** are the same and false (0) if they are different. -** -** Globbing rules: -** -** '*' Matches any sequence of zero or more characters. -** -** '?' Matches exactly one character. -** -** [...] Matches one character from the enclosed list of -** characters. -** -** [^...] Matches one character not in the enclosed list. -** -** With the [...] and [^...] matching, a ']' character can be included -** in the list by making it the first character after '[' or '^'. A -** range of characters can be specified using '-'. Example: -** "[a-z]" matches any single lower-case letter. To match a '-', make -** it the last character in the list. -** -** This routine is usually quick, but can be N**2 in the worst case. -** -** Hints: to match '*' or '?', put them in "[]". Like this: -** -** abc[*]xyz Matches "abc*xyz" only -*/ -int -sqlite3GlobCompare(const unsigned char *zPattern, const unsigned char *zString){ - register int c; - int invert; - int seen; - int c2; - - while( (c = *zPattern)!=0 ){ - switch( c ){ - case '*': - while( (c=zPattern[1]) == '*' || c == '?' ){ - if( c=='?' ){ - if( *zString==0 ) return 0; - sqliteNextChar(zString); - } - zPattern++; - } - if( c==0 ) return 1; - if( c=='[' ){ - while( *zString && sqlite3GlobCompare(&zPattern[1],zString)==0 ){ - sqliteNextChar(zString); - } - return *zString!=0; - }else{ - while( (c2 = *zString)!=0 ){ - while( c2 != 0 && c2 != c ){ c2 = *++zString; } - if( c2==0 ) return 0; - if( sqlite3GlobCompare(&zPattern[1],zString) ) return 1; - sqliteNextChar(zString); - } - return 0; - } - case '?': { - if( *zString==0 ) return 0; - sqliteNextChar(zString); - zPattern++; - break; - } - case '[': { - int prior_c = 0; - seen = 0; - invert = 0; - c = sqliteCharVal(zString); - if( c==0 ) return 0; - c2 = *++zPattern; - if( c2=='^' ){ invert = 1; c2 = *++zPattern; } - if( c2==']' ){ - if( c==']' ) seen = 1; - c2 = *++zPattern; - } - while( (c2 = sqliteCharVal(zPattern))!=0 && c2!=']' ){ - if( c2=='-' && zPattern[1]!=']' && zPattern[1]!=0 && prior_c>0 ){ - zPattern++; - c2 = sqliteCharVal(zPattern); - if( c>=prior_c && c<=c2 ) seen = 1; - prior_c = 0; - }else if( c==c2 ){ - seen = 1; - prior_c = c2; - }else{ - prior_c = c2; - } - sqliteNextChar(zPattern); - } - if( c2==0 || (seen ^ invert)==0 ) return 0; - sqliteNextChar(zString); - zPattern++; - break; - } - default: { - if( c != *zString ) return 0; - zPattern++; - zString++; - break; - } - } - } - return *zString==0; -} /* ** Change the sqlite.magic from SQLITE_MAGIC_OPEN to SQLITE_MAGIC_BUSY.