1 /*
2 
3   silchashtable.h
4 
5   Author: Pekka Riikonen <priikone@silcnet.org>
6 
7   Copyright (C) 2001 - 2006 Pekka Riikonen
8 
9   The contents of this file are subject to one of the Licenses specified
10   in the COPYING file;  You may not use this file except in compliance
11   with the License.
12 
13   The software distributed under the License is distributed on an "AS IS"
14   basis, in the hope that it will be useful, but WITHOUT WARRANTY OF ANY
15   KIND, either expressed or implied.  See the COPYING file for more
16   information.
17 
18 */
19 
20 /****h* silcutil/SILC Hash Table Interface
21  *
22  * DESCRIPTION
23  *
24  * Implementation of collision resistant hash table. This is a hash table
25  * that provides a reliable (what you add there stays there, and duplicate
26  * keys are allowed) with as fast reference to the key as possible. If
27  * there are a lot of duplicate keys in the hash table the lookup gets
28  * slower of course. However, this is reliable and no data is lost at any
29  * point. If you know that you never have duplicate keys then this is as
30  * fast as any simple hash table.
31  *
32  * The interface provides many ways to search the hash table including
33  * an extended interface where caller can specify its own hash and comparison
34  * functions.
35  *
36  * There are two ways to traverse the entire hash table if this feature
37  * is needed. There exists a foreach function that calls a foreach
38  * callback for each entry in the hash table. Other way is to use
39  * SilcHashTableList structure and traverse the hash table inside while()
40  * using the list structure. Both are equally fast.
41  *
42  * The hash table is not thread safe.  If same hash table context is used in
43  * multi thread environment concurrency control must be employed.
44  *
45  ***/
46 
47 #ifndef SILCHASHTABLE_H
48 #define SILCHASHTABLE_H
49 
50 /****s* silcutil/SilcHashTableAPI/SilcHashTable
51  *
52  * NAME
53  *
54  *    typedef struct SilcHashTableStruct *SilcHashTable;
55  *
56  * DESCRIPTION
57  *
58  *    This context is the actual hash table and is allocated
59  *    by silc_hash_table_alloc and given as argument usually to
60  *    all silc_hash_table_* functions.  It is freed by the
61  *    silc_hash_table_free function.
62  *
63  ***/
64 typedef struct SilcHashTableStruct *SilcHashTable;
65 
66 /****s* silcutil/SilcHashTableAPI/SilcHashTableList
67  *
68  * NAME
69  *
70  *    typedef struct SilcHashTableListStruct SilcHashTableList;
71  *
72  * DESCRIPTION
73  *
74  *    This structure is used to tarverse the hash table. This structure
75  *    is given as argument to the silc_hash_table_list function to
76  *    initialize it and then used to traverse the hash table with the
77  *    silc_hash_table_get function. It needs not be allocated or freed.
78  *
79  * EXAMPLE
80  *
81  *    SilcHashTableList htl;
82  *    silc_hash_table_list(hash_table, &htl);
83  *    while (silc_hash_table_get(&htl, (void *)&key, (void *)&context))
84  *      ...
85  *    silc_hash_table_list_reset(&htl);
86  *
87  * SOURCE
88  */
89 typedef struct SilcHashTableListStruct SilcHashTableList;
90 
91 /* List structure to traverse the hash table. */
92 struct SilcHashTableListStruct {
93   SilcHashTable ht;
94   void *entry;
95   unsigned int index        : 31;
96   unsigned int auto_rehash  : 1;
97 };
98 /***/
99 
100 /****f* silcutil/SilcHashTableAPI/SilcHashFunction
101  *
102  * SYNOPSIS
103  *
104  *    typedef SilcUInt32 (*SilcHashFunction)(void *key, void *user_context);
105  *
106  * DESCRIPTION
107  *
108  *    A type for the hash function. This function is used to hash the
109  *    provided key value `key' and return the index for the hash table.
110  *    The `user_context' is application specific context and is delivered
111  *    to the callback.
112  *
113  ***/
114 typedef SilcUInt32 (*SilcHashFunction)(void *key, void *user_context);
115 
116 /****f* silcutil/SilcHashTableAPI/SilcHashCompare
117  *
118  * SYNOPSIS
119  *
120  *    typedef SilcBool (*SilcHashCompare)(void *key1, void *key2,
121  *                                        void *user_context);
122  *
123  * DESCRIPTION
124  *
125  *    A comparison funtion that is called to compare the two keys `key1' and
126  *    `key2'. If they are equal this must return TRUE or FALSE otherwise.
127  *    The application provides this function when allocating a new hash table.
128  *    The `user_context' is application specific context and is delivered
129  *    to the callback.
130  *
131  ***/
132 typedef SilcBool (*SilcHashCompare)(void *key1, void *key2,
133 				    void *user_context);
134 
135 /****f* silcutil/SilcHashTableAPI/SilcHashDestructor
136  *
137  * SYNOPSIS
138  *
139  *    typedef void (*SilcHashDestructor)(void *key, void *context,
140  *                                       void *user_context);
141  *
142  * DESCRIPTION
143  *
144  *    A destructor callback that the library will call to destroy the
145  *    `key' and `context'.  The application provides the function when
146  *    allocating a new hash table. The `user_context' is application
147  *    specific context and is delivered to the callback.
148  *
149  ***/
150 typedef void (*SilcHashDestructor)(void *key, void *context,
151 				   void *user_context);
152 
153 /****f* silcutil/SilcHashTableAPI/SilcHashForeach
154  *
155  * SYNOPSIS
156  *
157  *    typedef void (*SilcHashForeach)(void *key, void *context,
158  *                                    void *user_context);
159  *
160  * DESCRIPTION
161  *
162  *    Foreach function. This is called when traversing the entrys in the
163  *    hash table using silc_hash_table_foreach. The `user_context' is
164  *    application specific context and is delivered to the callback.
165  *
166  ***/
167 typedef void (*SilcHashForeach)(void *key, void *context, void *user_context);
168 
169 /* Simple hash table interface */
170 
171 /****f* silcutil/SilcHashTableAPI/silc_hash_table_alloc
172  *
173  * SYNOPSIS
174  *
175  *    SilcHashTable silc_hash_table_alloc(SilcUInt32 table_size,
176  *                                        SilcHashFunction hash,
177  *                                        void *hash_user_context,
178  *                                        SilcHashCompare compare,
179  *                                        void *compare_user_context,
180  *                                        SilcHashDestructor destructor,
181  *                                        void *destructor_user_context,
182  *                                        SilcBool auto_rehash);
183  *
184  * DESCRIPTION
185  *
186  *    Allocates new hash table and returns it.  If the `table_size' is not
187  *    zero then the hash table size is the size provided. If zero then the
188  *    default size will be used. Note that if the `table_size' is provided
189  *    it should be a prime. The `hash', `compare' and `destructor' are
190  *    the hash function, the key comparison function and key and context
191  *    destructor function, respectively. The `hash' is mandatory, the others
192  *    are optional.
193  *
194  ***/
195 SilcHashTable silc_hash_table_alloc(SilcUInt32 table_size,
196 				    SilcHashFunction hash,
197 				    void *hash_user_context,
198 				    SilcHashCompare compare,
199 				    void *compare_user_context,
200 				    SilcHashDestructor destructor,
201 				    void *destructor_user_context,
202 				    SilcBool auto_rehash);
203 
204 /****f* silcutil/SilcHashTableAPI/silc_hash_table_free
205  *
206  * SYNOPSIS
207  *
208  *    void silc_hash_table_free(SilcHashTable ht);
209  *
210  * DESCRIPTION
211  *
212  *    Frees the hash table. The destructor function provided in the
213  *    silc_hash_table_alloc will be called for all keys in the hash table.
214  *
215  ***/
216 void silc_hash_table_free(SilcHashTable ht);
217 
218 /****f* silcutil/SilcHashTableAPI/silc_hash_table_size
219  *
220  * SYNOPSIS
221  *
222  *    SilcUInt32 silc_hash_table_size(SilcHashTable ht);
223  *
224  * DESCRIPTION
225  *
226  *    Returns the size of the hash table. This is the true size of the
227  *    hash table.
228  *
229  ***/
230 SilcUInt32 silc_hash_table_size(SilcHashTable ht);
231 
232 /****f* silcutil/SilcHashTableAPI/silc_hash_table_count
233  *
234  * SYNOPSIS
235  *
236  *    SilcUInt32 silc_hash_table_count(SilcHashTable ht);
237  *
238  * DESCRIPTION
239  *
240  *    Returns the number of the entires in the hash table. If there is more
241  *    entries in the table thatn the size of the hash table calling the
242  *    silc_hash_table_rehash is recommended.
243  *
244  ***/
245 SilcUInt32 silc_hash_table_count(SilcHashTable ht);
246 
247 /****f* silcutil/SilcHashTableAPI/silc_hash_table_add
248  *
249  * SYNOPSIS
250  *
251  *    SilcBool silc_hash_table_add(SilcHashTable ht, void *key, void *context);
252  *
253  * DESCRIPTION
254  *
255  *    Adds new entry to the hash table. The `key' is hashed using the
256  *    hash function and the both `key' and `context' will be saved to the
257  *    hash table. This function quarantees that the entry is always added
258  *    to the hash table reliably (it is collision resistant).
259  *
260  ***/
261 SilcBool silc_hash_table_add(SilcHashTable ht, void *key, void *context);
262 
263 /****f* silcutil/SilcHashTableAPI/silc_hash_table_replace
264  *
265  * SYNOPSIS
266  *
267  *    SilcBool silc_hash_table_replace(SilcHashTable ht, void *key,
268  *                                     void *context);
269  *
270  * DESCRIPTION
271  *
272  *    Same as silc_hash_table_add but if the `key' already exists in the
273  *    hash table the old key and the old context will be replaced with the
274  *    `key' and the `context. The destructor function will be called for the
275  *    replaced key and context.
276  *
277  ***/
278 SilcBool silc_hash_table_replace(SilcHashTable ht, void *key, void *context);
279 
280 /****f* silcutil/SilcHashTableAPI/silc_hash_table_del
281  *
282  * SYNOPSIS
283  *
284  *    SilcBool silc_hash_table_del(SilcHashTable ht, void *key);
285  *
286  * DESCRIPTION
287  *
288  *    Removes the entry from the hash table by the provided `key'. This will
289  *    call the destructor funtion for the found entry. Return TRUE if the
290  *    entry was removed successfully and FALSE otherwise.
291  *
292  ***/
293 SilcBool silc_hash_table_del(SilcHashTable ht, void *key);
294 
295 /****f* silcutil/SilcHashTableAPI/silc_hash_table_del_by_context
296  *
297  * SYNOPSIS
298  *
299  *    SilcBool silc_hash_table_del_by_context(SilcHashTable ht, void *key,
300  *                                            void *context);
301  *
302  * DESCRIPTION
303  *
304  *    Same as silc_hash_table_del but verifies that the context associated
305  *    with the `key' matches the `context'. This is handy to use with hash
306  *    tables that may have duplicate keys. In that case the `context' may
307  *    be used to check whether the correct entry is being deleted.
308  *
309  ***/
310 SilcBool silc_hash_table_del_by_context(SilcHashTable ht, void *key,
311 					void *context);
312 
313 /****f* silcutil/SilcHashTableAPI/silc_hash_table_find
314  *
315  * SYNOPSIS
316  *
317  *    SilcBool silc_hash_table_find(SilcHashTable ht, void *key,
318  *                                  void **ret_key, void **ret_context);
319  *
320  * DESCRIPTION
321  *
322  *    Finds the entry in the hash table by the provided `key' as fast as
323  *    possible. Return TRUE if the entry was found and FALSE otherwise.
324  *    The found entry is returned to the `ret_key' and `ret_context',
325  *    respectively. If the `ret_key and `ret_context' are NULL then this
326  *    maybe used only to check whether given key exists in the table.
327  *
328  ***/
329 SilcBool silc_hash_table_find(SilcHashTable ht, void *key,
330 			      void **ret_key, void **ret_context);
331 
332 /****f* silcutil/SilcHashTableAPI/silc_hash_table_find_by_context
333  *
334  * SYNOPSIS
335  *
336  *    SilcBool silc_hash_table_find_by_context(SilcHashTable ht, void *key,
337  *                                             void *context, void **ret_key);
338  *
339  * DESCRIPTION
340  *
341  *    Finds the entry in the hash table by the provided `key' and
342  *    `context' as fast as possible.  This is handy function when there
343  *    can be multiple same keys in the hash table.  By using this function
344  *    the specific key with specific context can be found.  Return
345  *    TRUE if the entry with the key and context was found and FALSE
346  *    otherwise.  The function returns only the key to `ret_key' since
347  *    the caller already knows the context.
348  *
349  ***/
350 SilcBool silc_hash_table_find_by_context(SilcHashTable ht, void *key,
351 					 void *context, void **ret_key);
352 
353 /****f* silcutil/SilcHashTableAPI/silc_hash_table_find_foreach
354  *
355  * SYNOPSIS
356  *
357  *    void silc_hash_table_find_foreach(SilcHashTable ht, void *key,
358  *                                      SilcHashForeach foreach,
359  *                                      void *user_context);
360  *
361  * DESCRIPTION
362  *
363  *    As the hash table is collision resistant it is possible to save duplicate
364  *    keys to the hash table. This function can be used to find all keys
365  *    and contexts from the hash table that are found using the `key'. The
366  *    `foreach' is called for every found key. If no entries can be found
367  *    the `foreach' will be called once with the context set NULL and
368  *    `key' and `user_context' sent to the function.
369  *
370  * NOTES
371  *
372  *    The hash table will not be rehashed during the traversing of the table,
373  *    even if the table was marked as auto rehashable.  The caller also must
374  *    not call silc_hash_table_rehash while traversing the table.
375  *
376  ***/
377 void silc_hash_table_find_foreach(SilcHashTable ht, void *key,
378 				  SilcHashForeach foreach, void *user_context);
379 
380 /****f* silcutil/SilcHashTableAPI/silc_hash_table_foreach
381  *
382  * SYNOPSIS
383  *
384  *    void silc_hash_table_foreach(SilcHashTable ht, SilcHashForeach foreach,
385  *                                 void *user_context);
386  *
387  * DESCRIPTION
388  *
389  *    Traverse all entrys in the hash table and call the `foreach' for
390  *    every entry with the `user_context' context.
391  *
392  * NOTES
393  *
394  *    The hash table will not be rehashed during the traversing of the table,
395  *    even if the table was marked as auto rehashable.  The caller also must
396  *    not call silc_hash_table_rehash while traversing the table.
397  *
398  ***/
399 void silc_hash_table_foreach(SilcHashTable ht, SilcHashForeach foreach,
400 			     void *user_context);
401 
402 /****f* silcutil/SilcHashTableAPI/silc_hash_table_rehash
403  *
404  * SYNOPSIS
405  *
406  *    void silc_hash_table_rehash(SilcHashTable ht, SilcUInt32 new_size);
407  *
408  * DESCRIPTION
409  *
410  *    Rehashs the hash table. The size of the new hash table is provided
411  *    as `new_size'. If the `new_size' is zero then this routine will make
412  *    the new table of a suitable size. Note that this operation may be
413  *    very slow.
414  *
415  ***/
416 void silc_hash_table_rehash(SilcHashTable ht, SilcUInt32 new_size);
417 
418 /****f* silcutil/SilcHashTableAPI/silc_hash_table_list
419  *
420  * SYNOPSIS
421  *
422  *    void silc_hash_table_list(SilcHashTable ht, SilcHashTableList *htl);
423  *
424  * DESCRIPTION
425  *
426  *    Prepares the `htl' SilcHashTableList sent as argument to be used in the
427  *    hash table traversing with the silc_hash_table_get.  After the hash
428  *    table traversing is completed the silc_hash_table_list_reset must be
429  *    called.
430  *
431  * NOTES
432  *
433  *    The hash table will not be rehashed during the traversing of the list,
434  *    even if the table was marked as auto rehashable.  The caller also must
435  *    not call silc_hash_table_rehash while traversing the list.
436  *
437  ***/
438 void silc_hash_table_list(SilcHashTable ht, SilcHashTableList *htl);
439 
440 /****f* silcutil/SilcHashTableAPI/silc_hash_table_list_reset
441  *
442  * SYNOPSIS
443  *
444  *    void silc_hash_table_list_reset(SilcHashTableList *htl);
445  *
446  * DESCRIPTION
447  *
448  *    Resets the `htl' SilcHashTableList.  This must be called after the
449  *    hash table traversing is completed.
450  *
451  ***/
452 void silc_hash_table_list_reset(SilcHashTableList *htl);
453 
454 /****f* silcutil/SilcHashTableAPI/silc_hash_table_get
455  *
456  * SYNOPSIS
457  *
458  *    SilcBool silc_hash_table_get(SilcHashTableList *htl, void **key,
459  *                                 void **context);
460  *
461  * DESCRIPTION
462  *
463  *    Returns always the next entry in the hash table into the `key' and
464  *    `context' and TRUE.  If this returns FALSE then there are no more
465  *    entries.
466  *
467  * EXAMPLE
468  *
469  *    SilcHashTableList htl;
470  *    silc_hash_table_list(hash_table, &htl);
471  *    while (silc_hash_table_get(&htl, (void *)&key, (void *)&context))
472  *      ...
473  *    silc_hash_table_list_reset(&htl);
474  *
475  ***/
476 SilcBool silc_hash_table_get(SilcHashTableList *htl,
477 			     void **key, void **context);
478 
479 
480 /* Extended hash table interface (same as above but with specific
481    hash and comparison functions). */
482 
483 /****f* silcutil/SilcHashTableAPI/silc_hash_table_add_ext
484  *
485  * SYNOPSIS
486  *
487  *    SilcBool silc_hash_table_add_ext(SilcHashTable ht, void *key,
488  *                                     void *context,
489  *                                     SilcHashFunction hash,
490  *                                     void *hash_user_context);
491  *
492  * DESCRIPTION
493  *
494  *    Adds new entry to the hash table. The `key' is hashed using the
495  *    hash function and the both `key' and `context' will be saved to the
496  *    hash table. This function quarantees that the entry is always added
497  *    to the hash table reliably (it is collision resistant).
498  *
499  *    The `hash' and `hash_user_context' are application specified hash
500  *    function. If not provided the hash table's default is used.
501  *
502  ***/
503 SilcBool silc_hash_table_add_ext(SilcHashTable ht,
504 				 void *key, void *context,
505 				 SilcHashFunction hash,
506 				 void *hash_user_context);
507 
508 /****f* silcutil/SilcHashTableAPI/silc_hash_table_replace_ext
509  *
510  * SYNOPSIS
511  *
512  *    SilcBool silc_hash_table_replace_ext(SilcHashTable ht, void *key,
513  *                                         void *context,
514  *                                         SilcHashFunction hash,
515  *                                         void *hash_user_context);
516  *
517  * DESCRIPTION
518  *
519  *    Same as silc_hash_table_add_ext but if the `key' already exists in the
520  *    hash table the old key and the old context will be replaced with the
521  *    `key' and the `context. The destructor function will be called for the
522  *    replaced key and context.
523  *
524  *    The `hash' and `hash_user_context' are application specified hash
525  *    function. If not provided the hash table's default is used.
526  *
527  ***/
528 SilcBool silc_hash_table_replace_ext(SilcHashTable ht,
529 				     void *key, void *context,
530 				     SilcHashFunction hash,
531 				     void *hash_user_context);
532 
533 /****f* silcutil/SilcHashTableAPI/silc_hash_table_del_ext
534  *
535  * SYNOPSIS
536  *
537  *    SilcBool silc_hash_table_del_ext(SilcHashTable ht, void *key,
538  *                                     SilcHashFunction hash,
539  *                                     void *hash_user_context,
540  *                                     SilcHashCompare compare,
541  *                                     void *compare_user_context,
542  *                                     SilcHashDestructor destructor,
543  *                                     void *destructor_user_context);
544  *
545  * DESCRIPTION
546  *
547  *    Removes the entry from the hash table by the provided `key'. This will
548  *    call the destructor funtion for the found entry. Return TRUE if the
549  *    entry was removed successfully and FALSE otherwise.
550  *
551  *    The `hash' and `hash_user_context' are application specified hash
552  *    function. If not provided the hash table's default is used.
553  *    The `compare' and `compare_user_context' are application specified
554  *    comparing function. If not provided the hash table's default is used.
555  *    The `destructor' and `destructor_user_context' are application
556  *    specific destructor function.
557  *
558  ***/
559 SilcBool silc_hash_table_del_ext(SilcHashTable ht, void *key,
560 				 SilcHashFunction hash,
561 				 void *hash_user_context,
562 				 SilcHashCompare compare,
563 				 void *compare_user_context,
564 				 SilcHashDestructor destructor,
565 				 void *destructor_user_context);
566 
567 /****f* silcutil/SilcHashTableAPI/silc_hash_table_del_by_context_ext
568  *
569  * SYNOPSIS
570  *
571  *    SilcBool
572  *    silc_hash_table_del_by_context_ext(SilcHashTable ht, void *key,
573  *                                       void *context,
574  *                                       SilcHashFunction hash,
575  *                                       void *hash_user_context,
576  *                                       SilcHashCompare compare,
577  *                                       void *compare_user_context,
578  *                                       SilcHashDestructor destructor,
579  *                                       void *destructor_user_context);
580  *
581  * DESCRIPTION
582  *
583  *    Same as silc_hash_table_del but verifies that the context associated
584  *    with the `key' matches the `context'. This is handy to use with hash
585  *    tables that may have duplicate keys. In that case the `context' may
586  *    be used to check whether the correct entry is being deleted.
587  *
588  *    The `hash' and `hash_user_context' are application specified hash
589  *    function. If not provided the hash table's default is used.
590  *    The `compare' and `compare_user_context' are application specified
591  *    comparing function. If not provided the hash table's default is used.
592  *    The `destructor' and `destructor_user_context' are application
593  *    specific destructor function.
594  *
595  ***/
596 SilcBool silc_hash_table_del_by_context_ext(SilcHashTable ht, void *key,
597 					    void *context,
598 					    SilcHashFunction hash,
599 					    void *hash_user_context,
600 					    SilcHashCompare compare,
601 					    void *compare_user_context,
602 					    SilcHashDestructor destructor,
603 					    void *destructor_user_context);
604 
605 /****f* silcutil/SilcHashTableAPI/silc_hash_table_find_ext
606  *
607  * SYNOPSIS
608  *
609  *    SilcBool silc_hash_table_find_ext(SilcHashTable ht, void *key,
610  *                                      void **ret_key, void **ret_context,
611  *                                      SilcHashFunction hash,
612  *                                      void *hash_user_context,
613  *                                      SilcHashCompare compare,
614  *                                      void *compare_user_context);
615  *
616  * DESCRIPTION
617  *
618  *    Finds the entry in the hash table by the provided `key' as fast as
619  *    possible. Return TRUE if the entry was found and FALSE otherwise.
620  *    The found entry is returned to the `ret_key' and `ret_context',
621  *    respectively. If the `ret_key and `ret_context' are NULL then this
622  *    maybe used only to check whether given key exists in the table.
623  *
624  *    The `hash' and `hash_user_context' are application specified hash
625  *    function. If not provided the hash table's default is used.
626  *    The `compare' and `compare_user_context' are application specified
627  *    comparing function. If not provided the hash table's default is used.
628  *
629  ***/
630 SilcBool silc_hash_table_find_ext(SilcHashTable ht, void *key,
631 				  void **ret_key, void **ret_context,
632 				  SilcHashFunction hash,
633 				  void *hash_user_context,
634 				  SilcHashCompare compare,
635 				  void *compare_user_context);
636 
637 /****f* silcutil/SilcHashTableAPI/silc_hash_table_find_by_context_ext
638  *
639  * SYNOPSIS
640  *
641  *    SilcBool
642  *    silc_hash_table_find_by_context_ext(SilcHashTable ht, void *key,
643  *                                        void *context, void **ret_key,
644  *                                        SilcHashFunction hash,
645  *                                        void *hash_user_context,
646  *                                        SilcHashCompare compare,
647  *                                        void *compare_user_context);
648  *
649  * DESCRIPTION
650  *
651  *    Finds the entry in the hash table by the provided `key' and
652  *    `context' as fast as possible.  This is handy function when there
653  *    can be multiple same keys in the hash table.  By using this function
654  *    the specific key with specific context can be found.  Return
655  *    TRUE if the entry with the key and context was found and FALSE
656  *    otherwise.  The function returns only the key to `ret_key' since
657  *    the caller already knows the context.
658  *
659  *    The `hash' and `hash_user_context' are application specified hash
660  *    function. If not provided the hash table's default is used.
661  *    The `compare' and `compare_user_context' are application specified
662  *    comparing function. If not provided the hash table's default is used.
663  *
664  ***/
665 SilcBool silc_hash_table_find_by_context_ext(SilcHashTable ht, void *key,
666 					     void *context, void **ret_key,
667 					     SilcHashFunction hash,
668 					     void *hash_user_context,
669 					     SilcHashCompare compare,
670 					     void *compare_user_context);
671 
672 /****f* silcutil/SilcHashTableAPI/silc_hash_table_find_foreach_ext
673  *
674  * SYNOPSIS
675  *
676  *    void silc_hash_table_find_foreach_ext(SilcHashTable ht, void *key,
677  *                                          SilcHashFunction hash,
678  *                                          void *hash_user_context,
679  *                                          SilcHashCompare compare,
680  *                                          void *compare_user_context,
681  *                                          SilcHashForeach foreach,
682  *                                          void *foreach_user_context);
683  *
684  * DESCRIPTION
685  *
686  *    As the hash table is collision resistant it is possible to save duplicate
687  *    keys to the hash table. This function can be used to find all keys
688  *    and contexts from the hash table that are found using the `key'. The
689  *    `foreach' is called for every found key. If no entries can be found
690  *    the `foreach' will be called once with the context set NULL and
691  *    `key' and `user_context' sent to the function.
692  *
693  *    The `hash' and `hash_user_context' are application specified hash
694  *    function. If not provided the hash table's default is used.
695  *    The `compare' and `compare_user_context' are application specified
696  *    comparing function. If not provided the hash table's default is used.
697  *
698  * NOTES
699  *
700  *    The hash table will not be rehashed during the traversing of the table,
701  *    even if the table was marked as auto rehashable.  The caller also must
702  *    not call silc_hash_table_rehash while traversing the table.
703  *
704  ***/
705 void silc_hash_table_find_foreach_ext(SilcHashTable ht, void *key,
706 				      SilcHashFunction hash,
707 				      void *hash_user_context,
708 				      SilcHashCompare compare,
709 				      void *compare_user_context,
710 				      SilcHashForeach foreach,
711 				      void *foreach_user_context);
712 
713 /****f* silcutil/SilcHashTableAPI/silc_hash_table_rehash_ext
714  *
715  * SYNOPSIS
716  *
717  *    void silc_hash_table_rehash_ext(SilcHashTable ht, SilcUInt32 new_size,
718  *                                    SilcHashFunction hash,
719  *                                    void *hash_user_context);
720  *
721  * DESCRIPTION
722  *
723  *    Rehashs the hash table. The size of the new hash table is provided
724  *    as `new_size'. If the `new_size' is zero then this routine will make
725  *    the new table of a suitable size. Note that this operation may be
726  *    very slow.
727  *
728  *    The `hash' and `hash_user_context' are application specified hash
729  *    function. If not provided the hash table's default is used.
730  *
731  ***/
732 void silc_hash_table_rehash_ext(SilcHashTable ht, SilcUInt32 new_size,
733 				SilcHashFunction hash,
734 				void *hash_user_context);
735 
736 #endif
737