~ubuntu-branches/ubuntu/wily/ruby-ferret/wily

« back to all changes in this revision

Viewing changes to ext/hash.h

  • Committer: Bazaar Package Importer
  • Author(s): Antonio Terceiro
  • Date: 2011-07-28 00:02:49 UTC
  • Revision ID: james.westby@ubuntu.com-20110728000249-v0443y69ftcpxwi6
Tags: upstream-0.11.6
ImportĀ upstreamĀ versionĀ 0.11.6

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#ifndef FRT_HASH_H
 
2
#define FRT_HASH_H
 
3
 
 
4
#include "global.h"
 
5
 
 
6
/****************************************************************************
 
7
 *
 
8
 * HashTable
 
9
 *
 
10
 ****************************************************************************/
 
11
 
 
12
#define HASH_MINSIZE 8
 
13
#define SLOW_DOWN 50000         /* stop increasing the hash table so quickly to
 
14
                                 * conserve memory */
 
15
 
 
16
/**
 
17
 * Return values for h_set
 
18
 */
 
19
enum HashSetValues
 
20
{
 
21
    HASH_KEY_DOES_NOT_EXIST = 0,
 
22
    HASH_KEY_EQUAL = 1,
 
23
    HASH_KEY_SAME = 2
 
24
};
 
25
 
 
26
/**
 
27
 * struct used internally to store values in the HashTable
 
28
 */
 
29
typedef struct
 
30
{
 
31
    unsigned long hash;
 
32
    void *key;
 
33
    void *value;
 
34
} HashEntry;
 
35
 
 
36
/**
 
37
 * As the hash table is filled and entries are deleted, Dummy HashEntries are
 
38
 * put in place. We therefor keep two counts. +size+ is the number active
 
39
 * elements and +fill+ is the number of active elements together with the
 
40
 * number of dummy elements. +fill+ is basically just kept around so that we
 
41
 * know when to resize. The HashTable is resized when more than two thirds of
 
42
 * the HashTable is Filled. 
 
43
 */
 
44
typedef struct HashTable
 
45
{
 
46
    int fill;                   /* num Active + num Dummy */
 
47
    int size;                   /* num Active ie, num keys set */
 
48
    int mask;                   /* capacity_of_table - 1 */
 
49
    int ref_cnt;
 
50
 
 
51
    /* table points to smalltable initially. If the table grows beyond 2/3 of
 
52
     * HASH_MINSIZE it will point to newly malloced memory as it grows. */
 
53
    HashEntry *table;
 
54
 
 
55
    /* When a HashTable is created it needs an initial table to start if off.
 
56
     * All HashTables will start with smalltable and then malloc a larger
 
57
     * table as the HashTable grows */
 
58
    HashEntry smalltable[HASH_MINSIZE];
 
59
 
 
60
    /* the following function pointers are used internally and should not be
 
61
     * used outside of the HashTable methods */
 
62
    HashEntry    *(*lookup_i)(struct HashTable *self, register const void *key);
 
63
    unsigned long (*hash_i)(const void *key);
 
64
    int           (*eq_i)(const void *key1, const void *key2);
 
65
    void          (*free_key_i)(void *p);
 
66
    void          (*free_value_i)(void *p);
 
67
} HashTable;
 
68
 
 
69
/**
 
70
 * Hashing function type used by HashTable. A function of this type must be
 
71
 * passed to create a new HashTable.
 
72
 *
 
73
 * @param key object to hash
 
74
 * @return an unsigned 32-bit integer hash value
 
75
 */
 
76
typedef unsigned long (*hash_ft)(const void *key);
 
77
 
 
78
/**
 
79
 * Equals function type used by HashTable. A function of this type must be
 
80
 * passed to create a new HashTable.
 
81
 */
 
82
typedef int (*eq_ft)(const void *key1, const void *key2);
 
83
 
 
84
/**
 
85
 * Determine a hash value for a string. The string must be null terminated
 
86
 *
 
87
 * @param str string to hash
 
88
 * @return an unsigned long integer hash value
 
89
 */
 
90
extern unsigned long str_hash(const char *const str);
 
91
 
 
92
/**
 
93
 * Determine a hash value for a pointer. Just cast the pointer to an unsigned
 
94
 * long.
 
95
 *
 
96
 * @param ptr pointer to hash
 
97
 * @return an unsigned long integer hash value
 
98
 */
 
