modernc.org/cc@v1.0.1/v2/testdata/_sqlite/ext/fts5/fts5_buffer.c (about)

     1  /*
     2  ** 2014 May 31
     3  **
     4  ** The author disclaims copyright to this source code.  In place of
     5  ** a legal notice, here is a blessing:
     6  **
     7  **    May you do good and not evil.
     8  **    May you find forgiveness for yourself and forgive others.
     9  **    May you share freely, never taking more than you give.
    10  **
    11  ******************************************************************************
    12  */
    13  
    14  
    15  
    16  #include "fts5Int.h"
    17  
    18  int sqlite3Fts5BufferSize(int *pRc, Fts5Buffer *pBuf, u32 nByte){
    19    if( (u32)pBuf->nSpace<nByte ){
    20      u32 nNew = pBuf->nSpace ? pBuf->nSpace : 64;
    21      u8 *pNew;
    22      while( nNew<nByte ){
    23        nNew = nNew * 2;
    24      }
    25      pNew = sqlite3_realloc(pBuf->p, nNew);
    26      if( pNew==0 ){
    27        *pRc = SQLITE_NOMEM;
    28        return 1;
    29      }else{
    30        pBuf->nSpace = nNew;
    31        pBuf->p = pNew;
    32      }
    33    }
    34    return 0;
    35  }
    36  
    37  
    38  /*
    39  ** Encode value iVal as an SQLite varint and append it to the buffer object
    40  ** pBuf. If an OOM error occurs, set the error code in p.
    41  */
    42  void sqlite3Fts5BufferAppendVarint(int *pRc, Fts5Buffer *pBuf, i64 iVal){
    43    if( fts5BufferGrow(pRc, pBuf, 9) ) return;
    44    pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], iVal);
    45  }
    46  
    47  void sqlite3Fts5Put32(u8 *aBuf, int iVal){
    48    aBuf[0] = (iVal>>24) & 0x00FF;
    49    aBuf[1] = (iVal>>16) & 0x00FF;
    50    aBuf[2] = (iVal>> 8) & 0x00FF;
    51    aBuf[3] = (iVal>> 0) & 0x00FF;
    52  }
    53  
    54  int sqlite3Fts5Get32(const u8 *aBuf){
    55    return (aBuf[0] << 24) + (aBuf[1] << 16) + (aBuf[2] << 8) + aBuf[3];
    56  }
    57  
    58  /*
    59  ** Append buffer nData/pData to buffer pBuf. If an OOM error occurs, set 
    60  ** the error code in p. If an error has already occurred when this function
    61  ** is called, it is a no-op.
    62  */
    63  void sqlite3Fts5BufferAppendBlob(
    64    int *pRc,
    65    Fts5Buffer *pBuf, 
    66    u32 nData, 
    67    const u8 *pData
    68  ){
    69    assert_nc( *pRc || nData>=0 );
    70    if( nData ){
    71      if( fts5BufferGrow(pRc, pBuf, nData) ) return;
    72      memcpy(&pBuf->p[pBuf->n], pData, nData);
    73      pBuf->n += nData;
    74    }
    75  }
    76  
    77  /*
    78  ** Append the nul-terminated string zStr to the buffer pBuf. This function
    79  ** ensures that the byte following the buffer data is set to 0x00, even 
    80  ** though this byte is not included in the pBuf->n count.
    81  */
    82  void sqlite3Fts5BufferAppendString(
    83    int *pRc,
    84    Fts5Buffer *pBuf, 
    85    const char *zStr
    86  ){
    87    int nStr = (int)strlen(zStr);
    88    sqlite3Fts5BufferAppendBlob(pRc, pBuf, nStr+1, (const u8*)zStr);
    89    pBuf->n--;
    90  }
    91  
    92  /*
    93  ** Argument zFmt is a printf() style format string. This function performs
    94  ** the printf() style processing, then appends the results to buffer pBuf.
    95  **
    96  ** Like sqlite3Fts5BufferAppendString(), this function ensures that the byte 
    97  ** following the buffer data is set to 0x00, even though this byte is not
    98  ** included in the pBuf->n count.
    99  */ 
   100  void sqlite3Fts5BufferAppendPrintf(
   101    int *pRc,
   102    Fts5Buffer *pBuf, 
   103    char *zFmt, ...
   104  ){
   105    if( *pRc==SQLITE_OK ){
   106      char *zTmp;
   107      va_list ap;
   108      va_start(ap, zFmt);
   109      zTmp = sqlite3_vmprintf(zFmt, ap);
   110      va_end(ap);
   111  
   112      if( zTmp==0 ){
   113        *pRc = SQLITE_NOMEM;
   114      }else{
   115        sqlite3Fts5BufferAppendString(pRc, pBuf, zTmp);
   116        sqlite3_free(zTmp);
   117      }
   118    }
   119  }
   120  
   121  char *sqlite3Fts5Mprintf(int *pRc, const char *zFmt, ...){
   122    char *zRet = 0;
   123    if( *pRc==SQLITE_OK ){
   124      va_list ap;
   125      va_start(ap, zFmt);
   126      zRet = sqlite3_vmprintf(zFmt, ap);
   127      va_end(ap);
   128      if( zRet==0 ){
   129        *pRc = SQLITE_NOMEM; 
   130      }
   131    }
   132    return zRet;
   133  }
   134   
   135  
   136  /*
   137  ** Free any buffer allocated by pBuf. Zero the structure before returning.
   138  */
   139  void sqlite3Fts5BufferFree(Fts5Buffer *pBuf){
   140    sqlite3_free(pBuf->p);
   141    memset(pBuf, 0, sizeof(Fts5Buffer));
   142  }
   143  
   144  /*
   145  ** Zero the contents of the buffer object. But do not free the associated 
   146  ** memory allocation.
   147  */
   148  void sqlite3Fts5BufferZero(Fts5Buffer *pBuf){
   149    pBuf->n = 0;
   150  }
   151  
   152  /*
   153  ** Set the buffer to contain nData/pData. If an OOM error occurs, leave an
   154  ** the error code in p. If an error has already occurred when this function
   155  ** is called, it is a no-op.
   156  */
   157  void sqlite3Fts5BufferSet(
   158    int *pRc,
   159    Fts5Buffer *pBuf, 
   160    int nData, 
   161    const u8 *pData
   162  ){
   163    pBuf->n = 0;
   164    sqlite3Fts5BufferAppendBlob(pRc, pBuf, nData, pData);
   165  }
   166  
   167  int sqlite3Fts5PoslistNext64(
   168    const u8 *a, int n,             /* Buffer containing poslist */
   169    int *pi,                        /* IN/OUT: Offset within a[] */
   170    i64 *piOff                      /* IN/OUT: Current offset */
   171  ){
   172    int i = *pi;
   173    if( i>=n ){
   174      /* EOF */
   175      *piOff = -1;
   176      return 1;  
   177    }else{
   178      i64 iOff = *piOff;
   179      int iVal;
   180      fts5FastGetVarint32(a, i, iVal);
   181      if( iVal==1 ){
   182        fts5FastGetVarint32(a, i, iVal);
   183        iOff = ((i64)iVal) << 32;
   184        fts5FastGetVarint32(a, i, iVal);
   185      }
   186      *piOff = iOff + (iVal-2);
   187      *pi = i;
   188      return 0;
   189    }
   190  }
   191  
   192  
   193  /*
   194  ** Advance the iterator object passed as the only argument. Return true
   195  ** if the iterator reaches EOF, or false otherwise.
   196  */
   197  int sqlite3Fts5PoslistReaderNext(Fts5PoslistReader *pIter){
   198    if( sqlite3Fts5PoslistNext64(pIter->a, pIter->n, &pIter->i, &pIter->iPos) ){
   199      pIter->bEof = 1;
   200    }
   201    return pIter->bEof;
   202  }
   203  
   204  int sqlite3Fts5PoslistReaderInit(
   205    const u8 *a, int n,             /* Poslist buffer to iterate through */
   206    Fts5PoslistReader *pIter        /* Iterator object to initialize */
   207  ){
   208    memset(pIter, 0, sizeof(*pIter));
   209    pIter->a = a;
   210    pIter->n = n;
   211    sqlite3Fts5PoslistReaderNext(pIter);
   212    return pIter->bEof;
   213  }
   214  
   215  /*
   216  ** Append position iPos to the position list being accumulated in buffer
   217  ** pBuf, which must be already be large enough to hold the new data.
   218  ** The previous position written to this list is *piPrev. *piPrev is set
   219  ** to iPos before returning.
   220  */
   221  void sqlite3Fts5PoslistSafeAppend(
   222    Fts5Buffer *pBuf, 
   223    i64 *piPrev, 
   224    i64 iPos
   225  ){
   226    static const i64 colmask = ((i64)(0x7FFFFFFF)) << 32;
   227    if( (iPos & colmask) != (*piPrev & colmask) ){
   228      pBuf->p[pBuf->n++] = 1;
   229      pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], (iPos>>32));
   230      *piPrev = (iPos & colmask);
   231    }
   232    pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], (iPos-*piPrev)+2);
   233    *piPrev = iPos;
   234  }
   235  
   236  int sqlite3Fts5PoslistWriterAppend(
   237    Fts5Buffer *pBuf, 
   238    Fts5PoslistWriter *pWriter,
   239    i64 iPos
   240  ){
   241    int rc = 0;   /* Initialized only to suppress erroneous warning from Clang */
   242    if( fts5BufferGrow(&rc, pBuf, 5+5+5) ) return rc;
   243    sqlite3Fts5PoslistSafeAppend(pBuf, &pWriter->iPrev, iPos);
   244    return SQLITE_OK;
   245  }
   246  
   247  void *sqlite3Fts5MallocZero(int *pRc, int nByte){
   248    void *pRet = 0;
   249    if( *pRc==SQLITE_OK ){
   250      pRet = sqlite3_malloc(nByte);
   251      if( pRet==0 ){
   252        if( nByte>0 ) *pRc = SQLITE_NOMEM;
   253      }else{
   254        memset(pRet, 0, nByte);
   255      }
   256    }
   257    return pRet;
   258  }
   259  
   260  /*
   261  ** Return a nul-terminated copy of the string indicated by pIn. If nIn
   262  ** is non-negative, then it is the length of the string in bytes. Otherwise,
   263  ** the length of the string is determined using strlen().
   264  **
   265  ** It is the responsibility of the caller to eventually free the returned
   266  ** buffer using sqlite3_free(). If an OOM error occurs, NULL is returned. 
   267  */
   268  char *sqlite3Fts5Strndup(int *pRc, const char *pIn, int nIn){
   269    char *zRet = 0;
   270    if( *pRc==SQLITE_OK ){
   271      if( nIn<0 ){
   272        nIn = (int)strlen(pIn);
   273      }
   274      zRet = (char*)sqlite3_malloc(nIn+1);
   275      if( zRet ){
   276        memcpy(zRet, pIn, nIn);
   277        zRet[nIn] = '\0';
   278      }else{
   279        *pRc = SQLITE_NOMEM;
   280      }
   281    }
   282    return zRet;
   283  }
   284  
   285  
   286  /*
   287  ** Return true if character 't' may be part of an FTS5 bareword, or false
   288  ** otherwise. Characters that may be part of barewords:
   289  **
   290  **   * All non-ASCII characters,
   291  **   * The 52 upper and lower case ASCII characters, and
   292  **   * The 10 integer ASCII characters.
   293  **   * The underscore character "_" (0x5F).
   294  **   * The unicode "subsitute" character (0x1A).
   295  */
   296  int sqlite3Fts5IsBareword(char t){
   297    u8 aBareword[128] = {
   298      0, 0, 0, 0, 0, 0, 0, 0,    0, 0, 0, 0, 0, 0, 0, 0,   /* 0x00 .. 0x0F */
   299      0, 0, 0, 0, 0, 0, 0, 0,    0, 0, 1, 0, 0, 0, 0, 0,   /* 0x10 .. 0x1F */
   300      0, 0, 0, 0, 0, 0, 0, 0,    0, 0, 0, 0, 0, 0, 0, 0,   /* 0x20 .. 0x2F */
   301      1, 1, 1, 1, 1, 1, 1, 1,    1, 1, 0, 0, 0, 0, 0, 0,   /* 0x30 .. 0x3F */
   302      0, 1, 1, 1, 1, 1, 1, 1,    1, 1, 1, 1, 1, 1, 1, 1,   /* 0x40 .. 0x4F */
   303      1, 1, 1, 1, 1, 1, 1, 1,    1, 1, 1, 0, 0, 0, 0, 1,   /* 0x50 .. 0x5F */
   304      0, 1, 1, 1, 1, 1, 1, 1,    1, 1, 1, 1, 1, 1, 1, 1,   /* 0x60 .. 0x6F */
   305      1, 1, 1, 1, 1, 1, 1, 1,    1, 1, 1, 0, 0, 0, 0, 0    /* 0x70 .. 0x7F */
   306    };
   307  
   308    return (t & 0x80) || aBareword[(int)t];
   309  }
   310  
   311  
   312  /*************************************************************************
   313  */
   314  typedef struct Fts5TermsetEntry Fts5TermsetEntry;
   315  struct Fts5TermsetEntry {
   316    char *pTerm;
   317    int nTerm;
   318    int iIdx;                       /* Index (main or aPrefix[] entry) */
   319    Fts5TermsetEntry *pNext;
   320  };
   321  
   322  struct Fts5Termset {
   323    Fts5TermsetEntry *apHash[512];
   324  };
   325  
   326  int sqlite3Fts5TermsetNew(Fts5Termset **pp){
   327    int rc = SQLITE_OK;
   328    *pp = sqlite3Fts5MallocZero(&rc, sizeof(Fts5Termset));
   329    return rc;
   330  }
   331  
   332  int sqlite3Fts5TermsetAdd(
   333    Fts5Termset *p, 
   334    int iIdx,
   335    const char *pTerm, int nTerm, 
   336    int *pbPresent
   337  ){
   338    int rc = SQLITE_OK;
   339    *pbPresent = 0;
   340    if( p ){
   341      int i;
   342      u32 hash = 13;
   343      Fts5TermsetEntry *pEntry;
   344  
   345      /* Calculate a hash value for this term. This is the same hash checksum
   346      ** used by the fts5_hash.c module. This is not important for correct
   347      ** operation of the module, but is necessary to ensure that some tests
   348      ** designed to produce hash table collisions really do work.  */
   349      for(i=nTerm-1; i>=0; i--){
   350        hash = (hash << 3) ^ hash ^ pTerm[i];
   351      }
   352      hash = (hash << 3) ^ hash ^ iIdx;
   353      hash = hash % ArraySize(p->apHash);
   354  
   355      for(pEntry=p->apHash[hash]; pEntry; pEntry=pEntry->pNext){
   356        if( pEntry->iIdx==iIdx 
   357            && pEntry->nTerm==nTerm 
   358            && memcmp(pEntry->pTerm, pTerm, nTerm)==0 
   359        ){
   360          *pbPresent = 1;
   361          break;
   362        }
   363      }
   364  
   365      if( pEntry==0 ){
   366        pEntry = sqlite3Fts5MallocZero(&rc, sizeof(Fts5TermsetEntry) + nTerm);
   367        if( pEntry ){
   368          pEntry->pTerm = (char*)&pEntry[1];
   369          pEntry->nTerm = nTerm;
   370          pEntry->iIdx = iIdx;
   371          memcpy(pEntry->pTerm, pTerm, nTerm);
   372          pEntry->pNext = p->apHash[hash];
   373          p->apHash[hash] = pEntry;
   374        }
   375      }
   376    }
   377  
   378    return rc;
   379  }
   380  
   381  void sqlite3Fts5TermsetFree(Fts5Termset *p){
   382    if( p ){
   383      u32 i;
   384      for(i=0; i<ArraySize(p->apHash); i++){
   385        Fts5TermsetEntry *pEntry = p->apHash[i];
   386        while( pEntry ){
   387          Fts5TermsetEntry *pDel = pEntry;
   388          pEntry = pEntry->pNext;
   389          sqlite3_free(pDel);
   390        }
   391      }
   392      sqlite3_free(p);
   393    }
   394  }