File: hash.h

package info (click to toggle)
libconvert-binary-c-perl 0.74-1
  • links: PTS, VCS
  • area: main
  • in suites: squeeze
  • size: 9,100 kB
  • ctags: 21,416
  • sloc: ansic: 63,666; perl: 18,582; yacc: 2,143; makefile: 44
file content (334 lines) | stat: -rw-r--r-- 10,686 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
/*******************************************************************************
*
* HEADER: hash
*
********************************************************************************
*
* DESCRIPTION: Generic hash table routines
*
********************************************************************************
*
* $Project: /Convert-Binary-C $
* $Author: mhx $
* $Date: 2009/03/15 04:10:46 +0100 $
* $Revision: 21 $
* $Source: /util/hash.h $
*
********************************************************************************
*
* Copyright (c) 2002-2009 Marcus Holland-Moritz. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of either the Artistic License or the
* GNU General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
*******************************************************************************/

/**
 *  \file hash.h
 *  \brief Generic implementation of Hash Tables
 */
#ifndef _UTIL_HASH_H
#define _UTIL_HASH_H

/**
 *  Maximum allowed hash size
 *
 *  This controls the maximum number of hash buckets,
 *  currently 2^16 = 65536.
 */
#define MAX_HASH_TABLE_SIZE 16

/**
 *  Compute hash sum and string length
 *
 *  The HASH_STR_LEN() macro computes the hash sum and
 *  string length of a zero terminated string.
 *
 *  \param hash         Variable that will receive the
 *                      hash sum.
 *
 *  \param str          Pointer to the zero terminated
 *                      string.
 *
 *  \param len          Variable that will receive the
 *                      string length.
 *
 *  \see HASH_STRING() and HASH_DATA()
 *  \hideinitializer
 */
#define HASH_STR_LEN( hash, str, len )         \
        do {                                   \
          register int         _len = 0;       \
          register const char *_str = str;     \
          register HashSum     _hash = 0;      \
                                               \
          while( *_str ) {                     \
            _len++;                            \
            _hash += *_str++;                  \
            _hash += (_hash << 10);            \
            _hash ^= (_hash >> 6);             \
          }                                    \
                                               \
          _hash += (_hash << 3);               \
          _hash ^= (_hash >> 11);              \
          (hash) = (_hash + (_hash << 15));    \
          (len)  = _len;                       \
        } while(0)

/**
 *  Compute hash sum
 *
 *  The HASH_STRING() macro computes the hash sum
 *  of a zero terminated string.
 *
 *  \param hash         Variable that will receive the
 *                      hash sum.
 *
 *  \param str          Pointer to the zero terminated
 *                      string.
 *
 *  \see HASH_STR_LEN() and HASH_DATA()
 *  \hideinitializer
 */
#define HASH_STRING( hash, str )               \
        do {                                   \
          register const char *_str = str;     \
          register HashSum     _hash = 0;      \
                                               \
          while( *_str ) {                     \
            _hash += *_str++;                  \
            _hash += (_hash << 10);            \
            _hash ^= (_hash >> 6);             \
          }                                    \
                                               \
          _hash += (_hash << 3);               \
          _hash ^= (_hash >> 11);              \
          (hash) = (_hash + (_hash << 15));    \
        } while(0)

/**
 *  Compute hash sum of arbitrary data
 *
 *  The HASH_DATA() macro computes the hash sum
 *  of a an arbitrary data memory block.
 *
 *  \param hash         Variable that will receive the
 *                      hash sum.
 *
 *  \param len          Length of the data block.
 *
 *  \param data         Pointer to the data block.
 *
 *  \see HASH_STR_LEN() and HASH_STRING()
 *  \hideinitializer
 */
#define HASH_DATA( hash, len, data )           \
        do {                                   \
          register const char *_data = data;   \
          register int         _len  = len;    \
          register HashSum     _hash = 0;      \
                                               \
          while( _len-- ) {                    \
            _hash += *_data++;                 \
            _hash += (_hash << 10);            \
            _hash ^= (_hash >> 6);             \
          }                                    \
                                               \
          _hash += (_hash << 3);               \
          _hash ^= (_hash >> 11);              \
          (hash) = (_hash + (_hash << 15));    \
        } while(0)

/**
 *  Hash Table Handle
 */
typedef struct _hashTable * HashTable;
typedef const struct _hashTable * ConstHashTable;

/**
 *  Hash Sum
 */
typedef unsigned long HashSum;

/**
 *  Hash Node
 */
typedef struct _hashNode *HashNode;
typedef const struct _hashNode *ConstHashNode;

struct _hashNode {
  HashNode  next;
  void     *pObj;
  HashSum   hash;
  int       keylen;
  char      key[1];
};

/**
 *  Hash Table Iterator
 */
typedef struct _hashIterator {
  ConstHashNode pNode;
  HashNode *pBucket;
  int remain;
#ifdef DEBUG_UTIL_HASH
  ConstHashTable table;
  unsigned orig_state;
#endif
} HashIterator;

/**
 *  Destructor Function Pointer
 */
typedef void (* HTDestroyFunc)(void *);

/**
 *  Cloning Function Pointer
 */
