~drizzle-trunk/drizzle/development

1 by brian
clean slate
1
/* Copyright (C) 2000 MySQL AB
2
3
   This program is free software; you can redistribute it and/or modify
4
   it under the terms of the GNU General Public License as published by
5
   the Free Software Foundation; version 2 of the License.
6
7
   This program is distributed in the hope that it will be useful,
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
   GNU General Public License for more details.
11
12
   You should have received a copy of the GNU General Public License
13
   along with this program; if not, write to the Free Software
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
16
/* Quick & light hash implementation for tab completion purposes
17
 *
18
 * by  Andi Gutmans <andi@zend.com>
19
 * and Zeev Suraski <zeev@zend.com>
477 by Monty Taylor
Removed my_free(). It turns out that it had been def'd to ignore the flags passed to it in the second arg anyway. Gotta love that.
20
 * Small portability changes by Monty.
1 by brian
clean slate
21
 */
22
212.5.39 by Monty Taylor
Phew. Moved my_base and my_global.
23
#include "client_priv.h"
212.5.18 by Monty Taylor
Moved m_ctype, m_string and my_bitmap. Removed t_ctype.
24
#include <mystrings/m_string.h>
1 by brian
clean slate
25
#include "completion_hash.h"
26
893 by Brian Aker
First pass of stripping uint
27
uint32_t hashpjw(const char *arKey, uint32_t nKeyLength)
1 by brian
clean slate
28
{
893 by Brian Aker
First pass of stripping uint
29
  uint32_t h = 0, g, i;
1 by brian
clean slate
30
31
  for (i = 0; i < nKeyLength; i++) {
32
    h = (h << 4) + arKey[i];
33
    if ((g = (h & 0xF0000000))) {
34
      h = h ^ (g >> 24);
35
      h = h ^ g;
36
    }
37
  }
38
  return h;
39
}
40
893 by Brian Aker
First pass of stripping uint
41
int completion_hash_init(HashTable *ht, uint32_t nSize)
1 by brian
clean slate
42
{
477 by Monty Taylor
Removed my_free(). It turns out that it had been def'd to ignore the flags passed to it in the second arg anyway. Gotta love that.
43
  ht->arBuckets = (Bucket **) malloc(nSize* sizeof(Bucket *));
44
  memset(ht->arBuckets, 0, nSize* sizeof(Bucket *));
1 by brian
clean slate
45
46
  if (!ht->arBuckets)
47
  {
48
    ht->initialized = 0;
49
    return FAILURE;
50
  }
51
  init_alloc_root(&ht->mem_root, 8192, 0);
52
  ht->pHashFunction = hashpjw;
53
  ht->nTableSize = nSize;
54
  ht->initialized = 1;
55
  return SUCCESS;
56
}
57
58
893 by Brian Aker
First pass of stripping uint
59
int completion_hash_update(HashTable *ht, char *arKey, uint32_t nKeyLength,
1 by brian
clean slate
60
			   char *str)
61
{
893 by Brian Aker
First pass of stripping uint
62
  uint32_t h, nIndex;
1 by brian
clean slate
63
64
  Bucket *p;
65
66
  h = ht->pHashFunction(arKey, nKeyLength);
67
  nIndex = h % ht->nTableSize;
68
69
  if (nKeyLength <= 0) {
70
    return FAILURE;
71
  }
72
  p = ht->arBuckets[nIndex];
73
  while (p)
74
  {
75
    if ((p->h == h) && (p->nKeyLength == nKeyLength)) {
76
      if (!memcmp(p->arKey, arKey, nKeyLength)) {
77
	entry *n;
78
79
	if (!(n = (entry *) alloc_root(&ht->mem_root,sizeof(entry))))
80
          return FAILURE;
81
	n->pNext = p->pData;
82
	n->str = str;
83
	p->pData = n;
84
	p->count++;
85
86
	return SUCCESS;
87
      }
88
    }
89
    p = p->pNext;
90
  }
91
92
  if (!(p = (Bucket *) alloc_root(&ht->mem_root, sizeof(Bucket))))
93
    return FAILURE;
94
95
  p->arKey = arKey;
96
  p->nKeyLength = nKeyLength;
97
  p->h = h;
98
99
  if (!(p->pData = (entry*) alloc_root(&ht->mem_root, sizeof(entry))))
100
    return FAILURE;
101
102
  p->pData->str = str;
103
  p->pData->pNext = 0;
104
  p->count = 1;
105
106
  p->pNext = ht->arBuckets[nIndex];
107
  ht->arBuckets[nIndex] = p;
108
109
  return SUCCESS;
110
}
111
112
static Bucket *completion_hash_find(HashTable *ht, const char *arKey,
893 by Brian Aker
First pass of stripping uint
113
				    uint32_t nKeyLength)
