Пример #1
0
/*
** 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
*/
static 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 */
  const int esc                    /* The escape character */
){
  int c, c2;
  int invert;
  int seen;
  u8 matchOne = pInfo->matchOne;
  u8 matchAll = pInfo->matchAll;
  u8 matchSet = pInfo->matchSet;
  u8 noCase = pInfo->noCase; 
  int prevEscape = 0;     /* True if the previous character was 'escape' */

  while( (c = sqlite3Utf8Read(zPattern,0,&zPattern))!=0 ){
    if( !prevEscape && c==matchAll ){
      while( (c=sqlite3Utf8Read(zPattern,0,&zPattern)) == matchAll
               || c == matchOne ){
        if( c==matchOne && sqlite3Utf8Read(zString, 0, &zString)==0 ){
          return 0;
        }
      }
      if( c==0 ){
        return 1;
      }else if( c==esc ){
        c = sqlite3Utf8Read(zPattern, 0, &zPattern);
        if( c==0 ){
          return 0;
        }
      }else if( c==matchSet ){
        assert( esc==0 );         /* This is GLOB, not LIKE */
        assert( matchSet<0x80 );  /* '[' is a single-byte character */
        while( *zString && patternCompare(&zPattern[-1],zString,pInfo,esc)==0 ){
          SQLITE_SKIP_UTF8(zString);
        }
        return *zString!=0;
      }
      while( (c2 = sqlite3Utf8Read(zString,0,&zString))!=0 ){
        if( noCase ){
          c2 = c2<0x80 ? sqlite3UpperToLower[c2] : c2;
          c = c<0x80 ? sqlite3UpperToLower[c] : c;
          while( c2 != 0 && c2 != c ){
            c2 = sqlite3Utf8Read(zString, 0, &zString);
            if( c2<0x80 ) c2 = sqlite3UpperToLower[c2];
          }
        }else{
          while( c2 != 0 && c2 != c ){
            c2 = sqlite3Utf8Read(zString, 0, &zString);
          }
        }
        if( c2==0 ) return 0;
        if( patternCompare(zPattern,zString,pInfo,esc) ) return 1;
      }
      return 0;
    }else if( !prevEscape && c==matchOne ){
      if( sqlite3Utf8Read(zString, 0, &zString)==0 ){
        return 0;
      }
    }else if( c==matchSet ){
      int prior_c = 0;
      assert( esc==0 );    /* This only occurs for GLOB, not LIKE */
      seen = 0;
      invert = 0;
      c = sqlite3Utf8Read(zString, 0, &zString);
      if( c==0 ) return 0;
      c2 = sqlite3Utf8Read(zPattern, 0, &zPattern);
      if( c2=='^' ){
        invert = 1;
        c2 = sqlite3Utf8Read(zPattern, 0, &zPattern);
      }
      if( c2==']' ){
        if( c==']' ) seen = 1;
        c2 = sqlite3Utf8Read(zPattern, 0, &zPattern);
      }
      while( c2 && c2!=']' ){
        if( c2=='-' && zPattern[0]!=']' && zPattern[0]!=0 && prior_c>0 ){
          c2 = sqlite3Utf8Read(zPattern, 0, &zPattern);
          if( c>=prior_c && c<=c2 ) seen = 1;
          prior_c = 0;
        }else{
          if( c==c2 ){
            seen = 1;
          }
          prior_c = c2;
        }
        c2 = sqlite3Utf8Read(zPattern, 0, &zPattern);
      }
      if( c2==0 || (seen ^ invert)==0 ){
        return 0;
      }
    }else if( esc==c && !prevEscape ){
      prevEscape = 1;
    }else{
      c2 = sqlite3Utf8Read(zString, 0, &zString);
      if( noCase ){
        c = c<0x80 ? sqlite3UpperToLower[c] : c;
        c2 = c2<0x80 ? sqlite3UpperToLower[c2] : c2;
      }
      if( c!=c2 ){
        return 0;
      }
      prevEscape = 0;
    }
  }
  return *zString==0;
}
Пример #2
0
/*
** Implementation of the substr() function.
**
** substr(x,p1,p2)  returns p2 characters of x[] beginning with p1.
** p1 is 1-indexed.  So substr(x,1,1) returns the first character
** of x.  If x is text, then we actually count UTF-8 characters.
** If x is a blob, then we count bytes.
**
** If p1 is negative, then we begin abs(p1) from the end of x[].
**
** If p2 is negative, return the p2 characters preceeding p1.
*/
static void substrFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  const unsigned char *z;
  const unsigned char *z2;
  int len;
  int p0type;
  i64 p1, p2;
  int negP2 = 0;

  assert( argc==3 || argc==2 );
  if( sqlite3_value_type(argv[1])==SQLITE_NULL
   || (argc==3 && sqlite3_value_type(argv[2])==SQLITE_NULL)
  ){
    return;
  }
  p0type = sqlite3_value_type(argv[0]);
  p1 = sqlite3_value_int(argv[1]);
  if( p0type==SQLITE_BLOB ){
    len = sqlite3_value_bytes(argv[0]);
    z = sqlite3_value_blob(argv[0]);
    if( z==0 ) return;
    assert( len==sqlite3_value_bytes(argv[0]) );
  }else{
    z = sqlite3_value_text(argv[0]);
    if( z==0 ) return;
    len = 0;
    if( p1<0 ){
      for(z2=z; *z2; len++){
        SQLITE_SKIP_UTF8(z2);
      }
    }
  }
  if( argc==3 ){
    p2 = sqlite3_value_int(argv[2]);
    if( p2<0 ){
      p2 = -p2;
      negP2 = 1;
    }
  }else{
    p2 = sqlite3_context_db_handle(context)->aLimit[SQLITE_LIMIT_LENGTH];
  }
  if( p1<0 ){
    p1 += len;
    if( p1<0 ){
      p2 += p1;
      if( p2<0 ) p2 = 0;
      p1 = 0;
    }
  }else if( p1>0 ){
    p1--;
  }else if( p2>0 ){
    p2--;
  }
  if( negP2 ){
    p1 -= p2;
    if( p1<0 ){
      p2 += p1;
      p1 = 0;
    }
  }
  assert( p1>=0 && p2>=0 );
  if( p0type!=SQLITE_BLOB ){
    while( *z && p1 ){
      SQLITE_SKIP_UTF8(z);
      p1--;
    }
    for(z2=z; *z2 && p2; p2--){
      SQLITE_SKIP_UTF8(z2);
    }
    sqlite3_result_text(context, (char*)z, (int)(z2-z), SQLITE_TRANSIENT);
  }else{
    if( p1+p2>len ){
      p2 = len-p1;
      if( p2<0 ) p2 = 0;
    }
    sqlite3_result_blob(context, (char*)&z[p1], (int)p2, SQLITE_TRANSIENT);
  }
}
Пример #3
0
extern void  my_substring_index(sqlite3_context * context, 
                                int               argc, 
                                sqlite3_value  ** argv) {
     
    int    found = 0;
    unsigned char  *needle;
    int    nlen;
    unsigned char  *haystack;
    int    count;
    unsigned char  *h;
    unsigned char  *p;
                
    _ksu_null_if_null_param(argc, argv);
    haystack = (unsigned char *)sqlite3_value_text(argv[0]);
    needle = (unsigned char *)sqlite3_value_text(argv[1]);
    nlen = strlen((char *)needle);
    count = my_value_int(argv[2], 0);
    if (count == 0) {
      sqlite3_result_text(context, "", -1, SQLITE_STATIC);
    } else {
      if (count > 0) {
        h = haystack;
        while ((found < count)
               && ((p = (unsigned char *)strstr((char *)h,
                                (char *)needle)) != (unsigned char *)NULL)) {
          found++;
          p += nlen;
          h = p;
        }
        // Return everything to the left of the delimiter
        if (p) {
          sqlite3_result_text(context, (char *)haystack,
                              p - haystack - nlen, NULL);
        } else {
          sqlite3_result_text(context, (char *)haystack, -1, NULL);
        }
      } else {
        if ((p = (unsigned char *)strrchr((char *)haystack,
                                   (char)*needle)) != (unsigned char *)NULL) {
          if (strncmp((char *)p, (char *)needle, nlen) == 0) {
            found--;
          }
          _ksu_utf8_decr(p);
          while ((p >= haystack)
                 && (found > count)) {
            if ((*p == *needle)
                && (strncmp((char *)p, (char *)needle, nlen) == 0)) {
              found--;
            }
            _ksu_utf8_decr(p);
          }
          if (p >= haystack) {
            // Re-increment p to point to "needle"
            SQLITE_SKIP_UTF8(p);
            // Return everything to the right
            p += nlen;
            sqlite3_result_text(context, (char *)p, -1, NULL);
          } else {
            if (found == count) {
               p = haystack + nlen;
            } else {
               p = haystack;
            }
            sqlite3_result_text(context, (char *)p, -1, NULL);
          }
        } else {
          sqlite3_result_text(context, (char *)haystack, -1, NULL);
        }
      }
    }
} 
Пример #4
0
/*
** Implementation of the TRIM(), LTRIM(), and RTRIM() functions.
** The userdata is 0x1 for left trim, 0x2 for right trim, 0x3 for both.
*/
static void trimFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  const unsigned char *zIn;         /* Input string */
  const unsigned char *zCharSet;    /* Set of characters to trim */
  int nIn;                          /* Number of bytes in input */
  int flags;                        /* 1: trimleft  2: trimright  3: trim */
  int i;                            /* Loop counter */
  unsigned char *aLen = 0;          /* Length of each character in zCharSet */
  unsigned char **azChar = 0;       /* Individual characters in zCharSet */
  int nChar;                        /* Number of characters in zCharSet */

  if( sqlite3_value_type(argv[0])==SQLITE_NULL ){
    return;
  }
  zIn = sqlite3_value_text(argv[0]);
  if( zIn==0 ) return;
  nIn = sqlite3_value_bytes(argv[0]);
  assert( zIn==sqlite3_value_text(argv[0]) );
  if( argc==1 ){
    static const unsigned char lenOne[] = { 1 };
    static unsigned char * const azOne[] = { (u8*)" " };
    nChar = 1;
    aLen = (u8*)lenOne;
    azChar = (unsigned char **)azOne;
    zCharSet = 0;
  }else if( (zCharSet = sqlite3_value_text(argv[1]))==0 ){
    return;
  }else{
    const unsigned char *z;
    for(z=zCharSet, nChar=0; *z; nChar++){
      SQLITE_SKIP_UTF8(z);
    }
    if( nChar>0 ){
      azChar = contextMalloc(context, ((i64)nChar)*(sizeof(char*)+1));
      if( azChar==0 ){
        return;
      }
      aLen = (unsigned char*)&azChar[nChar];
      for(z=zCharSet, nChar=0; *z; nChar++){
        azChar[nChar] = (unsigned char *)z;
        SQLITE_SKIP_UTF8(z);
        aLen[nChar] = (u8)(z - azChar[nChar]);
      }
    }
  }
  if( nChar>0 ){
    flags = SQLITE_PTR_TO_INT(sqlite3_user_data(context));
    if( flags & 1 ){
      while( nIn>0 ){
        int len = 0;
        for(i=0; i<nChar; i++){
          len = aLen[i];
          if( len<=nIn && memcmp(zIn, azChar[i], len)==0 ) break;
        }
        if( i>=nChar ) break;
        zIn += len;
        nIn -= len;
      }
    }
    if( flags & 2 ){
      while( nIn>0 ){
        int len = 0;
        for(i=0; i<nChar; i++){
          len = aLen[i];
          if( len<=nIn && memcmp(&zIn[nIn-len],azChar[i],len)==0 ) break;
        }
        if( i>=nChar ) break;
        nIn -= len;
      }
    }
    if( zCharSet ){
      sqlite3_free((void*)azChar);
    }
  }
  sqlite3_result_text(context, (char*)zIn, nIn, SQLITE_TRANSIENT);
}
Пример #5
0
/*
 *   INITCAP(string_to_be_formatted)
 *
 *   INITCAP makes the first letter of each word a capital letter, while
 *   making the rest of the words lowercase. Numbers and punctuation
 *   remain the same.
 *
 *   string_to_be_formatted represents the input string of characters
 *   that the user wishes to format. It is the only parameter.
 */
