/ Hex Artifact Content
Login

Artifact 348f7d08cae05285794e23dc4fe8b8fdf66e264a:


0000: 2f 2a 0a 2a 2a 20 32 30 31 31 20 4a 75 6e 20 31  /*.** 2011 Jun 1
0010: 33 0a 2a 2a 0a 2a 2a 20 54 68 65 20 61 75 74 68  3.**.** The auth
0020: 6f 72 20 64 69 73 63 6c 61 69 6d 73 20 63 6f 70  or disclaims cop
0030: 79 72 69 67 68 74 20 74 6f 20 74 68 69 73 20 73  yright to this s
0040: 6f 75 72 63 65 20 63 6f 64 65 2e 20 20 49 6e 20  ource code.  In 
0050: 70 6c 61 63 65 20 6f 66 0a 2a 2a 20 61 20 6c 65  place of.** a le
0060: 67 61 6c 20 6e 6f 74 69 63 65 2c 20 68 65 72 65  gal notice, here
0070: 20 69 73 20 61 20 62 6c 65 73 73 69 6e 67 3a 0a   is a blessing:.
0080: 2a 2a 0a 2a 2a 20 20 20 20 4d 61 79 20 79 6f 75  **.**    May you
0090: 20 64 6f 20 67 6f 6f 64 20 61 6e 64 20 6e 6f 74   do good and not
00a0: 20 65 76 69 6c 2e 0a 2a 2a 20 20 20 20 4d 61 79   evil..**    May
00b0: 20 79 6f 75 20 66 69 6e 64 20 66 6f 72 67 69 76   you find forgiv
00c0: 65 6e 65 73 73 20 66 6f 72 20 79 6f 75 72 73 65  eness for yourse
00d0: 6c 66 20 61 6e 64 20 66 6f 72 67 69 76 65 20 6f  lf and forgive o
00e0: 74 68 65 72 73 2e 0a 2a 2a 20 20 20 20 4d 61 79  thers..**    May
00f0: 20 79 6f 75 20 73 68 61 72 65 20 66 72 65 65 6c   you share freel
0100: 79 2c 20 6e 65 76 65 72 20 74 61 6b 69 6e 67 20  y, never taking 
0110: 6d 6f 72 65 20 74 68 61 6e 20 79 6f 75 20 67 69  more than you gi
0120: 76 65 2e 0a 2a 2a 0a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ve..**.*********
0130: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0140: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0150: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0160: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0170: 2a 2a 2a 2a 2a 0a 2a 2a 0a 2a 2a 20 54 68 69 73  *****.**.** This
0180: 20 66 69 6c 65 20 69 73 20 6e 6f 74 20 70 61 72   file is not par
0190: 74 20 6f 66 20 74 68 65 20 70 72 6f 64 75 63 74  t of the product
01a0: 69 6f 6e 20 46 54 53 20 63 6f 64 65 2e 20 49 74  ion FTS code. It
01b0: 20 69 73 20 6f 6e 6c 79 20 75 73 65 64 20 66 6f   is only used fo
01c0: 72 0a 2a 2a 20 74 65 73 74 69 6e 67 2e 20 49 74  r.** testing. It
01d0: 20 63 6f 6e 74 61 69 6e 73 20 61 20 54 63 6c 20   contains a Tcl 
01e0: 63 6f 6d 6d 61 6e 64 20 74 68 61 74 20 63 61 6e  command that can
01f0: 20 62 65 20 75 73 65 64 20 74 6f 20 74 65 73 74   be used to test
0200: 20 69 66 20 61 20 64 6f 63 75 6d 65 6e 74 0a 2a   if a document.*
0210: 2a 20 6d 61 74 63 68 65 73 20 61 6e 20 46 54 53  * matches an FTS
0220: 20 4e 45 41 52 20 65 78 70 72 65 73 73 69 6f 6e   NEAR expression
0230: 2e 0a 2a 2a 0a 2a 2a 20 41 73 20 6f 66 20 4d 61  ..**.** As of Ma
0240: 72 63 68 20 32 30 31 32 2c 20 69 74 20 61 6c 73  rch 2012, it als
0250: 6f 20 63 6f 6e 74 61 69 6e 73 20 61 20 76 65 72  o contains a ver
0260: 73 69 6f 6e 20 31 20 74 6f 6b 65 6e 69 7a 65 72  sion 1 tokenizer
0270: 20 75 73 65 64 20 66 6f 72 20 74 65 73 74 69 6e   used for testin
0280: 67 0a 2a 2a 20 74 68 61 74 20 74 68 65 20 73 71  g.** that the sq
0290: 6c 69 74 65 33 5f 74 6f 6b 65 6e 69 7a 65 72 5f  lite3_tokenizer_
02a0: 6d 6f 64 75 6c 65 2e 78 4c 61 6e 67 75 61 67 65  module.xLanguage
02b0: 28 29 20 6d 65 74 68 6f 64 20 69 73 20 69 6e 76  () method is inv
02c0: 6f 6b 65 64 20 63 6f 72 72 65 63 74 6c 79 2e 0a  oked correctly..
02d0: 2a 2f 0a 0a 23 69 6e 63 6c 75 64 65 20 3c 74 63  */..#include <tc
02e0: 6c 2e 68 3e 0a 23 69 6e 63 6c 75 64 65 20 3c 73  l.h>.#include <s
02f0: 74 72 69 6e 67 2e 68 3e 0a 23 69 6e 63 6c 75 64  tring.h>.#includ
0300: 65 20 3c 61 73 73 65 72 74 2e 68 3e 0a 0a 23 69  e <assert.h>..#i
0310: 66 20 64 65 66 69 6e 65 64 28 53 51 4c 49 54 45  f defined(SQLITE
0320: 5f 54 45 53 54 29 0a 23 69 66 20 64 65 66 69 6e  _TEST).#if defin
0330: 65 64 28 53 51 4c 49 54 45 5f 45 4e 41 42 4c 45  ed(SQLITE_ENABLE
0340: 5f 46 54 53 33 29 20 7c 7c 20 64 65 66 69 6e 65  _FTS3) || define
0350: 64 28 53 51 4c 49 54 45 5f 45 4e 41 42 4c 45 5f  d(SQLITE_ENABLE_
0360: 46 54 53 34 29 0a 0a 2f 2a 20 52 65 71 75 69 72  FTS4)../* Requir
0370: 65 64 20 73 6f 20 74 68 61 74 20 74 68 65 20 22  ed so that the "
0380: 69 66 64 65 66 20 53 51 4c 49 54 45 5f 45 4e 41  ifdef SQLITE_ENA
0390: 42 4c 45 5f 46 54 53 33 22 20 62 65 6c 6f 77 20  BLE_FTS3" below 
03a0: 77 6f 72 6b 73 20 2a 2f 0a 23 69 6e 63 6c 75 64  works */.#includ
03b0: 65 20 22 66 74 73 33 49 6e 74 2e 68 22 0a 0a 23  e "fts3Int.h"..#
03c0: 64 65 66 69 6e 65 20 4e 4d 5f 4d 41 58 5f 54 4f  define NM_MAX_TO
03d0: 4b 45 4e 20 31 32 0a 0a 74 79 70 65 64 65 66 20  KEN 12..typedef 
03e0: 73 74 72 75 63 74 20 4e 65 61 72 50 68 72 61 73  struct NearPhras
03f0: 65 20 4e 65 61 72 50 68 72 61 73 65 3b 0a 74 79  e NearPhrase;.ty
0400: 70 65 64 65 66 20 73 74 72 75 63 74 20 4e 65 61  pedef struct Nea
0410: 72 44 6f 63 75 6d 65 6e 74 20 4e 65 61 72 44 6f  rDocument NearDo
0420: 63 75 6d 65 6e 74 3b 0a 74 79 70 65 64 65 66 20  cument;.typedef 
0430: 73 74 72 75 63 74 20 4e 65 61 72 54 6f 6b 65 6e  struct NearToken
0440: 20 4e 65 61 72 54 6f 6b 65 6e 3b 0a 0a 73 74 72   NearToken;..str
0450: 75 63 74 20 4e 65 61 72 44 6f 63 75 6d 65 6e 74  uct NearDocument
0460: 20 7b 0a 20 20 69 6e 74 20 6e 54 6f 6b 65 6e 3b   {.  int nToken;
0470: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0480: 20 20 20 20 20 2f 2a 20 4c 65 6e 67 74 68 20 6f       /* Length o
0490: 66 20 74 6f 6b 65 6e 20 69 6e 20 62 79 74 65 73  f token in bytes
04a0: 20 2a 2f 0a 20 20 4e 65 61 72 54 6f 6b 65 6e 20   */.  NearToken 
04b0: 2a 61 54 6f 6b 65 6e 3b 20 20 20 20 20 20 20 20  *aToken;        
04c0: 20 20 20 20 20 20 2f 2a 20 54 6f 6b 65 6e 20 61        /* Token a
04d0: 72 72 61 79 20 2a 2f 0a 7d 3b 0a 0a 73 74 72 75  rray */.};..stru
04e0: 63 74 20 4e 65 61 72 54 6f 6b 65 6e 20 7b 0a 20  ct NearToken {. 
04f0: 20 69 6e 74 20 6e 3b 20 20 20 20 20 20 20 20 20   int n;         
0500: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0510: 20 2f 2a 20 4c 65 6e 67 74 68 20 6f 66 20 74 6f   /* Length of to
0520: 6b 65 6e 20 69 6e 20 62 79 74 65 73 20 2a 2f 0a  ken in bytes */.
0530: 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 3b    const char *z;
0540: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0550: 20 20 2f 2a 20 50 6f 69 6e 74 65 72 20 74 6f 20    /* Pointer to 
0560: 74 6f 6b 65 6e 20 73 74 72 69 6e 67 20 2a 2f 0a  token string */.
0570: 7d 3b 0a 0a 73 74 72 75 63 74 20 4e 65 61 72 50  };..struct NearP
0580: 68 72 61 73 65 20 7b 0a 20 20 69 6e 74 20 6e 4e  hrase {.  int nN
0590: 65 61 72 3b 20 20 20 20 20 20 20 20 20 20 20 20  ear;            
05a0: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 50 72 65            /* Pre
05b0: 63 65 64 69 6e 67 20 4e 45 41 52 20 76 61 6c 75  ceding NEAR valu
05c0: 65 20 2a 2f 0a 20 20 69 6e 74 20 6e 54 6f 6b 65  e */.  int nToke
05d0: 6e 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20  n;              
05e0: 20 20 20 20 20 20 20 2f 2a 20 4e 75 6d 62 65 72         /* Number
05f0: 20 6f 66 20 74 6f 6b 65 6e 73 20 69 6e 20 74 68   of tokens in th
0600: 69 73 20 70 68 72 61 73 65 20 2a 2f 0a 20 20 4e  is phrase */.  N
0610: 65 61 72 54 6f 6b 65 6e 20 61 54 6f 6b 65 6e 5b  earToken aToken[
0620: 4e 4d 5f 4d 41 58 5f 54 4f 4b 45 4e 5d 3b 20 2f  NM_MAX_TOKEN]; /
0630: 2a 20 41 72 72 61 79 20 6f 66 20 74 6f 6b 65 6e  * Array of token
0640: 73 20 69 6e 20 74 68 69 73 20 70 68 72 61 73 65  s in this phrase
0650: 20 2a 2f 0a 7d 3b 0a 0a 73 74 61 74 69 63 20 69   */.};..static i
0660: 6e 74 20 6e 6d 5f 70 68 72 61 73 65 5f 6d 61 74  nt nm_phrase_mat
0670: 63 68 28 0a 20 20 4e 65 61 72 50 68 72 61 73 65  ch(.  NearPhrase
0680: 20 2a 70 2c 0a 20 20 4e 65 61 72 54 6f 6b 65 6e   *p,.  NearToken
0690: 20 2a 61 54 6f 6b 65 6e 0a 29 7b 0a 20 20 69 6e   *aToken.){.  in
06a0: 74 20 69 69 3b 0a 0a 20 20 66 6f 72 28 69 69 3d  t ii;..  for(ii=
06b0: 30 3b 20 69 69 3c 70 2d 3e 6e 54 6f 6b 65 6e 3b  0; ii<p->nToken;
06c0: 20 69 69 2b 2b 29 7b 0a 20 20 20 20 4e 65 61 72   ii++){.    Near
06d0: 54 6f 6b 65 6e 20 2a 70 54 6f 6b 65 6e 20 3d 20  Token *pToken = 
06e0: 26 70 2d 3e 61 54 6f 6b 65 6e 5b 69 69 5d 3b 0a  &p->aToken[ii];.
06f0: 20 20 20 20 69 66 28 20 70 54 6f 6b 65 6e 2d 3e      if( pToken->
0700: 6e 3e 30 20 26 26 20 70 54 6f 6b 65 6e 2d 3e 7a  n>0 && pToken->z
0710: 5b 70 54 6f 6b 65 6e 2d 3e 6e 2d 31 5d 3d 3d 27  [pToken->n-1]=='
0720: 2a 27 20 29 7b 0a 20 20 20 20 20 20 69 66 28 20  *' ){.      if( 
0730: 61 54 6f 6b 65 6e 5b 69 69 5d 2e 6e 3c 28 70 54  aToken[ii].n<(pT
0740: 6f 6b 65 6e 2d 3e 6e 2d 31 29 20 29 20 72 65 74  oken->n-1) ) ret
0750: 75 72 6e 20 30 3b 0a 20 20 20 20 20 20 69 66 28  urn 0;.      if(
0760: 20 6d 65 6d 63 6d 70 28 61 54 6f 6b 65 6e 5b 69   memcmp(aToken[i
0770: 69 5d 2e 7a 2c 20 70 54 6f 6b 65 6e 2d 3e 7a 2c  i].z, pToken->z,
0780: 20 70 54 6f 6b 65 6e 2d 3e 6e 2d 31 29 20 29 20   pToken->n-1) ) 
0790: 72 65 74 75 72 6e 20 30 3b 0a 20 20 20 20 7d 65  return 0;.    }e
07a0: 6c 73 65 7b 0a 20 20 20 20 20 20 69 66 28 20 61  lse{.      if( a
07b0: 54 6f 6b 65 6e 5b 69 69 5d 2e 6e 21 3d 70 54 6f  Token[ii].n!=pTo
07c0: 6b 65 6e 2d 3e 6e 20 29 20 72 65 74 75 72 6e 20  ken->n ) return 
07d0: 30 3b 0a 20 20 20 20 20 20 69 66 28 20 6d 65 6d  0;.      if( mem
07e0: 63 6d 70 28 61 54 6f 6b 65 6e 5b 69 69 5d 2e 7a  cmp(aToken[ii].z
07f0: 2c 20 70 54 6f 6b 65 6e 2d 3e 7a 2c 20 70 54 6f  , pToken->z, pTo
0800: 6b 65 6e 2d 3e 6e 29 20 29 20 72 65 74 75 72 6e  ken->n) ) return
0810: 20 30 3b 0a 20 20 20 20 7d 0a 20 20 7d 0a 0a 20   0;.    }.  }.. 
0820: 20 72 65 74 75 72 6e 20 31 3b 0a 7d 0a 0a 73 74   return 1;.}..st
0830: 61 74 69 63 20 69 6e 74 20 6e 6d 5f 6e 65 61 72  atic int nm_near
0840: 5f 63 68 61 69 6e 28 0a 20 20 69 6e 74 20 69 44  _chain(.  int iD
0850: 69 72 2c 20 20 20 20 20 20 20 20 20 20 20 20 20  ir,             
0860: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 44 69 72            /* Dir
0870: 65 63 74 69 6f 6e 20 74 6f 20 69 74 65 72 61 74  ection to iterat
0880: 65 20 74 68 72 6f 75 67 68 20 61 50 68 72 61 73  e through aPhras
0890: 65 5b 5d 20 2a 2f 0a 20 20 4e 65 61 72 44 6f 63  e[] */.  NearDoc
08a0: 75 6d 65 6e 74 20 2a 70 44 6f 63 2c 20 20 20 20  ument *pDoc,    
08b0: 20 20 20 20 20 20 20 20 20 2f 2a 20 44 6f 63 75           /* Docu
08c0: 6d 65 6e 74 20 74 6f 20 6d 61 74 63 68 20 61 67  ment to match ag
08d0: 61 69 6e 73 74 20 2a 2f 0a 20 20 69 6e 74 20 69  ainst */.  int i
08e0: 50 6f 73 2c 20 20 20 20 20 20 20 20 20 20 20 20  Pos,            
08f0: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 50 6f             /* Po
0900: 73 69 74 69 6f 6e 20 61 74 20 77 68 69 63 68 20  sition at which 
0910: 69 50 68 72 61 73 65 20 77 61 73 20 66 6f 75 6e  iPhrase was foun
0920: 64 20 2a 2f 0a 20 20 69 6e 74 20 6e 50 68 72 61  d */.  int nPhra
0930: 73 65 2c 20 20 20 20 20 20 20 20 20 20 20 20 20  se,             
0940: 20 20 20 20 20 20 20 2f 2a 20 53 69 7a 65 20 6f         /* Size o
0950: 66 20 70 68 72 61 73 65 20 61 72 72 61 79 20 2a  f phrase array *
0960: 2f 0a 20 20 4e 65 61 72 50 68 72 61 73 65 20 2a  /.  NearPhrase *
0970: 61 50 68 72 61 73 65 2c 20 20 20 20 20 20 20 20  aPhrase,        
0980: 20 20 20 20 2f 2a 20 50 68 72 61 73 65 20 61 72      /* Phrase ar
0990: 72 61 79 20 2a 2f 0a 20 20 69 6e 74 20 69 50 68  ray */.  int iPh
09a0: 72 61 73 65 20 20 20 20 20 20 20 20 20 20 20 20  rase            
09b0: 20 20 20 20 20 20 20 20 20 2f 2a 20 49 6e 64 65           /* Inde
09c0: 78 20 6f 66 20 70 68 72 61 73 65 20 66 6f 75 6e  x of phrase foun
09d0: 64 20 2a 2f 0a 29 7b 0a 20 20 69 6e 74 20 69 53  d */.){.  int iS
09e0: 74 61 72 74 3b 0a 20 20 69 6e 74 20 69 53 74 6f  tart;.  int iSto
09f0: 70 3b 0a 20 20 69 6e 74 20 69 69 3b 0a 20 20 69  p;.  int ii;.  i
0a00: 6e 74 20 6e 4e 65 61 72 3b 0a 20 20 69 6e 74 20  nt nNear;.  int 
0a10: 69 50 68 72 61 73 65 32 3b 0a 20 20 4e 65 61 72  iPhrase2;.  Near
0a20: 50 68 72 61 73 65 20 2a 70 3b 0a 20 20 4e 65 61  Phrase *p;.  Nea
0a30: 72 50 68 72 61 73 65 20 2a 70 50 72 65 76 3b 0a  rPhrase *pPrev;.
0a40: 0a 20 20 61 73 73 65 72 74 28 20 69 44 69 72 3d  .  assert( iDir=
0a50: 3d 31 20 7c 7c 20 69 44 69 72 3d 3d 2d 31 20 29  =1 || iDir==-1 )
0a60: 3b 0a 0a 20 20 69 66 28 20 69 44 69 72 3d 3d 31  ;..  if( iDir==1
0a70: 20 29 7b 0a 20 20 20 20 69 66 28 20 28 69 50 68   ){.    if( (iPh
0a80: 72 61 73 65 2b 31 29 3d 3d 6e 50 68 72 61 73 65  rase+1)==nPhrase
0a90: 20 29 20 72 65 74 75 72 6e 20 31 3b 0a 20 20 20   ) return 1;.   
0aa0: 20 6e 4e 65 61 72 20 3d 20 61 50 68 72 61 73 65   nNear = aPhrase
0ab0: 5b 69 50 68 72 61 73 65 2b 31 5d 2e 6e 4e 65 61  [iPhrase+1].nNea
0ac0: 72 3b 0a 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20  r;.  }else{.    
0ad0: 69 66 28 20 69 50 68 72 61 73 65 3d 3d 30 20 29  if( iPhrase==0 )
0ae0: 20 72 65 74 75 72 6e 20 31 3b 0a 20 20 20 20 6e   return 1;.    n
0af0: 4e 65 61 72 20 3d 20 61 50 68 72 61 73 65 5b 69  Near = aPhrase[i
0b00: 50 68 72 61 73 65 5d 2e 6e 4e 65 61 72 3b 0a 20  Phrase].nNear;. 
0b10: 20 7d 0a 20 20 70 50 72 65 76 20 3d 20 26 61 50   }.  pPrev = &aP
0b20: 68 72 61 73 65 5b 69 50 68 72 61 73 65 5d 3b 0a  hrase[iPhrase];.
0b30: 20 20 69 50 68 72 61 73 65 32 20 3d 20 69 50 68    iPhrase2 = iPh
0b40: 72 61 73 65 2b 69 44 69 72 3b 0a 20 20 70 20 3d  rase+iDir;.  p =
0b50: 20 26 61 50 68 72 61 73 65 5b 69 50 68 72 61 73   &aPhrase[iPhras
0b60: 65 32 5d 3b 0a 0a 20 20 69 53 74 61 72 74 20 3d  e2];..  iStart =
0b70: 20 69 50 6f 73 20 2d 20 6e 4e 65 61 72 20 2d 20   iPos - nNear - 
0b80: 70 2d 3e 6e 54 6f 6b 65 6e 3b 0a 20 20 69 53 74  p->nToken;.  iSt
0b90: 6f 70 20 3d 20 69 50 6f 73 20 2b 20 6e 4e 65 61  op = iPos + nNea
0ba0: 72 20 2b 20 70 50 72 65 76 2d 3e 6e 54 6f 6b 65  r + pPrev->nToke
0bb0: 6e 3b 0a 0a 20 20 69 66 28 20 69 53 74 61 72 74  n;..  if( iStart
0bc0: 3c 30 20 29 20 69 53 74 61 72 74 20 3d 20 30 3b  <0 ) iStart = 0;
0bd0: 0a 20 20 69 66 28 20 69 53 74 6f 70 20 3e 20 70  .  if( iStop > p
0be0: 44 6f 63 2d 3e 6e 54 6f 6b 65 6e 20 2d 20 70 2d  Doc->nToken - p-
0bf0: 3e 6e 54 6f 6b 65 6e 20 29 20 69 53 74 6f 70 20  >nToken ) iStop 
0c00: 3d 20 70 44 6f 63 2d 3e 6e 54 6f 6b 65 6e 20 2d  = pDoc->nToken -
0c10: 20 70 2d 3e 6e 54 6f 6b 65 6e 3b 0a 0a 20 20 66   p->nToken;..  f
0c20: 6f 72 28 69 69 3d 69 53 74 61 72 74 3b 20 69 69  or(ii=iStart; ii
0c30: 3c 3d 69 53 74 6f 70 3b 20 69 69 2b 2b 29 7b 0a  <=iStop; ii++){.
0c40: 20 20 20 20 69 66 28 20 6e 6d 5f 70 68 72 61 73      if( nm_phras
0c50: 65 5f 6d 61 74 63 68 28 70 2c 20 26 70 44 6f 63  e_match(p, &pDoc
0c60: 2d 3e 61 54 6f 6b 65 6e 5b 69 69 5d 29 20 29 7b  ->aToken[ii]) ){
0c70: 0a 20 20 20 20 20 20 69 66 28 20 6e 6d 5f 6e 65  .      if( nm_ne
0c80: 61 72 5f 63 68 61 69 6e 28 69 44 69 72 2c 20 70  ar_chain(iDir, p
0c90: 44 6f 63 2c 20 69 69 2c 20 6e 50 68 72 61 73 65  Doc, ii, nPhrase
0ca0: 2c 20 61 50 68 72 61 73 65 2c 20 69 50 68 72 61  , aPhrase, iPhra
0cb0: 73 65 32 29 20 29 20 72 65 74 75 72 6e 20 31 3b  se2) ) return 1;
0cc0: 0a 20 20 20 20 7d 0a 20 20 7d 0a 0a 20 20 72 65  .    }.  }..  re
0cd0: 74 75 72 6e 20 30 3b 0a 7d 0a 0a 73 74 61 74 69  turn 0;.}..stati
0ce0: 63 20 69 6e 74 20 6e 6d 5f 6d 61 74 63 68 5f 63  c int nm_match_c
0cf0: 6f 75 6e 74 28 0a 20 20 4e 65 61 72 44 6f 63 75  ount(.  NearDocu
0d00: 6d 65 6e 74 20 2a 70 44 6f 63 2c 20 20 20 20 20  ment *pDoc,     
0d10: 20 20 20 20 20 20 20 20 2f 2a 20 44 6f 63 75 6d          /* Docum
0d20: 65 6e 74 20 74 6f 20 6d 61 74 63 68 20 61 67 61  ent to match aga
0d30: 69 6e 73 74 20 2a 2f 0a 20 20 69 6e 74 20 6e 50  inst */.  int nP
0d40: 68 72 61 73 65 2c 20 20 20 20 20 20 20 20 20 20  hrase,          
0d50: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 53 69 7a            /* Siz
0d60: 65 20 6f 66 20 70 68 72 61 73 65 20 61 72 72 61  e of phrase arra
0d70: 79 20 2a 2f 0a 20 20 4e 65 61 72 50 68 72 61 73  y */.  NearPhras
0d80: 65 20 2a 61 50 68 72 61 73 65 2c 20 20 20 20 20  e *aPhrase,     
0d90: 20 20 20 20 20 20 20 2f 2a 20 50 68 72 61 73 65         /* Phrase
0da0: 20 61 72 72 61 79 20 2a 2f 0a 20 20 69 6e 74 20   array */.  int 
0db0: 69 50 68 72 61 73 65 20 20 20 20 20 20 20 20 20  iPhrase         
0dc0: 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 49              /* I
0dd0: 6e 64 65 78 20 6f 66 20 70 68 72 61 73 65 20 74  ndex of phrase t
0de0: 6f 20 63 6f 75 6e 74 20 6d 61 74 63 68 65 73 20  o count matches 
0df0: 66 6f 72 20 2a 2f 0a 29 7b 0a 20 20 69 6e 74 20  for */.){.  int 
0e00: 6e 4f 63 63 20 3d 20 30 3b 0a 20 20 69 6e 74 20  nOcc = 0;.  int 
0e10: 69 69 3b 0a 20 20 4e 65 61 72 50 68 72 61 73 65  ii;.  NearPhrase
0e20: 20 2a 70 20 3d 20 26 61 50 68 72 61 73 65 5b 69   *p = &aPhrase[i
0e30: 50 68 72 61 73 65 5d 3b 0a 0a 20 20 66 6f 72 28  Phrase];..  for(
0e40: 69 69 3d 30 3b 20 69 69 3c 28 70 44 6f 63 2d 3e  ii=0; ii<(pDoc->
0e50: 6e 54 6f 6b 65 6e 20 2b 20 31 20 2d 20 70 2d 3e  nToken + 1 - p->
0e60: 6e 54 6f 6b 65 6e 29 3b 20 69 69 2b 2b 29 7b 0a  nToken); ii++){.
0e70: 20 20 20 20 69 66 28 20 6e 6d 5f 70 68 72 61 73      if( nm_phras
0e80: 65 5f 6d 61 74 63 68 28 70 2c 20 26 70 44 6f 63  e_match(p, &pDoc
0e90: 2d 3e 61 54 6f 6b 65 6e 5b 69 69 5d 29 20 29 7b  ->aToken[ii]) ){
0ea0: 0a 20 20 20 20 20 20 2f 2a 20 54 65 73 74 20 66  .      /* Test f
0eb0: 6f 72 77 61 72 64 20 4e 45 41 52 20 63 68 61 69  orward NEAR chai
0ec0: 6e 20 28 69 3e 69 50 68 72 61 73 65 29 20 2a 2f  n (i>iPhrase) */
0ed0: 0a 20 20 20 20 20 20 69 66 28 20 30 3d 3d 6e 6d  .      if( 0==nm
0ee0: 5f 6e 65 61 72 5f 63 68 61 69 6e 28 31 2c 20 70  _near_chain(1, p
0ef0: 44 6f 63 2c 20 69 69 2c 20 6e 50 68 72 61 73 65  Doc, ii, nPhrase
0f00: 2c 20 61 50 68 72 61 73 65 2c 20 69 50 68 72 61  , aPhrase, iPhra
0f10: 73 65 29 20 29 20 63 6f 6e 74 69 6e 75 65 3b 0a  se) ) continue;.
0f20: 0a 20 20 20 20 20 20 2f 2a 20 54 65 73 74 20 72  .      /* Test r
0f30: 65 76 65 72 73 65 20 4e 45 41 52 20 63 68 61 69  everse NEAR chai
0f40: 6e 20 28 69 3c 69 50 68 72 61 73 65 29 20 2a 2f  n (i<iPhrase) */
0f50: 0a 20 20 20 20 20 20 69 66 28 20 30 3d 3d 6e 6d  .      if( 0==nm
0f60: 5f 6e 65 61 72 5f 63 68 61 69 6e 28 2d 31 2c 20  _near_chain(-1, 
0f70: 70 44 6f 63 2c 20 69 69 2c 20 6e 50 68 72 61 73  pDoc, ii, nPhras
0f80: 65 2c 20 61 50 68 72 61 73 65 2c 20 69 50 68 72  e, aPhrase, iPhr
0f90: 61 73 65 29 20 29 20 63 6f 6e 74 69 6e 75 65 3b  ase) ) continue;
0fa0: 0a 0a 20 20 20 20 20 20 2f 2a 20 54 68 69 73 20  ..      /* This 
0fb0: 69 73 20 61 20 72 65 61 6c 20 6d 61 74 63 68 2e  is a real match.
0fc0: 20 49 6e 63 72 65 6d 65 6e 74 20 74 68 65 20 63   Increment the c
0fd0: 6f 75 6e 74 65 72 2e 20 2a 2f 0a 20 20 20 20 20  ounter. */.     
0fe0: 20 6e 4f 63 63 2b 2b 3b 0a 20 20 20 20 7d 0a 20   nOcc++;.    }. 
0ff0: 20 7d 20 0a 0a 20 20 72 65 74 75 72 6e 20 6e 4f   } ..  return nO
1000: 63 63 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 54 63 6c  cc;.}../*.** Tcl
1010: 63 6d 64 3a 20 66 74 73 33 5f 6e 65 61 72 5f 6d  cmd: fts3_near_m
1020: 61 74 63 68 20 44 4f 43 55 4d 45 4e 54 20 45 58  atch DOCUMENT EX
1030: 50 52 20 3f 4f 50 54 49 4f 4e 53 3f 0a 2a 2f 0a  PR ?OPTIONS?.*/.
1040: 73 74 61 74 69 63 20 69 6e 74 20 66 74 73 33 5f  static int fts3_
1050: 6e 65 61 72 5f 6d 61 74 63 68 5f 63 6d 64 28 0a  near_match_cmd(.
1060: 20 20 43 6c 69 65 6e 74 44 61 74 61 20 63 6c 69    ClientData cli
1070: 65 6e 74 44 61 74 61 2c 0a 20 20 54 63 6c 5f 49  entData,.  Tcl_I
1080: 6e 74 65 72 70 20 2a 69 6e 74 65 72 70 2c 0a 20  nterp *interp,. 
1090: 20 69 6e 74 20 6f 62 6a 63 2c 0a 20 20 54 63 6c   int objc,.  Tcl
10a0: 5f 4f 62 6a 20 2a 43 4f 4e 53 54 20 6f 62 6a 76  _Obj *CONST objv
10b0: 5b 5d 0a 29 7b 0a 20 20 69 6e 74 20 6e 54 6f 74  [].){.  int nTot
10c0: 61 6c 20 3d 20 30 3b 0a 20 20 69 6e 74 20 72 63  al = 0;.  int rc
10d0: 3b 0a 20 20 69 6e 74 20 69 69 3b 0a 20 20 69 6e  ;.  int ii;.  in
10e0: 74 20 6e 50 68 72 61 73 65 3b 0a 20 20 4e 65 61  t nPhrase;.  Nea
10f0: 72 50 68 72 61 73 65 20 2a 61 50 68 72 61 73 65  rPhrase *aPhrase
1100: 20 3d 20 30 3b 0a 20 20 4e 65 61 72 44 6f 63 75   = 0;.  NearDocu
1110: 6d 65 6e 74 20 64 6f 63 20 3d 20 7b 30 2c 20 30  ment doc = {0, 0
1120: 7d 3b 0a 20 20 54 63 6c 5f 4f 62 6a 20 2a 2a 61  };.  Tcl_Obj **a
1130: 70 44 6f 63 54 6f 6b 65 6e 3b 0a 20 20 54 63 6c  pDocToken;.  Tcl
1140: 5f 4f 62 6a 20 2a 70 52 65 74 3b 0a 20 20 54 63  _Obj *pRet;.  Tc
1150: 6c 5f 4f 62 6a 20 2a 70 50 68 72 61 73 65 63 6f  l_Obj *pPhraseco
1160: 75 6e 74 20 3d 20 30 3b 0a 20 20 0a 20 20 54 63  unt = 0;.  .  Tc
1170: 6c 5f 4f 62 6a 20 2a 2a 61 70 45 78 70 72 54 6f  l_Obj **apExprTo
1180: 6b 65 6e 3b 0a 20 20 69 6e 74 20 6e 45 78 70 72  ken;.  int nExpr
1190: 54 6f 6b 65 6e 3b 0a 0a 20 20 55 4e 55 53 45 44  Token;..  UNUSED
11a0: 5f 50 41 52 41 4d 45 54 45 52 28 63 6c 69 65 6e  _PARAMETER(clien
11b0: 74 44 61 74 61 29 3b 0a 0a 20 20 2f 2a 20 4d 75  tData);..  /* Mu
11c0: 73 74 20 68 61 76 65 20 33 20 6f 72 20 6d 6f 72  st have 3 or mor
11d0: 65 20 61 72 67 75 6d 65 6e 74 73 2e 20 2a 2f 0a  e arguments. */.
11e0: 20 20 69 66 28 20 6f 62 6a 63 3c 33 20 7c 7c 20    if( objc<3 || 
11f0: 28 6f 62 6a 63 25 32 29 3d 3d 30 20 29 7b 0a 20  (objc%2)==0 ){. 
1200: 20 20 20 54 63 6c 5f 57 72 6f 6e 67 4e 75 6d 41     Tcl_WrongNumA
1210: 72 67 73 28 69 6e 74 65 72 70 2c 20 31 2c 20 6f  rgs(interp, 1, o
1220: 62 6a 76 2c 20 22 44 4f 43 55 4d 45 4e 54 20 45  bjv, "DOCUMENT E
1230: 58 50 52 20 3f 4f 50 54 49 4f 4e 20 56 41 4c 55  XPR ?OPTION VALU
1240: 45 3f 2e 2e 2e 22 29 3b 0a 20 20 20 20 72 63 20  E?...");.    rc 
1250: 3d 20 54 43 4c 5f 45 52 52 4f 52 3b 0a 20 20 20  = TCL_ERROR;.   
1260: 20 67 6f 74 6f 20 6e 65 61 72 5f 6d 61 74 63 68   goto near_match
1270: 5f 6f 75 74 3b 0a 20 20 7d 0a 0a 20 20 66 6f 72  _out;.  }..  for
1280: 28 69 69 3d 33 3b 20 69 69 3c 6f 62 6a 63 3b 20  (ii=3; ii<objc; 
1290: 69 69 2b 3d 32 29 7b 0a 20 20 20 20 65 6e 75 6d  ii+=2){.    enum
12a0: 20 4e 4d 5f 65 6e 75 6d 20 7b 20 4e 4d 5f 50 48   NM_enum { NM_PH
12b0: 52 41 53 45 43 4f 55 4e 54 53 20 7d 3b 0a 20 20  RASECOUNTS };.  
12c0: 20 20 73 74 72 75 63 74 20 54 65 73 74 6e 6d 53    struct TestnmS
12d0: 75 62 63 6d 64 20 7b 0a 20 20 20 20 20 20 63 68  ubcmd {.      ch
12e0: 61 72 20 2a 7a 4e 61 6d 65 3b 0a 20 20 20 20 20  ar *zName;.     
12f0: 20 65 6e 75 6d 20 4e 4d 5f 65 6e 75 6d 20 65 4f   enum NM_enum eO
1300: 70 74 3b 0a 20 20 20 20 7d 20 61 4f 70 74 5b 5d  pt;.    } aOpt[]
1310: 20 3d 20 7b 0a 20 20 20 20 20 20 7b 20 22 2d 70   = {.      { "-p
1320: 68 72 61 73 65 63 6f 75 6e 74 76 61 72 22 2c 20  hrasecountvar", 
1330: 4e 4d 5f 50 48 52 41 53 45 43 4f 55 4e 54 53 20  NM_PHRASECOUNTS 
1340: 7d 2c 0a 20 20 20 20 20 20 7b 20 30 2c 20 30 20  },.      { 0, 0 
1350: 7d 0a 20 20 20 20 7d 3b 0a 20 20 20 20 69 6e 74  }.    };.    int
1360: 20 69 4f 70 74 3b 0a 20 20 20 20 69 66 28 20 54   iOpt;.    if( T
1370: 63 6c 5f 47 65 74 49 6e 64 65 78 46 72 6f 6d 4f  cl_GetIndexFromO
1380: 62 6a 53 74 72 75 63 74 28 0a 20 20 20 20 20 20  bjStruct(.      
1390: 20 20 69 6e 74 65 72 70 2c 20 6f 62 6a 76 5b 69    interp, objv[i
13a0: 69 5d 2c 20 61 4f 70 74 2c 20 73 69 7a 65 6f 66  i], aOpt, sizeof
13b0: 28 61 4f 70 74 5b 30 5d 29 2c 20 22 6f 70 74 69  (aOpt[0]), "opti
13c0: 6f 6e 22 2c 20 30 2c 20 26 69 4f 70 74 29 20 0a  on", 0, &iOpt) .
13d0: 20 20 20 20 29 7b 0a 20 20 20 20 20 20 72 65 74      ){.      ret
13e0: 75 72 6e 20 54 43 4c 5f 45 52 52 4f 52 3b 0a 20  urn TCL_ERROR;. 
13f0: 20 20 20 7d 0a 0a 20 20 20 20 73 77 69 74 63 68     }..    switch
1400: 28 20 61 4f 70 74 5b 69 4f 70 74 5d 2e 65 4f 70  ( aOpt[iOpt].eOp
1410: 74 20 29 7b 0a 20 20 20 20 20 20 63 61 73 65 20  t ){.      case 
1420: 4e 4d 5f 50 48 52 41 53 45 43 4f 55 4e 54 53 3a  NM_PHRASECOUNTS:
1430: 0a 20 20 20 20 20 20 20 20 70 50 68 72 61 73 65  .        pPhrase
1440: 63 6f 75 6e 74 20 3d 20 6f 62 6a 76 5b 69 69 2b  count = objv[ii+
1450: 31 5d 3b 0a 20 20 20 20 20 20 20 20 62 72 65 61  1];.        brea
1460: 6b 3b 0a 20 20 20 20 7d 0a 20 20 7d 0a 0a 20 20  k;.    }.  }..  
1470: 72 63 20 3d 20 54 63 6c 5f 4c 69 73 74 4f 62 6a  rc = Tcl_ListObj
1480: 47 65 74 45 6c 65 6d 65 6e 74 73 28 69 6e 74 65  GetElements(inte
1490: 72 70 2c 20 6f 62 6a 76 5b 31 5d 2c 20 26 64 6f  rp, objv[1], &do
14a0: 63 2e 6e 54 6f 6b 65 6e 2c 20 26 61 70 44 6f 63  c.nToken, &apDoc
14b0: 54 6f 6b 65 6e 29 3b 0a 20 20 69 66 28 20 72 63  Token);.  if( rc
14c0: 21 3d 54 43 4c 5f 4f 4b 20 29 20 67 6f 74 6f 20  !=TCL_OK ) goto 
14d0: 6e 65 61 72 5f 6d 61 74 63 68 5f 6f 75 74 3b 0a  near_match_out;.
14e0: 20 20 64 6f 63 2e 61 54 6f 6b 65 6e 20 3d 20 28    doc.aToken = (
14f0: 4e 65 61 72 54 6f 6b 65 6e 20 2a 29 63 6b 61 6c  NearToken *)ckal
1500: 6c 6f 63 28 64 6f 63 2e 6e 54 6f 6b 65 6e 2a 73  loc(doc.nToken*s
1510: 69 7a 65 6f 66 28 4e 65 61 72 54 6f 6b 65 6e 29  izeof(NearToken)
1520: 29 3b 0a 20 20 66 6f 72 28 69 69 3d 30 3b 20 69  );.  for(ii=0; i
1530: 69 3c 64 6f 63 2e 6e 54 6f 6b 65 6e 3b 20 69 69  i<doc.nToken; ii
1540: 2b 2b 29 7b 0a 20 20 20 20 64 6f 63 2e 61 54 6f  ++){.    doc.aTo
1550: 6b 65 6e 5b 69 69 5d 2e 7a 20 3d 20 54 63 6c 5f  ken[ii].z = Tcl_
1560: 47 65 74 53 74 72 69 6e 67 46 72 6f 6d 4f 62 6a  GetStringFromObj
1570: 28 61 70 44 6f 63 54 6f 6b 65 6e 5b 69 69 5d 2c  (apDocToken[ii],
1580: 20 26 64 6f 63 2e 61 54 6f 6b 65 6e 5b 69 69 5d   &doc.aToken[ii]
1590: 2e 6e 29 3b 0a 20 20 7d 0a 0a 20 20 72 63 20 3d  .n);.  }..  rc =
15a0: 20 54 63 6c 5f 4c 69 73 74 4f 62 6a 47 65 74 45   Tcl_ListObjGetE
15b0: 6c 65 6d 65 6e 74 73 28 69 6e 74 65 72 70 2c 20  lements(interp, 
15c0: 6f 62 6a 76 5b 32 5d 2c 20 26 6e 45 78 70 72 54  objv[2], &nExprT
15d0: 6f 6b 65 6e 2c 20 26 61 70 45 78 70 72 54 6f 6b  oken, &apExprTok
15e0: 65 6e 29 3b 0a 20 20 69 66 28 20 72 63 21 3d 54  en);.  if( rc!=T
15f0: 43 4c 5f 4f 4b 20 29 20 67 6f 74 6f 20 6e 65 61  CL_OK ) goto nea
1600: 72 5f 6d 61 74 63 68 5f 6f 75 74 3b 0a 0a 20 20  r_match_out;..  
1610: 6e 50 68 72 61 73 65 20 3d 20 28 6e 45 78 70 72  nPhrase = (nExpr
1620: 54 6f 6b 65 6e 20 2b 20 31 29 20 2f 20 32 3b 0a  Token + 1) / 2;.
1630: 20 20 61 50 68 72 61 73 65 20 3d 20 28 4e 65 61    aPhrase = (Nea
1640: 72 50 68 72 61 73 65 20 2a 29 63 6b 61 6c 6c 6f  rPhrase *)ckallo
1650: 63 28 6e 50 68 72 61 73 65 20 2a 20 73 69 7a 65  c(nPhrase * size
1660: 6f 66 28 4e 65 61 72 50 68 72 61 73 65 29 29 3b  of(NearPhrase));
1670: 0a 20 20 6d 65 6d 73 65 74 28 61 50 68 72 61 73  .  memset(aPhras
1680: 65 2c 20 30 2c 20 6e 50 68 72 61 73 65 20 2a 20  e, 0, nPhrase * 
1690: 73 69 7a 65 6f 66 28 4e 65 61 72 50 68 72 61 73  sizeof(NearPhras
16a0: 65 29 29 3b 0a 20 20 66 6f 72 28 69 69 3d 30 3b  e));.  for(ii=0;
16b0: 20 69 69 3c 6e 50 68 72 61 73 65 3b 20 69 69 2b   ii<nPhrase; ii+
16c0: 2b 29 7b 0a 20 20 20 20 54 63 6c 5f 4f 62 6a 20  +){.    Tcl_Obj 
16d0: 2a 70 50 68 72 61 73 65 20 3d 20 61 70 45 78 70  *pPhrase = apExp
16e0: 72 54 6f 6b 65 6e 5b 69 69 2a 32 5d 3b 0a 20 20  rToken[ii*2];.  
16f0: 20 20 54 63 6c 5f 4f 62 6a 20 2a 2a 61 70 54 6f    Tcl_Obj **apTo
1700: 6b 65 6e 3b 0a 20 20 20 20 69 6e 74 20 6e 54 6f  ken;.    int nTo
1710: 6b 65 6e 3b 0a 20 20 20 20 69 6e 74 20 6a 6a 3b  ken;.    int jj;
1720: 0a 0a 20 20 20 20 72 63 20 3d 20 54 63 6c 5f 4c  ..    rc = Tcl_L
1730: 69 73 74 4f 62 6a 47 65 74 45 6c 65 6d 65 6e 74  istObjGetElement
1740: 73 28 69 6e 74 65 72 70 2c 20 70 50 68 72 61 73  s(interp, pPhras
1750: 65 2c 20 26 6e 54 6f 6b 65 6e 2c 20 26 61 70 54  e, &nToken, &apT
1760: 6f 6b 65 6e 29 3b 0a 20 20 20 20 69 66 28 20 72  oken);.    if( r
1770: 63 21 3d 54 43 4c 5f 4f 4b 20 29 20 67 6f 74 6f  c!=TCL_OK ) goto
1780: 20 6e 65 61 72 5f 6d 61 74 63 68 5f 6f 75 74 3b   near_match_out;
1790: 0a 20 20 20 20 69 66 28 20 6e 54 6f 6b 65 6e 3e  .    if( nToken>
17a0: 4e 4d 5f 4d 41 58 5f 54 4f 4b 45 4e 20 29 7b 0a  NM_MAX_TOKEN ){.
17b0: 20 20 20 20 20 20 54 63 6c 5f 41 70 70 65 6e 64        Tcl_Append
17c0: 52 65 73 75 6c 74 28 69 6e 74 65 72 70 2c 20 22  Result(interp, "
17d0: 54 6f 6f 20 6d 61 6e 79 20 74 6f 6b 65 6e 73 20  Too many tokens 
17e0: 69 6e 20 70 68 72 61 73 65 22 2c 20 30 29 3b 0a  in phrase", 0);.
17f0: 20 20 20 20 20 20 72 63 20 3d 20 54 43 4c 5f 45        rc = TCL_E
1800: 52 52 4f 52 3b 0a 20 20 20 20 20 20 67 6f 74 6f  RROR;.      goto
1810: 20 6e 65 61 72 5f 6d 61 74 63 68 5f 6f 75 74 3b   near_match_out;
1820: 0a 20 20 20 20 7d 0a 20 20 20 20 66 6f 72 28 6a  .    }.    for(j
1830: 6a 3d 30 3b 20 6a 6a 3c 6e 54 6f 6b 65 6e 3b 20  j=0; jj<nToken; 
1840: 6a 6a 2b 2b 29 7b 0a 20 20 20 20 20 20 4e 65 61  jj++){.      Nea
1850: 72 54 6f 6b 65 6e 20 2a 70 54 20 3d 20 26 61 50  rToken *pT = &aP
1860: 68 72 61 73 65 5b 69 69 5d 2e 61 54 6f 6b 65 6e  hrase[ii].aToken
1870: 5b 6a 6a 5d 3b 0a 20 20 20 20 20 20 70 54 2d 3e  [jj];.      pT->
1880: 7a 20 3d 20 54 63 6c 5f 47 65 74 53 74 72 69 6e  z = Tcl_GetStrin
1890: 67 46 72 6f 6d 4f 62 6a 28 61 70 54 6f 6b 65 6e  gFromObj(apToken
18a0: 5b 6a 6a 5d 2c 20 26 70 54 2d 3e 6e 29 3b 0a 20  [jj], &pT->n);. 
18b0: 20 20 20 7d 0a 20 20 20 20 61 50 68 72 61 73 65     }.    aPhrase
18c0: 5b 69 69 5d 2e 6e 54 6f 6b 65 6e 20 3d 20 6e 54  [ii].nToken = nT
18d0: 6f 6b 65 6e 3b 0a 20 20 7d 0a 20 20 66 6f 72 28  oken;.  }.  for(
18e0: 69 69 3d 31 3b 20 69 69 3c 6e 50 68 72 61 73 65  ii=1; ii<nPhrase
18f0: 3b 20 69 69 2b 2b 29 7b 0a 20 20 20 20 54 63 6c  ; ii++){.    Tcl
1900: 5f 4f 62 6a 20 2a 70 4e 65 61 72 20 3d 20 61 70  _Obj *pNear = ap
1910: 45 78 70 72 54 6f 6b 65 6e 5b 32 2a 69 69 2d 31  ExprToken[2*ii-1
1920: 5d 3b 0a 20 20 20 20 69 6e 74 20 6e 4e 65 61 72  ];.    int nNear
1930: 3b 0a 20 20 20 20 72 63 20 3d 20 54 63 6c 5f 47  ;.    rc = Tcl_G
1940: 65 74 49 6e 74 46 72 6f 6d 4f 62 6a 28 69 6e 74  etIntFromObj(int
1950: 65 72 70 2c 20 70 4e 65 61 72 2c 20 26 6e 4e 65  erp, pNear, &nNe
1960: 61 72 29 3b 0a 20 20 20 20 69 66 28 20 72 63 21  ar);.    if( rc!
1970: 3d 54 43 4c 5f 4f 4b 20 29 20 67 6f 74 6f 20 6e  =TCL_OK ) goto n
1980: 65 61 72 5f 6d 61 74 63 68 5f 6f 75 74 3b 0a 20  ear_match_out;. 
1990: 20 20 20 61 50 68 72 61 73 65 5b 69 69 5d 2e 6e     aPhrase[ii].n
19a0: 4e 65 61 72 20 3d 20 6e 4e 65 61 72 3b 0a 20 20  Near = nNear;.  
19b0: 7d 0a 0a 20 20 70 52 65 74 20 3d 20 54 63 6c 5f  }..  pRet = Tcl_
19c0: 4e 65 77 4f 62 6a 28 29 3b 0a 20 20 54 63 6c 5f  NewObj();.  Tcl_
19d0: 49 6e 63 72 52 65 66 43 6f 75 6e 74 28 70 52 65  IncrRefCount(pRe
19e0: 74 29 3b 0a 20 20 66 6f 72 28 69 69 3d 30 3b 20  t);.  for(ii=0; 
19f0: 69 69 3c 6e 50 68 72 61 73 65 3b 20 69 69 2b 2b  ii<nPhrase; ii++
1a00: 29 7b 0a 20 20 20 20 69 6e 74 20 6e 4f 63 63 20  ){.    int nOcc 
1a10: 3d 20 6e 6d 5f 6d 61 74 63 68 5f 63 6f 75 6e 74  = nm_match_count
1a20: 28 26 64 6f 63 2c 20 6e 50 68 72 61 73 65 2c 20  (&doc, nPhrase, 
1a30: 61 50 68 72 61 73 65 2c 20 69 69 29 3b 0a 20 20  aPhrase, ii);.  
1a40: 20 20 54 63 6c 5f 4c 69 73 74 4f 62 6a 41 70 70    Tcl_ListObjApp
1a50: 65 6e 64 45 6c 65 6d 65 6e 74 28 69 6e 74 65 72  endElement(inter
1a60: 70 2c 20 70 52 65 74 2c 20 54 63 6c 5f 4e 65 77  p, pRet, Tcl_New
1a70: 49 6e 74 4f 62 6a 28 6e 4f 63 63 29 29 3b 0a 20  IntObj(nOcc));. 
1a80: 20 20 20 6e 54 6f 74 61 6c 20 2b 3d 20 6e 4f 63     nTotal += nOc
1a90: 63 3b 0a 20 20 7d 0a 20 20 69 66 28 20 70 50 68  c;.  }.  if( pPh
1aa0: 72 61 73 65 63 6f 75 6e 74 20 29 7b 0a 20 20 20  rasecount ){.   
1ab0: 20 54 63 6c 5f 4f 62 6a 53 65 74 56 61 72 32 28   Tcl_ObjSetVar2(
1ac0: 69 6e 74 65 72 70 2c 20 70 50 68 72 61 73 65 63  interp, pPhrasec
1ad0: 6f 75 6e 74 2c 20 30 2c 20 70 52 65 74 2c 20 30  ount, 0, pRet, 0
1ae0: 29 3b 0a 20 20 7d 0a 20 20 54 63 6c 5f 44 65 63  );.  }.  Tcl_Dec
1af0: 72 52 65 66 43 6f 75 6e 74 28 70 52 65 74 29 3b  rRefCount(pRet);
1b00: 0a 20 20 54 63 6c 5f 53 65 74 4f 62 6a 52 65 73  .  Tcl_SetObjRes
1b10: 75 6c 74 28 69 6e 74 65 72 70 2c 20 54 63 6c 5f  ult(interp, Tcl_
1b20: 4e 65 77 42 6f 6f 6c 65 61 6e 4f 62 6a 28 6e 54  NewBooleanObj(nT
1b30: 6f 74 61 6c 3e 30 29 29 3b 0a 0a 20 6e 65 61 72  otal>0));.. near
1b40: 5f 6d 61 74 63 68 5f 6f 75 74 3a 20 0a 20 20 63  _match_out: .  c
1b50: 6b 66 72 65 65 28 28 63 68 61 72 20 2a 29 61 50  kfree((char *)aP
1b60: 68 72 61 73 65 29 3b 0a 20 20 63 6b 66 72 65 65  hrase);.  ckfree
1b70: 28 28 63 68 61 72 20 2a 29 64 6f 63 2e 61 54 6f  ((char *)doc.aTo
1b80: 6b 65 6e 29 3b 0a 20 20 72 65 74 75 72 6e 20 72  ken);.  return r
1b90: 63 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 20 20 54 63  c;.}../*.**   Tc
1ba0: 6c 63 6d 64 3a 20 66 74 73 33 5f 63 6f 6e 66 69  lcmd: fts3_confi
1bb0: 67 75 72 65 5f 69 6e 63 72 5f 6c 6f 61 64 20 3f  gure_incr_load ?
1bc0: 43 48 55 4e 4b 53 49 5a 45 20 54 48 52 45 53 48  CHUNKSIZE THRESH
1bd0: 4f 4c 44 3f 0a 2a 2a 0a 2a 2a 20 4e 6f 72 6d 61  OLD?.**.** Norma
1be0: 6c 6c 79 2c 20 46 54 53 20 75 73 65 73 20 68 61  lly, FTS uses ha
1bf0: 72 64 2d 63 6f 64 65 64 20 76 61 6c 75 65 73 20  rd-coded values 
1c00: 74 6f 20 64 65 74 65 72 6d 69 6e 65 20 74 68 65  to determine the
1c10: 20 6d 69 6e 69 6d 75 6d 20 64 6f 63 6c 69 73 74   minimum doclist
1c20: 0a 2a 2a 20 73 69 7a 65 20 65 6c 69 67 69 62 6c  .** size eligibl
1c30: 65 20 66 6f 72 20 69 6e 63 72 65 6d 65 6e 74 61  e for incrementa
1c40: 6c 20 6c 6f 61 64 69 6e 67 2c 20 61 6e 64 20 74  l loading, and t
1c50: 68 65 20 73 69 7a 65 20 6f 66 20 74 68 65 20 63  he size of the c
1c60: 68 75 6e 6b 73 20 6c 6f 61 64 65 64 0a 2a 2a 20  hunks loaded.** 
1c70: 77 68 65 6e 20 61 20 64 6f 63 6c 69 73 74 20 69  when a doclist i
1c80: 73 20 69 6e 63 72 65 6d 65 6e 74 61 6c 6c 79 20  s incrementally 
1c90: 6c 6f 61 64 65 64 2e 20 54 68 69 73 20 63 6f 6d  loaded. This com
1ca0: 6d 61 6e 64 20 61 6c 6c 6f 77 73 20 74 68 65 20  mand allows the 
1cb0: 62 75 69 6c 74 2d 69 6e 0a 2a 2a 20 76 61 6c 75  built-in.** valu
1cc0: 65 73 20 74 6f 20 62 65 20 6f 76 65 72 72 69 64  es to be overrid
1cd0: 64 65 6e 20 66 6f 72 20 74 65 73 74 69 6e 67 20  den for testing 
1ce0: 70 75 72 70 6f 73 65 73 2e 0a 2a 2a 0a 2a 2a 20  purposes..**.** 
1cf0: 49 66 20 70 72 65 73 65 6e 74 2c 20 74 68 65 20  If present, the 
1d00: 66 69 72 73 74 20 61 72 67 75 6d 65 6e 74 20 69  first argument i
1d10: 73 20 74 68 65 20 63 68 75 6e 6b 73 69 7a 65 20  s the chunksize 
1d20: 69 6e 20 62 79 74 65 73 20 74 6f 20 6c 6f 61 64  in bytes to load
1d30: 20 64 6f 63 6c 69 73 74 73 0a 2a 2a 20 69 6e 2e   doclists.** in.
1d40: 20 54 68 65 20 73 65 63 6f 6e 64 20 61 72 67 75   The second argu
1d50: 6d 65 6e 74 20 69 73 20 74 68 65 20 6d 69 6e 69  ment is the mini
1d60: 6d 75 6d 20 64 6f 63 6c 69 73 74 20 73 69 7a 65  mum doclist size
1d70: 20 69 6e 20 62 79 74 65 73 20 74 6f 20 75 73 65   in bytes to use
1d80: 0a 2a 2a 20 69 6e 63 72 65 6d 65 6e 74 61 6c 20  .** incremental 
1d90: 6c 6f 61 64 69 6e 67 20 77 69 74 68 2e 0a 2a 2a  loading with..**
1da0: 0a 2a 2a 20 57 68 65 74 68 65 72 20 6f 72 20 6e  .** Whether or n
1db0: 6f 74 20 74 68 65 20 61 72 67 75 6d 65 6e 74 73  ot the arguments
1dc0: 20 61 72 65 20 70 72 65 73 65 6e 74 2c 20 74 68   are present, th
1dd0: 69 73 20 63 6f 6d 6d 61 6e 64 20 72 65 74 75 72  is command retur
1de0: 6e 73 20 61 20 6c 69 73 74 20 6f 66 0a 2a 2a 20  ns a list of.** 
1df0: 74 77 6f 20 69 6e 74 65 67 65 72 73 20 2d 20 74  two integers - t
1e00: 68 65 20 69 6e 69 74 69 61 6c 20 63 68 75 6e 6b  he initial chunk
1e10: 73 69 7a 65 20 61 6e 64 20 74 68 72 65 73 68 6f  size and thresho
1e20: 6c 64 20 77 68 65 6e 20 74 68 65 20 63 6f 6d 6d  ld when the comm
1e30: 61 6e 64 20 69 73 0a 2a 2a 20 69 6e 76 6f 6b 65  and is.** invoke
1e40: 64 2e 20 54 68 69 73 20 63 61 6e 20 62 65 20 75  d. This can be u
1e50: 73 65 64 20 74 6f 20 72 65 73 74 6f 72 65 20 74  sed to restore t
1e60: 68 65 20 64 65 66 61 75 6c 74 20 62 65 68 61 76  he default behav
1e70: 69 6f 75 72 20 61 66 74 65 72 20 72 75 6e 6e 69  iour after runni
1e80: 6e 67 0a 2a 2a 20 74 65 73 74 73 2e 20 46 6f 72  ng.** tests. For
1e90: 20 65 78 61 6d 70 6c 65 3a 0a 2a 2a 0a 2a 2a 20   example:.**.** 
1ea0: 20 20 20 23 20 4f 76 65 72 72 69 64 65 20 69 6e     # Override in
1eb0: 63 72 2d 6c 6f 61 64 20 73 65 74 74 69 6e 67 73  cr-load settings
1ec0: 20 66 6f 72 20 74 65 73 74 69 6e 67 3a 0a 2a 2a   for testing:.**
1ed0: 20 20 20 20 73 65 74 20 63 66 67 20 5b 66 74 73      set cfg [fts
1ee0: 33 5f 63 6f 6e 66 69 67 75 72 65 5f 69 6e 63 72  3_configure_incr
1ef0: 5f 6c 6f 61 64 20 24 6e 65 77 5f 63 68 75 6e 6b  _load $new_chunk
1f00: 73 69 7a 65 20 24 6e 65 77 5f 74 68 72 65 73 68  size $new_thresh
1f10: 6f 6c 64 5d 0a 2a 2a 0a 2a 2a 20 20 20 20 2e 2e  old].**.**    ..
1f20: 2e 2e 20 72 75 6e 20 74 65 73 74 73 20 2e 2e 2e  .. run tests ...
1f30: 2e 0a 2a 2a 0a 2a 2a 20 20 20 20 23 20 52 65 73  ..**.**    # Res
1f40: 74 6f 72 65 20 69 6e 69 74 69 61 6c 20 69 6e 63  tore initial inc
1f50: 72 2d 6c 6f 61 64 20 73 65 74 74 69 6e 67 73 3a  r-load settings:
1f60: 0a 2a 2a 20 20 20 20 65 76 61 6c 20 66 74 73 33  .**    eval fts3
1f70: 5f 63 6f 6e 66 69 67 75 72 65 5f 69 6e 63 72 5f  _configure_incr_
1f80: 6c 6f 61 64 20 24 63 66 67 0a 2a 2f 0a 73 74 61  load $cfg.*/.sta
1f90: 74 69 63 20 69 6e 74 20 66 74 73 33 5f 63 6f 6e  tic int fts3_con
1fa0: 66 69 67 75 72 65 5f 69 6e 63 72 5f 6c 6f 61 64  figure_incr_load
1fb0: 5f 63 6d 64 28 0a 20 20 43 6c 69 65 6e 74 44 61  _cmd(.  ClientDa
1fc0: 74 61 20 63 6c 69 65 6e 74 44 61 74 61 2c 0a 20  ta clientData,. 
1fd0: 20 54 63 6c 5f 49 6e 74 65 72 70 20 2a 69 6e 74   Tcl_Interp *int
1fe0: 65 72 70 2c 0a 20 20 69 6e 74 20 6f 62 6a 63 2c  erp,.  int objc,
1ff0: 0a 20 20 54 63 6c 5f 4f 62 6a 20 2a 43 4f 4e 53  .  Tcl_Obj *CONS
2000: 54 20 6f 62 6a 76 5b 5d 0a 29 7b 0a 23 69 66 64  T objv[].){.#ifd
2010: 65 66 20 53 51 4c 49 54 45 5f 45 4e 41 42 4c 45  ef SQLITE_ENABLE
2020: 5f 46 54 53 33 0a 20 20 65 78 74 65 72 6e 20 69  _FTS3.  extern i
2030: 6e 74 20 74 65 73 74 5f 66 74 73 33 5f 6e 6f 64  nt test_fts3_nod
2040: 65 5f 63 68 75 6e 6b 73 69 7a 65 3b 0a 20 20 65  e_chunksize;.  e
2050: 78 74 65 72 6e 20 69 6e 74 20 74 65 73 74 5f 66  xtern int test_f
2060: 74 73 33 5f 6e 6f 64 65 5f 63 68 75 6e 6b 5f 74  ts3_node_chunk_t
2070: 68 72 65 73 68 6f 6c 64 3b 0a 20 20 54 63 6c 5f  hreshold;.  Tcl_
2080: 4f 62 6a 20 2a 70 52 65 74 3b 0a 0a 20 20 69 66  Obj *pRet;..  if
2090: 28 20 6f 62 6a 63 21 3d 31 20 26 26 20 6f 62 6a  ( objc!=1 && obj
20a0: 63 21 3d 33 20 29 7b 0a 20 20 20 20 54 63 6c 5f  c!=3 ){.    Tcl_
20b0: 57 72 6f 6e 67 4e 75 6d 41 72 67 73 28 69 6e 74  WrongNumArgs(int
20c0: 65 72 70 2c 20 31 2c 20 6f 62 6a 76 2c 20 22 3f  erp, 1, objv, "?
20d0: 43 48 55 4e 4b 53 49 5a 45 20 54 48 52 45 53 48  CHUNKSIZE THRESH
20e0: 4f 4c 44 3f 22 29 3b 0a 20 20 20 20 72 65 74 75  OLD?");.    retu
20f0: 72 6e 20 54 43 4c 5f 45 52 52 4f 52 3b 0a 20 20  rn TCL_ERROR;.  
2100: 7d 0a 0a 20 20 70 52 65 74 20 3d 20 54 63 6c 5f  }..  pRet = Tcl_
2110: 4e 65 77 4f 62 6a 28 29 3b 0a 20 20 54 63 6c 5f  NewObj();.  Tcl_
2120: 49 6e 63 72 52 65 66 43 6f 75 6e 74 28 70 52 65  IncrRefCount(pRe
2130: 74 29 3b 0a 20 20 54 63 6c 5f 4c 69 73 74 4f 62  t);.  Tcl_ListOb
2140: 6a 41 70 70 65 6e 64 45 6c 65 6d 65 6e 74 28 0a  jAppendElement(.
2150: 20 20 20 20 20 20 69 6e 74 65 72 70 2c 20 70 52        interp, pR
2160: 65 74 2c 20 54 63 6c 5f 4e 65 77 49 6e 74 4f 62  et, Tcl_NewIntOb
2170: 6a 28 74 65 73 74 5f 66 74 73 33 5f 6e 6f 64 65  j(test_fts3_node
2180: 5f 63 68 75 6e 6b 73 69 7a 65 29 29 3b 0a 20 20  _chunksize));.  
2190: 54 63 6c 5f 4c 69 73 74 4f 62 6a 41 70 70 65 6e  Tcl_ListObjAppen
21a0: 64 45 6c 65 6d 65 6e 74 28 0a 20 20 20 20 20 20  dElement(.      
21b0: 69 6e 74 65 72 70 2c 20 70 52 65 74 2c 20 54 63  interp, pRet, Tc
21c0: 6c 5f 4e 65 77 49 6e 74 4f 62 6a 28 74 65 73 74  l_NewIntObj(test
21d0: 5f 66 74 73 33 5f 6e 6f 64 65 5f 63 68 75 6e 6b  _fts3_node_chunk
21e0: 5f 74 68 72 65 73 68 6f 6c 64 29 29 3b 0a 0a 20  _threshold));.. 
21f0: 20 69 66 28 20 6f 62 6a 63 3d 3d 33 20 29 7b 0a   if( objc==3 ){.
2200: 20 20 20 20 69 6e 74 20 69 41 72 67 31 3b 0a 20      int iArg1;. 
2210: 20 20 20 69 6e 74 20 69 41 72 67 32 3b 0a 20 20     int iArg2;.  
2220: 20 20 69 66 28 20 54 63 6c 5f 47 65 74 49 6e 74    if( Tcl_GetInt
2230: 46 72 6f 6d 4f 62 6a 28 69 6e 74 65 72 70 2c 20  FromObj(interp, 
2240: 6f 62 6a 76 5b 31 5d 2c 20 26 69 41 72 67 31 29  objv[1], &iArg1)
2250: 0a 20 20 20 20 20 7c 7c 20 54 63 6c 5f 47 65 74  .     || Tcl_Get
2260: 49 6e 74 46 72 6f 6d 4f 62 6a 28 69 6e 74 65 72  IntFromObj(inter
2270: 70 2c 20 6f 62 6a 76 5b 32 5d 2c 20 26 69 41 72  p, objv[2], &iAr
2280: 67 32 29 0a 20 20 20 20 29 7b 0a 20 20 20 20 20  g2).    ){.     
2290: 20 54 63 6c 5f 44 65 63 72 52 65 66 43 6f 75 6e   Tcl_DecrRefCoun
22a0: 74 28 70 52 65 74 29 3b 0a 20 20 20 20 20 20 72  t(pRet);.      r
22b0: 65 74 75 72 6e 20 54 43 4c 5f 45 52 52 4f 52 3b  eturn TCL_ERROR;
22c0: 0a 20 20 20 20 7d 0a 20 20 20 20 74 65 73 74 5f  .    }.    test_
22d0: 66 74 73 33 5f 6e 6f 64 65 5f 63 68 75 6e 6b 73  fts3_node_chunks
22e0: 69 7a 65 20 3d 20 69 41 72 67 31 3b 0a 20 20 20  ize = iArg1;.   
22f0: 20 74 65 73 74 5f 66 74 73 33 5f 6e 6f 64 65 5f   test_fts3_node_
2300: 63 68 75 6e 6b 5f 74 68 72 65 73 68 6f 6c 64 20  chunk_threshold 
2310: 3d 20 69 41 72 67 32 3b 0a 20 20 7d 0a 0a 20 20  = iArg2;.  }..  
2320: 54 63 6c 5f 53 65 74 4f 62 6a 52 65 73 75 6c 74  Tcl_SetObjResult
2330: 28 69 6e 74 65 72 70 2c 20 70 52 65 74 29 3b 0a  (interp, pRet);.
2340: 20 20 54 63 6c 5f 44 65 63 72 52 65 66 43 6f 75    Tcl_DecrRefCou
2350: 6e 74 28 70 52 65 74 29 3b 0a 23 65 6e 64 69 66  nt(pRet);.#endif
2360: 0a 20 20 55 4e 55 53 45 44 5f 50 41 52 41 4d 45  .  UNUSED_PARAME
2370: 54 45 52 28 63 6c 69 65 6e 74 44 61 74 61 29 3b  TER(clientData);
2380: 0a 20 20 72 65 74 75 72 6e 20 54 43 4c 5f 4f 4b  .  return TCL_OK
2390: 3b 0a 7d 0a 0a 23 69 66 64 65 66 20 53 51 4c 49  ;.}..#ifdef SQLI
23a0: 54 45 5f 45 4e 41 42 4c 45 5f 46 54 53 33 0a 2f  TE_ENABLE_FTS3./
23b0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
23c0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
23d0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
23e0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
23f0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 0a 2a 2a 20 42 65  **********.** Be
2400: 67 69 6e 6e 69 6e 67 20 6f 66 20 74 65 73 74 20  ginning of test 
2410: 74 6f 6b 65 6e 69 7a 65 72 20 63 6f 64 65 2e 0a  tokenizer code..
2420: 2a 2a 0a 2a 2a 20 46 6f 72 20 6c 61 6e 67 75 61  **.** For langua
2430: 67 65 20 30 2c 20 74 68 69 73 20 74 6f 6b 65 6e  ge 0, this token
2440: 69 7a 65 72 20 69 73 20 73 69 6d 69 6c 61 72 20  izer is similar 
2450: 74 6f 20 74 68 65 20 64 65 66 61 75 6c 74 20 27  to the default '
2460: 73 69 6d 70 6c 65 27 20 0a 2a 2a 20 74 6f 6b 65  simple' .** toke
2470: 6e 69 7a 65 72 2e 20 46 6f 72 20 6f 74 68 65 72  nizer. For other
2480: 20 6c 61 6e 67 75 61 67 65 73 20 4c 2c 20 74 68   languages L, th
2490: 65 20 66 6f 6c 6c 6f 77 69 6e 67 3a 0a 2a 2a 0a  e following:.**.
24a0: 2a 2a 20 20 20 2a 20 4f 64 64 20 6e 75 6d 62 65  **   * Odd numbe
24b0: 72 65 64 20 6c 61 6e 67 75 61 67 65 73 20 61 72  red languages ar
24c0: 65 20 63 61 73 65 2d 73 65 6e 73 69 74 69 76 65  e case-sensitive
24d0: 2e 20 45 76 65 6e 20 6e 75 6d 62 65 72 65 64 20  . Even numbered 
24e0: 0a 2a 2a 20 20 20 20 20 6c 61 6e 67 75 61 67 65  .**     language
24f0: 73 20 61 72 65 20 6e 6f 74 2e 0a 2a 2a 0a 2a 2a  s are not..**.**
2500: 20 20 20 2a 20 4c 61 6e 67 75 61 67 65 20 69 64     * Language id
2510: 73 20 31 30 30 20 6f 72 20 67 72 65 61 74 65 72  s 100 or greater
2520: 20 61 72 65 20 63 6f 6e 73 69 64 65 72 65 64 20   are considered 
2530: 61 6e 20 65 72 72 6f 72 2e 0a 2a 2a 0a 2a 2a 20  an error..**.** 
2540: 54 68 65 20 69 6d 70 6c 65 6d 65 6e 74 61 74 69  The implementati
2550: 6f 6e 20 61 73 73 75 6d 65 73 20 74 68 61 74 20  on assumes that 
2560: 74 68 65 20 69 6e 70 75 74 20 63 6f 6e 74 61 69  the input contai
2570: 6e 73 20 6f 6e 6c 79 20 41 53 43 49 49 20 63 68  ns only ASCII ch
2580: 61 72 61 63 74 65 72 73 0a 2a 2a 20 28 69 2e 65  aracters.** (i.e
2590: 2e 20 74 68 6f 73 65 20 74 68 61 74 20 6d 61 79  . those that may
25a0: 20 62 65 20 65 6e 63 6f 64 65 64 20 69 6e 20 55   be encoded in U
25b0: 54 46 2d 38 20 75 73 69 6e 67 20 61 20 73 69 6e  TF-8 using a sin
25c0: 67 6c 65 20 62 79 74 65 29 2e 0a 2a 2f 0a 74 79  gle byte)..*/.ty
25d0: 70 65 64 65 66 20 73 74 72 75 63 74 20 74 65 73  pedef struct tes
25e0: 74 5f 74 6f 6b 65 6e 69 7a 65 72 20 7b 0a 20 20  t_tokenizer {.  
25f0: 73 71 6c 69 74 65 33 5f 74 6f 6b 65 6e 69 7a 65  sqlite3_tokenize
2600: 72 20 62 61 73 65 3b 0a 7d 20 74 65 73 74 5f 74  r base;.} test_t
2610: 6f 6b 65 6e 69 7a 65 72 3b 0a 0a 74 79 70 65 64  okenizer;..typed
2620: 65 66 20 73 74 72 75 63 74 20 74 65 73 74 5f 74  ef struct test_t
2630: 6f 6b 65 6e 69 7a 65 72 5f 63 75 72 73 6f 72 20  okenizer_cursor 
2640: 7b 0a 20 20 73 71 6c 69 74 65 33 5f 74 6f 6b 65  {.  sqlite3_toke
2650: 6e 69 7a 65 72 5f 63 75 72 73 6f 72 20 62 61 73  nizer_cursor bas
2660: 65 3b 0a 20 20 63 6f 6e 73 74 20 63 68 61 72 20  e;.  const char 
2670: 2a 61 49 6e 70 75 74 3b 20 20 20 20 20 20 20 20  *aInput;        
2680: 20 20 2f 2a 20 49 6e 70 75 74 20 62 65 69 6e 67    /* Input being
2690: 20 74 6f 6b 65 6e 69 7a 65 64 20 2a 2f 0a 20 20   tokenized */.  
26a0: 69 6e 74 20 6e 49 6e 70 75 74 3b 20 20 20 20 20  int nInput;     
26b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20               /* 
26c0: 53 69 7a 65 20 6f 66 20 74 68 65 20 69 6e 70 75  Size of the inpu
26d0: 74 20 69 6e 20 62 79 74 65 73 20 2a 2f 0a 20 20  t in bytes */.  
26e0: 69 6e 74 20 69 49 6e 70 75 74 3b 20 20 20 20 20  int iInput;     
26f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20               /* 
2700: 43 75 72 72 65 6e 74 20 6f 66 66 73 65 74 20 69  Current offset i
2710: 6e 20 61 49 6e 70 75 74 20 2a 2f 0a 20 20 69 6e  n aInput */.  in
2720: 74 20 69 54 6f 6b 65 6e 3b 20 20 20 20 20 20 20  t iToken;       
2730: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 49 6e             /* In
2740: 64 65 78 20 6f 66 20 6e 65 78 74 20 74 6f 6b 65  dex of next toke
2750: 6e 20 74 6f 20 62 65 20 72 65 74 75 72 6e 65 64  n to be returned
2760: 20 2a 2f 0a 20 20 63 68 61 72 20 2a 61 42 75 66   */.  char *aBuf
2770: 66 65 72 3b 20 20 20 20 20 20 20 20 20 20 20 20  fer;            
2780: 20 20 20 2f 2a 20 42 75 66 66 65 72 20 63 6f 6e     /* Buffer con
2790: 74 61 69 6e 69 6e 67 20 63 75 72 72 65 6e 74 20  taining current 
27a0: 74 6f 6b 65 6e 20 2a 2f 0a 20 20 69 6e 74 20 6e  token */.  int n
27b0: 42 75 66 66 65 72 3b 20 20 20 20 20 20 20 20 20  Buffer;         
27c0: 20 20 20 20 20 20 20 20 2f 2a 20 4e 75 6d 62 65          /* Numbe
27d0: 72 20 6f 66 20 62 79 74 65 73 20 61 6c 6c 6f 63  r of bytes alloc
27e0: 61 74 65 64 20 61 74 20 70 54 6f 6b 65 6e 20 2a  ated at pToken *
27f0: 2f 0a 20 20 69 6e 74 20 69 4c 61 6e 67 69 64 3b  /.  int iLangid;
2800: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2810: 20 2f 2a 20 43 6f 6e 66 69 67 75 72 65 64 20 6c   /* Configured l
2820: 61 6e 67 75 61 67 65 20 69 64 20 2a 2f 0a 7d 20  anguage id */.} 
2830: 74 65 73 74 5f 74 6f 6b 65 6e 69 7a 65 72 5f 63  test_tokenizer_c
2840: 75 72 73 6f 72 3b 0a 0a 73 74 61 74 69 63 20 69  ursor;..static i
2850: 6e 74 20 74 65 73 74 54 6f 6b 65 6e 69 7a 65 72  nt testTokenizer
2860: 43 72 65 61 74 65 28 0a 20 20 69 6e 74 20 61 72  Create(.  int ar
2870: 67 63 2c 20 63 6f 6e 73 74 20 63 68 61 72 20 2a  gc, const char *
2880: 20 63 6f 6e 73 74 20 2a 61 72 67 76 2c 0a 20 20   const *argv,.  
2890: 73 71 6c 69 74 65 33 5f 74 6f 6b 65 6e 69 7a 65  sqlite3_tokenize
28a0: 72 20 2a 2a 70 70 54 6f 6b 65 6e 69 7a 65 72 0a  r **ppTokenizer.
28b0: 29 7b 0a 20 20 74 65 73 74 5f 74 6f 6b 65 6e 69  ){.  test_tokeni
28c0: 7a 65 72 20 2a 70 4e 65 77 3b 0a 20 20 55 4e 55  zer *pNew;.  UNU
28d0: 53 45 44 5f 50 41 52 41 4d 45 54 45 52 28 61 72  SED_PARAMETER(ar
28e0: 67 63 29 3b 0a 20 20 55 4e 55 53 45 44 5f 50 41  gc);.  UNUSED_PA
28f0: 52 41 4d 45 54 45 52 28 61 72 67 76 29 3b 0a 0a  RAMETER(argv);..
2900: 20 20 70 4e 65 77 20 3d 20 73 71 6c 69 74 65 33    pNew = sqlite3
2910: 5f 6d 61 6c 6c 6f 63 28 73 69 7a 65 6f 66 28 74  _malloc(sizeof(t
2920: 65 73 74 5f 74 6f 6b 65 6e 69 7a 65 72 29 29 3b  est_tokenizer));
2930: 0a 20 20 69 66 28 20 21 70 4e 65 77 20 29 20 72  .  if( !pNew ) r
2940: 65 74 75 72 6e 20 53 51 4c 49 54 45 5f 4e 4f 4d  eturn SQLITE_NOM
2950: 45 4d 3b 0a 20 20 6d 65 6d 73 65 74 28 70 4e 65  EM;.  memset(pNe
2960: 77 2c 20 30 2c 20 73 69 7a 65 6f 66 28 74 65 73  w, 0, sizeof(tes
2970: 74 5f 74 6f 6b 65 6e 69 7a 65 72 29 29 3b 0a 0a  t_tokenizer));..
2980: 20 20 2a 70 70 54 6f 6b 65 6e 69 7a 65 72 20 3d    *ppTokenizer =
2990: 20 28 73 71 6c 69 74 65 33 5f 74 6f 6b 65 6e 69   (sqlite3_tokeni
29a0: 7a 65 72 20 2a 29 70 4e 65 77 3b 0a 20 20 72 65  zer *)pNew;.  re
29b0: 74 75 72 6e 20 53 51 4c 49 54 45 5f 4f 4b 3b 0a  turn SQLITE_OK;.
29c0: 7d 0a 0a 73 74 61 74 69 63 20 69 6e 74 20 74 65  }..static int te
29d0: 73 74 54 6f 6b 65 6e 69 7a 65 72 44 65 73 74 72  stTokenizerDestr
29e0: 6f 79 28 73 71 6c 69 74 65 33 5f 74 6f 6b 65 6e  oy(sqlite3_token
29f0: 69 7a 65 72 20 2a 70 54 6f 6b 65 6e 69 7a 65 72  izer *pTokenizer
2a00: 29 7b 0a 20 20 74 65 73 74 5f 74 6f 6b 65 6e 69  ){.  test_tokeni
2a10: 7a 65 72 20 2a 70 20 3d 20 28 74 65 73 74 5f 74  zer *p = (test_t
2a20: 6f 6b 65 6e 69 7a 65 72 20 2a 29 70 54 6f 6b 65  okenizer *)pToke
2a30: 6e 69 7a 65 72 3b 0a 20 20 73 71 6c 69 74 65 33  nizer;.  sqlite3
2a40: 5f 66 72 65 65 28 70 29 3b 0a 20 20 72 65 74 75  _free(p);.  retu
2a50: 72 6e 20 53 51 4c 49 54 45 5f 4f 4b 3b 0a 7d 0a  rn SQLITE_OK;.}.
2a60: 0a 73 74 61 74 69 63 20 69 6e 74 20 74 65 73 74  .static int test
2a70: 54 6f 6b 65 6e 69 7a 65 72 4f 70 65 6e 28 0a 20  TokenizerOpen(. 
2a80: 20 73 71 6c 69 74 65 33 5f 74 6f 6b 65 6e 69 7a   sqlite3_tokeniz
2a90: 65 72 20 2a 70 54 6f 6b 65 6e 69 7a 65 72 2c 20  er *pTokenizer, 
2aa0: 20 20 20 20 20 20 20 20 2f 2a 20 54 68 65 20 74          /* The t
2ab0: 6f 6b 65 6e 69 7a 65 72 20 2a 2f 0a 20 20 63 6f  okenizer */.  co
2ac0: 6e 73 74 20 63 68 61 72 20 2a 70 49 6e 70 75 74  nst char *pInput
2ad0: 2c 20 69 6e 74 20 6e 42 79 74 65 73 2c 20 20 20  , int nBytes,   
2ae0: 20 20 20 20 20 2f 2a 20 53 74 72 69 6e 67 20 74       /* String t
2af0: 6f 20 62 65 20 74 6f 6b 65 6e 69 7a 65 64 20 2a  o be tokenized *
2b00: 2f 0a 20 20 73 71 6c 69 74 65 33 5f 74 6f 6b 65  /.  sqlite3_toke
2b10: 6e 69 7a 65 72 5f 63 75 72 73 6f 72 20 2a 2a 70  nizer_cursor **p
2b20: 70 43 75 72 73 6f 72 20 20 20 20 2f 2a 20 4f 55  pCursor    /* OU
2b30: 54 3a 20 54 6f 6b 65 6e 69 7a 61 74 69 6f 6e 20  T: Tokenization 
2b40: 63 75 72 73 6f 72 20 2a 2f 0a 29 7b 0a 20 20 69  cursor */.){.  i
2b50: 6e 74 20 72 63 20 3d 20 53 51 4c 49 54 45 5f 4f  nt rc = SQLITE_O
2b60: 4b 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20  K;              
2b70: 20 20 20 20 20 20 2f 2a 20 52 65 74 75 72 6e 20        /* Return 
2b80: 63 6f 64 65 20 2a 2f 0a 20 20 74 65 73 74 5f 74  code */.  test_t
2b90: 6f 6b 65 6e 69 7a 65 72 5f 63 75 72 73 6f 72 20  okenizer_cursor 
2ba0: 2a 70 43 73 72 3b 20 20 20 20 20 20 20 20 20 20  *pCsr;          
2bb0: 20 2f 2a 20 4e 65 77 20 63 75 72 73 6f 72 20 6f   /* New cursor o
2bc0: 62 6a 65 63 74 20 2a 2f 0a 0a 20 20 55 4e 55 53  bject */..  UNUS
2bd0: 45 44 5f 50 41 52 41 4d 45 54 45 52 28 70 54 6f  ED_PARAMETER(pTo
2be0: 6b 65 6e 69 7a 65 72 29 3b 0a 0a 20 20 70 43 73  kenizer);..  pCs
2bf0: 72 20 3d 20 28 74 65 73 74 5f 74 6f 6b 65 6e 69  r = (test_tokeni
2c00: 7a 65 72 5f 63 75 72 73 6f 72 20 2a 29 73 71 6c  zer_cursor *)sql
2c10: 69 74 65 33 5f 6d 61 6c 6c 6f 63 28 73 69 7a 65  ite3_malloc(size
2c20: 6f 66 28 74 65 73 74 5f 74 6f 6b 65 6e 69 7a 65  of(test_tokenize
2c30: 72 5f 63 75 72 73 6f 72 29 29 3b 0a 20 20 69 66  r_cursor));.  if
2c40: 28 20 70 43 73 72 3d 3d 30 20 29 7b 0a 20 20 20  ( pCsr==0 ){.   
2c50: 20 72 63 20 3d 20 53 51 4c 49 54 45 5f 4e 4f 4d   rc = SQLITE_NOM
2c60: 45 4d 3b 0a 20 20 7d 65 6c 73 65 7b 0a 20 20 20  EM;.  }else{.   
2c70: 20 6d 65 6d 73 65 74 28 70 43 73 72 2c 20 30 2c   memset(pCsr, 0,
2c80: 20 73 69 7a 65 6f 66 28 74 65 73 74 5f 74 6f 6b   sizeof(test_tok
2c90: 65 6e 69 7a 65 72 5f 63 75 72 73 6f 72 29 29 3b  enizer_cursor));
2ca0: 0a 20 20 20 20 70 43 73 72 2d 3e 61 49 6e 70 75  .    pCsr->aInpu
2cb0: 74 20 3d 20 70 49 6e 70 75 74 3b 0a 20 20 20 20  t = pInput;.    
2cc0: 69 66 28 20 6e 42 79 74 65 73 3c 30 20 29 7b 0a  if( nBytes<0 ){.
2cd0: 20 20 20 20 20 20 70 43 73 72 2d 3e 6e 49 6e 70        pCsr->nInp
2ce0: 75 74 20 3d 20 28 69 6e 74 29 73 74 72 6c 65 6e  ut = (int)strlen
2cf0: 28 70 49 6e 70 75 74 29 3b 0a 20 20 20 20 7d 65  (pInput);.    }e
2d00: 6c 73 65 7b 0a 20 20 20 20 20 20 70 43 73 72 2d  lse{.      pCsr-
2d10: 3e 6e 49 6e 70 75 74 20 3d 20 6e 42 79 74 65 73  >nInput = nBytes
2d20: 3b 0a 20 20 20 20 7d 0a 20 20 7d 0a 0a 20 20 2a  ;.    }.  }..  *
2d30: 70 70 43 75 72 73 6f 72 20 3d 20 28 73 71 6c 69  ppCursor = (sqli
2d40: 74 65 33 5f 74 6f 6b 65 6e 69 7a 65 72 5f 63 75  te3_tokenizer_cu
2d50: 72 73 6f 72 20 2a 29 70 43 73 72 3b 0a 20 20 72  rsor *)pCsr;.  r
2d60: 65 74 75 72 6e 20 72 63 3b 0a 7d 0a 0a 73 74 61  eturn rc;.}..sta
2d70: 74 69 63 20 69 6e 74 20 74 65 73 74 54 6f 6b 65  tic int testToke
2d80: 6e 69 7a 65 72 43 6c 6f 73 65 28 73 71 6c 69 74  nizerClose(sqlit
2d90: 65 33 5f 74 6f 6b 65 6e 69 7a 65 72 5f 63 75 72  e3_tokenizer_cur
2da0: 73 6f 72 20 2a 70 43 75 72 73 6f 72 29 7b 0a 20  sor *pCursor){. 
2db0: 20 74 65 73 74 5f 74 6f 6b 65 6e 69 7a 65 72 5f   test_tokenizer_
2dc0: 63 75 72 73 6f 72 20 2a 70 43 73 72 20 3d 20 28  cursor *pCsr = (
2dd0: 74 65 73 74 5f 74 6f 6b 65 6e 69 7a 65 72 5f 63  test_tokenizer_c
2de0: 75 72 73 6f 72 20 2a 29 70 43 75 72 73 6f 72 3b  ursor *)pCursor;
2df0: 0a 20 20 73 71 6c 69 74 65 33 5f 66 72 65 65 28  .  sqlite3_free(
2e00: 70 43 73 72 2d 3e 61 42 75 66 66 65 72 29 3b 0a  pCsr->aBuffer);.
2e10: 20 20 73 71 6c 69 74 65 33 5f 66 72 65 65 28 70    sqlite3_free(p
2e20: 43 73 72 29 3b 0a 20 20 72 65 74 75 72 6e 20 53  Csr);.  return S
2e30: 51 4c 49 54 45 5f 4f 4b 3b 0a 7d 0a 0a 73 74 61  QLITE_OK;.}..sta
2e40: 74 69 63 20 69 6e 74 20 74 65 73 74 49 73 54 6f  tic int testIsTo
2e50: 6b 65 6e 43 68 61 72 28 63 68 61 72 20 63 29 7b  kenChar(char c){
2e60: 0a 20 20 72 65 74 75 72 6e 20 28 63 3e 3d 27 61  .  return (c>='a
2e70: 27 20 26 26 20 63 3c 3d 27 7a 27 29 20 7c 7c 20  ' && c<='z') || 
2e80: 28 63 3e 3d 27 41 27 20 26 26 20 63 3c 3d 27 5a  (c>='A' && c<='Z
2e90: 27 29 3b 0a 7d 0a 73 74 61 74 69 63 20 69 6e 74  ');.}.static int
2ea0: 20 74 65 73 74 54 6f 6c 6f 77 65 72 28 63 68 61   testTolower(cha
2eb0: 72 20 63 29 7b 0a 20 20 63 68 61 72 20 72 65 74  r c){.  char ret
2ec0: 20 3d 20 63 3b 0a 20 20 69 66 28 20 72 65 74 3e   = c;.  if( ret>
2ed0: 3d 27 41 27 20 26 26 20 72 65 74 3c 3d 27 5a 27  ='A' && ret<='Z'
2ee0: 29 20 72 65 74 20 3d 20 72 65 74 20 2d 20 28 27  ) ret = ret - ('
2ef0: 41 27 2d 27 61 27 29 3b 0a 20 20 72 65 74 75 72  A'-'a');.  retur
2f00: 6e 20 72 65 74 3b 0a 7d 0a 0a 73 74 61 74 69 63  n ret;.}..static
2f10: 20 69 6e 74 20 74 65 73 74 54 6f 6b 65 6e 69 7a   int testTokeniz
2f20: 65 72 4e 65 78 74 28 0a 20 20 73 71 6c 69 74 65  erNext(.  sqlite
2f30: 33 5f 74 6f 6b 65 6e 69 7a 65 72 5f 63 75 72 73  3_tokenizer_curs
2f40: 6f 72 20 2a 70 43 75 72 73 6f 72 2c 20 20 2f 2a  or *pCursor,  /*
2f50: 20 43 75 72 73 6f 72 20 72 65 74 75 72 6e 65 64   Cursor returned
2f60: 20 62 79 20 74 65 73 74 54 6f 6b 65 6e 69 7a 65   by testTokenize
2f70: 72 4f 70 65 6e 20 2a 2f 0a 20 20 63 6f 6e 73 74  rOpen */.  const
2f80: 20 63 68 61 72 20 2a 2a 70 70 54 6f 6b 65 6e 2c   char **ppToken,
2f90: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f                 /
2fa0: 2a 20 4f 55 54 3a 20 2a 70 70 54 6f 6b 65 6e 20  * OUT: *ppToken 
2fb0: 69 73 20 74 68 65 20 74 6f 6b 65 6e 20 74 65 78  is the token tex
2fc0: 74 20 2a 2f 0a 20 20 69 6e 74 20 2a 70 6e 42 79  t */.  int *pnBy
2fd0: 74 65 73 2c 20 20 20 20 20 20 20 20 20 20 20 20  tes,            
2fe0: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 4f 55             /* OU
2ff0: 54 3a 20 4e 75 6d 62 65 72 20 6f 66 20 62 79 74  T: Number of byt
3000: 65 73 20 69 6e 20 74 6f 6b 65 6e 20 2a 2f 0a 20  es in token */. 
3010: 20 69 6e 74 20 2a 70 69 53 74 61 72 74 4f 66 66   int *piStartOff
3020: 73 65 74 2c 20 20 20 20 20 20 20 20 20 20 20 20  set,            
3030: 20 20 20 20 20 2f 2a 20 4f 55 54 3a 20 53 74 61       /* OUT: Sta
3040: 72 74 69 6e 67 20 6f 66 66 73 65 74 20 6f 66 20  rting offset of 
3050: 74 6f 6b 65 6e 20 2a 2f 0a 20 20 69 6e 74 20 2a  token */.  int *
3060: 70 69 45 6e 64 4f 66 66 73 65 74 2c 20 20 20 20  piEndOffset,    
3070: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f                 /
3080: 2a 20 4f 55 54 3a 20 45 6e 64 69 6e 67 20 6f 66  * OUT: Ending of
3090: 66 73 65 74 20 6f 66 20 74 6f 6b 65 6e 20 2a 2f  fset of token */
30a0: 0a 20 20 69 6e 74 20 2a 70 69 50 6f 73 69 74 69  .  int *piPositi
30b0: 6f 6e 20 20 20 20 20 20 20 20 20 20 20 20 20 20  on              
30c0: 20 20 20 20 20 20 20 2f 2a 20 4f 55 54 3a 20 50         /* OUT: P
30d0: 6f 73 69 74 69 6f 6e 20 69 6e 74 65 67 65 72 20  osition integer 
30e0: 6f 66 20 74 6f 6b 65 6e 20 2a 2f 0a 29 7b 0a 20  of token */.){. 
30f0: 20 74 65 73 74 5f 74 6f 6b 65 6e 69 7a 65 72 5f   test_tokenizer_
3100: 63 75 72 73 6f 72 20 2a 70 43 73 72 20 3d 20 28  cursor *pCsr = (
3110: 74 65 73 74 5f 74 6f 6b 65 6e 69 7a 65 72 5f 63  test_tokenizer_c
3120: 75 72 73 6f 72 20 2a 29 70 43 75 72 73 6f 72 3b  ursor *)pCursor;
3130: 0a 20 20 69 6e 74 20 72 63 20 3d 20 53 51 4c 49  .  int rc = SQLI
3140: 54 45 5f 4f 4b 3b 0a 20 20 63 6f 6e 73 74 20 63  TE_OK;.  const c
3150: 68 61 72 20 2a 70 3b 0a 20 20 63 6f 6e 73 74 20  har *p;.  const 
3160: 63 68 61 72 20 2a 70 45 6e 64 3b 0a 0a 20 20 70  char *pEnd;..  p
3170: 20 3d 20 26 70 43 73 72 2d 3e 61 49 6e 70 75 74   = &pCsr->aInput
3180: 5b 70 43 73 72 2d 3e 69 49 6e 70 75 74 5d 3b 0a  [pCsr->iInput];.
3190: 20 20 70 45 6e 64 20 3d 20 26 70 43 73 72 2d 3e    pEnd = &pCsr->
31a0: 61 49 6e 70 75 74 5b 70 43 73 72 2d 3e 6e 49 6e  aInput[pCsr->nIn
31b0: 70 75 74 5d 3b 0a 0a 20 20 2f 2a 20 53 6b 69 70  put];..  /* Skip
31c0: 20 70 61 73 74 20 61 6e 79 20 77 68 69 74 65 2d   past any white-
31d0: 73 70 61 63 65 20 2a 2f 0a 20 20 61 73 73 65 72  space */.  asser
31e0: 74 28 20 70 3c 3d 70 45 6e 64 20 29 3b 0a 20 20  t( p<=pEnd );.  
31f0: 77 68 69 6c 65 28 20 70 3c 70 45 6e 64 20 26 26  while( p<pEnd &&
3200: 20 74 65 73 74 49 73 54 6f 6b 65 6e 43 68 61 72   testIsTokenChar
3210: 28 2a 70 29 3d 3d 30 20 29 20 70 2b 2b 3b 0a 0a  (*p)==0 ) p++;..
3220: 20 20 69 66 28 20 70 3d 3d 70 45 6e 64 20 29 7b    if( p==pEnd ){
3230: 0a 20 20 20 20 72 63 20 3d 20 53 51 4c 49 54 45  .    rc = SQLITE
3240: 5f 44 4f 4e 45 3b 0a 20 20 7d 65 6c 73 65 7b 0a  _DONE;.  }else{.
3250: 20 20 20 20 2f 2a 20 41 64 76 61 6e 63 65 20 74      /* Advance t
3260: 6f 20 74 68 65 20 65 6e 64 20 6f 66 20 74 68 65  o the end of the
3270: 20 74 6f 6b 65 6e 20 2a 2f 0a 20 20 20 20 63 6f   token */.    co
3280: 6e 73 74 20 63 68 61 72 20 2a 70 54 6f 6b 65 6e  nst char *pToken
3290: 20 3d 20 70 3b 0a 20 20 20 20 69 6e 74 20 6e 54   = p;.    int nT
32a0: 6f 6b 65 6e 3b 0a 20 20 20 20 77 68 69 6c 65 28  oken;.    while(
32b0: 20 70 3c 70 45 6e 64 20 26 26 20 74 65 73 74 49   p<pEnd && testI
32c0: 73 54 6f 6b 65 6e 43 68 61 72 28 2a 70 29 20 29  sTokenChar(*p) )
32d0: 20 70 2b 2b 3b 0a 20 20 20 20 6e 54 6f 6b 65 6e   p++;.    nToken
32e0: 20 3d 20 28 69 6e 74 29 28 70 2d 70 54 6f 6b 65   = (int)(p-pToke
32f0: 6e 29 3b 0a 0a 20 20 20 20 2f 2a 20 43 6f 70 79  n);..    /* Copy
3300: 20 74 68 65 20 74 6f 6b 65 6e 20 69 6e 74 6f 20   the token into 
3310: 74 68 65 20 62 75 66 66 65 72 20 2a 2f 0a 20 20  the buffer */.  
3320: 20 20 69 66 28 20 6e 54 6f 6b 65 6e 3e 70 43 73    if( nToken>pCs
3330: 72 2d 3e 6e 42 75 66 66 65 72 20 29 7b 0a 20 20  r->nBuffer ){.  
3340: 20 20 20 20 73 71 6c 69 74 65 33 5f 66 72 65 65      sqlite3_free
3350: 28 70 43 73 72 2d 3e 61 42 75 66 66 65 72 29 3b  (pCsr->aBuffer);
3360: 0a 20 20 20 20 20 20 70 43 73 72 2d 3e 61 42 75  .      pCsr->aBu
3370: 66 66 65 72 20 3d 20 73 71 6c 69 74 65 33 5f 6d  ffer = sqlite3_m
3380: 61 6c 6c 6f 63 28 6e 54 6f 6b 65 6e 29 3b 0a 20  alloc(nToken);. 
3390: 20 20 20 7d 0a 20 20 20 20 69 66 28 20 70 43 73     }.    if( pCs
33a0: 72 2d 3e 61 42 75 66 66 65 72 3d 3d 30 20 29 7b  r->aBuffer==0 ){
33b0: 0a 20 20 20 20 20 20 72 63 20 3d 20 53 51 4c 49  .      rc = SQLI
33c0: 54 45 5f 4e 4f 4d 45 4d 3b 0a 20 20 20 20 7d 65  TE_NOMEM;.    }e
33d0: 6c 73 65 7b 0a 20 20 20 20 20 20 69 6e 74 20 69  lse{.      int i
33e0: 3b 0a 0a 20 20 20 20 20 20 69 66 28 20 70 43 73  ;..      if( pCs
33f0: 72 2d 3e 69 4c 61 6e 67 69 64 20 26 20 30 78 30  r->iLangid & 0x0
3400: 30 30 30 30 30 30 31 20 29 7b 0a 20 20 20 20 20  0000001 ){.     
3410: 20 20 20 66 6f 72 28 69 3d 30 3b 20 69 3c 6e 54     for(i=0; i<nT
3420: 6f 6b 65 6e 3b 20 69 2b 2b 29 20 70 43 73 72 2d  oken; i++) pCsr-
3430: 3e 61 42 75 66 66 65 72 5b 69 5d 20 3d 20 70 54  >aBuffer[i] = pT
3440: 6f 6b 65 6e 5b 69 5d 3b 0a 20 20 20 20 20 20 7d  oken[i];.      }
3450: 65 6c 73 65 7b 0a 20 20 20 20 20 20 20 20 66 6f  else{.        fo
3460: 72 28 69 3d 30 3b 20 69 3c 6e 54 6f 6b 65 6e 3b  r(i=0; i<nToken;
3470: 20 69 2b 2b 29 20 70 43 73 72 2d 3e 61 42 75 66   i++) pCsr->aBuf
3480: 66 65 72 5b 69 5d 20 3d 20 74 65 73 74 54 6f 6c  fer[i] = testTol
3490: 6f 77 65 72 28 70 54 6f 6b 65 6e 5b 69 5d 29 3b  ower(pToken[i]);
34a0: 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20 70  .      }.      p
34b0: 43 73 72 2d 3e 69 54 6f 6b 65 6e 2b 2b 3b 0a 20  Csr->iToken++;. 
34c0: 20 20 20 20 20 70 43 73 72 2d 3e 69 49 6e 70 75       pCsr->iInpu
34d0: 74 20 3d 20 28 69 6e 74 29 28 70 20 2d 20 70 43  t = (int)(p - pC
34e0: 73 72 2d 3e 61 49 6e 70 75 74 29 3b 0a 0a 20 20  sr->aInput);..  
34f0: 20 20 20 20 2a 70 70 54 6f 6b 65 6e 20 3d 20 70      *ppToken = p
3500: 43 73 72 2d 3e 61 42 75 66 66 65 72 3b 0a 20 20  Csr->aBuffer;.  
3510: 20 20 20 20 2a 70 6e 42 79 74 65 73 20 3d 20 6e      *pnBytes = n
3520: 54 6f 6b 65 6e 3b 0a 20 20 20 20 20 20 2a 70 69  Token;.      *pi
3530: 53 74 61 72 74 4f 66 66 73 65 74 20 3d 20 28 69  StartOffset = (i
3540: 6e 74 29 28 70 54 6f 6b 65 6e 20 2d 20 70 43 73  nt)(pToken - pCs
3550: 72 2d 3e 61 49 6e 70 75 74 29 3b 0a 20 20 20 20  r->aInput);.    
3560: 20 20 2a 70 69 45 6e 64 4f 66 66 73 65 74 20 3d    *piEndOffset =
3570: 20 28 69 6e 74 29 28 70 20 2d 20 70 43 73 72 2d   (int)(p - pCsr-
3580: 3e 61 49 6e 70 75 74 29 3b 0a 20 20 20 20 20 20  >aInput);.      
3590: 2a 70 69 50 6f 73 69 74 69 6f 6e 20 3d 20 70 43  *piPosition = pC
35a0: 73 72 2d 3e 69 54 6f 6b 65 6e 3b 0a 20 20 20 20  sr->iToken;.    
35b0: 7d 0a 20 20 7d 0a 0a 20 20 72 65 74 75 72 6e 20  }.  }..  return 
35c0: 72 63 3b 0a 7d 0a 0a 73 74 61 74 69 63 20 69 6e  rc;.}..static in
35d0: 74 20 74 65 73 74 54 6f 6b 65 6e 69 7a 65 72 4c  t testTokenizerL
35e0: 61 6e 67 75 61 67 65 28 0a 20 20 73 71 6c 69 74  anguage(.  sqlit
35f0: 65 33 5f 74 6f 6b 65 6e 69 7a 65 72 5f 63 75 72  e3_tokenizer_cur
3600: 73 6f 72 20 2a 70 43 75 72 73 6f 72 2c 0a 20 20  sor *pCursor,.  
3610: 69 6e 74 20 69 4c 61 6e 67 69 64 0a 29 7b 0a 20  int iLangid.){. 
3620: 20 69 6e 74 20 72 63 20 3d 20 53 51 4c 49 54 45   int rc = SQLITE
3630: 5f 4f 4b 3b 0a 20 20 74 65 73 74 5f 74 6f 6b 65  _OK;.  test_toke
3640: 6e 69 7a 65 72 5f 63 75 72 73 6f 72 20 2a 70 43  nizer_cursor *pC
3650: 73 72 20 3d 20 28 74 65 73 74 5f 74 6f 6b 65 6e  sr = (test_token
3660: 69 7a 65 72 5f 63 75 72 73 6f 72 20 2a 29 70 43  izer_cursor *)pC
3670: 75 72 73 6f 72 3b 0a 20 20 70 43 73 72 2d 3e 69  ursor;.  pCsr->i
3680: 4c 61 6e 67 69 64 20 3d 20 69 4c 61 6e 67 69 64  Langid = iLangid
3690: 3b 0a 20 20 69 66 28 20 70 43 73 72 2d 3e 69 4c  ;.  if( pCsr->iL
36a0: 61 6e 67 69 64 3e 3d 31 30 30 20 29 7b 0a 20 20  angid>=100 ){.  
36b0: 20 20 72 63 20 3d 20 53 51 4c 49 54 45 5f 45 52    rc = SQLITE_ER
36c0: 52 4f 52 3b 0a 20 20 7d 0a 20 20 72 65 74 75 72  ROR;.  }.  retur
36d0: 6e 20 72 63 3b 0a 7d 0a 23 65 6e 64 69 66 0a 0a  n rc;.}.#endif..
36e0: 73 74 61 74 69 63 20 69 6e 74 20 66 74 73 33 5f  static int fts3_
36f0: 74 65 73 74 5f 74 6f 6b 65 6e 69 7a 65 72 5f 63  test_tokenizer_c
3700: 6d 64 28 0a 20 20 43 6c 69 65 6e 74 44 61 74 61  md(.  ClientData
3710: 20 63 6c 69 65 6e 74 44 61 74 61 2c 0a 20 20 54   clientData,.  T
3720: 63 6c 5f 49 6e 74 65 72 70 20 2a 69 6e 74 65 72  cl_Interp *inter
3730: 70 2c 0a 20 20 69 6e 74 20 6f 62 6a 63 2c 0a 20  p,.  int objc,. 
3740: 20 54 63 6c 5f 4f 62 6a 20 2a 43 4f 4e 53 54 20   Tcl_Obj *CONST 
3750: 6f 62 6a 76 5b 5d 0a 29 7b 0a 23 69 66 64 65 66  objv[].){.#ifdef
3760: 20 53 51 4c 49 54 45 5f 45 4e 41 42 4c 45 5f 46   SQLITE_ENABLE_F
3770: 54 53 33 0a 20 20 73 74 61 74 69 63 20 63 6f 6e  TS3.  static con
3780: 73 74 20 73 71 6c 69 74 65 33 5f 74 6f 6b 65 6e  st sqlite3_token
3790: 69 7a 65 72 5f 6d 6f 64 75 6c 65 20 74 65 73 74  izer_module test
37a0: 54 6f 6b 65 6e 69 7a 65 72 4d 6f 64 75 6c 65 20  TokenizerModule 
37b0: 3d 20 7b 0a 20 20 20 20 31 2c 0a 20 20 20 20 74  = {.    1,.    t
37c0: 65 73 74 54 6f 6b 65 6e 69 7a 65 72 43 72 65 61  estTokenizerCrea
37d0: 74 65 2c 0a 20 20 20 20 74 65 73 74 54 6f 6b 65  te,.    testToke
37e0: 6e 69 7a 65 72 44 65 73 74 72 6f 79 2c 0a 20 20  nizerDestroy,.  
37f0: 20 20 74 65 73 74 54 6f 6b 65 6e 69 7a 65 72 4f    testTokenizerO
3800: 70 65 6e 2c 0a 20 20 20 20 74 65 73 74 54 6f 6b  pen,.    testTok
3810: 65 6e 69 7a 65 72 43 6c 6f 73 65 2c 0a 20 20 20  enizerClose,.   
3820: 20 74 65 73 74 54 6f 6b 65 6e 69 7a 65 72 4e 65   testTokenizerNe
3830: 78 74 2c 0a 20 20 20 20 74 65 73 74 54 6f 6b 65  xt,.    testToke
3840: 6e 69 7a 65 72 4c 61 6e 67 75 61 67 65 0a 20 20  nizerLanguage.  
3850: 7d 3b 0a 20 20 63 6f 6e 73 74 20 73 71 6c 69 74  };.  const sqlit
3860: 65 33 5f 74 6f 6b 65 6e 69 7a 65 72 5f 6d 6f 64  e3_tokenizer_mod
3870: 75 6c 65 20 2a 70 50 74 72 20 3d 20 26 74 65 73  ule *pPtr = &tes
3880: 74 54 6f 6b 65 6e 69 7a 65 72 4d 6f 64 75 6c 65  tTokenizerModule
3890: 3b 0a 20 20 69 66 28 20 6f 62 6a 63 21 3d 31 20  ;.  if( objc!=1 
38a0: 29 7b 0a 20 20 20 20 54 63 6c 5f 57 72 6f 6e 67  ){.    Tcl_Wrong
38b0: 4e 75 6d 41 72 67 73 28 69 6e 74 65 72 70 2c 20  NumArgs(interp, 
38c0: 31 2c 20 6f 62 6a 76 2c 20 22 22 29 3b 0a 20 20  1, objv, "");.  
38d0: 20 20 72 65 74 75 72 6e 20 54 43 4c 5f 45 52 52    return TCL_ERR
38e0: 4f 52 3b 0a 20 20 7d 0a 20 20 54 63 6c 5f 53 65  OR;.  }.  Tcl_Se
38f0: 74 4f 62 6a 52 65 73 75 6c 74 28 69 6e 74 65 72  tObjResult(inter
3900: 70 2c 20 54 63 6c 5f 4e 65 77 42 79 74 65 41 72  p, Tcl_NewByteAr
3910: 72 61 79 4f 62 6a 28 0a 20 20 20 20 28 63 6f 6e  rayObj(.    (con
3920: 73 74 20 75 6e 73 69 67 6e 65 64 20 63 68 61 72  st unsigned char
3930: 20 2a 29 26 70 50 74 72 2c 20 73 69 7a 65 6f 66   *)&pPtr, sizeof
3940: 28 73 71 6c 69 74 65 33 5f 74 6f 6b 65 6e 69 7a  (sqlite3_tokeniz
3950: 65 72 5f 6d 6f 64 75 6c 65 20 2a 29 0a 20 20 29  er_module *).  )
3960: 29 3b 0a 23 65 6e 64 69 66 0a 20 20 55 4e 55 53  );.#endif.  UNUS
3970: 45 44 5f 50 41 52 41 4d 45 54 45 52 28 63 6c 69  ED_PARAMETER(cli
3980: 65 6e 74 44 61 74 61 29 3b 0a 20 20 72 65 74 75  entData);.  retu
3990: 72 6e 20 54 43 4c 5f 4f 4b 3b 0a 7d 0a 0a 2f 2a  rn TCL_OK;.}../*
39a0: 20 0a 2a 2a 20 45 6e 64 20 6f 66 20 74 6f 6b 65   .** End of toke
39b0: 6e 69 7a 65 72 20 63 6f 64 65 2e 0a 2a 2a 2a 2a  nizer code..****
39c0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
39d0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
39e0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
39f0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
3a00: 2a 2a 2a 2a 2a 2a 2f 20 0a 0a 69 6e 74 20 53 71  ******/ ..int Sq
3a10: 6c 69 74 65 74 65 73 74 66 74 73 33 5f 49 6e 69  litetestfts3_Ini
3a20: 74 28 54 63 6c 5f 49 6e 74 65 72 70 20 2a 69 6e  t(Tcl_Interp *in
3a30: 74 65 72 70 29 7b 0a 20 20 54 63 6c 5f 43 72 65  terp){.  Tcl_Cre
3a40: 61 74 65 4f 62 6a 43 6f 6d 6d 61 6e 64 28 69 6e  ateObjCommand(in
3a50: 74 65 72 70 2c 20 22 66 74 73 33 5f 6e 65 61 72  terp, "fts3_near
3a60: 5f 6d 61 74 63 68 22 2c 20 66 74 73 33 5f 6e 65  _match", fts3_ne
3a70: 61 72 5f 6d 61 74 63 68 5f 63 6d 64 2c 20 30 2c  ar_match_cmd, 0,
3a80: 20 30 29 3b 0a 20 20 54 63 6c 5f 43 72 65 61 74   0);.  Tcl_Creat
3a90: 65 4f 62 6a 43 6f 6d 6d 61 6e 64 28 69 6e 74 65  eObjCommand(inte
3aa0: 72 70 2c 20 0a 20 20 20 20 20 20 22 66 74 73 33  rp, .      "fts3
3ab0: 5f 63 6f 6e 66 69 67 75 72 65 5f 69 6e 63 72 5f  _configure_incr_
3ac0: 6c 6f 61 64 22 2c 20 66 74 73 33 5f 63 6f 6e 66  load", fts3_conf
3ad0: 69 67 75 72 65 5f 69 6e 63 72 5f 6c 6f 61 64 5f  igure_incr_load_
3ae0: 63 6d 64 2c 20 30 2c 20 30 0a 20 20 29 3b 0a 20  cmd, 0, 0.  );. 
3af0: 20 54 63 6c 5f 43 72 65 61 74 65 4f 62 6a 43 6f   Tcl_CreateObjCo
3b00: 6d 6d 61 6e 64 28 0a 20 20 20 20 20 20 69 6e 74  mmand(.      int
3b10: 65 72 70 2c 20 22 66 74 73 33 5f 74 65 73 74 5f  erp, "fts3_test_
3b20: 74 6f 6b 65 6e 69 7a 65 72 22 2c 20 66 74 73 33  tokenizer", fts3
3b30: 5f 74 65 73 74 5f 74 6f 6b 65 6e 69 7a 65 72 5f  _test_tokenizer_
3b40: 63 6d 64 2c 20 30 2c 20 30 0a 20 20 29 3b 0a 20  cmd, 0, 0.  );. 
3b50: 20 72 65 74 75 72 6e 20 54 43 4c 5f 4f 4b 3b 0a   return TCL_OK;.
3b60: 7d 0a 23 65 6e 64 69 66 20 20 20 20 20 20 20 20  }.#endif        
3b70: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 53 51 4c            /* SQL
3b80: 49 54 45 5f 45 4e 41 42 4c 45 5f 46 54 53 33 20  ITE_ENABLE_FTS3 
3b90: 7c 7c 20 53 51 4c 49 54 45 5f 45 4e 41 42 4c 45  || SQLITE_ENABLE
3ba0: 5f 46 54 53 34 20 2a 2f 0a 23 65 6e 64 69 66 20  _FTS4 */.#endif 
3bb0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3bc0: 20 2f 2a 20 69 66 64 65 66 20 53 51 4c 49 54 45   /* ifdef SQLITE
3bd0: 5f 54 45 53 54 20 2a 2f 0a                       _TEST */.