亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關于我們
? 蟲蟲下載站

?? fts1_porter.c

?? sqlite 3.3.8 支持加密的版本
?? C
?? 第 1 頁 / 共 2 頁
字號:
/*
** 2006 September 30
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Implementation of the full-text-search tokenizer that implements
** a Porter stemmer.
*/

/*
** The code in this file is only compiled if:
**
**     * The FTS1 module is being built as an extension
**       (in which case SQLITE_CORE is not defined), or
**
**     * The FTS1 module is being built into the core of
**       SQLite (in which case SQLITE_ENABLE_FTS1 is defined).
*/
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS1)


#include <assert.h>
#if !defined(__APPLE__)
#include <malloc.h>
#else
#include <stdlib.h>
#endif
#include <stdio.h>
#include <string.h>
#include <ctype.h>

#include "fts1_tokenizer.h"

/*
** Class derived from sqlite3_tokenizer
*/
typedef struct porter_tokenizer {
  sqlite3_tokenizer base;      /* Base class */
} porter_tokenizer;

/*
** Class derived from sqlit3_tokenizer_cursor
*/
typedef struct porter_tokenizer_cursor {
  sqlite3_tokenizer_cursor base;
  const char *zInput;          /* input we are tokenizing */
  int nInput;                  /* size of the input */
  int iOffset;                 /* current position in zInput */
  int iToken;                  /* index of next token to be returned */
  char *zToken;                /* storage for current token */
  int nAllocated;              /* space allocated to zToken buffer */
} porter_tokenizer_cursor;


/* Forward declaration */
static const sqlite3_tokenizer_module porterTokenizerModule;


/*
** Create a new tokenizer instance.
*/
static int porterCreate(
  int argc, const char * const *argv,
  sqlite3_tokenizer **ppTokenizer
){
  porter_tokenizer *t;
  int i;

for(i=0; i<argc; i++) printf("argv[%d] = %s\n", i, argv[i]);
  t = (porter_tokenizer *) calloc(sizeof(porter_tokenizer), 1);
  *ppTokenizer = &t->base;
  return SQLITE_OK;
}

/*
** Destroy a tokenizer
*/
static int porterDestroy(sqlite3_tokenizer *pTokenizer){
  free(pTokenizer);
  return SQLITE_OK;
}

/*
** Prepare to begin tokenizing a particular string.  The input
** string to be tokenized is zInput[0..nInput-1].  A cursor
** used to incrementally tokenize this string is returned in 
** *ppCursor.
*/
static int porterOpen(
  sqlite3_tokenizer *pTokenizer,         /* The tokenizer */
  const char *zInput, int nInput,        /* String to be tokenized */
  sqlite3_tokenizer_cursor **ppCursor    /* OUT: Tokenization cursor */
){
  porter_tokenizer_cursor *c;

  c = (porter_tokenizer_cursor *) malloc(sizeof(porter_tokenizer_cursor));
  c->zInput = zInput;
  if( zInput==0 ){
    c->nInput = 0;
  }else if( nInput<0 ){
    c->nInput = (int)strlen(zInput);
  }else{
    c->nInput = nInput;
  }
  c->iOffset = 0;                 /* start tokenizing at the beginning */
  c->iToken = 0;
  c->zToken = NULL;               /* no space allocated, yet. */
  c->nAllocated = 0;

  *ppCursor = &c->base;
  return SQLITE_OK;
}

/*
** Close a tokenization cursor previously opened by a call to
** porterOpen() above.
*/
static int porterClose(sqlite3_tokenizer_cursor *pCursor){
  porter_tokenizer_cursor *c = (porter_tokenizer_cursor *) pCursor;
  free(c->zToken);
  free(c);
  return SQLITE_OK;
}
/*
** Vowel or consonant
*/
static const char cType[] = {
   0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0,
   1, 1, 1, 2, 1
};

