]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Combine the implementation of LIKE and GLOB into a single parameterized
authordrh <drh@noemail.net>
Tue, 31 Aug 2004 00:52:37 +0000 (00:52 +0000)
committerdrh <drh@noemail.net>
Tue, 31 Aug 2004 00:52:37 +0000 (00:52 +0000)
function. (CVS 1923)

FossilOrigin-Name: 0a47c8f86d1649e9ae7edd4c49a6fe5f5272351e

manifest
manifest.uuid
src/func.c
src/sqliteInt.h
src/utf.c
src/util.c

index 5465488ce3c49d128526c95d3cc14190cc34bf91..a43ef5f86e8c0abc6393e8497cec647ed7e82cb0 100644 (file)
--- 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
index 283fbb4b9dbee843461498801a87683756ec42c8..7ccd0c432f611c099da33632cdd0f13947b16a67 100644 (file)
@@ -1 +1 @@
-8f5b199e845fa7ae3444ef69bd840716d305cf73
\ No newline at end of file
+0a47c8f86d1649e9ae7edd4c49a6fe5f5272351e
\ No newline at end of file
index bad96d2a17f4a02e1300f37a4fab80b42bdcd399..33ebfc4e5a06167a9548212ed96bd92ec27d7619 100644 (file)
@@ -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 <ctype.h>
 #include <math.h>
@@ -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;
+static const struct compareInfo globInfo = { '*', '?', '[', 0 };
+static const struct compareInfo likeInfo = { '%', '_',   0, 1 };
+
+/*
+** 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)
 
-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; i<pLike->nState; i++){
-    k += sprintf(&zBuf[k], " %d:(%d, %d)", i, pLike->aState[i].val,
-        pLike->aState[i].failstate);
-  }
-  return zBuf;
-}
-#endif
 
 /*
-** This function compiles an SQL 'LIKE' pattern into a state machine, 
-** represented by a LikePattern structure.
+** 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.
 **
-** 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'.
+** Globbing rules:
 **
-** 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).
+**      '*'       Matches any sequence of zero or more characters.
 **
-** 1   S = 0
-** 2   DO 
-** 3       C = <Next character from input string>
-** 4       IF( C matches <State S val> )
-** 5           S = S+1
-** 6       ELSE IF( S != <State S failstate> )
-** 7           S = <State S failstate>
-** 8           <Rewind Input string 1 character>
-** 9   WHILE( (C != NUL) AND (S != FAILED) )
-** 10
-** 11  IF( S == <number of states> )
-** 12      RETURN MATCH
-** 13  ELSE
-** 14      RETURN NO-MATCH
-**       
-** In practice there is a small optimization to avoid the <Rewind>
-** operation in line 8 of the description above.
+**      '?'       Matches exactly one character.
 **
-** For example, the following pattern, 'X%ABabc%_Y' is compiled to
-** the state machine below.
+**     [...]      Matches one character from the enclosed list of
+**                characters.
 **
-** 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
+**     [^...]     Matches one character not in the enclosed list.
 **
-** The algorithms implemented to compile and execute the state machine were
-** first presented in "Fast pattern matching in strings", Knuth, Morris and
-** Pratt, 1977.
-**       
-*/
-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;
-
-  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:
+** 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.
 **
-**       A LIKE B
+** This routine is usually quick, but can be N**2 in the worst case.
 **
-** is implemented as like(B,A).
+** Hints: to match '*' or '?', put them in "[]".  Like this:
 **
-** If the pointer retrieved by via a call to sqlite3_user_data() is
-** not NULL, then this function uses UTF-16. Otherwise UTF-8.
+**         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;
-
-  /* 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);
+  int invert;
+  int seen;
+  int c2;
+  u8 matchOne = pInfo->matchOne;
+  u8 matchAll = pInfo->matchAll;
+  u8 matchSet = pInfo->matchSet;
+  u8 noCase = pInfo->noCase; 
+
+  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++;
       }
+      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{
-      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( 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
index 3881dfa4358670c47f265235f33feaf794d51452..a5d8ebc08bc0b68a52949ebc05822d0d1a5e1275 100644 (file)
@@ -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
index 563df634781f934e28f3629e7b0a4a712a003b65..033ed38a7892b427f5991f7d8eced7010d346071 100644 (file)
--- 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:
 **
 #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()
 */
index 8c7985d46408b3d20a5d8ba753fe19cb5cb383ca..f31359620ff6bc02b6a3a88fb7687741311bf346 100644 (file)
@@ -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 <stdarg.h>
@@ -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.