The world's most popular open source database
00001 /* Copyright (C) 2000 MySQL AB 00002 00003 This program is free software; you can redistribute it and/or modify 00004 it under the terms of the GNU General Public License as published by 00005 the Free Software Foundation; either version 2 of the License, or 00006 (at your option) any later version. 00007 00008 This program is distributed in the hope that it will be useful, 00009 but WITHOUT ANY WARRANTY; without even the implied warranty of 00010 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00011 GNU General Public License for more details. 00012 00013 You should have received a copy of the GNU General Public License 00014 along with this program; if not, write to the Free Software 00015 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ 00016 00017 /* Quick & light hash implementation for tab completion purposes 00018 * 00019 * by Andi Gutmans <andi@zend.com> 00020 * and Zeev Suraski <zeev@zend.com> 00021 * Small portability changes by Monty. Changed also to use my_malloc/my_free 00022 */ 00023 00024 #include <my_global.h> 00025 #include <m_string.h> 00026 #undef SAFEMALLOC // Speed things up 00027 #include <my_sys.h> 00028 #include "completion_hash.h" 00029 00030 uint hashpjw(const char *arKey, uint nKeyLength) 00031 { 00032 uint h = 0, g, i; 00033 00034 for (i = 0; i < nKeyLength; i++) { 00035 h = (h << 4) + arKey[i]; 00036 if ((g = (h & 0xF0000000))) { 00037 h = h ^ (g >> 24); 00038 h = h ^ g; 00039 } 00040 } 00041 return h; 00042 } 00043 00044 int completion_hash_init(HashTable *ht, uint nSize) 00045 { 00046 ht->arBuckets = (Bucket **) my_malloc(nSize* sizeof(Bucket *), 00047 MYF(MY_ZEROFILL | MY_WME)); 00048 00049 if (!ht->arBuckets) 00050 { 00051 ht->initialized = 0; 00052 return FAILURE; 00053 } 00054 init_alloc_root(&ht->mem_root, 8192, 0); 00055 ht->pHashFunction = hashpjw; 00056 ht->nTableSize = nSize; 00057 ht->initialized = 1; 00058 return SUCCESS; 00059 } 00060 00061 00062 int completion_hash_update(HashTable *ht, char *arKey, uint nKeyLength, 00063 char *str) 00064 { 00065 uint h, nIndex; 00066 00067 Bucket *p; 00068 00069 h = ht->pHashFunction(arKey, nKeyLength); 00070 nIndex = h % ht->nTableSize; 00071 00072 if (nKeyLength <= 0) { 00073 return FAILURE; 00074 } 00075 p = ht->arBuckets[nIndex]; 00076 while (p) 00077 { 00078 if ((p->h == h) && (p->nKeyLength == nKeyLength)) { 00079 if (!memcmp(p->arKey, arKey, nKeyLength)) { 00080 entry *n; 00081 00082 if (!(n = (entry *) alloc_root(&ht->mem_root,sizeof(entry)))) 00083 return FAILURE; 00084 n->pNext = p->pData; 00085 n->str = str; 00086 p->pData = n; 00087 p->count++; 00088 00089 return SUCCESS; 00090 } 00091 } 00092 p = p->pNext; 00093 } 00094 00095 if (!(p = (Bucket *) alloc_root(&ht->mem_root, sizeof(Bucket)))) 00096 return FAILURE; 00097 00098 p->arKey = arKey; 00099 p->nKeyLength = nKeyLength; 00100 p->h = h; 00101 00102 if (!(p->pData = (entry*) alloc_root(&ht->mem_root, sizeof(entry)))) 00103 return FAILURE; 00104 00105 p->pData->str = str; 00106 p->pData->pNext = 0; 00107 p->count = 1; 00108 00109 p->pNext = ht->arBuckets[nIndex]; 00110 ht->arBuckets[nIndex] = p; 00111 00112 return SUCCESS; 00113 } 00114 00115 static Bucket *completion_hash_find(HashTable *ht, const char *arKey, 00116 uint nKeyLength) 00117 { 00118 uint h, nIndex; 00119 Bucket *p; 00120 00121 h = ht->pHashFunction(arKey, nKeyLength); 00122 nIndex = h % ht->nTableSize; 00123 00124 p = ht->arBuckets[nIndex]; 00125 while (p) 00126 { 00127 if ((p->h == h) && (p->nKeyLength == nKeyLength)) { 00128 if (!memcmp(p->arKey, arKey, nKeyLength)) { 00129 return p; 00130 } 00131 } 00132 p = p->pNext; 00133 } 00134 return (Bucket*) 0; 00135 } 00136 00137 00138 int completion_hash_exists(HashTable *ht, char *arKey, uint nKeyLength) 00139 { 00140 uint h, nIndex; 00141 Bucket *p; 00142 00143 h = ht->pHashFunction(arKey, nKeyLength); 00144 nIndex = h % ht->nTableSize; 00145 00146 p = ht->arBuckets[nIndex]; 00147 while (p) 00148 { 00149 if ((p->h == h) && (p->nKeyLength == nKeyLength)) 00150 { 00151 if (!strcmp(p->arKey, arKey)) { 00152 return 1; 00153 } 00154 } 00155 p = p->pNext; 00156 } 00157 return 0; 00158 } 00159 00160 Bucket *find_all_matches(HashTable *ht, const char *str, uint length, 00161 uint *res_length) 00162 { 00163 Bucket *b; 00164 00165 b = completion_hash_find(ht,str,length); 00166 if (!b) { 00167 *res_length = 0; 00168 return (Bucket*) 0; 00169 } else { 00170 *res_length = length; 00171 return b; 00172 } 00173 } 00174 00175 Bucket *find_longest_match(HashTable *ht, char *str, uint length, 00176 uint *res_length) 00177 { 00178 Bucket *b,*return_b; 00179 char *s; 00180 uint count; 00181 uint lm; 00182 00183 b = completion_hash_find(ht,str,length); 00184 if (!b) { 00185 *res_length = 0; 00186 return (Bucket*) 0; 00187 } 00188 00189 count = b->count; 00190 lm = length; 00191 s = b->pData->str; 00192 00193 return_b = b; 00194 while (s[lm]!=0 && (b=completion_hash_find(ht,s,lm+1))) { 00195 if (b->count<count) { 00196 *res_length=lm; 00197 return return_b; 00198 } 00199 return_b=b; 00200 lm++; 00201 } 00202 *res_length=lm; 00203 return return_b; 00204 } 00205 00206 00207 void completion_hash_clean(HashTable *ht) 00208 { 00209 free_root(&ht->mem_root,MYF(0)); 00210 bzero((char*) ht->arBuckets,ht->nTableSize*sizeof(Bucket *)); 00211 } 00212 00213 00214 void completion_hash_free(HashTable *ht) 00215 { 00216 completion_hash_clean(ht); 00217 my_free((gptr) ht->arBuckets,MYF(0)); 00218 } 00219 00220 00221 void add_word(HashTable *ht,char *str) 00222 { 00223 int i; 00224 char *pos=str; 00225 for (i=1; *pos; i++, pos++) 00226 completion_hash_update(ht, str, i, str); 00227 }
1.4.7