/*
** isConsonant() and isVowel() determine if their first character in
** the string they point to is a consonant or a vowel, according
** to Porter ruls.  
**
** A consonate is any letter other than 'a', 'e', 'i', 'o', or 'u'.
** 'Y' is a consonant unless it follows another consonant,
** in which case it is a vowel.
**
** In these routine, the letters are in reverse order.  So the 'y' rule
** is that 'y' is a consonant unless it is followed by another
** consonent.
*/
static int isVowel(const char*);
static int isConsonant(const char *z){
  int j;
  char x = *z;
  if( x==0 ) return 0;
  assert( x>='a' && x<='z' );
  j = cType[x-'a'];
  if( j<2 ) return j;
  return z[1]==0 || isVowel(z + 1);
}
static int isVowel(const char *z){
  int j;
  char x = *z;
  if( x==0 ) return 0;
  assert( x>='a' && x<='z' );
  j = cType[x-'a'];
  if( j<2 ) return 1-j;
  return isConsonant(z + 1);
}

/*
** Let any sequence of one or more vowels be represented by V and let
** C be sequence of one or more consonants.  Then every word can be
** represented as:
**
**           [C] (VC){m} [V]
**
** In prose:  A word is an optional consonant followed by zero or
** vowel-consonant pairs followed by an optional vowel.  "m" is the
** number of vowel consonant pairs.  This routine computes the value
** of m for the first i bytes of a word.
**
** Return true if the m-value for z is 1 or more.  In other words,
** return true if z contains at least one vowel that is followed
** by a consonant.
**
** In this routine z[] is in reverse order.  So we are really looking
** for an instance of of a consonant followed by a vowel.
*/
static int m_gt_0(const char *z){
  while( isVowel(z) ){ z++; }
  if( *z==0 ) return 0;
  while( isConsonant(z) ){ z++; }
  return *z!=0;
}

/* Like mgt0 above except we are looking for a value of m which is
** exactly 1
*/
static int m_eq_1(const char *z){
  while( isVowel(z) ){ z++; }
  if( *z==0 ) return 0;
  while( isConsonant(z) ){ z++; }
  if( *z==0 ) return 0;
  while( isVowel(z) ){ z++; }
  if( *z==0 ) return 1;
  while( isConsonant(z) ){ z++; }
  return *z==0;
}

/* Like mgt0 above except we are looking for a value of m>1 instead
** or m>0
*/
static int m_gt_1(const char *z){
  while( isVowel(z) ){ z++; }
  if( *z==0 ) return 0;
  while( isConsonant(z) ){ z++; }
  if( *z==0 ) return 0;
  while( isVowel(z) ){ z++; }
  if( *z==0 ) return 0;
  while( isConsonant(z) ){ z++; }
  return *z!=0;
}

/*
** Return TRUE if there is a vowel anywhere within z[0..n-1]
*/
static int hasVowel(const char *z){
  while( isConsonant(z) ){ z++; }
  return *z!=0;
}

/*
** Return TRUE if the word ends in a double consonant.
**
** The text is reversed here. So we are really looking at
** the first two characters of z[].
*/
static int doubleConsonant(const char *z){
  return isConsonant(z) && z[0]==z[1] && isConsonant(z+1);
}

/*
** Return TRUE if the word ends with three letters which
** are consonant-vowel-consonent and where the final consonant
** is not 'w', 'x', or 'y'.
**
** The word is reversed here.  So we are really checking the
** first three letters and the first one cannot be in [wxy].
*/
static int star_oh(const char *z){
  return
    z[0]!=0 && isConsonant(z) &&
    z[0]!='w' && z[0]!='x' && z[0]!='y' &&
    z[1]!=0 && isVowel(z+1) &&
    z[2]!=0 && isConsonant(z+2);
}

/*
** If the word ends with zFrom and xCond() is true for the stem
** of the word that preceeds the zFrom ending, then change the 
** ending to zTo.
**
** The input word *pz and zFrom are both in reverse order.  zTo
** is in normal order. 
**
** Return TRUE if zFrom matches.  Return FALSE if zFrom does not
** match.  Not that TRUE is returned even if xCond() fails and
** no substitution occurs.
*/
static int stem(
  char **pz,             /* The word being stemmed (Reversed) */
  const char *zFrom,     /* If the ending matches this... (Reversed) */
  const char *zTo,       /* ... change the ending to this (not reversed) */
  int (*xCond)(const char*)   /* Condition that must be true */
){
  char *z = *pz;
  while( *zFrom && *zFrom==*z ){ z++; zFrom++; }
  if( *zFrom!=0 ) return 0;
  if( xCond && !xCond(z) ) return 1;
  while( *zTo ){
    *(--z) = *(zTo++);
  }
  *pz = z;
  return 1;
}