extern void ora_initcap(sqlite3_context  *context,
                        int argc,
                        sqlite3_value   **argv)
{
   int len1;  //The number of characters in the string that is being passed in.
   unsigned char   *str1;         // The string being passed in.
   unsigned char   *str2;         // Result 
   unsigned char   *strptr1 = NULL;// An additional pointer to str1.
   unsigned char   *strptr2 = NULL;// An additional pointer to str2.
   unsigned char    utf8[5];

   _ksu_null_if_null_param(argc, argv);
   // In this case, we know that we have valid input. We read in
   // the input, and calculate the length of the string. We also
   // assign an additional pointer to the string for the purpose
   // of formatting the string.
   str1 = (unsigned char *)sqlite3_value_text(argv[0]);
   strptr1 = str1;
   len1 = ksu_charlen(str1);
   if ((str2 = (unsigned char *)sqlite3_malloc(1 + sizeof(unsigned char)
                              * len1 * 4)) != (unsigned char *)NULL) {
      int first; // This simply represents whether or not we are modifying
                 // the first letter of a word. It is 1 if so, and 0 if not.

      // Now we need to go through the entire string to ensure proper
      // formatting. This will make iniial characters uppercase, the other
      // characters lowercase, and leave the other characters the same.
      strptr2 = str2;
      while (*strptr1 != '\0') {
         first = 1;
         while (*strptr1 && !ksu_is_letter(strptr1)) {
            _ksu_utf8_copychar(strptr1, strptr2);
         }
         while (*strptr1 && ksu_is_letter(strptr1)) {
            if (first == 1) {
               strcpy((char *)strptr2,
                      (char *)ksu_utf8_charupper(strptr1, utf8));
               while (*strptr2) {
                  SQLITE_SKIP_UTF8(strptr2);
               }
               SQLITE_SKIP_UTF8(strptr1);
               first = 0;
            } else   {
               strcpy((char *)strptr2,
                      (char *)ksu_utf8_charlower(strptr1, utf8));
               while (*strptr2) {
                  SQLITE_SKIP_UTF8(strptr2);
               }
               SQLITE_SKIP_UTF8(strptr1);
            }
         }
      }
      //The formatted string is then outputed to SQLite.
      sqlite3_result_text(context,
                       (char *)str2,
                       -1,           // Length - -1 means terminated by \0
                       sqlite3_free);  // Function for freeing memory
   } else {
      sqlite3_result_null(context);
   }
}