sdsykes-ferret 0.11.6.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (195) hide show
  1. data/CHANGELOG +24 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README +102 -0
  4. data/Rakefile +338 -0
  5. data/TODO +17 -0
  6. data/TUTORIAL +231 -0
  7. data/bin/ferret-browser +79 -0
  8. data/ext/analysis.c +1555 -0
  9. data/ext/analysis.h +219 -0
  10. data/ext/api.c +69 -0
  11. data/ext/api.h +27 -0
  12. data/ext/array.c +123 -0
  13. data/ext/array.h +53 -0
  14. data/ext/bitvector.c +540 -0
  15. data/ext/bitvector.h +272 -0
  16. data/ext/compound_io.c +383 -0
  17. data/ext/config.h +42 -0
  18. data/ext/document.c +156 -0
  19. data/ext/document.h +53 -0
  20. data/ext/except.c +120 -0
  21. data/ext/except.h +168 -0
  22. data/ext/extconf.rb +14 -0
  23. data/ext/ferret.c +402 -0
  24. data/ext/ferret.h +91 -0
  25. data/ext/filter.c +156 -0
  26. data/ext/fs_store.c +483 -0
  27. data/ext/global.c +418 -0
  28. data/ext/global.h +117 -0
  29. data/ext/hash.c +567 -0
  30. data/ext/hash.h +473 -0
  31. data/ext/hashset.c +170 -0
  32. data/ext/hashset.h +187 -0
  33. data/ext/header.h +58 -0
  34. data/ext/helper.c +62 -0
  35. data/ext/helper.h +13 -0
  36. data/ext/inc/lang.h +48 -0
  37. data/ext/inc/threading.h +31 -0
  38. data/ext/index.c +6425 -0
  39. data/ext/index.h +961 -0
  40. data/ext/lang.h +66 -0
  41. data/ext/libstemmer.c +92 -0
  42. data/ext/libstemmer.h +79 -0
  43. data/ext/mempool.c +87 -0
  44. data/ext/mempool.h +35 -0
  45. data/ext/modules.h +162 -0
  46. data/ext/multimapper.c +310 -0
  47. data/ext/multimapper.h +51 -0
  48. data/ext/posh.c +1006 -0
  49. data/ext/posh.h +1007 -0
  50. data/ext/priorityqueue.c +151 -0
  51. data/ext/priorityqueue.h +143 -0
  52. data/ext/q_boolean.c +1608 -0
  53. data/ext/q_const_score.c +161 -0
  54. data/ext/q_filtered_query.c +209 -0
  55. data/ext/q_fuzzy.c +268 -0
  56. data/ext/q_match_all.c +148 -0
  57. data/ext/q_multi_term.c +677 -0
  58. data/ext/q_parser.c +2825 -0
  59. data/ext/q_phrase.c +1126 -0
  60. data/ext/q_prefix.c +100 -0
  61. data/ext/q_range.c +350 -0
  62. data/ext/q_span.c +2402 -0
  63. data/ext/q_term.c +337 -0
  64. data/ext/q_wildcard.c +171 -0
  65. data/ext/r_analysis.c +2575 -0
  66. data/ext/r_index.c +3472 -0
  67. data/ext/r_qparser.c +585 -0
  68. data/ext/r_search.c +4105 -0
  69. data/ext/r_store.c +513 -0
  70. data/ext/r_utils.c +963 -0
  71. data/ext/ram_store.c +471 -0
  72. data/ext/search.c +1741 -0
  73. data/ext/search.h +885 -0
  74. data/ext/similarity.c +150 -0
  75. data/ext/similarity.h +82 -0
  76. data/ext/sort.c +983 -0
  77. data/ext/stem_ISO_8859_1_danish.c +338 -0
  78. data/ext/stem_ISO_8859_1_danish.h +16 -0
  79. data/ext/stem_ISO_8859_1_dutch.c +635 -0
  80. data/ext/stem_ISO_8859_1_dutch.h +16 -0
  81. data/ext/stem_ISO_8859_1_english.c +1156 -0
  82. data/ext/stem_ISO_8859_1_english.h +16 -0
  83. data/ext/stem_ISO_8859_1_finnish.c +792 -0
  84. data/ext/stem_ISO_8859_1_finnish.h +16 -0
  85. data/ext/stem_ISO_8859_1_french.c +1276 -0
  86. data/ext/stem_ISO_8859_1_french.h +16 -0
  87. data/ext/stem_ISO_8859_1_german.c +512 -0
  88. data/ext/stem_ISO_8859_1_german.h +16 -0
  89. data/ext/stem_ISO_8859_1_italian.c +1091 -0
  90. data/ext/stem_ISO_8859_1_italian.h +16 -0
  91. data/ext/stem_ISO_8859_1_norwegian.c +296 -0
  92. data/ext/stem_ISO_8859_1_norwegian.h +16 -0
  93. data/ext/stem_ISO_8859_1_porter.c +776 -0
  94. data/ext/stem_ISO_8859_1_porter.h +16 -0
  95. data/ext/stem_ISO_8859_1_portuguese.c +1035 -0
  96. data/ext/stem_ISO_8859_1_portuguese.h +16 -0
  97. data/ext/stem_ISO_8859_1_spanish.c +1119 -0
  98. data/ext/stem_ISO_8859_1_spanish.h +16 -0
  99. data/ext/stem_ISO_8859_1_swedish.c +307 -0
  100. data/ext/stem_ISO_8859_1_swedish.h +16 -0
  101. data/ext/stem_KOI8_R_russian.c +701 -0
  102. data/ext/stem_KOI8_R_russian.h +16 -0
  103. data/ext/stem_UTF_8_danish.c +344 -0
  104. data/ext/stem_UTF_8_danish.h +16 -0
  105. data/ext/stem_UTF_8_dutch.c +653 -0
  106. data/ext/stem_UTF_8_dutch.h +16 -0
  107. data/ext/stem_UTF_8_english.c +1176 -0
  108. data/ext/stem_UTF_8_english.h +16 -0
  109. data/ext/stem_UTF_8_finnish.c +808 -0
  110. data/ext/stem_UTF_8_finnish.h +16 -0
  111. data/ext/stem_UTF_8_french.c +1296 -0
  112. data/ext/stem_UTF_8_french.h +16 -0
  113. data/ext/stem_UTF_8_german.c +526 -0
  114. data/ext/stem_UTF_8_german.h +16 -0
  115. data/ext/stem_UTF_8_italian.c +1113 -0
  116. data/ext/stem_UTF_8_italian.h +16 -0
  117. data/ext/stem_UTF_8_norwegian.c +302 -0
  118. data/ext/stem_UTF_8_norwegian.h +16 -0
  119. data/ext/stem_UTF_8_porter.c +794 -0
  120. data/ext/stem_UTF_8_porter.h +16 -0
  121. data/ext/stem_UTF_8_portuguese.c +1055 -0
  122. data/ext/stem_UTF_8_portuguese.h +16 -0
  123. data/ext/stem_UTF_8_russian.c +709 -0
  124. data/ext/stem_UTF_8_russian.h +16 -0
  125. data/ext/stem_UTF_8_spanish.c +1137 -0
  126. data/ext/stem_UTF_8_spanish.h +16 -0
  127. data/ext/stem_UTF_8_swedish.c +313 -0
  128. data/ext/stem_UTF_8_swedish.h +16 -0
  129. data/ext/stopwords.c +401 -0
  130. data/ext/store.c +692 -0
  131. data/ext/store.h +777 -0
  132. data/ext/term_vectors.c +352 -0
  133. data/ext/threading.h +31 -0
  134. data/ext/utilities.c +446 -0
  135. data/ext/win32.h +54 -0
  136. data/lib/ferret.rb +29 -0
  137. data/lib/ferret/browser.rb +246 -0
  138. data/lib/ferret/browser/s/global.js +192 -0
  139. data/lib/ferret/browser/s/style.css +148 -0
  140. data/lib/ferret/browser/views/document/list.rhtml +49 -0
  141. data/lib/ferret/browser/views/document/show.rhtml +27 -0
  142. data/lib/ferret/browser/views/error/index.rhtml +7 -0
  143. data/lib/ferret/browser/views/help/index.rhtml +8 -0
  144. data/lib/ferret/browser/views/home/index.rhtml +29 -0
  145. data/lib/ferret/browser/views/layout.rhtml +22 -0
  146. data/lib/ferret/browser/views/term-vector/index.rhtml +4 -0
  147. data/lib/ferret/browser/views/term/index.rhtml +199 -0
  148. data/lib/ferret/browser/views/term/termdocs.rhtml +1 -0
  149. data/lib/ferret/browser/webrick.rb +14 -0
  150. data/lib/ferret/document.rb +130 -0
  151. data/lib/ferret/field_infos.rb +44 -0
  152. data/lib/ferret/index.rb +786 -0
  153. data/lib/ferret/number_tools.rb +157 -0
  154. data/lib/ferret_version.rb +3 -0
  155. data/setup.rb +1555 -0
  156. data/test/test_all.rb +5 -0
  157. data/test/test_helper.rb +24 -0
  158. data/test/threading/number_to_spoken.rb +132 -0
  159. data/test/threading/thread_safety_index_test.rb +79 -0
  160. data/test/threading/thread_safety_read_write_test.rb +76 -0
  161. data/test/threading/thread_safety_test.rb +133 -0
  162. data/test/unit/analysis/tc_analyzer.rb +548 -0
  163. data/test/unit/analysis/tc_token_stream.rb +646 -0
  164. data/test/unit/index/tc_index.rb +762 -0
  165. data/test/unit/index/tc_index_reader.rb +699 -0
  166. data/test/unit/index/tc_index_writer.rb +437 -0
  167. data/test/unit/index/th_doc.rb +315 -0
  168. data/test/unit/largefile/tc_largefile.rb +46 -0
  169. data/test/unit/query_parser/tc_query_parser.rb +238 -0
  170. data/test/unit/search/tc_filter.rb +135 -0
  171. data/test/unit/search/tc_fuzzy_query.rb +147 -0
  172. data/test/unit/search/tc_index_searcher.rb +61 -0
  173. data/test/unit/search/tc_multi_searcher.rb +128 -0
  174. data/test/unit/search/tc_multiple_search_requests.rb +58 -0
  175. data/test/unit/search/tc_search_and_sort.rb +179 -0
  176. data/test/unit/search/tc_sort.rb +49 -0
  177. data/test/unit/search/tc_sort_field.rb +27 -0
  178. data/test/unit/search/tc_spans.rb +190 -0
  179. data/test/unit/search/tm_searcher.rb +384 -0
  180. data/test/unit/store/tc_fs_store.rb +77 -0
  181. data/test/unit/store/tc_ram_store.rb +35 -0
  182. data/test/unit/store/tm_store.rb +34 -0
  183. data/test/unit/store/tm_store_lock.rb +68 -0
  184. data/test/unit/tc_document.rb +81 -0
  185. data/test/unit/ts_analysis.rb +2 -0
  186. data/test/unit/ts_index.rb +2 -0
  187. data/test/unit/ts_largefile.rb +4 -0
  188. data/test/unit/ts_query_parser.rb +2 -0
  189. data/test/unit/ts_search.rb +2 -0
  190. data/test/unit/ts_store.rb +2 -0
  191. data/test/unit/ts_utils.rb +2 -0
  192. data/test/unit/utils/tc_bit_vector.rb +295 -0
  193. data/test/unit/utils/tc_number_tools.rb +117 -0
  194. data/test/unit/utils/tc_priority_queue.rb +106 -0
  195. metadata +285 -0