/*
** This is the fallback stemmer used when the porter stemmer is
** inappropriate.  The input word is copied into the output with
** US-ASCII case folding.  If the input word is too long (more
** than 20 bytes if it contains no digits or more than 6 bytes if
** it contains digits) then word is truncated to 20 or 6 bytes
** by taking 10 or 3 bytes from the beginning and end.
*/
static void copy_stemmer(const char *zIn, int nIn, char *zOut, int *pnOut){
  int i, mx, j;
  int hasDigit = 0;
  for(i=0; i<nIn; i++){
    int c = zIn[i];
    if( c>='A' && c<='Z' ){
      zOut[i] = c - 'A' + 'a';
    }else{
      if( c>='0' && c<='9' ) hasDigit = 1;
      zOut[i] = c;
    }
  }
  mx = hasDigit ? 3 : 10;
  if( nIn>mx*2 ){
    for(j=mx, i=nIn-mx; i<nIn; i++, j++){
      zOut[j] = zOut[i];
    }
    i = j;
  }
  zOut[i] = 0;
  *pnOut = i;
}


/*
** Stem the input word zIn[0..nIn-1].  Store the output in zOut.
** zOut is at least big enough to hold nIn bytes.  Write the actual
** size of the output word (exclusive of the '\0' terminator) into *pnOut.

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
成人毛片老司机大片| 日韩色在线观看| 亚洲欧洲国产日韩| 丁香一区二区三区| 中文字幕亚洲在| 欧美性猛交xxxx黑人交| 性欧美疯狂xxxxbbbb| 91精品久久久久久蜜臀| 麻豆91精品91久久久的内涵| 26uuu亚洲婷婷狠狠天堂| 国产激情精品久久久第一区二区| 国产日韩视频一区二区三区| 国产成人精品亚洲777人妖| 国产精品毛片久久久久久久| 日本精品一级二级| 青青草97国产精品免费观看无弹窗版| 精品国产sm最大网站免费看| 粉嫩欧美一区二区三区高清影视| 亚洲欧洲精品天堂一级| 欧美一级生活片| 国产成人在线网站| 亚洲激情图片小说视频| 欧美一级电影网站| 成人激情免费网站| 偷偷要91色婷婷| 日本一区二区三区国色天香| 欧美系列日韩一区| 国产精品一区二区三区乱码| ㊣最新国产の精品bt伙计久久| 欧美日韩色一区| 国产精品亚洲一区二区三区妖精 | 国产大片一区二区| 亚洲精品中文字幕乱码三区| 欧美一区二区性放荡片| 91在线免费视频观看| 日本亚洲三级在线| 综合色中文字幕| 欧美精品一区二区三区高清aⅴ| 91丨九色丨尤物| 国产主播一区二区三区| 亚洲第一福利一区| 国产精品护士白丝一区av| 91精品国产91久久久久久一区二区 | 国产精品激情偷乱一区二区∴| 欧美日韩一区二区欧美激情| 成人av在线影院| 久久99精品久久久久| 亚洲一区二区三区四区在线 | 欧美一区二区视频网站| 99久久婷婷国产综合精品| 久久99精品国产.久久久久久 | 精品国产乱码久久久久久免费| 亚洲一二三四在线| 欧美日韩国产a| aa级大片欧美| 成人av动漫在线| 欧美视频你懂的| 精品一区二区三区免费观看| 精品久久国产老人久久综合| 色先锋aa成人| 精品久久人人做人人爱| 国内久久精品视频| 日韩精品欧美成人高清一区二区| 精品欧美乱码久久久久久 | 一区二区激情小说| 国产欧美一区二区精品性色超碰 | 国产福利一区二区三区在线视频| 欧美网站大全在线观看| 国产一区二区三区综合| 欧美日韩日日夜夜| 不卡的av在线| 国产麻豆精品视频| 国产精品亚洲第一区在线暖暖韩国| 日韩av电影免费观看高清完整版| 亚洲成人一区二区| 亚洲在线视频免费观看| 一区二区在线看| 亚洲男同性视频| 亚洲欧美日韩国产成人精品影院| 国产精品免费网站在线观看| 欧美国产1区2区| 成人欧美一区二区三区白人| 国产精品蜜臀av| 亚洲三级电影全部在线观看高清| **欧美大码日韩| 一区二区三区日韩欧美| 亚洲国产精品影院| 日韩电影免费一区| 久久91精品国产91久久小草| 精品一区二区三区久久| 国产在线日韩欧美| 成人av网在线| 在线观看日韩毛片| 欧美一区二区三级| 精品粉嫩aⅴ一区二区三区四区| 久久久一区二区三区| 国产精品视频一二三| 国产精品久久久久aaaa樱花| 欧美videossexotv100| 欧美日韩国产成人在线免费| 日韩免费观看2025年上映的电影| 欧美成人精品1314www| 国产欧美日产一区| 亚洲欧美日韩小说| 麻豆精品视频在线观看视频| 国产精一区二区三区| 99re热这里只有精品免费视频| 一本到不卡精品视频在线观看| 欧美日韩综合不卡| 精品国产乱子伦一区| 《视频一区视频二区| 日韩av网站在线观看| 成人一区在线看| 欧美色综合网站| 国产亚洲精品福利| 亚洲综合在线免费观看| 麻豆精品在线看| 色天使久久综合网天天| 亚洲影院在线观看| 夜夜嗨av一区二区三区中文字幕| 免费在线观看一区| 99久久综合精品| 日韩一区二区三区在线观看| 欧美高清在线视频| 日韩电影在线免费| 95精品视频在线| 日韩欧美卡一卡二| 亚洲最大的成人av| 国产成人综合亚洲网站| 欧美高清视频一二三区 | 久久精品理论片| 成人av电影在线观看| 日韩免费成人网| 亚洲精品日日夜夜| 国产成人免费视频精品含羞草妖精| 欧美日韩高清一区| 中文字幕亚洲视频| 精久久久久久久久久久| 91高清视频免费看| 国产欧美一区二区精品久导航| 午夜精品久久久久久久久久久 | 亚洲黄色小视频| 亚洲天堂中文字幕| 国产一区二区电影| 国产一区高清在线| 国产宾馆实践打屁股91| 欧美一区二区三区视频免费| 亚洲精品午夜久久久| 国产不卡一区视频| 欧美成人精精品一区二区频| 亚洲大型综合色站| 一道本成人在线| 国产精品乱码妇女bbbb| 国产美女在线精品| 精品国产网站在线观看| 日韩成人伦理电影在线观看| 在线视频观看一区| 成人欧美一区二区三区在线播放| 懂色av一区二区夜夜嗨| 国产欧美一二三区| 成人中文字幕合集| 日本一二三四高清不卡| 蜜臀精品久久久久久蜜臀| 欧美日韩在线观看一区二区 | 亚洲欧洲精品一区二区三区| 激情五月婷婷综合| 精品国产欧美一区二区| 麻豆免费看一区二区三区| 亚洲欧美自拍偷拍| 欧美一区二区三区日韩视频| 亚洲成人av免费| 欧美精品一二三四| 日本91福利区| 日韩欧美另类在线| 蜜桃精品视频在线| 欧美成人三级在线| 国产乱码字幕精品高清av| 久久这里只有精品首页| 国产精品123| 国产精品久久久久久久久图文区| 成人精品国产一区二区4080| 久久久99免费| av在线不卡电影| 亚洲激情自拍偷拍| 欧美一区二区三区在线观看| 美女在线视频一区| 国产亚洲成年网址在线观看| 波波电影院一区二区三区| 中文字幕综合网| 久久先锋影音av| 欧美一级电影网站| 久久精品国产亚洲aⅴ| 久久久久久久国产精品影院| 国产ts人妖一区二区| 亚洲欧洲日产国产综合网| 色婷婷香蕉在线一区二区| 五月婷婷激情综合网| 精品国产99国产精品| 成人ar影院免费观看视频| 亚洲香肠在线观看|