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

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2000 MySQL 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. /* Quick & light hash implementation for tab completion purposes
  14.  *
  15.  * by  Andi Gutmans <andi@zend.com>
  16.  * and Zeev Suraski <zeev@zend.com>
  17.  * Small portability changes by Monty. Changed also to use my_malloc/my_free
  18.  */
  19. #include <my_global.h>
  20. #include <m_string.h>
  21. #undef SAFEMALLOC // Speed things up
  22. #include <my_sys.h>
  23. #include "completion_hash.h"
  24. uint hashpjw(const char *arKey, uint nKeyLength)
  25. {
  26.   uint h = 0, g, i;
  27.   for (i = 0; i < nKeyLength; i++) {
  28.     h = (h << 4) + arKey[i];
  29.     if ((g = (h & 0xF0000000))) {
  30.       h = h ^ (g >> 24);
  31.       h = h ^ g;
  32.     }
  33.   }
  34.   return h;
  35. }
  36. int completion_hash_init(HashTable *ht, uint nSize)
  37. {
  38.   ht->arBuckets = (Bucket **) my_malloc(nSize* sizeof(Bucket *),
  39. MYF(MY_ZEROFILL | MY_WME));
  40.   if (!ht->arBuckets)
  41.   {
  42.     ht->initialized = 0;
  43.     return FAILURE;
  44.   }
  45.   init_alloc_root(&ht->mem_root, 8192, 0);
  46.   ht->pHashFunction = hashpjw;
  47.   ht->nTableSize = nSize;
  48.   ht->initialized = 1;
  49.   return SUCCESS;
  50. }
  51. int completion_hash_update(HashTable *ht, char *arKey, uint nKeyLength,
  52.    char *str)
  53. {
  54.   uint h, nIndex;
  55.   Bucket *p;
  56.   h = ht->pHashFunction(arKey, nKeyLength);
  57.   nIndex = h % ht->nTableSize;
  58.   if (nKeyLength <= 0) {
  59.     return FAILURE;
  60.   }
  61.   p = ht->arBuckets[nIndex];
  62.   while (p)
  63.   {
  64.     if ((p->h == h) && (p->nKeyLength == nKeyLength)) {
  65.       if (!memcmp(p->arKey, arKey, nKeyLength)) {
  66. entry *n;
  67. if (!(n = (entry *) alloc_root(&ht->mem_root,sizeof(entry))))
  68.           return FAILURE;
  69. n->pNext = p->pData;
  70. n->str = str;
  71. p->pData = n;
  72. p->count++;
  73. return SUCCESS;
  74.       }
  75.     }
  76.     p = p->pNext;
  77.   }
  78.   if (!(p = (Bucket *) alloc_root(&ht->mem_root, sizeof(Bucket))))
  79.     return FAILURE;
  80.   p->arKey = arKey;
  81.   p->nKeyLength = nKeyLength;
  82.   p->h = h;
  83.   if (!(p->pData = (entry*) alloc_root(&ht->mem_root, sizeof(entry))))
  84.     return FAILURE;
  85.   p->pData->str = str;
  86.   p->pData->pNext = 0;
  87.   p->count = 1;
  88.   p->pNext = ht->arBuckets[nIndex];
  89.   ht->arBuckets[nIndex] = p;
  90.   return SUCCESS;
  91. }
  92. static Bucket *completion_hash_find(HashTable *ht, const char *arKey,
  93.     uint nKeyLength)
  94. {
  95.   uint h, nIndex;
  96.   Bucket *p;
  97.   h = ht->pHashFunction(arKey, nKeyLength);
  98.   nIndex = h % ht->nTableSize;
  99.   p = ht->arBuckets[nIndex];
  100.   while (p)
  101.   {
  102.     if ((p->h == h) && (p->nKeyLength == nKeyLength)) {
  103.       if (!memcmp(p->arKey, arKey, nKeyLength)) {
  104. return p;
  105.       }
  106.     }
  107.     p = p->pNext;
  108.   }
  109.   return (Bucket*) 0;
  110. }
  111. int completion_hash_exists(HashTable *ht, char *arKey, uint nKeyLength)
  112. {
  113.   uint h, nIndex;
  114.   Bucket *p;
  115.   h = ht->pHashFunction(arKey, nKeyLength);
  116.   nIndex = h % ht->nTableSize;
  117.   p = ht->arBuckets[nIndex];
  118.   while (p)
  119.   {
  120.     if ((p->h == h) && (p->nKeyLength == nKeyLength))
  121.     {
  122.       if (!strcmp(p->arKey, arKey)) {
  123. return 1;
  124.       }
  125.     }
  126.     p = p->pNext;
  127.   }
  128.   return 0;
  129. }
  130. Bucket *find_all_matches(HashTable *ht, const char *str, uint length,
  131.  uint *res_length)
  132. {
  133.   Bucket *b;
  134.   b = completion_hash_find(ht,str,length);
  135.   if (!b) {
  136.     *res_length = 0;
  137.     return (Bucket*) 0;
  138.   } else {
  139.     *res_length = length;
  140.     return b;
  141.   }
  142. }
  143. Bucket *find_longest_match(HashTable *ht, char *str, uint length,
  144.    uint *res_length)
  145. {
  146.   Bucket *b,*return_b;
  147.   char *s;
  148.   uint count;
  149.   uint lm;
  150.   b = completion_hash_find(ht,str,length);
  151.   if (!b) {
  152.     *res_length = 0;
  153.     return (Bucket*) 0;
  154.   }
  155.   count = b->count;
  156.   lm = length;
  157.   s = b->pData->str;
  158.   return_b = b;
  159.   while (s[lm]!=0 && (b=completion_hash_find(ht,s,lm+1))) {
  160.     if (b->count<count) {
  161.       *res_length=lm;
  162.       return return_b;
  163.     }
  164.     return_b=b;
  165.     lm++;
  166.   }
  167.   *res_length=lm;
  168.   return return_b;
  169. }
  170. void completion_hash_clean(HashTable *ht)
  171. {
  172.   free_root(&ht->mem_root,MYF(0));
  173.   bzero((char*) ht->arBuckets,ht->nTableSize*sizeof(Bucket *));
  174. }
  175. void completion_hash_free(HashTable *ht)
  176. {
  177.   completion_hash_clean(ht);
  178.   my_free((gptr) ht->arBuckets,MYF(0));
  179. }
  180. void add_word(HashTable *ht,char *str)
  181. {
  182.   int i;
  183.   char *pos=str;
  184.   for (i=1; *pos; i++, pos++)
  185.     completion_hash_update(ht, str, i, str);
  186. }