99
extern unsigned long ptr_hash(const void *const ptr);
 
100
 
 
101
/**
 
102
 * Determine if two pointers point to the same point in memory.
 
103
 *
 
104
 * @param q1 first pointer
 
105
 * @param q2 second pointer
 
106
 * @return true if the pointers are equal
 
107
 */
 
108
extern int ptr_eq(const void *q1, const void *q2);
 
109
 
 
110
/**
 
111
 * Create a new HashTable that uses any type of object as it's key. The
 
112
 * HashTable will store all keys and values so if you want to destroy those
 
113
 * values when the HashTable is destroyed then you should pass free functions.
 
114
 * NULL will suffice otherwise.
 
115
 *
 
116
 * @param hash function to determine the hash value of a key in the HashTable
 
117
 * @param eq function to determine the equality of to keys in the HashTable
 
118
 * @param free_key function to free the key stored in the HashTable when an
 
119
 *    entry is deleted, replaced or when the HashTable is destroyed. If you
 
120
 *    pass NULL in place of this parameter the key will not be destroyed.
 
121
 * @param free_value function to free the value stored in the HashTable when
 
122
 *    an entry is deleted, replaced or when the HashTable is destroyed. If you
 
123
 *    pass NULL in place of this parameter the value will not be destroyed.
 
124
 * @return A newly allocated HashTable
 
125
 */
 
126
extern HashTable *h_new(hash_ft hash, eq_ft eq, free_ft free_key,
 
127
                        free_ft free_value);
 
128
 
 
129
/**
 
130
 * Create a new HashTable that uses null-terminated strings as it's keys. The
 
131
 * HashTable will store all keys and values so if you want to destroy those
 
132
 * values when the HashTable is destroyed then you should pass free functions.
 
133
 * NULL will suffice otherwise.
 
134
 *
 
135
 * @param free_key function to free the key stored in the HashTable when an
 
136
 *    entry is deleted, replaced or when the HashTable is destroyed. If you
 
137
 *    pass NULL in place of this parameter the key will not be destroyed.
 
138
 * @param free_value function to free the value stored in the HashTable when
 
139
 *    an entry is deleted, replaced or when the HashTable is destroyed. If you
 
140
 *    pass NULL in place of this parameter the value will not be destroyed.
 
141
 * @return A newly allocated HashTable
 
142
 */
 
143
extern HashTable *h_new_str(free_ft free_key, free_ft free_value);
 
144
 
 
145
/**
 
146
 * Create a new HashTable that uses integers as it's keys. The
 
147
 * HashTable will store all values so if you want to destroy those
 
148
 * values when the HashTable is destroyed then you should pass a free function.
 
149
 * NULL will suffice otherwise.
 
150
 *
 
151
 * @param free_value function to free the value stored in the HashTable when
 
152
 *    an entry is deleted, replaced or when the HashTable is destroyed. If you
 
153
 *    pass NULL in place of this parameter the value will not be destroyed.
 
154
 * @return A newly allocated HashTable
 
155
 */
 
156
extern HashTable *h_new_int(free_ft free_value);
 
157
 
 
158
/**
 
159
 * Destroy the HashTable. This function will also destroy all keys and values
 
160
 * in the HashTable depending on how the free_key and free_value were set.
 
161
 *
 
162
 * @param self the HashTable to destroy
 
163
 */
 
164
extern void h_destroy(HashTable *self);
 
165
 
 
166
/**
 
167
 * Clear the HashTable. This function will delete all keys and values from the
 
168
 * hash table, also destroying all keys and values in the HashTable depending
 
169
 * on how the free_key and free_value were set.
 
170
 *
 
171
 * @param self the HashTable to clear
 
172
 */
 
173
extern void h_clear(HashTable *self);
 
174
 
 
175
/**
 
176
 * Get the value in the HashTable referenced by the key +key+.
 
177
 *
 
178
 * @param self the HashTable to reference
 
179
 * @param key the key to lookup
 
180
 * @return the value referenced by the key +key+. If there is no value
 
181
 *   referenced by that key, NULL is returned.
 
182
 */
 
183
extern void *h_get(HashTable *self, const void *key);
 
