ft_parser.c
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:4k
源码类别:

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. #ifdef EVAL_RUN
  16. #ifdef PIVOT_STAT
  17. ulong collstat=0;
  18. #endif
  19. #endif /* EVAL_RUN */
  20. typedef struct st_ft_docstat {
  21.   FT_WORD *list;
  22.   uint uniq;
  23.   double sum;
  24. #ifdef EVAL_RUN
  25.   uint words, totlen;
  26.   double max, nsum, nsum2;
  27. #endif /* EVAL_RUN */
  28.   MI_INFO *info;
  29.   uint keynr;
  30.   byte *keybuf;
  31. } FT_DOCSTAT;
  32. static int FT_WORD_cmp(FT_WORD *w1, FT_WORD *w2)
  33. {
  34.   return _mi_compare_text(default_charset_info,
  35.   (uchar*) w1->pos,w1->len,
  36.   (uchar*) w2->pos, w2->len,0);
  37. }
  38. static int walk_and_copy(FT_WORD *word,uint32 count,FT_DOCSTAT *docstat)
  39. {
  40.     word->weight=LWS_IN_USE;
  41. #ifdef EVAL_RUN
  42.     word->cnt= (uchar) count;
  43.     if(docstat->max < word->weight) docstat->max=word->weight;
  44.     docstat->words+=count;
  45.     docstat->totlen+=word->len;
  46. #endif /* EVAL_RUN */
  47.     docstat->sum+=word->weight;
  48.     memcpy_fixed((docstat->list)++,word,sizeof(FT_WORD));
  49.     return 0;
  50. }
  51. /* transforms tree of words into the array, applying normalization */
  52. FT_WORD * ft_linearize(MI_INFO *info, uint keynr, byte *keybuf, TREE *wtree)
  53. {
  54.   FT_WORD *wlist,*p;
  55.   FT_DOCSTAT docstat;
  56.   if ((wlist=(FT_WORD *) my_malloc(sizeof(FT_WORD)*
  57.    (1+wtree->elements_in_tree),MYF(0))))
  58.   {
  59.     docstat.info=info;
  60.     docstat.keynr=keynr;
  61.     docstat.keybuf=keybuf;
  62.     docstat.list=wlist;
  63.     docstat.uniq=wtree->elements_in_tree;
  64. #ifdef EVAL_RUN
  65.     docstat.nsum=docstat.nsum2=docstat.max=docstat.words=docstat.totlen=
  66. #endif /* EVAL_RUN */
  67.     docstat.sum=0;
  68.     tree_walk(wtree,(tree_walk_action)&walk_and_copy,&docstat,left_root_right);
  69.   }
  70.   delete_tree(wtree);
  71.   my_free((char*) wtree,MYF(0));
  72.   if (!wlist)
  73.     return NULL;
  74.   docstat.list->pos=NULL;
  75.   for(p=wlist;p->pos;p++)
  76.   {
  77.     p->weight=PRENORM_IN_USE;
  78. #ifdef EVAL_RUN
  79.     docstat.nsum+=p->weight;
  80.     docstat.nsum2+=p->weight*p->weight;
  81. #endif /* EVAL_RUN */
  82.   }
  83. #ifdef EVAL_RUN
  84. #ifdef PIVOT_STAT
  85.   collstat+=PIVOT_STAT;
  86. #endif
  87. #endif /* EVAL_RUN */
  88.   for(p=wlist;p->pos;p++)
  89.   {
  90.     p->weight/=NORM_IN_USE;
  91.   }
  92.   return wlist;
  93. }
  94. #ifdef HYPHEN_IS_DELIM
  95. #define word_char(X) (isalnum(X) || (X)=='_' || (X)==''')
  96. #else
  97. #define word_char(X) (isalnum(X) || (X)=='_' || (X)==''' || (X)=='-')
  98. #endif
  99. /* this is rather dumb first version of the parser */
  100. TREE * ft_parse(TREE *wtree, byte *doc, int doclen)
  101. {
  102.   byte *end=doc+doclen;
  103.   FT_WORD w;
  104.   if (!wtree)
  105.   {
  106.     if (!(wtree=(TREE *)my_malloc(sizeof(TREE),MYF(0)))) return NULL;
  107.     init_tree(wtree,0,sizeof(FT_WORD),(qsort_cmp)&FT_WORD_cmp,0,NULL);
  108.   }
  109.   w.weight=0;
  110.   while (doc<end)
  111.   {
  112.     for (;doc<end;doc++)
  113.       if (word_char(*doc)) break;
  114.     for (w.pos=doc; doc<end; doc++)
  115.       if (!word_char(*doc)) break;
  116.     if ((w.len= (uint) (doc-w.pos)) < MIN_WORD_LEN) continue;
  117.     if (w.len >= HA_FT_MAXLEN) continue;
  118.     if (is_stopword(w.pos, w.len)) continue;
  119.     if (!tree_insert(wtree, &w, 0))
  120.     {
  121.       delete_tree(wtree);
  122.       my_free((char*) wtree,MYF(0));
  123.       return NULL;
  124.     }
  125.   }
  126.   return wtree;
  127. }