/src/MapServer/src/maphash.c
Line | Count | Source |
1 | | /****************************************************************************** |
2 | | * $Id$ |
3 | | * |
4 | | * Project: MapServer |
5 | | * Purpose: Implement hashTableObj class. |
6 | | * Author: Sean Gillies, sgillies@frii.com |
7 | | * |
8 | | ****************************************************************************** |
9 | | * Copyright (c) 1996-2005 Regents of the University of Minnesota. |
10 | | * |
11 | | * Permission is hereby granted, free of charge, to any person obtaining a |
12 | | * copy of this software and associated documentation files (the "Software"), |
13 | | * to deal in the Software without restriction, including without limitation |
14 | | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
15 | | * and/or sell copies of the Software, and to permit persons to whom the |
16 | | * Software is furnished to do so, subject to the following conditions: |
17 | | * |
18 | | * The above copyright notice and this permission notice shall be included in |
19 | | * all copies of this Software or works derived from this Software. |
20 | | * |
21 | | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
22 | | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
23 | | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
24 | | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
25 | | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
26 | | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
27 | | * DEALINGS IN THE SOFTWARE. |
28 | | ****************************************************************************/ |
29 | | |
30 | | #include <ctype.h> |
31 | | |
32 | | #include "mapserver.h" |
33 | | #include "maphash.h" |
34 | | |
35 | 30.5k | static unsigned hash(const char *key) { |
36 | 30.5k | unsigned hashval; |
37 | | |
38 | 357k | for (hashval = 0; *key != '\0'; key++) |
39 | 326k | hashval = tolower(*key) + 31 * hashval; |
40 | | |
41 | 30.5k | return (hashval % MS_HASHSIZE); |
42 | 30.5k | } |
43 | | |
44 | 0 | hashTableObj *msCreateHashTable() { |
45 | 0 | int i; |
46 | 0 | hashTableObj *table; |
47 | |
|
48 | 0 | table = (hashTableObj *)msSmallMalloc(sizeof(hashTableObj)); |
49 | 0 | table->items = |
50 | 0 | (struct hashObj **)msSmallMalloc(sizeof(struct hashObj *) * MS_HASHSIZE); |
51 | |
|
52 | 0 | for (i = 0; i < MS_HASHSIZE; i++) |
53 | 0 | table->items[i] = NULL; |
54 | 0 | table->numitems = 0; |
55 | |
|
56 | 0 | return table; |
57 | 0 | } |
58 | | |
59 | 8.17k | int initHashTable(hashTableObj *table) { |
60 | 8.17k | int i; |
61 | | |
62 | 8.17k | table->items = |
63 | 8.17k | (struct hashObj **)malloc(sizeof(struct hashObj *) * MS_HASHSIZE); |
64 | 8.17k | MS_CHECK_ALLOC(table->items, sizeof(struct hashObj *) * MS_HASHSIZE, |
65 | 8.17k | MS_FAILURE); |
66 | | |
67 | 343k | for (i = 0; i < MS_HASHSIZE; i++) |
68 | 335k | table->items[i] = NULL; |
69 | 8.17k | table->numitems = 0; |
70 | 8.17k | return MS_SUCCESS; |
71 | 8.17k | } |
72 | | |
73 | 0 | void msFreeHashTable(hashTableObj *table) { |
74 | 0 | if (table != NULL) { |
75 | 0 | msFreeHashItems(table); |
76 | 0 | free(table); |
77 | 0 | } |
78 | 0 | } |
79 | | |
80 | 0 | int msHashIsEmpty(const hashTableObj *table) { |
81 | 0 | if (table->numitems == 0) |
82 | 0 | return MS_TRUE; |
83 | 0 | else |
84 | 0 | return MS_FALSE; |
85 | 0 | } |
86 | | |
87 | 8.17k | void msFreeHashItems(hashTableObj *table) { |
88 | 8.17k | int i; |
89 | 8.17k | struct hashObj *tp = NULL; |
90 | 8.17k | struct hashObj *prev_tp = NULL; |
91 | | |
92 | 8.17k | if (table) { |
93 | 8.17k | if (table->items) { |
94 | 343k | for (i = 0; i < MS_HASHSIZE; i++) { |
95 | 335k | if (table->items[i] != NULL) { |
96 | 13.1k | for (tp = table->items[i]; tp != NULL; |
97 | 7.34k | prev_tp = tp, tp = tp->next, free(prev_tp)) { |
98 | 7.34k | msFree(tp->key); |
99 | 7.34k | msFree(tp->data); |
100 | 7.34k | } |
101 | 5.82k | } |
102 | 335k | } |
103 | 8.17k | free(table->items); |
104 | 8.17k | table->items = NULL; |
105 | 8.17k | } else { |
106 | 0 | msSetError(MS_HASHERR, "No items allocated.", "msFreeHashItems()"); |
107 | 0 | } |
108 | 8.17k | } else { |
109 | 0 | msSetError(MS_HASHERR, "Can't free NULL table", "msFreeHashItems()"); |
110 | 0 | } |
111 | 8.17k | } |
112 | | |
113 | | struct hashObj *msInsertHashTable(hashTableObj *table, const char *key, |
114 | 9.86k | const char *value) { |
115 | 9.86k | struct hashObj *tp; |
116 | 9.86k | unsigned hashval; |
117 | | |
118 | 9.86k | if (!table || !key || !value) { |
119 | 0 | msSetError(MS_HASHERR, "Invalid hash table or key", "msInsertHashTable"); |
120 | 0 | return NULL; |
121 | 0 | } |
122 | | |
123 | 13.5k | for (tp = table->items[hash(key)]; tp != NULL; tp = tp->next) |
124 | 6.23k | if (strcasecmp(key, tp->key) == 0) |
125 | 2.52k | break; |
126 | | |
127 | 9.86k | if (tp == NULL) { /* not found */ |
128 | 7.34k | tp = (struct hashObj *)malloc(sizeof(*tp)); |
129 | 7.34k | MS_CHECK_ALLOC(tp, sizeof(*tp), NULL); |
130 | 7.34k | tp->key = msStrdup(key); |
131 | 7.34k | hashval = hash(key); |
132 | 7.34k | tp->next = table->items[hashval]; |
133 | 7.34k | table->items[hashval] = tp; |
134 | 7.34k | table->numitems++; |
135 | 7.34k | } else { |
136 | 2.52k | free(tp->data); |
137 | 2.52k | } |
138 | | |
139 | 9.86k | if ((tp->data = msStrdup(value)) == NULL) |
140 | 0 | return NULL; |
141 | | |
142 | 9.86k | return tp; |
143 | 9.86k | } |
144 | | |
145 | 6.69k | const char *msLookupHashTable(const hashTableObj *table, const char *key) { |
146 | 6.69k | struct hashObj *tp; |
147 | | |
148 | 6.69k | if (!table || !key) { |
149 | 0 | return (NULL); |
150 | 0 | } |
151 | | |
152 | 8.96k | for (tp = table->items[hash(key)]; tp != NULL; tp = tp->next) |
153 | 8.96k | if (strcasecmp(key, tp->key) == 0) |
154 | 6.69k | return (tp->data); |
155 | | |
156 | 0 | return NULL; |
157 | 6.69k | } |
158 | | |
159 | 0 | int msRemoveHashTable(hashTableObj *table, const char *key) { |
160 | 0 | struct hashObj *tp; |
161 | 0 | struct hashObj *prev_tp = NULL; |
162 | 0 | int status = MS_FAILURE; |
163 | |
|
164 | 0 | if (!table || !key) { |
165 | 0 | msSetError(MS_HASHERR, "No hash table", "msRemoveHashTable"); |
166 | 0 | return MS_FAILURE; |
167 | 0 | } |
168 | | |
169 | 0 | tp = table->items[hash(key)]; |
170 | 0 | if (!tp) { |
171 | 0 | msSetError(MS_HASHERR, "No such hash entry", "msRemoveHashTable"); |
172 | 0 | return MS_FAILURE; |
173 | 0 | } |
174 | | |
175 | 0 | prev_tp = NULL; |
176 | 0 | while (tp != NULL) { |
177 | 0 | if (strcasecmp(key, tp->key) == 0) { |
178 | 0 | status = MS_SUCCESS; |
179 | 0 | if (prev_tp) { |
180 | 0 | prev_tp->next = tp->next; |
181 | 0 | msFree(tp->key); |
182 | 0 | msFree(tp->data); |
183 | 0 | free(tp); |
184 | 0 | break; |
185 | 0 | } else { |
186 | 0 | table->items[hash(key)] = tp->next; |
187 | 0 | msFree(tp->key); |
188 | 0 | msFree(tp->data); |
189 | 0 | free(tp); |
190 | 0 | break; |
191 | 0 | } |
192 | 0 | } |
193 | 0 | prev_tp = tp; |
194 | 0 | tp = tp->next; |
195 | 0 | } |
196 | |
|
197 | 0 | if (status == MS_SUCCESS) |
198 | 0 | table->numitems--; |
199 | |
|
200 | 0 | return status; |
201 | 0 | } |
202 | | |
203 | 2.22k | const char *msFirstKeyFromHashTable(const hashTableObj *table) { |
204 | 2.22k | int hash_index; |
205 | | |
206 | 2.22k | if (!table) { |
207 | 0 | msSetError(MS_HASHERR, "No hash table", "msFirstKeyFromHashTable"); |
208 | 0 | return NULL; |
209 | 0 | } |
210 | | |
211 | 32.2k | for (hash_index = 0; hash_index < MS_HASHSIZE; hash_index++) { |
212 | 32.2k | if (table->items[hash_index] != NULL) |
213 | 2.21k | return table->items[hash_index]->key; |
214 | 32.2k | } |
215 | | |
216 | 7 | return NULL; |
217 | 2.22k | } |
218 | | |
219 | | const char *msNextKeyFromHashTable(const hashTableObj *table, |
220 | 6.69k | const char *lastKey) { |
221 | 6.69k | int hash_index; |
222 | 6.69k | struct hashObj *link; |
223 | | |
224 | 6.69k | if (!table) { |
225 | 0 | msSetError(MS_HASHERR, "No hash table", "msNextKeyFromHashTable"); |
226 | 0 | return NULL; |
227 | 0 | } |
228 | | |
229 | 6.69k | if (lastKey == NULL) |
230 | 0 | return msFirstKeyFromHashTable(table); |
231 | | |
232 | 6.69k | hash_index = hash(lastKey); |
233 | 6.69k | for (link = table->items[hash_index]; |
234 | 8.96k | link != NULL && strcasecmp(lastKey, link->key) != 0; link = link->next) { |
235 | 2.26k | } |
236 | | |
237 | 6.69k | if (link != NULL && link->next != NULL) |
238 | 1.29k | return link->next->key; |
239 | | |
240 | 61.0k | while (++hash_index < MS_HASHSIZE) { |
241 | 58.8k | if (table->items[hash_index] != NULL) |
242 | 3.18k | return table->items[hash_index]->key; |
243 | 58.8k | } |
244 | | |
245 | 2.21k | return NULL; |
246 | 5.39k | } |