184
 
 
185
/**
 
186
 * Delete the value in HashTable referenced by the key +key+. When the value
 
187
 * is deleted it is also destroyed along with the key depending on how
 
188
 * free_key and free_value where set when the HashTable was created. If you
 
189
 * don't want to destroy the value use h_rem. 
 
190
 *
 
191
 * This functions returns +true+ if the value was deleted successfully or
 
192
 * false if the key was not found.
 
193
 *
 
194
 * @see h_rem
 
195
 *
 
196
 * @param self the HashTable to reference
 
197
 * @param key the key to lookup
 
198
 * @return true if the object was successfully deleted or false if the key was
 
199
 *   not found
 
200
 */
 
201
extern int h_del(HashTable *self, const void *key);
 
202
 
 
203
/**
 
204
 * Remove the value in HashTable referenced by the key +key+. When the value
 
205
 * is removed it is returned rather than destroyed. The key however is
 
206
 * destroyed using the free_key functions passed when the HashTable is created
 
207
 * if del_key is true.
 
208
 *
 
209
 * If you want the value to be destroyed, use the h_del function.
 
210
 *
 
211
 * @see h_del
 
212
 *
 
213
 * @param self the HashTable to reference
 
214
 * @param key the key to lookup
 
215
 * @param del_key set to true if you want the key to be deleted when the value
 
216
 *   is removed from the HashTable
 
217
 * @return the value referenced by +key+ if it can be found or NULL otherwise
 
218
 */
 
219
extern void *h_rem(HashTable *self, const void *key, bool del_key);
 
220
 
 
221
/**
 
222
 * WARNING: this function may destroy an old value or key if the key already
 
223
 * exists in the HashTable, depending on how free_value and free_key were set
 
224
 * for this HashTable.
 
225
 *
 
226
 * Add the value +value+ to the HashTable referencing it with key +key+.
 
227
 *
 
228
 * When a value is added to the HashTable it replaces any value that
 
229
 * might already be stored under that key. If free_value is already set then
 
230
 * the old value will be freed using that function.
 
231
 *
 
232
 * Similarly the old key might replace be replaced by the new key if they are
 
233
 * are equal (according to the HashTable's eq function) but seperately
 
234
 * allocated objects.
 
235
 *
 
236
 * @param self the HashTable to add the value to
 
237
 * @param key the key to use to reference the value
 
238
 * @param value the value to add to the HashTable
 
239
 * @return one of three values;
 
240
 *   <pre>
 
241
 *     HASH_KEY_DOES_NOT_EXIST  there was no value stored with that key
 
242
 *     HASH_KEY_EQUAL           the key existed and was seperately allocated.
 
243
 *                              In this situation the old key will have been
 
244
 *                              destroyed if free_key was set
 
245
 *     HASH_KEY_SAME            the key was identical (same memory pointer) to
 
246
 *                              the existing key so no key was freed
 
247
 *   </pre>
 
248
 */
 
249
extern int h_set(HashTable *self, const void *key, void *value);
 
250
 
 
251
/**
 
252
 * Add the value +value+ to the HashTable referencing it with key +key+. If
 
253
 * the key already exists in the HashTable, the value won't be added and the
 
254
 * function will return false. Otherwise it will return true.
 
255
 *
 
256
 * @param self the HashTable to add the value to
 
257
 * @param key the key to use to reference the value
 
258
 * @param value the value to add to the HashTable
 
259
 * @return true if the value was successfully added or false otherwise
 
260
 */
 
261
extern int h_set_safe(HashTable *self, const void *key, void *value);
 
262
 
 
263
/**
 
264
 * Return a hash entry object so you can handle the insert yourself. This can
 
265
 * be used for performance reasons or for more control over how a value is
 
266
 * added. Say, for example, you wanted to append a value to an array, or add a
 
267
 * new array if non-existed, you could use this method by checking the value
 
268
 * of the HashEntry returned.
 
269
 *
 
270
 * @param self the HashTable to add the value to
 
271
 * @param key the key to use to reference the value
 
272
 * @return HashEntry a pointer to the hash entry object now reserved for this
 
273
 * value. Be sure to set both the *key* and the *value*
 
274
 */
 
275
extern HashEntry *h_set_ext(HashTable *ht, const void *key);
 
