home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 January / Chip_2001-01_cd1.bin / tema / mysql / mysql-3.23.28g-win-source.exe / client / completion_hash.cpp next >
C/C++ Source or Header  |  2000-08-31  |  5KB  |  250 lines

  1. /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
  2.    
  3.    This library is free software; you can redistribute it and/or
  4.    modify it under the terms of the GNU Library General Public
  5.    License as published by the Free Software Foundation; either
  6.    version 2 of the License, or (at your option) any later version.
  7.    
  8.    This library is distributed in the hope that it will be useful,
  9.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  11.    Library General Public License for more details.
  12.    
  13.    You should have received a copy of the GNU Library General Public
  14.    License along with this library; if not, write to the Free
  15.    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
  16.    MA 02111-1307, USA */
  17.  
  18. /* Quick & light hash implementation for tab completion purposes
  19.  *
  20.  * by  Andi Gutmans <andi@zend.com>
  21.  * and Zeev Suraski <zeev@zend.com>
  22.  * Small portability changes by Monty. Changed also to use my_malloc/my_free
  23.  */
  24.  
  25. #include <global.h>
  26. #include <m_string.h>
  27. #undef SAFEMALLOC                // Speed things up
  28. #include <my_sys.h>
  29. #include "completion_hash.h"
  30.  
  31. uint hashpjw(char *arKey, uint nKeyLength)
  32. {
  33.   uint h = 0, g, i;
  34.  
  35.   for (i = 0; i < nKeyLength; i++) {
  36.     h = (h << 4) + arKey[i];
  37.     if ((g = (h & 0xF0000000))) {
  38.       h = h ^ (g >> 24);
  39.       h = h ^ g;
  40.     }
  41.   }
  42.   return h;
  43. }
  44.  
  45. int completion_hash_init(HashTable *ht, uint nSize)
  46. {
  47.   ht->arBuckets = (Bucket **) my_malloc(nSize* sizeof(Bucket *),
  48.                     MYF(MY_ZEROFILL | MY_WME));
  49.  
  50.   if (!ht->arBuckets) {
  51.     ht->initialized = 0;
  52.     return FAILURE;
  53.   }
  54.   ht->pHashFunction = hashpjw;
  55.   ht->nTableSize = nSize;
  56.   ht->initialized = 1;
  57.   return SUCCESS;
  58. }
  59.  
  60.  
  61. int completion_hash_update(HashTable *ht, char *arKey, uint nKeyLength,
  62.                char *str)
  63. {
  64.   uint h, nIndex;
  65.  
  66.   Bucket *p;
  67.  
  68.   h = ht->pHashFunction(arKey, nKeyLength);
  69.   nIndex = h % ht->nTableSize;
  70.  
  71.   if (nKeyLength <= 0) {
  72.     return FAILURE;
  73.   }
  74.   p = ht->arBuckets[nIndex];
  75.   while (p)
  76.   {
  77.     if ((p->h == h) && (p->nKeyLength == nKeyLength)) {
  78.       if (!memcmp(p->arKey, arKey, nKeyLength)) {
  79.     entry *n;
  80.  
  81.     n = (entry *) my_malloc(sizeof(entry),
  82.                 MYF(MY_WME));
  83.     n->pNext = p->pData;
  84.     n->str = str;
  85.     p->pData = n;
  86.     p->count++;
  87.  
  88.     return SUCCESS;
  89.       }
  90.     }
  91.     p = p->pNext;
  92.   }
  93.  
  94.   p = (Bucket *) my_malloc(sizeof(Bucket),MYF(MY_WME));
  95.  
  96.   if (!p) {
  97.     return FAILURE;
  98.   }
  99.   p->arKey = arKey;
  100.   p->nKeyLength = nKeyLength;
  101.   p->h = h;
  102.  
  103.   p->pData = (entry*) my_malloc(sizeof(entry),MYF(MY_WME));
  104.   if (!p->pData) {
  105.     my_free((gptr) p,MYF(0));
  106.     return FAILURE;
  107.   }
  108.   p->pData->str = str;
  109.   p->pData->pNext = 0;
  110.   p->count = 1;
  111.  
  112.   p->pNext = ht->arBuckets[nIndex];
  113.   ht->arBuckets[nIndex] = p;
  114.  
  115.   return SUCCESS;
  116. }
  117.  
  118. static Bucket *completion_hash_find(HashTable *ht, char *arKey,
  119.                     uint nKeyLength)
  120. {
  121.   uint h, nIndex;
  122.   Bucket *p;
  123.  
  124.   h = ht->pHashFunction(arKey, nKeyLength);
  125.   nIndex = h % ht->nTableSize;
  126.  
  127.   p = ht->arBuckets[nIndex];
  128.   while (p)
  129.   {
  130.     if ((p->h == h) && (p->nKeyLength == nKeyLength)) {
  131.       if (!memcmp(p->arKey, arKey, nKeyLength)) {
  132.     return p;
  133.       }
  134.     }
  135.     p = p->pNext;
  136.   }
  137.   return (Bucket*) 0;
  138. }
  139.  
  140.  
  141. int completion_hash_exists(HashTable *ht, char *arKey, uint nKeyLength)
  142. {
  143.   uint h, nIndex;
  144.   Bucket *p;
  145.  
  146.   h = ht->pHashFunction(arKey, nKeyLength);
  147.   nIndex = h % ht->nTableSize;
  148.  
  149.   p = ht->arBuckets[nIndex];
  150.   while (p)
  151.   {
  152.     if ((p->h == h) && (p->nKeyLength == nKeyLength))
  153.     {
  154.       if (!strcmp(p->arKey, arKey)) {
  155.     return 1;
  156.       }
  157.     }
  158.     p = p->pNext;
  159.   }
  160.   return 0;
  161. }
  162.  
  163. Bucket *find_all_matches(HashTable *ht, char *str, uint length,
  164.              uint *res_length)
  165. {
  166.   Bucket *b;
  167.  
  168.   b = completion_hash_find(ht,str,length);
  169.   if (!b) {
  170.     *res_length = 0;
  171.     return (Bucket*) 0;
  172.   } else {
  173.     *res_length = length;
  174.     return b;
  175.   }
  176. }
  177.  
  178. Bucket *find_longest_match(HashTable *ht, char *str, uint length,
  179.                uint *res_length)
  180. {
  181.   Bucket *b,*return_b;
  182.   char *s;
  183.   uint count;
  184.   uint lm;
  185.  
  186.   b = completion_hash_find(ht,str,length);
  187.   if (!b) {
  188.     *res_length = 0;
  189.     return (Bucket*) 0;
  190.   }
  191.  
  192.   count = b->count;
  193.   lm = length;
  194.   s = b->pData->str;
  195.  
  196.   return_b = b;
  197.   while (s[lm]!=0 && (b=completion_hash_find(ht,s,lm+1))) {
  198.     if (b->count<count) {
  199.       *res_length=lm;
  200.       return return_b;
  201.     }
  202.     return_b=b;
  203.     lm++;
  204.   }
  205.   *res_length=lm;
  206.   return return_b;
  207. }
  208.  
  209.  
  210. void completion_hash_clean(HashTable *ht)
  211. {
  212.   uint i;
  213.   entry *e, *t;
  214.   Bucket *b, *tmp;
  215.  
  216.   for (i=0; i<ht->nTableSize; i++) {
  217.     b = ht->arBuckets[i];
  218.     while (b) {
  219.       e =  b->pData;
  220.       while (e) {
  221.     t = e;
  222.     e = e->pNext;
  223.     my_free((gptr) t,MYF(0));
  224.       }
  225.       tmp = b;
  226.       b = b->pNext;
  227.       my_free((gptr) tmp,MYF(0));
  228.     }
  229.   }
  230.   bzero((char*) ht->arBuckets,ht->nTableSize*sizeof(Bucket *));
  231. }
  232.  
  233.  
  234. void completion_hash_free(HashTable *ht)
  235. {
  236.   completion_hash_clean(ht);
  237.   my_free((gptr) ht->arBuckets,MYF(0));
  238. }
  239.  
  240.  
  241. void add_word(HashTable *ht,char *str)
  242. {
  243.   int i;
  244.   int length= (int) strlen(str);
  245.  
  246.   for (i=1; i<=length; i++) {
  247.     completion_hash_update(ht, str, i, str);
  248.   }
  249. }
  250.