| Index: third_party/sqlite/src/ext/fts5/fts5_buffer.c
|
| diff --git a/third_party/sqlite/src/ext/fts5/fts5_buffer.c b/third_party/sqlite/src/ext/fts5/fts5_buffer.c
|
| index e9aab4622af2a6b7c427e3382dd4ed0dcd8b523b..0098846be961eaa6c778754701cee2a0d6d89320 100644
|
| --- a/third_party/sqlite/src/ext/fts5/fts5_buffer.c
|
| +++ b/third_party/sqlite/src/ext/fts5/fts5_buffer.c
|
| @@ -15,19 +15,21 @@
|
|
|
| #include "fts5Int.h"
|
|
|
| -int sqlite3Fts5BufferSize(int *pRc, Fts5Buffer *pBuf, int nByte){
|
| - int nNew = pBuf->nSpace ? pBuf->nSpace*2 : 64;
|
| - u8 *pNew;
|
| - while( nNew<nByte ){
|
| - nNew = nNew * 2;
|
| - }
|
| - pNew = sqlite3_realloc(pBuf->p, nNew);
|
| - if( pNew==0 ){
|
| - *pRc = SQLITE_NOMEM;
|
| - return 1;
|
| - }else{
|
| - pBuf->nSpace = nNew;
|
| - pBuf->p = pNew;
|
| +int sqlite3Fts5BufferSize(int *pRc, Fts5Buffer *pBuf, u32 nByte){
|
| + if( (u32)pBuf->nSpace<nByte ){
|
| + u32 nNew = pBuf->nSpace ? pBuf->nSpace : 64;
|
| + u8 *pNew;
|
| + while( nNew<nByte ){
|
| + nNew = nNew * 2;
|
| + }
|
| + pNew = sqlite3_realloc(pBuf->p, nNew);
|
| + if( pNew==0 ){
|
| + *pRc = SQLITE_NOMEM;
|
| + return 1;
|
| + }else{
|
| + pBuf->nSpace = nNew;
|
| + pBuf->p = pNew;
|
| + }
|
| }
|
| return 0;
|
| }
|
| @@ -61,10 +63,10 @@ int sqlite3Fts5Get32(const u8 *aBuf){
|
| void sqlite3Fts5BufferAppendBlob(
|
| int *pRc,
|
| Fts5Buffer *pBuf,
|
| - int nData,
|
| + u32 nData,
|
| const u8 *pData
|
| ){
|
| - assert( *pRc || nData>=0 );
|
| + assert_nc( *pRc || nData>=0 );
|
| if( fts5BufferGrow(pRc, pBuf, nData) ) return;
|
| memcpy(&pBuf->p[pBuf->n], pData, nData);
|
| pBuf->n += nData;
|
| @@ -208,23 +210,36 @@ int sqlite3Fts5PoslistReaderInit(
|
| return pIter->bEof;
|
| }
|
|
|
| -int sqlite3Fts5PoslistWriterAppend(
|
| +/*
|
| +** Append position iPos to the position list being accumulated in buffer
|
| +** pBuf, which must be already be large enough to hold the new data.
|
| +** The previous position written to this list is *piPrev. *piPrev is set
|
| +** to iPos before returning.
|
| +*/
|
| +void sqlite3Fts5PoslistSafeAppend(
|
| Fts5Buffer *pBuf,
|
| - Fts5PoslistWriter *pWriter,
|
| + i64 *piPrev,
|
| i64 iPos
|
| ){
|
| static const i64 colmask = ((i64)(0x7FFFFFFF)) << 32;
|
| - int rc = SQLITE_OK;
|
| - if( 0==fts5BufferGrow(&rc, pBuf, 5+5+5) ){
|
| - if( (iPos & colmask) != (pWriter->iPrev & colmask) ){
|
| - pBuf->p[pBuf->n++] = 1;
|
| - pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], (iPos>>32));
|
| - pWriter->iPrev = (iPos & colmask);
|
| - }
|
| - pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], (iPos-pWriter->iPrev)+2);
|
| - pWriter->iPrev = iPos;
|
| + if( (iPos & colmask) != (*piPrev & colmask) ){
|
| + pBuf->p[pBuf->n++] = 1;
|
| + pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], (iPos>>32));
|
| + *piPrev = (iPos & colmask);
|
| }
|
| - return rc;
|
| + pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], (iPos-*piPrev)+2);
|
| + *piPrev = iPos;
|
| +}
|
| +
|
| +int sqlite3Fts5PoslistWriterAppend(
|
| + Fts5Buffer *pBuf,
|
| + Fts5PoslistWriter *pWriter,
|
| + i64 iPos
|
| +){
|
| + int rc = 0; /* Initialized only to suppress erroneous warning from Clang */
|
| + if( fts5BufferGrow(&rc, pBuf, 5+5+5) ) return rc;
|
| + sqlite3Fts5PoslistSafeAppend(pBuf, &pWriter->iPrev, iPos);
|
| + return SQLITE_OK;
|
| }
|
|
|
| void *sqlite3Fts5MallocZero(int *pRc, int nByte){
|
| @@ -292,3 +307,86 @@ int sqlite3Fts5IsBareword(char t){
|
| }
|
|
|
|
|
| +/*************************************************************************
|
| +*/
|
| +typedef struct Fts5TermsetEntry Fts5TermsetEntry;
|
| +struct Fts5TermsetEntry {
|
| + char *pTerm;
|
| + int nTerm;
|
| + int iIdx; /* Index (main or aPrefix[] entry) */
|
| + Fts5TermsetEntry *pNext;
|
| +};
|
| +
|
| +struct Fts5Termset {
|
| + Fts5TermsetEntry *apHash[512];
|
| +};
|
| +
|
| +int sqlite3Fts5TermsetNew(Fts5Termset **pp){
|
| + int rc = SQLITE_OK;
|
| + *pp = sqlite3Fts5MallocZero(&rc, sizeof(Fts5Termset));
|
| + return rc;
|
| +}
|
| +
|
| +int sqlite3Fts5TermsetAdd(
|
| + Fts5Termset *p,
|
| + int iIdx,
|
| + const char *pTerm, int nTerm,
|
| + int *pbPresent
|
| +){
|
| + int rc = SQLITE_OK;
|
| + *pbPresent = 0;
|
| + if( p ){
|
| + int i;
|
| + u32 hash = 13;
|
| + Fts5TermsetEntry *pEntry;
|
| +
|
| + /* Calculate a hash value for this term. This is the same hash checksum
|
| + ** used by the fts5_hash.c module. This is not important for correct
|
| + ** operation of the module, but is necessary to ensure that some tests
|
| + ** designed to produce hash table collisions really do work. */
|
| + for(i=nTerm-1; i>=0; i--){
|
| + hash = (hash << 3) ^ hash ^ pTerm[i];
|
| + }
|
| + hash = (hash << 3) ^ hash ^ iIdx;
|
| + hash = hash % ArraySize(p->apHash);
|
| +
|
| + for(pEntry=p->apHash[hash]; pEntry; pEntry=pEntry->pNext){
|
| + if( pEntry->iIdx==iIdx
|
| + && pEntry->nTerm==nTerm
|
| + && memcmp(pEntry->pTerm, pTerm, nTerm)==0
|
| + ){
|
| + *pbPresent = 1;
|
| + break;
|
| + }
|
| + }
|
| +
|
| + if( pEntry==0 ){
|
| + pEntry = sqlite3Fts5MallocZero(&rc, sizeof(Fts5TermsetEntry) + nTerm);
|
| + if( pEntry ){
|
| + pEntry->pTerm = (char*)&pEntry[1];
|
| + pEntry->nTerm = nTerm;
|
| + pEntry->iIdx = iIdx;
|
| + memcpy(pEntry->pTerm, pTerm, nTerm);
|
| + pEntry->pNext = p->apHash[hash];
|
| + p->apHash[hash] = pEntry;
|
| + }
|
| + }
|
| + }
|
| +
|
| + return rc;
|
| +}
|
| +
|
| +void sqlite3Fts5TermsetFree(Fts5Termset *p){
|
| + if( p ){
|
| + u32 i;
|
| + for(i=0; i<ArraySize(p->apHash); i++){
|
| + Fts5TermsetEntry *pEntry = p->apHash[i];
|
| + while( pEntry ){
|
| + Fts5TermsetEntry *pDel = pEntry;
|
| + pEntry = pEntry->pNext;
|
| + sqlite3_free(pDel);
|
| + }
|
| + }
|
| + sqlite3_free(p);
|
| + }
|
| +}
|
|
|