@@ -0,0 +1,567 @@
1
+ #include "hash.h"
2
+ #include "global.h"
3
+ #include <string.h>
4
+
5
+ /****************************************************************************
6
+ *
7
+ * HashTable
8
+ *
9
+ * This hash table is modeled after Python's dictobject and a description of
10
+ * the algorithm can be found in the file dictobject.c in Python's src
11
+ ****************************************************************************/
12
+
13
+ static char *dummy_key = "";
14
+
15
+ #define PERTURB_SHIFT 5
16
+ #define MAX_FREE_HASH_TABLES 80
17
+
18
+ static HashTable *free_hts[MAX_FREE_HASH_TABLES];
19
+ static int num_free_hts = 0;
20
+
21
+ unsigned long str_hash(const char *const str)
22
+ {
23
+ register unsigned long h = 0;
24
+ register unsigned char *p = (unsigned char *) str;
25
+
26
+ for (; *p; p++) {
27
+ h = 37 * h + *p;
28
+ }
29
+
30
+ return h;
31
+ }
32
+
33
+ unsigned long ptr_hash(const void *const ptr)
34
+ {
35
+ return (unsigned long)ptr;
36
+ }
37
+
38
+ int ptr_eq(const void *q1, const void *q2)
39
+ {
40
+ return q1 == q2;
41
+ }
42
+
43
+ static int int_eq(const void *q1, const void *q2)
44
+ {
45
+ (void)q1;
46
+ (void)q2;
47
+ return true;
48
+ }
49
+
50
+ static unsigned long int_hash(const void *i)
51
+ {
52
+ return *((unsigned long *)i);
53
+ }
54
+
55
+ typedef HashEntry *(*lookup_ft)(struct HashTable *ht, register const void *key);
56
+
57
+ /**
58
+ * Fast lookup function for resizing as we know there are no equal elements or
59
+ * deletes to worry about.
60
+ *
61
+ * @param ht the HashTable to do the fast lookup in
62
+ * @param the hashkey we are looking for
63
+ */
64
+ static INLINE HashEntry *h_resize_lookup(HashTable *ht,
65
+ register const unsigned long hash)
66
+ {
67
+ register unsigned long perturb;
68
+ register int mask = ht->mask;
69
+ register HashEntry *he0 = ht->table;
70
+ register int i = hash & mask;
71
+ register HashEntry *he = &he0[i];
72
+
73
+ if (he->key == NULL) {
74
+ he->hash = hash;
75
+ return he;
76
+ }
77
+
78
+ for (perturb = hash;; perturb >>= PERTURB_SHIFT) {
79
+ i = (i << 2) + i + perturb + 1;
80
+ he = &he0[i & mask];
81
+ if (he->key == NULL) {
82
+ he->hash = hash;
83
+ return he;
84
+ }
85
+ }
86
+ }
87
+
88
+ HashEntry *h_lookup_int(HashTable *ht, const void *key)
89
+ {
90
+ register unsigned long hash = *((int *)key);
91
+ register unsigned long perturb;
92
+ register int mask = ht->mask;
93
+ register HashEntry *he0 = ht->table;
94
+ register int i = hash & mask;
95
+ register HashEntry *he = &he0[i];
96
+ register HashEntry *freeslot = NULL;
97
+
98
+ if (he->key == NULL || he->hash == hash) {
99
+ he->hash = hash;
100
+ return he;
101
+ }
102
+ if (he->key == dummy_key) {
103
+ freeslot = he;
104
+ }
105
+
106
+ for (perturb = hash;; perturb >>= PERTURB_SHIFT) {
107
+ i = (i << 2) + i + perturb + 1;
108
+ he = &he0[i & mask];
109
+ if (he->key == NULL) {
110
+ if (freeslot != NULL) {
111
+ he = freeslot;
112
+ }
113
+ he->hash = hash;
114
+ return he;
115
+ }
116
+ if (he->hash == hash) {
117
+ return he;
118
+ }
119
+ if (he->key == dummy_key && freeslot == NULL) {
120
+ freeslot = he;
121
+ }
122
+ }
123
+ }
124
+
125
+ HashEntry *h_lookup_str(HashTable *ht, register const char *key)
126
+ {
127
+ register unsigned long hash = str_hash(key);
128
+ register unsigned long perturb;
129
+ register int mask = ht->mask;
130
+ register HashEntry *he0 = ht->table;
131
+ register int i = hash & mask;
132
+ register HashEntry *he = &he0[i];
133
+ register HashEntry *freeslot;
134
+
135
+ if (he->key == NULL || he->key == key) {
136
+ he->hash = hash;
137
+ return he;
138
+ }
139
+ if (he->key == dummy_key) {
140
+ freeslot = he;
141
+ }
142
+ else {
143
+ if ((he->hash == hash) && (strcmp(he->key, key) == 0)) {
144
+ return he;
145
+ }
146
+ freeslot = NULL;
147
+ }
148
+
149
+ for (perturb = hash;; perturb >>= PERTURB_SHIFT) {
150
+ i = (i << 2) + i + perturb + 1;
151
+ he = &he0[i & mask];
152
+ if (he->key == NULL) {
153
+ if (freeslot != NULL) {
154
+ he = freeslot;
155
+ }
156
+ he->hash = hash;
157
+ return he;
158
+ }
159
+ if (he->key == key
160
+ || (he->hash == hash
161
+ && he->key != dummy_key && strcmp(he->key, key) == 0)) {
162
+ return he;
163
+ }
164
+ if (he->key == dummy_key && freeslot == NULL) {
165
+ freeslot = he;
166
+ }
167
+ }
168
+ }
169
+
170
+ HashEntry *h_lookup(HashTable *ht, register const void *key)
171
+ {
172
+ register unsigned int hash = ht->hash_i(key);
173
+ register unsigned int perturb;
174
+ register int mask = ht->mask;
175
+ register HashEntry *he0 = ht->table;
176
+ register int i = hash & mask;
177
+ register HashEntry *he = &he0[i];
178
+ register HashEntry *freeslot;
179
+ eq_ft eq = ht->eq_i;
180
+
181
+ if (he->key == NULL || he->key == key) {
182
+ he->hash = hash;
183
+ return he;
184
+ }
185
+ if (he->key == dummy_key) {
186
+ freeslot = he;
187
+ }
188
+ else {
189
+ if ((he->hash == hash) && eq(he->key, key)) {
190
+ return he;
191
+ }
192
+ freeslot = NULL;
193
+ }
194
+
195
+ for (perturb = hash;; perturb >>= PERTURB_SHIFT) {
196
+ i = (i << 2) + i + perturb + 1;
197
+ he = &he0[i & mask];
198
+ if (he->key == NULL) {
199
+ if (freeslot != NULL) {
200
+ he = freeslot;
201
+ }
202
+ he->hash = hash;
203
+ return he;
204
+ }
205
+ if (he->key == key
206
+ || (he->hash == hash
207
+ && he->key != dummy_key && eq(he->key, key))) {
208
+ return he;
209
+ }
210
+ if (he->key == dummy_key && freeslot == NULL) {
211
+ freeslot = he;
212
+ }
213
+ }
214
+ }
215
+
216
+ HashTable *h_new_str(free_ft free_key, free_ft free_value)
217
+ {
218
+ HashTable *ht;
219
+ if (num_free_hts > 0) {
220
+ ht = free_hts[--num_free_hts];
221
+ }
222
+ else {
223
+ ht = ALLOC(HashTable);
224
+ }
225
+ ht->fill = 0;
226
+ ht->size = 0;
227
+ ht->mask = HASH_MINSIZE - 1;
228
+ ht->table = ht->smalltable;
229
+ memset(ht->smalltable, 0, sizeof(ht->smalltable));
230
+ ht->lookup_i = (lookup_ft)&h_lookup_str;
231
+
232
+ ht->free_key_i = free_key != NULL ? free_key : &dummy_free;
233
+ ht->free_value_i = free_value != NULL ? free_value : &dummy_free;
234
+ ht->ref_cnt = 1;
235
+ return ht;
236
+ }
237
+
238
+ HashTable *h_new_int(free_ft free_value)
239
+ {
240
+ HashTable *ht = h_new_str(NULL, free_value);
241
+ ht->lookup_i = &h_lookup_int;
242
+ ht->eq_i = int_eq;
243
+ ht->hash_i = int_hash;
244
+ return ht;
245
+ }
246
+
247
+ HashTable *h_new(hash_ft hash, eq_ft eq, free_ft free_key, free_ft free_value)
248
+ {
249
+ HashTable *ht = h_new_str(free_key, free_value);
250
+
251
+ ht->lookup_i = &h_lookup;
252
+ ht->eq_i = eq;
253
+ ht->hash_i = hash;
254
+ return ht;
255
+ }
256
+
257
+ void h_clear(HashTable *ht)
258
+ {
259
+ int i;
260
+ HashEntry *he;
261
+ free_ft free_key = ht->free_key_i;
262
+ free_ft free_value = ht->free_value_i;
263
+
264
+ /* Clear all the hash values and keys as necessary */
265
+ if (free_key != dummy_free || free_value != dummy_free) {
266
+ for (i = 0; i <= ht->mask; i++) {
267
+ he = &ht->table[i];
268
+ if (he->key != NULL && he->key != dummy_key) {
269
+ free_value(he->value);
270
+ free_key(he->key);
271
+ }
272
+ he->key = NULL;
273
+ }
274
+ }
275
+ ZEROSET_N(ht->table, HashEntry, ht->mask + 1);
276
+ ht->size = 0;
277
+ ht->fill = 0;
278
+ }
279
+
280
+ void h_destroy(HashTable *ht)
281
+ {
282
+ if (--(ht->ref_cnt) <= 0) {
283
+ h_clear(ht);
284
+
285
+ /* if a new table was created, be sure to free it */
286
+ if (ht->table != ht->smalltable) {
287
+ free(ht->table);
288
+ }
289
+
290
+ #ifdef DEBUG
291
+ free(ht);
292
+ #else
293
+ if (num_free_hts < MAX_FREE_HASH_TABLES) {
294
+ free_hts[num_free_hts++] = ht;
295
+ }
296
+ else {
297
+ free(ht);
298
+ }
299
+ #endif
300
+ }
301
+ }
302
+
303
+ void *h_get(HashTable *ht, const void *key)
304
+ {
305
+ /* Note: lookup_i will never return NULL. */
306
+ return ht->lookup_i(ht, key)->value;
307
+ }
308
+
309
+ int h_del(HashTable *ht, const void *key)
310
+ {
311
+ HashEntry *he = ht->lookup_i(ht, key);
312
+
313
+ if (he->key != NULL && he->key != dummy_key) {
314
+ ht->free_key_i(he->key);
315
+ ht->free_value_i(he->value);
316
+ he->key = dummy_key;
317
+ he->value = NULL;
318
+ ht->size--;
319
+ return true;
320
+ }
321
+ else {
322
+ return false;
323
+ }
324
+ }
325
+
326
+ void *h_rem(HashTable *ht, const void *key, bool destroy_key)
327
+ {
328
+ void *val;
329
+ HashEntry *he = ht->lookup_i(ht, key);
330
+
331
+ if (he->key != NULL && he->key != dummy_key) {
332
+ if (destroy_key) {
333
+ ht->free_key_i(he->key);
334
+ }
335
+
336
+ he->key = dummy_key;
337
+ val = he->value;
338
+ he->value = NULL;
339
+ ht->size--;
340
+ return val;
341
+ }
342
+ else {
343
+ return NULL;
344
+ }
345
+ }
346
+
347
+ static int h_resize(HashTable *ht, int min_newsize)
348
+ {
349
+ HashEntry smallcopy[HASH_MINSIZE];
350
+ HashEntry *oldtable;
351
+ HashEntry *he_old, *he_new;
352
+ int newsize, num_active;
353
+
354
+ /* newsize will be a power of two */
355
+ for (newsize = HASH_MINSIZE; newsize < min_newsize; newsize <<= 1) {
356
+ }
357
+
358
+ oldtable = ht->table;
359
+ if (newsize == HASH_MINSIZE) {
360
+ if (ht->table == ht->smalltable) {
361
+ /* need to copy the d*(int *)ata out so we can rebuild the table into
362
+ * the same space */
363
+ memcpy(smallcopy, ht->smalltable, sizeof(smallcopy));
364
+ oldtable = smallcopy;
365
+ }
366
+ else {
367
+ ht->table = ht->smalltable;
368
+ }
369
+ }
370
+ else {
371
+ ht->table = ALLOC_N(HashEntry, newsize);
372
+ }
373
+ memset(ht->table, 0, sizeof(HashEntry) * newsize);
374
+ ht->fill = ht->size;
375
+ ht->mask = newsize - 1;
376
+
377
+ for (num_active = ht->size, he_old = oldtable; num_active > 0; he_old++) {
378
+ if (he_old->key && he_old->key != dummy_key) { /* active entry */
379
+ /*he_new = ht->lookup_i(ht, he_old->key); */
380
+ he_new = h_resize_lookup(ht, he_old->hash);
381
+ he_new->key = he_old->key;
382
+ he_new->value = he_old->value;
383
+ num_active--;
384
+ } /* else empty entry so nothing to do */
385
+ }
386
+ if (oldtable != smallcopy && oldtable != ht->smalltable) {
387
+ free(oldtable);
388
+ }
389
+ return 0;
390
+ }
391
+
392
+ int h_set(HashTable *ht, const void *key, void *value)
393
+ {
394
+ int ret_val = HASH_KEY_DOES_NOT_EXIST;
395
+ HashEntry *he = ht->lookup_i(ht, key);
396
+ if (he->key == NULL) {
397
+ if (ht->fill * 3 > ht->mask * 2) {
398
+ h_resize(ht, ht->size * ((ht->size > SLOW_DOWN) ? 4 : 2));
399
+ he = ht->lookup_i(ht, key);
400
+ }
401
+ ht->fill++;
402
+ ht->size++;
403
+ }
404
+ else if (he->key == dummy_key) {
405
+ ht->size++;
406
+ }
407
+ else if (he->key != key) {
408
+ ht->free_key_i(he->key);
409
+ if (he->value != value) {
410
+ ht->free_value_i(he->value);
411
+ }
412
+ ret_val = HASH_KEY_EQUAL;
413
+ }
414
+ else {
415
+ /* safety check. Only free old value if it isn't the new value */
416
+ if (he->value != value) {
417
+ ht->free_value_i(he->value);
418
+ }
419
+ ret_val = HASH_KEY_SAME;
420
+ }
421
+ he->key = (void *)key;
422
+ he->value = value;
423
+
424
+ /*
425
+ if ((ht->fill > fill) && (ht->fill * 3 > ht->mask * 2)) {
426
+ h_resize(ht, ht->size * ((ht->size > SLOW_DOWN) ? 4 : 2));
427
+ }
428
+ */
429
+ return ret_val;
430
+ }
431
+
432
+ HashEntry *h_set_ext(HashTable *ht, const void *key)
433
+ {
434
+ HashEntry *he = ht->lookup_i(ht, key);
435
+ if (he->key == NULL) {
436
+ if (ht->fill * 3 > ht->mask * 2) {
437
+ h_resize(ht, ht->size * ((ht->size > SLOW_DOWN) ? 4 : 2));
438
+ he = ht->lookup_i(ht, key);
439
+ }
440
+ ht->fill++;
441
+ ht->size++;
442
+ }
443
+ else if (he->key == dummy_key) {
444
+ ht->size++;
445
+ }
446
+
447
+ return he;
448
+ }
449
+
450
+ int h_set_safe(HashTable *ht, const void *key, void *value)
451
+ {
452
+ HashEntry *he = ht->lookup_i(ht, key);
453
+ int fill = ht->fill;
454
+ if (he->key == NULL) {
455
+ ht->fill++;
456
+ ht->size++;
457
+ }
458
+ else if (he->key == dummy_key) {
459
+ ht->size++;
460
+ }
461
+ else {
462
+ return false;
463
+ }
464
+ he->key = (void *)key;
465
+ he->value = value;
466
+
467
+ if ((ht->fill > fill) && (ht->fill * 3 > ht->mask * 2)) {
468
+ h_resize(ht, ht->size * ((ht->size > SLOW_DOWN) ? 4 : 2));
469
+ }
470
+ return true;
471
+ }
472
+
473
+ int h_has_key(HashTable *ht, const void *key)
474
+ {
475
+ HashEntry *he = ht->lookup_i(ht, key);
476
+ if (he->key == NULL || he->key == dummy_key) {
477
+ return HASH_KEY_DOES_NOT_EXIST;
478
+ }
479
+ else if (he->key == key) {
480
+ return HASH_KEY_SAME;
481
+ }
482
+ else {
483
+ return HASH_KEY_EQUAL;
484
+ }
485
+ }
486
+
487
+ void *h_get_int(HashTable *self, const unsigned long key)
488
+ {
489
+ return h_get(self, &key);
490
+ }
491
+
492
+ int h_del_int(HashTable *self, const unsigned long key)
493
+ {
494
+ return h_del(self, &key);
495
+ }
496
+
497
+ void *h_rem_int(HashTable *self, const unsigned long key)
498
+ {
499
+ return h_rem(self, &key, false);
500
+ }
501
+
502
+ int h_set_int(HashTable *self, const unsigned long key, void *value)
503
+ {
504
+ return h_set(self, &key, value);
505
+ }
506
+
507
+ int h_set_safe_int(HashTable *self, const unsigned long key, void *value)
508
+ {
509
+ return h_set_safe(self, &key, value);
510
+ }
511
+
512
+ int h_has_key_int(HashTable *self, const unsigned long key)
513
+ {
514
+ return h_has_key(self, &key);
515
+ }
516
+
517
+ void h_each(HashTable *ht,
518
+ void (*each_kv) (void *key, void *value, void *arg), void *arg)
519
+ {
520
+ HashEntry *he;
521
+ int i = ht->size;
522
+ for (he = ht->table; i > 0; he++) {
523
+ if (he->key && he->key != dummy_key) { /* active entry */
524
+ each_kv(he->key, he->value, arg);
525
+ i--;
526
+ }
527
+ }
528
+ }
529
+
530
+ HashTable *h_clone(HashTable *ht,
531
+ h_clone_func_t clone_key, h_clone_func_t clone_value)
532
+ {
533
+ void *key, *value;
534
+ HashEntry *he;
535
+ int i = ht->size;
536
+ HashTable *ht_clone;
537
+
538
+ if (ht->lookup_i == (lookup_ft)&h_lookup_str) {
539
+ ht_clone = h_new_str(ht->free_key_i, ht->free_value_i);
540
+ }
541
+ else {
542
+ ht_clone = h_new(ht->hash_i, ht->eq_i, ht->free_key_i, ht->free_value_i);
543
+ }
544
+
545
+ for (he = ht->table; i > 0; he++) {
546
+ if (he->key && he->key != dummy_key) { /* active entry */
547
+ key = clone_key ? clone_key(he->key) : he->key;
548
+ value = clone_value ? clone_value(he->value) : he->value;
549
+ h_set(ht_clone, key, value);
550
+ i--;
551
+ }
552
+ }
553
+ return ht_clone;
554
+ }
555
+
556
+ void h_str_print_keys(HashTable *ht)
557
+ {
558
+ HashEntry *he;
559
+ int i = ht->size;
560
+ printf("keys:\n");
561
+ for (he = ht->table; i > 0; he++) {
562
+ if (he->key && he->key != dummy_key) { /* active entry */
563
+ printf("\t%s\n", (char *)he->key);
564
+ i--;
565
+ }
566
+ }
567
+ }