| Index: third_party/sqlite/src/ext/fts3/fts3_tokenizer.c
|
| diff --git a/third_party/sqlite/src/ext/fts3/fts3_tokenizer.c b/third_party/sqlite/src/ext/fts3/fts3_tokenizer.c
|
| index e5de9c935f91c83dcb6b21b8d91e0d1f456d30de..1121b005d2180cd6173cbdeb75aadf4012cb7ef2 100644
|
| --- a/third_party/sqlite/src/ext/fts3/fts3_tokenizer.c
|
| +++ b/third_party/sqlite/src/ext/fts3/fts3_tokenizer.c
|
| @@ -30,10 +30,10 @@
|
| SQLITE_EXTENSION_INIT1
|
| #endif
|
|
|
| -#include "fts3_hash.h"
|
| -#include "fts3_tokenizer.h"
|
| +#include "fts3Int.h"
|
| #include <assert.h>
|
| #include <stddef.h>
|
| +#include <string.h>
|
|
|
| /*
|
| ** Implementation of the SQL scalar function for accessing the underlying
|
| @@ -60,14 +60,14 @@ static void scalarFunc(
|
| int argc,
|
| sqlite3_value **argv
|
| ){
|
| - fts3Hash *pHash;
|
| + Fts3Hash *pHash;
|
| void *pPtr = 0;
|
| const unsigned char *zName;
|
| int nName;
|
|
|
| assert( argc==1 || argc==2 );
|
|
|
| - pHash = (fts3Hash *)sqlite3_user_data(context);
|
| + pHash = (Fts3Hash *)sqlite3_user_data(context);
|
|
|
| zName = sqlite3_value_text(argv[0]);
|
| nName = sqlite3_value_bytes(argv[0])+1;
|
| @@ -98,6 +98,127 @@ static void scalarFunc(
|
| sqlite3_result_blob(context, (void *)&pPtr, sizeof(pPtr), SQLITE_TRANSIENT);
|
| }
|
|
|
| +static int fts3IsIdChar(char c){
|
| + static const char isFtsIdChar[] = {
|
| + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x */
|
| + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1x */
|
| + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2x */
|
| + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 3x */
|
| + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 4x */
|
| + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 5x */
|
| + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6x */
|
| + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 7x */
|
| + };
|
| + return (c&0x80 || isFtsIdChar[(int)(c)]);
|
| +}
|
| +
|
| +const char *sqlite3Fts3NextToken(const char *zStr, int *pn){
|
| + const char *z1;
|
| + const char *z2 = 0;
|
| +
|
| + /* Find the start of the next token. */
|
| + z1 = zStr;
|
| + while( z2==0 ){
|
| + char c = *z1;
|
| + switch( c ){
|
| + case '\0': return 0; /* No more tokens here */
|
| + case '\'':
|
| + case '"':
|
| + case '`': {
|
| + z2 = z1;
|
| + while( *++z2 && (*z2!=c || *++z2==c) );
|
| + break;
|
| + }
|
| + case '[':
|
| + z2 = &z1[1];
|
| + while( *z2 && z2[0]!=']' ) z2++;
|
| + if( *z2 ) z2++;
|
| + break;
|
| +
|
| + default:
|
| + if( fts3IsIdChar(*z1) ){
|
| + z2 = &z1[1];
|
| + while( fts3IsIdChar(*z2) ) z2++;
|
| + }else{
|
| + z1++;
|
| + }
|
| + }
|
| + }
|
| +
|
| + *pn = (int)(z2-z1);
|
| + return z1;
|
| +}
|
| +
|
| +int sqlite3Fts3InitTokenizer(
|
| + Fts3Hash *pHash, /* Tokenizer hash table */
|
| + const char *zArg, /* Possible tokenizer specification */
|
| + sqlite3_tokenizer **ppTok, /* OUT: Tokenizer (if applicable) */
|
| + const char **pzTokenizer, /* OUT: Set to zArg if is tokenizer */
|
| + char **pzErr /* OUT: Set to malloced error message */
|
| +){
|
| + int rc;
|
| + char *z = (char *)zArg;
|
| + int n;
|
| + char *zCopy;
|
| + char *zEnd; /* Pointer to nul-term of zCopy */
|
| + sqlite3_tokenizer_module *m;
|
| +
|
| + if( !z ){
|
| + zCopy = sqlite3_mprintf("simple");
|
| + }else{
|
| + if( sqlite3_strnicmp(z, "tokenize", 8) || fts3IsIdChar(z[8])){
|
| + return SQLITE_OK;
|
| + }
|
| + zCopy = sqlite3_mprintf("%s", &z[8]);
|
| + *pzTokenizer = zArg;
|
| + }
|
| + if( !zCopy ){
|
| + return SQLITE_NOMEM;
|
| + }
|
| +
|
| + zEnd = &zCopy[strlen(zCopy)];
|
| +
|
| + z = (char *)sqlite3Fts3NextToken(zCopy, &n);
|
| + z[n] = '\0';
|
| + sqlite3Fts3Dequote(z);
|
| +
|
| + m = (sqlite3_tokenizer_module *)sqlite3Fts3HashFind(pHash, z, (int)strlen(z)+1);
|
| + if( !m ){
|
| + *pzErr = sqlite3_mprintf("unknown tokenizer: %s", z);
|
| + rc = SQLITE_ERROR;
|
| + }else{
|
| + char const **aArg = 0;
|
| + int iArg = 0;
|
| + z = &z[n+1];
|
| + while( z<zEnd && (NULL!=(z = (char *)sqlite3Fts3NextToken(z, &n))) ){
|
| + int nNew = sizeof(char *)*(iArg+1);
|
| + char const **aNew = (const char **)sqlite3_realloc((void *)aArg, nNew);
|
| + if( !aNew ){
|
| + sqlite3_free(zCopy);
|
| + sqlite3_free((void *)aArg);
|
| + return SQLITE_NOMEM;
|
| + }
|
| + aArg = aNew;
|
| + aArg[iArg++] = z;
|
| + z[n] = '\0';
|
| + sqlite3Fts3Dequote(z);
|
| + z = &z[n+1];
|
| + }
|
| + rc = m->xCreate(iArg, aArg, ppTok);
|
| + assert( rc!=SQLITE_OK || *ppTok );
|
| + if( rc!=SQLITE_OK ){
|
| + *pzErr = sqlite3_mprintf("unknown tokenizer");
|
| + }else{
|
| + (*ppTok)->pModule = m;
|
| + }
|
| + sqlite3_free((void *)aArg);
|
| + }
|
| +
|
| + sqlite3_free(zCopy);
|
| + return rc;
|
| +}
|
| +
|
| +
|
| #ifdef SQLITE_TEST
|
|
|
| #include <tcl.h>
|
| @@ -134,7 +255,7 @@ static void testFunc(
|
| int argc,
|
| sqlite3_value **argv
|
| ){
|
| - fts3Hash *pHash;
|
| + Fts3Hash *pHash;
|
| sqlite3_tokenizer_module *p;
|
| sqlite3_tokenizer *pTokenizer = 0;
|
| sqlite3_tokenizer_cursor *pCsr = 0;
|
| @@ -167,7 +288,7 @@ static void testFunc(
|
| zArg = (const char *)sqlite3_value_text(argv[1]);
|
| }
|
|
|
| - pHash = (fts3Hash *)sqlite3_user_data(context);
|
| + pHash = (Fts3Hash *)sqlite3_user_data(context);
|
| p = (sqlite3_tokenizer_module *)sqlite3Fts3HashFind(pHash, zName, nName+1);
|
|
|
| if( !p ){
|
| @@ -258,7 +379,7 @@ int queryTokenizer(
|
| sqlite3_bind_text(pStmt, 1, zName, -1, SQLITE_STATIC);
|
| if( SQLITE_ROW==sqlite3_step(pStmt) ){
|
| if( sqlite3_column_type(pStmt, 0)==SQLITE_BLOB ){
|
| - memcpy(pp, sqlite3_column_blob(pStmt, 0), sizeof(*pp));
|
| + memcpy((void *)pp, sqlite3_column_blob(pStmt, 0), sizeof(*pp));
|
| }
|
| }
|
|
|
| @@ -295,6 +416,9 @@ static void intTestFunc(
|
| const sqlite3_tokenizer_module *p2;
|
| sqlite3 *db = (sqlite3 *)sqlite3_user_data(context);
|
|
|
| + UNUSED_PARAMETER(argc);
|
| + UNUSED_PARAMETER(argv);
|
| +
|
| /* Test the query function */
|
| sqlite3Fts3SimpleTokenizerModule(&p1);
|
| rc = queryTokenizer(db, "simple", &p2);
|
| @@ -336,16 +460,16 @@ static void intTestFunc(
|
| */
|
| int sqlite3Fts3InitHashTable(
|
| sqlite3 *db,
|
| - fts3Hash *pHash,
|
| + Fts3Hash *pHash,
|
| const char *zName
|
| ){
|
| int rc = SQLITE_OK;
|
| void *p = (void *)pHash;
|
| const int any = SQLITE_ANY;
|
| - char *zTest = 0;
|
| - char *zTest2 = 0;
|
|
|
| #ifdef SQLITE_TEST
|
| + char *zTest = 0;
|
| + char *zTest2 = 0;
|
| void *pdb = (void *)db;
|
| zTest = sqlite3_mprintf("%s_test", zName);
|
| zTest2 = sqlite3_mprintf("%s_internal_test", zName);
|
| @@ -354,18 +478,21 @@ int sqlite3Fts3InitHashTable(
|
| }
|
| #endif
|
|
|
| - if( rc!=SQLITE_OK
|
| - || (rc = sqlite3_create_function(db, zName, 1, any, p, scalarFunc, 0, 0))
|
| - || (rc = sqlite3_create_function(db, zName, 2, any, p, scalarFunc, 0, 0))
|
| + if( SQLITE_OK!=rc
|
| + || SQLITE_OK!=(rc = sqlite3_create_function(db, zName, 1, any, p, scalarFunc, 0, 0))
|
| + || SQLITE_OK!=(rc = sqlite3_create_function(db, zName, 2, any, p, scalarFunc, 0, 0))
|
| #ifdef SQLITE_TEST
|
| - || (rc = sqlite3_create_function(db, zTest, 2, any, p, testFunc, 0, 0))
|
| - || (rc = sqlite3_create_function(db, zTest, 3, any, p, testFunc, 0, 0))
|
| - || (rc = sqlite3_create_function(db, zTest2, 0, any, pdb, intTestFunc, 0, 0))
|
| + || SQLITE_OK!=(rc = sqlite3_create_function(db, zTest, 2, any, p, testFunc, 0, 0))
|
| + || SQLITE_OK!=(rc = sqlite3_create_function(db, zTest, 3, any, p, testFunc, 0, 0))
|
| + || SQLITE_OK!=(rc = sqlite3_create_function(db, zTest2, 0, any, pdb, intTestFunc, 0, 0))
|
| #endif
|
| - );
|
| + );
|
|
|
| +#ifdef SQLITE_TEST
|
| sqlite3_free(zTest);
|
| sqlite3_free(zTest2);
|
| +#endif
|
| +
|
| return rc;
|
| }
|
|
|
|
|