276
 
 
277
/**
 
278
 * Check whether key +key+ exists in the HashTable.
 
279
 *
 
280
 * @param self the HashTable to check in
 
281
 * @param key the key to check for in the HashTable
 
282
 * @return true if the key exists in the HashTable, false otherwise.
 
283
 */
 
284
extern int h_has_key(HashTable *self, const void *key);
 
285
 
 
286
/**
 
287
 * Get the value in the HashTable referenced by an integer key +key+.
 
288
 *
 
289
 * @param self the HashTable to reference
 
290
 * @param key the integer key to lookup
 
291
 * @return the value referenced by the key +key+. If there is no value
 
292
 *   referenced by that key, NULL is returned.
 
293
 */
 
294
extern void *h_get_int(HashTable *self, const unsigned long key);
 
295
 
 
296
/**
 
297
 * Delete the value in HashTable referenced by the integer key +key+. When the
 
298
 * value is deleted it is also destroyed using the free_value function. If you
 
299
 * don't want to destroy the value use h_rem. 
 
300
 *
 
301
 * This functions returns +true+ if the value was deleted successfully or
 
302
 * false if the key was not found.
 
303
 *
 
304
 * @see h_rem
 
305
 *
 
306
 * @param self the HashTable to reference
 
307
 * @param key the integer key to lookup
 
308
 * @return true if the object was successfully deleted or false if the key was
 
309
 *   not found
 
310
 */
 
311
extern int h_del_int(HashTable *self, const unsigned long key);
 
312
 
 
313
/**
 
314
 * Remove the value in HashTable referenced by the integer key +key+. When the
 
315
 * value is removed it is returned rather than destroyed.
 
316
 *
 
317
 * If you want the value to be destroyed, use the h_del function.
 
318
 *
 
319
 * @see h_del
 
320
 *
 
321
 * @param self the HashTable to reference
 
322
 * @param key the integer key to lookup
 
323
 * @return the value referenced by +key+ if it can be found or NULL otherwise
 
324
 */
 
325
extern void *h_rem_int(HashTable *self, const unsigned long key);
 
326
 
 
327
/**
 
328
 * WARNING: this function may destroy an old value if the key already exists
 
329
 * in the HashTable, depending on how free_value was set for this HashTable.
 
330
 *
 
331
 * Add the value +value+ to the HashTable referencing it with an integer key
 
332
 * +key+.
 
333
 *
 
334
 * When a value is added to the HashTable it replaces any value that
 
335
 * might already be stored under that key. If free_value is already set then
 
336
 * the old value will be freed using that function.
 
337
 *
 
338
 * Similarly the old key might replace be replaced by the new key if they are
 
339
 * are equal (according to the HashTable's eq function) but seperately
 
340
 * allocated objects.
 
341
 *
 
342
 * @param self the HashTable to add the value to
 
343
 * @param key the integer key to use to reference the value
 
344
 * @param value the value to add to the HashTable
 
345
 * @return one of three values;
 
346
 *   <pre>
 
347
 *     HASH_KEY_DOES_NOT_EXIST  there was no value stored with that key
 
348
 *     HASH_KEY_EQUAL           the key existed and was seperately allocated.
 
349
 *                              In this situation the old key will have been
 
350
 *                              destroyed if free_key was set
 
351
 *     HASH_KEY_SAME            the key was identical (same memory pointer) to
 
352
 *                              the existing key so no key was freed
 
353
 *   </pre>
 
354
 */
 
355
extern int h_set_int(HashTable *self, const unsigned long key, void *value);
 
356
 
 
357
/**
 
358
 * Add the value +value+ to the HashTable referencing it with integer key
 
359
 * +key+. If the key already exists in the HashTable, the value won't be added
 
360
 * and the function will return false. Otherwise it will return true.
 
361
 *
 
362
 * @param self the HashTable to add the value to
 
363
 * @param key the integer key to use to reference the value
 
364
 * @param value the value to add to the HashTable
 
365
 * @return true if the value was successfully added or false otherwise
 
366
 */
 
367
extern int h_set_safe_int(HashTable *self, const unsigned long key, void *value);
 
368
/**
 
369
 * Check whether integer key +key+ exists in the HashTable.
 
370
 *
 
371
 * @param self the HashTable to check in
 
372
 * @param key the integer key to check for in the HashTable
 
373
 * @return true if the key exists in the HashTable, false otherwise.
 
374
 */
 