1 by brian
clean slate
114
{
893 by Brian Aker
First pass of stripping uint
115
  uint32_t h, nIndex;
1 by brian
clean slate
116
  Bucket *p;
117
118
  h = ht->pHashFunction(arKey, nKeyLength);
119
  nIndex = h % ht->nTableSize;
120
121
  p = ht->arBuckets[nIndex];
122
  while (p)
123
  {
124
    if ((p->h == h) && (p->nKeyLength == nKeyLength)) {
125
      if (!memcmp(p->arKey, arKey, nKeyLength)) {
126
	return p;
127
      }
128
    }
129
    p = p->pNext;
130
  }
131
  return (Bucket*) 0;
132
}
133
134
893 by Brian Aker
First pass of stripping uint
135
int completion_hash_exists(HashTable *ht, char *arKey, uint32_t nKeyLength)
1 by brian
clean slate
136
{
893 by Brian Aker
First pass of stripping uint
137
  uint32_t h, nIndex;
1 by brian
clean slate
138
  Bucket *p;
139
140
  h = ht->pHashFunction(arKey, nKeyLength);
141
  nIndex = h % ht->nTableSize;
142
143
  p = ht->arBuckets[nIndex];
144
  while (p)
145
  {
146
    if ((p->h == h) && (p->nKeyLength == nKeyLength))
147
    {
148
      if (!strcmp(p->arKey, arKey)) {
149
	return 1;
150
      }
151
    }
152
    p = p->pNext;
153
  }
154
  return 0;
155
}
156
893 by Brian Aker
First pass of stripping uint
157
Bucket *find_all_matches(HashTable *ht, const char *str, uint32_t length,
158
			 uint32_t *res_length)
1 by brian
clean slate
159
{
160
  Bucket *b;
161
162
  b = completion_hash_find(ht,str,length);
163
  if (!b) {
164
    *res_length = 0;
165
    return (Bucket*) 0;
166
  } else {
167
    *res_length = length;
168
    return b;
169
  }
170
}
171
893 by Brian Aker
First pass of stripping uint
172
Bucket *find_longest_match(HashTable *ht, char *str, uint32_t length,
173
			   uint32_t *res_length)
1 by brian
clean slate
174
{
175
  Bucket *b,*return_b;
176
  char *s;
893 by Brian Aker
First pass of stripping uint
177
  uint32_t count;
178
  uint32_t lm;
1 by brian
clean slate
179
180
  b = completion_hash_find(ht,str,length);
181
  if (!b) {
182
    *res_length = 0;
183
    return (Bucket*) 0;
184
  }
185
186
  count = b->count;
187
  lm = length;
188
  s = b->pData->str;
189
190
  return_b = b;
191
  while (s[lm]!=0 && (b=completion_hash_find(ht,s,lm+1))) {
192
    if (b->count<count) {
193
      *res_length=lm;
194
      return return_b;
195
    }
196
    return_b=b;
197
    lm++;
198
  }
199
  *res_length=lm;
200
  return return_b;
201
}
202
203
204
void completion_hash_clean(HashTable *ht)
205
{
206
  free_root(&ht->mem_root,MYF(0));
212.6.10 by Mats Kindahl
Removing redundant use of casts in client/ for memcmp(), memcpy(), memset(), and memmove().
207
  memset(ht->arBuckets, 0, ht->nTableSize*sizeof(Bucket *));
1 by brian
clean slate
208
}
209
210
211
void completion_hash_free(HashTable *ht)
212
{
213
  completion_hash_clean(ht);
477 by Monty Taylor
Removed my_free(). It turns out that it had been def'd to ignore the flags passed to it in the second arg anyway. Gotta love that.
214
  free(ht->arBuckets);
1 by brian
clean slate
215
}
216
217
218
void add_word(HashTable *ht,char *str)
219
{
220
  int i;
221
  char *pos=str;
222
  for (i=1; *pos; i++, pos++)
223
    completion_hash_update(ht, str, i, str);
224
}