typedef void * (* HTCloneFunc)(const void *);

HashTable  HT_new_ex( int size, unsigned long flags );
void       HT_delete( HashTable table );
void       HT_flush( HashTable table, HTDestroyFunc destroy );
void       HT_destroy( HashTable table, HTDestroyFunc destroy );
HashTable  HT_clone( ConstHashTable table, HTCloneFunc func );

int        HT_resize( HashTable table, int size );
int        HT_size( ConstHashTable table );
int        HT_count( ConstHashTable table );

HashNode   HN_new( const char *key, int keylen, HashSum hash );
void       HN_delete( HashNode node );

int        HT_storenode( HashTable table, HashNode node, void *pObj );
void *     HT_fetchnode( HashTable table, HashNode node );
void *     HT_rmnode( HashTable table, HashNode node );

int        HT_store( HashTable table, const char *key, int keylen, HashSum hash, void *pObj );
void *     HT_fetch( HashTable table, const char *key, int keylen, HashSum hash );
void *     HT_get( ConstHashTable table, const char *key, int keylen, HashSum hash );
int        HT_exists( ConstHashTable table, const char *key, int keylen, HashSum hash );

void       HI_init(HashIterator *it, ConstHashTable table);
int        HI_next(HashIterator *it, const char **ppKey, int *pKeylen, void **ppObj);

/* hash table flags */
#define HT_AUTOGROW            0x00000001
#define HT_AUTOSHRINK          0x00000002
#define HT_AUTOSIZE            (HT_AUTOGROW|HT_AUTOSHRINK)

/* debug flags */
#define DB_HASH_MAIN           0x00000001

#ifdef DEBUG_UTIL_HASH
void HT_dump( ConstHashTable table );
int  SetDebugHash( void (*dbfunc)(const char *, ...), unsigned long dbflags );
#else
#define SetDebugHash( func, flags ) 0
#endif

/**
 *  Constructor
 *
 *  Using the HT_new() function you create an empty hash table.
 *
 *  \param size         Hash table base size. You can specify
 *                      any value between 1 and 16. Depending
 *                      on how many elements you plan to store
 *                      in the hash table, values from 6 to 12
 *                      can be considered useful. The number
 *                      of buckets created is 2^size, so if
 *                      you specify a size of 10, 1024 buckets
 *                      will be created and the empty hash
 *                      table will consume about 4kB of memory.
 *                      However, 1024 buckets will be enough
 *                      to very efficiently manage 100000 hash
 *                      elements.
 *
 *  \return A handle to the newly created hash table.
 *
 *  \see HT_new_ex(), HT_delete() and HT_destroy()
 */
#define HT_new( size ) HT_new_ex( size, 0 )

/**
 *  Loop over all hash elements.
 *
 *  The HT_foreach() macro is actually only a shortcut for the
 *  following loop:
 *
 *  \code
 *  for( HT_reset(table); HT_next(table, (char **)&(pKey), NULL, (void **)&(pObj)); ) {
 *    // do something with pKey and pObj
 *  }
 *  \endcode
 *
 *  It is safe to use HT_foreach() even if \a hash table handle is NULL.
 *  In that case, the loop won't be executed.
 *
 *  \param pKey         Variable that will receive a pointer
 *                      to the current hash key string.
 *
 *  \param pObj         Variable that will receive a pointer
 *                      to the current object.
 *
 *  \param iter         Pointer to hash iterator object.
 *
 *  \param table        Handle to an existing hash table.
 *
 *  \see HT_reset() and HT_next()
 *  \hideinitializer
 */
#define HT_foreach(pKey, pObj, iter, table) \
          for (HI_init(&iter, table); HI_next(&iter, &(pKey), NULL, (void **)&(pObj)); )

/**
 *  Loop over all hash keys.
 *
 *  Like HT_foreach(), just that the value parameter isn't used.
 *
 *  It is safe to use HT_foreach_keys() even if \a hash table handle is NULL.
 *  In that case, the loop won't be executed.
 *
 *  \param pKey         Variable that will receive a pointer
 *                      to the current hash key string.
 *
 *  \param iter         Pointer to hash iterator object.
 *
 *  \param table        Handle to an existing hash table.
 *
 *  \see HT_foreach() and HT_foreach_values()
 *  \hideinitializer
 */
#define HT_foreach_keys(pKey, iter, table) \
          for (HI_init(&iter, table); HI_next(&iter, &(pKey), NULL, NULL); )

/**
 *  Loop over all hash values.
 *
 *  Like HT_foreach(), just that the key parameter isn't used.
 *
 *  It is safe to use HT_foreach_values() even if \a hash table handle is NULL.
 *  In that case, the loop won't be executed.
 *
 *  \param pObj         Variable that will receive a pointer
 *                      to the current object.
 *
 *  \param iter         Pointer to hash iterator object.
 *
 *  \param table        Handle to an existing hash table.
 *
 *  \see HT_foreach() and HT_foreach_keys()
 *  \hideinitializer
 */
#define HT_foreach_values(pObj, iter, table) \
          for (HI_init(&iter, table); HI_next(&iter, NULL, NULL, (void **)&(pObj)); )

#endif