/* ** 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; }
/* ** 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); } }
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); } } } }
/* ** 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); }
/* * 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); } }