375
extern int h_has_key_int(HashTable *self, const unsigned long key);
 
376
 
 
377
typedef void (*h_each_key_val_ft)(void *key, void *value, void *arg);
 
378
 
 
379
/**
 
380
 * Run function +each_key_val+ on each key and value in the HashTable. The third
 
381
 * argument +arg+ will also be passed to +each_key_val+. If you need to pass
 
382
 * more than one argument to the function you should pass a struct.
 
383
 *
 
384
 * example;
 
385
 *
 
386
 * // Lets say we have stored strings in a HashTable and we want to put them
 
387
 * // all into an array. First we need to create a struct to store the
 
388
 * // strings;
 
389
 *
 
390
 * struct StringArray {
 
391
 *   char **strings;
 
392
 *   int cnt;
 
393
 *   int size;
 
394
 * };
 
395
 *
 
396
 * static void add_string_ekv(void *key, void *value,
 
397
 *                            struct StringArray *str_arr)
 
398
 * {
 
399
 *   str_arr->strings[str_arr->cnt] = (char *)value;
 
400
 *   str_arr->cnt++;
 
401
 * }
 
402
 *
 
403
 * struct StringArray *h_extract_strings(HashTable *ht)
 
404
 * {
 
405
 *   struct StringArray *str_arr = ALLOC(struct StringArray);
 
406
 *
 
407
 *   str_arr->strings = ALLOC_N(char *, ht->size);
 
408
 *   str_arr->cnt = 0;
 
409
 *   str_arr->size = ht->size;
 
410
 *
 
411
 *   h_each(ht, (h_each_key_val_ft)add_string_ekv, str_arr);
 
412
 *
 
413
 *   return str_arr;
 
414
 * }
 
415
 *
 
416
 * @param self the HashTable to run the function on
 
417
 * @param each_key_val function to run on on each key and value in the
 
418
 *   HashTable
 
419
 * @param arg an extra argument to pass to each_key_val each time it is called
 
420
 */
 
421
extern void h_each(HashTable *self,
 
422
                   void (*each_key_val)(void *key, void *value, void *arg),
 
423
                   void *arg);
 
424
 
 
425
typedef void *(*h_clone_func_t)(void *val);
 
426
/**
 
427
 * Clone the HashTable as well as cloning each of the keys and values if you
 
428
 * want to do a deep clone. To do a deep clone you will need to pass a
 
429
 * clone_key function and/or a clone_value function.
 
430
 *
 
431
 * @param self the HashTable to clone
 
432
 * @param clone_key the function to clone the key with
 
433
 * @param clone_value the function to clone the value with
 
434
 * @return a clone of the original HashTable
 
435
 */
 
436
extern HashTable *h_clone(HashTable *self,
 
437
                          h_clone_func_t clone_key,
 
438
                          h_clone_func_t clone_value);
 
439
 
 
440
/*
 
441
 * The following functions should only be used in static HashTable
 
442
 * declarations
 
443
 */
 
444
/**
 
445
 * This is the lookup function for a hash table keyed with strings. Since it
 
446
 * is so common for hash tables to be keyed with strings it gets it's own
 
447
 * lookup function. This method will always return a HashEntry. If there is no
 
448
 * entry with the given key then an empty entry will be returned with the key
 
449
 * set to the key that was passed.
 
450
 *
 
451
 * @param ht the hash table to look in
 
452
 * @param key the key to lookup
 
453
 * @return the HashEntry that was found
 
454
 */
 
455
extern HashEntry *h_lookup_str(HashTable *ht, register const char *key);
 
456
 
 
457
/**
 
458
 * This is the lookup function for a hash table with non-string keys. The
 
459
 * hash() and eq() methods used are stored in the hash table. This method will
 
460
 * always return a HashEntry. If there is no entry with the given key then an
 
461
 * empty entry will be returned with the key set to the key that was passed.
 
462
 *
 
463
 * @param ht the hash table to look in
 
464
 * @param key the key to lookup
 
465
 * @return the HashEntry that was found
 
466
 */
 
467
extern HashEntry *h_lookup(HashTable *ht, register const void *key);
 
468
 
 
469
typedef HashEntry *(*h_lookup_ft)(HashTable *ht, register const void *key);
 
470
 
 
471
extern void h_str_print_keys(HashTable *ht);
 
472
 
 
473
#endif