ft_parser.c
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:6k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
  2.    This program is free software; you can redistribute it and/or modify
  3.    it under the terms of the GNU General Public License as published by
  4.    the Free Software Foundation; either version 2 of the License, or
  5.    (at your option) any later version.
  6.    This program is distributed in the hope that it will be useful,
  7.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  8.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  9.    GNU General Public License for more details.
  10.    You should have received a copy of the GNU General Public License
  11.    along with this program; if not, write to the Free Software
  12.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  13. /* Written by Sergei A. Golubchik, who has a shared copyright to this code */
  14. #include "ftdefs.h"
  15. typedef struct st_ft_docstat {
  16.   FT_WORD *list;
  17.   uint uniq;
  18.   double sum;
  19. } FT_DOCSTAT;
  20. static int FT_WORD_cmp(CHARSET_INFO* cs, FT_WORD *w1, FT_WORD *w2)
  21. {
  22.   return mi_compare_text(cs, (uchar*) w1->pos, w1->len,
  23.                          (uchar*) w2->pos, w2->len, 0, 0);
  24. }
  25. static int walk_and_copy(FT_WORD *word,uint32 count,FT_DOCSTAT *docstat)
  26. {
  27.     word->weight=LWS_IN_USE;
  28.     docstat->sum+=word->weight;
  29.     memcpy_fixed((docstat->list)++,word,sizeof(FT_WORD));
  30.     return 0;
  31. }
  32. /* transforms tree of words into the array, applying normalization */
  33. FT_WORD * ft_linearize(TREE *wtree)
  34. {
  35.   FT_WORD *wlist,*p;
  36.   FT_DOCSTAT docstat;
  37.   DBUG_ENTER("ft_linearize");
  38.   if ((wlist=(FT_WORD *) my_malloc(sizeof(FT_WORD)*
  39.    (1+wtree->elements_in_tree),MYF(0))))
  40.   {
  41.     docstat.list=wlist;
  42.     docstat.uniq=wtree->elements_in_tree;
  43.     docstat.sum=0;
  44.     tree_walk(wtree,(tree_walk_action)&walk_and_copy,&docstat,left_root_right);
  45.   }
  46.   delete_tree(wtree);
  47.   if (!wlist)
  48.     DBUG_RETURN(NULL);
  49.   docstat.list->pos=NULL;
  50.   for (p=wlist;p->pos;p++)
  51.   {
  52.     p->weight=PRENORM_IN_USE;
  53.   }
  54.   for (p=wlist;p->pos;p++)
  55.   {
  56.     p->weight/=NORM_IN_USE;
  57.   }
  58.   DBUG_RETURN(wlist);
  59. }
  60. my_bool ft_boolean_check_syntax_string(const byte *str)
  61. {
  62.   uint i, j;
  63.   if (!str ||
  64.       (strlen(str)+1 != sizeof(ft_boolean_syntax)) ||
  65.       (str[0] != ' ' && str[1] != ' '))
  66.     return 1;
  67.   for (i=0; i<sizeof(ft_boolean_syntax); i++)
  68.   {
  69.     /* limiting to 7-bit ascii only */
  70.     if ((unsigned char)(str[i]) > 127 || my_isalnum(default_charset_info, str[i]))
  71.       return 1;
  72.     for (j=0; j<i; j++)
  73.       if (str[i] == str[j] && (i != 11 || j != 10))
  74.         return 1;
  75.   }
  76.   return 0;
  77. }
  78. /* returns:
  79.  * 0 - eof
  80.  * 1 - word found
  81.  * 2 - left bracket
  82.  * 3 - right bracket
  83.  */
  84. byte ft_get_word(CHARSET_INFO *cs, byte **start, byte *end,
  85.                  FT_WORD *word, FTB_PARAM *param)
  86. {
  87.   byte *doc=*start;
  88.   uint mwc, length, mbl;
  89.   param->yesno=(FTB_YES==' ') ? 1 : (param->quot != 0);
  90.   param->plusminus=param->pmsign=0;
  91.   while (doc<end)
  92.   {
  93.     for (;doc<end;doc++)
  94.     {
  95.       if (true_word_char(cs,*doc)) break;
  96.       if (*doc == FTB_RQUOT && param->quot)
  97.       {
  98.         param->quot=doc;
  99.         *start=doc+1;
  100.         return 3; /* FTB_RBR */
  101.       }
  102.       if (!param->quot)
  103.       {
  104.         if (*doc == FTB_LBR || *doc == FTB_RBR || *doc == FTB_LQUOT)
  105.         {
  106.           /* param->prev=' '; */
  107.           *start=doc+1;
  108.           if (*doc == FTB_LQUOT) param->quot=*start;
  109.           return (*doc == FTB_RBR)+2;
  110.         }
  111.         if (param->prev == ' ')
  112.         {
  113.           if (*doc == FTB_YES ) { param->yesno=+1;    continue; } else
  114.           if (*doc == FTB_EGAL) { param->yesno= 0;    continue; } else
  115.           if (*doc == FTB_NO  ) { param->yesno=-1;    continue; } else
  116.           if (*doc == FTB_INC ) { param->plusminus++; continue; } else
  117.           if (*doc == FTB_DEC ) { param->plusminus--; continue; } else
  118.           if (*doc == FTB_NEG ) { param->pmsign=!param->pmsign; continue; }
  119.         }
  120.       }
  121.       param->prev=*doc;
  122.       param->yesno=(FTB_YES==' ') ? 1 : (param->quot != 0);
  123.       param->plusminus=param->pmsign=0;
  124.     }
  125.     mwc=length=0;
  126.     for (word->pos=doc; doc<end; length++, mbl=my_mbcharlen(cs, *(uchar *)doc), doc+=(mbl ? mbl : 1))
  127.       if (true_word_char(cs,*doc))
  128.         mwc=0;
  129.       else if (!misc_word_char(*doc) || mwc)
  130.         break;
  131.       else
  132.         mwc++;
  133.     param->prev='A'; /* be sure *prev is true_word_char */
  134.     word->len= (uint)(doc-word->pos) - mwc;
  135.     if ((param->trunc=(doc<end && *doc == FTB_TRUNC)))
  136.       doc++;
  137.     if (((length >= ft_min_word_len && !is_stopword(word->pos, word->len))
  138.          || param->trunc) && length < ft_max_word_len)
  139.     {
  140.       *start=doc;
  141.       return 1;
  142.     }
  143.   }
  144.   if (param->quot)
  145.   {
  146.     param->quot=*start=doc;
  147.     return 3; /* FTB_RBR */
  148.   }
  149.   return 0;
  150. }
  151. byte ft_simple_get_word(CHARSET_INFO *cs, byte **start, byte *end,
  152.                         FT_WORD *word)
  153. {
  154.   byte *doc= *start;
  155.   uint mwc, length, mbl;
  156.   DBUG_ENTER("ft_simple_get_word");
  157.   while (doc<end)
  158.   {
  159.     for (;doc<end;doc++)
  160.     {
  161.       if (true_word_char(cs,*doc)) break;
  162.     }
  163.     mwc= length= 0;
  164.     for (word->pos=doc; doc<end; length++, mbl=my_mbcharlen(cs, *(uchar *)doc), doc+=(mbl ? mbl : 1))
  165.       if (true_word_char(cs,*doc))
  166.         mwc= 0;
  167.       else if (!misc_word_char(*doc) || mwc)
  168.         break;
  169.       else
  170.         mwc++;
  171.     word->len= (uint)(doc-word->pos) - mwc;
  172.     if (length >= ft_min_word_len && length < ft_max_word_len &&
  173.         !is_stopword(word->pos, word->len))
  174.     {
  175.       *start= doc;
  176.       DBUG_RETURN(1);
  177.     }
  178.   }
  179.   DBUG_RETURN(0);
  180. }
  181. void ft_parse_init(TREE *wtree, CHARSET_INFO *cs)
  182. {
  183.   DBUG_ENTER("ft_parse_init");
  184.   if (!is_tree_inited(wtree))
  185.     init_tree(wtree,0,0,sizeof(FT_WORD),(qsort_cmp2)&FT_WORD_cmp,0,NULL, cs);
  186.   DBUG_VOID_RETURN;
  187. }
  188. int ft_parse(TREE *wtree, byte *doc, int doclen, my_bool with_alloc)
  189. {
  190.   byte   *end=doc+doclen;
  191.   FT_WORD w;
  192.   DBUG_ENTER("ft_parse");
  193.   while (ft_simple_get_word(wtree->custom_arg, &doc,end,&w))
  194.   {
  195.     if (with_alloc)
  196.     {
  197.       byte *ptr;
  198.       /* allocating the data in the tree - to avoid mallocs and frees */
  199.       DBUG_ASSERT(wtree->with_delete==0);
  200.       ptr=(byte *)alloc_root(& wtree->mem_root,w.len);
  201.       memcpy(ptr, w.pos, w.len);
  202.       w.pos=ptr;
  203.     }
  204.     if (!tree_insert(wtree, &w, 0, wtree->custom_arg))
  205.       goto err;
  206.   }
  207.   DBUG_RETURN(0);
  208. err:
  209.   delete_tree(wtree);
  210.   DBUG_RETURN(1);
  211. }