5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 2001 - 2008 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; version 2 of the License.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
20 /****h* silcutil/Hash Table Interface
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 slows down.
28 * However, this is reliable and no data is lost at any point. If you know
29 * that you never have duplicate keys then this is as fast as any simple hash
32 * The interface provides many ways to search the hash table including
33 * an extended interface where caller can specify their own hash and comparison
34 * functions. The interface also supports SilcStack and all memory allocated
35 * by the hash table can be allocated from SilcStack.
37 * There are two ways to traverse the entire hash table if this feature
38 * is needed. There exists a foreach function that calls a foreach
39 * callback for each entry in the hash table. Other way is to use
40 * SilcHashTableList structure and traverse the hash table inside while()
41 * using the list structure. Both are equally fast.
43 * The interface also provides many utility hashing and comparison functions
44 * that caller may use with SilcHashTable.
46 * The hash table is not thread safe. If same SilcHashtable context is used
47 * in multi thread environment concurrency control must be employed.
51 #ifndef SILCHASHTABLE_H
52 #define SILCHASHTABLE_H
54 /****s* silcutil/SilcHashTable
58 * typedef struct SilcHashTableStruct *SilcHashTable;
62 * This context is the actual hash table and is allocated
63 * by silc_hash_table_alloc and given as argument usually to
64 * all silc_hash_table_* functions. It is freed by the
65 * silc_hash_table_free function.
68 typedef struct SilcHashTableStruct *SilcHashTable;
70 /****s* silcutil/SilcHashTableList
74 * typedef struct SilcHashTableListStruct SilcHashTableList;
78 * This structure is used to tarverse the hash table. This structure
79 * is given as argument to the silc_hash_table_list function to
80 * initialize it and then used to traverse the hash table with the
81 * silc_hash_table_get function. It needs not be allocated or freed.
85 * SilcHashTableList htl;
86 * silc_hash_table_list(hash_table, &htl);
87 * while (silc_hash_table_get(&htl, (void *)&key, (void *)&context))
89 * silc_hash_table_list_reset(&htl);
93 typedef struct SilcHashTableListStruct SilcHashTableList;
95 /* List structure to traverse the hash table. */
96 struct SilcHashTableListStruct {
99 unsigned int index : 31;
100 unsigned int auto_rehash : 1;
104 /****f* silcutil/SilcHashFunction
108 * typedef SilcUInt32 (*SilcHashFunction)(void *key, void *user_context);
112 * A type for the hash function. This function is used to hash the
113 * provided key value `key' and return the index for the hash table.
114 * The `user_context' is application specific context and is delivered
118 typedef SilcUInt32 (*SilcHashFunction)(void *key, void *user_context);
120 /****f* silcutil/SilcHashCompare
124 * typedef SilcBool (*SilcHashCompare)(void *key1, void *key2,
125 * void *user_context);
129 * A comparison funtion that is called to compare the two keys `key1' and
130 * `key2'. If they are equal this must return TRUE or FALSE otherwise.
131 * The application provides this function when allocating a new hash table.
132 * The `user_context' is application specific context and is delivered
136 typedef SilcBool (*SilcHashCompare)(void *key1, void *key2,
139 /****f* silcutil/SilcHashDestructor
143 * typedef void (*SilcHashDestructor)(void *key, void *context,
144 * void *user_context);
148 * A destructor callback that the library will call to destroy the
149 * `key' and `context'. The application provides the function when
150 * allocating a new hash table. The `user_context' is application
151 * specific context and is delivered to the callback.
154 typedef void (*SilcHashDestructor)(void *key, void *context,
157 /****f* silcutil/SilcHashForeach
161 * typedef void (*SilcHashForeach)(void *key, void *context,
162 * void *user_context);
166 * Foreach function. This is called when traversing the entrys in the
167 * hash table using silc_hash_table_foreach. The `user_context' is
168 * application specific context and is delivered to the callback.
171 typedef void (*SilcHashForeach)(void *key, void *context, void *user_context);
173 /* Simple hash table interface */
175 /****f* silcutil/silc_hash_table_alloc
179 * SilcHashTable silc_hash_table_alloc(SilcStack stack,
180 * SilcUInt32 table_size,
181 * SilcHashFunction hash,
182 * void *hash_user_context,
183 * SilcHashCompare compare,
184 * void *compare_user_context,
185 * SilcHashDestructor destructor,
186 * void *destructor_user_context,
187 * SilcBool auto_rehash);
191 * Allocates new hash table and returns it. If the `stack' is non-NULL
192 * the hash table is allocated from `stack'. If the `table_size' is not
193 * zero then the hash table size is the size provided. If zero then the
194 * default size will be used. Note that if the `table_size' is provided
195 * it should be a prime. The `hash', `compare' and `destructor' are
196 * the hash function, the key comparison function and key and context
197 * destructor function, respectively. The `hash' is mandatory, the others
198 * are optional. Returns NULL if system is out of memory.
201 SilcHashTable silc_hash_table_alloc(SilcStack stack,
202 SilcUInt32 table_size,
203 SilcHashFunction hash,
204 void *hash_user_context,
205 SilcHashCompare compare,
206 void *compare_user_context,
207 SilcHashDestructor destructor,
208 void *destructor_user_context,
209 SilcBool auto_rehash);
211 /****f* silcutil/silc_hash_table_free
215 * void silc_hash_table_free(SilcHashTable ht);
219 * Frees the hash table. The destructor function provided in the
220 * silc_hash_table_alloc will be called for all keys in the hash table.
222 * If the SilcStack was given to silc_hash_table_alloc this call will
223 * release all memory allocated during the life time of the `ht' back
227 void silc_hash_table_free(SilcHashTable ht);
229 /****f* silcutil/silc_hash_table_size
233 * SilcUInt32 silc_hash_table_size(SilcHashTable ht);
237 * Returns the size of the hash table. This is the true size of the
241 SilcUInt32 silc_hash_table_size(SilcHashTable ht);
243 /****f* silcutil/silc_hash_table_count
247 * SilcUInt32 silc_hash_table_count(SilcHashTable ht);
251 * Returns the number of the entires in the hash table. If there is more
252 * entries in the table thatn the size of the hash table calling the
253 * silc_hash_table_rehash is recommended.
256 SilcUInt32 silc_hash_table_count(SilcHashTable ht);
258 /****f* silcutil/silc_hash_table_add
262 * SilcBool silc_hash_table_add(SilcHashTable ht, void *key, void *context);
266 * Adds new entry to the hash table. The `key' is hashed using the
267 * hash function and the both `key' and `context' will be saved to the
268 * hash table. This function quarantees that the entry is always added
269 * to the hash table reliably (it is collision resistant).
272 SilcBool silc_hash_table_add(SilcHashTable ht, void *key, void *context);
274 /****f* silcutil/silc_hash_table_set
278 * SilcBool silc_hash_table_set(SilcHashTable ht, void *key,
283 * Same as silc_hash_table_add but if the `key' already exists in the
284 * hash table the old key and the old context will be replaced with the
285 * `key' and the `context. The destructor function will be called for the
286 * replaced key and context.
289 SilcBool silc_hash_table_set(SilcHashTable ht, void *key, void *context);
291 /****f* silcutil/silc_hash_table_del
295 * SilcBool silc_hash_table_del(SilcHashTable ht, void *key);
299 * Removes the entry from the hash table by the provided `key'. This will
300 * call the destructor funtion for the found entry. Return TRUE if the
301 * entry was removed successfully and FALSE otherwise.
304 SilcBool silc_hash_table_del(SilcHashTable ht, void *key);
306 /****f* silcutil/silc_hash_table_del_by_context
310 * SilcBool silc_hash_table_del_by_context(SilcHashTable ht, void *key,
315 * Same as silc_hash_table_del but verifies that the context associated
316 * with the `key' matches the `context'. This is handy to use with hash
317 * tables that may have duplicate keys. In that case the `context' may
318 * be used to check whether the correct entry is being deleted.
321 SilcBool silc_hash_table_del_by_context(SilcHashTable ht, void *key,
324 /****f* silcutil/silc_hash_table_find
328 * SilcBool silc_hash_table_find(SilcHashTable ht, void *key,
329 * void **ret_key, void **ret_context);
333 * Finds the entry in the hash table by the provided `key' as fast as
334 * possible. Return TRUE if the entry was found and FALSE otherwise.
335 * The found entry is returned to the `ret_key' and `ret_context',
336 * respectively. If the `ret_key and `ret_context' are NULL then this
337 * maybe used only to check whether given key exists in the table.
340 SilcBool silc_hash_table_find(SilcHashTable ht, void *key,
341 void **ret_key, void **ret_context);
343 /****f* silcutil/silc_hash_table_find_by_context
347 * SilcBool silc_hash_table_find_by_context(SilcHashTable ht, void *key,
348 * void *context, void **ret_key);
352 * Finds the entry in the hash table by the provided `key' and
353 * `context' as fast as possible. This is handy function when there
354 * can be multiple same keys in the hash table. By using this function
355 * the specific key with specific context can be found. Return
356 * TRUE if the entry with the key and context was found and FALSE
357 * otherwise. The function returns only the key to `ret_key' since
358 * the caller already knows the context.
361 SilcBool silc_hash_table_find_by_context(SilcHashTable ht, void *key,
362 void *context, void **ret_key);
364 /****f* silcutil/silc_hash_table_find_foreach
368 * void silc_hash_table_find_foreach(SilcHashTable ht, void *key,
369 * SilcHashForeach foreach,
370 * void *user_context);
374 * As the hash table is collision resistant it is possible to save duplicate
375 * keys to the hash table. This function can be used to find all keys
376 * and contexts from the hash table that are found using the `key'. The
377 * `foreach' is called for every found key. If no entries can be found
378 * the `foreach' will be called once with the context set NULL and
379 * `key' and `user_context' sent to the function.
383 * The hash table will not be rehashed during the traversing of the table,
384 * even if the table was marked as auto rehashable. The caller also must
385 * not call silc_hash_table_rehash while traversing the table.
388 void silc_hash_table_find_foreach(SilcHashTable ht, void *key,
389 SilcHashForeach foreach, void *user_context);
391 /****f* silcutil/silc_hash_table_foreach
395 * void silc_hash_table_foreach(SilcHashTable ht, SilcHashForeach foreach,
396 * void *user_context);
400 * Traverse all entrys in the hash table and call the `foreach' for
401 * every entry with the `user_context' context.
405 * The hash table will not be rehashed during the traversing of the table,
406 * even if the table was marked as auto rehashable. The caller also must
407 * not call silc_hash_table_rehash while traversing the table.
410 void silc_hash_table_foreach(SilcHashTable ht, SilcHashForeach foreach,
413 /****f* silcutil/silc_hash_table_rehash
417 * void silc_hash_table_rehash(SilcHashTable ht, SilcUInt32 new_size);
421 * Rehashs the hash table. The size of the new hash table is provided
422 * as `new_size'. If the `new_size' is zero then this routine will make
423 * the new table of a suitable size. Note that this operation may be
427 void silc_hash_table_rehash(SilcHashTable ht, SilcUInt32 new_size);
429 /****f* silcutil/silc_hash_table_list
433 * void silc_hash_table_list(SilcHashTable ht, SilcHashTableList *htl);
437 * Prepares the `htl' SilcHashTableList sent as argument to be used in the
438 * hash table traversing with the silc_hash_table_get. After the hash
439 * table traversing is completed the silc_hash_table_list_reset must be
444 * The hash table will not be rehashed during the traversing of the list,
445 * even if the table was marked as auto rehashable. The caller also must
446 * not call silc_hash_table_rehash while traversing the list.
449 void silc_hash_table_list(SilcHashTable ht, SilcHashTableList *htl);
451 /****f* silcutil/silc_hash_table_list_reset
455 * void silc_hash_table_list_reset(SilcHashTableList *htl);
459 * Resets the `htl' SilcHashTableList. This must be called after the
460 * hash table traversing is completed.
463 void silc_hash_table_list_reset(SilcHashTableList *htl);
465 /****f* silcutil/silc_hash_table_get
469 * SilcBool silc_hash_table_get(SilcHashTableList *htl, void **key,
474 * Returns always the next entry in the hash table into the `key' and
475 * `context' and TRUE. If this returns FALSE then there are no more
480 * SilcHashTableList htl;
481 * silc_hash_table_list(hash_table, &htl);
482 * while (silc_hash_table_get(&htl, (void *)&key, (void *)&context))
484 * silc_hash_table_list_reset(&htl);
487 SilcBool silc_hash_table_get(SilcHashTableList *htl,
488 void **key, void **context);
491 /* Extended hash table interface (same as above but with specific
492 hash and comparison functions). */
494 /****f* silcutil/silc_hash_table_add_ext
498 * SilcBool silc_hash_table_add_ext(SilcHashTable ht, void *key,
500 * SilcHashFunction hash,
501 * void *hash_user_context);
505 * Adds new entry to the hash table. The `key' is hashed using the
506 * hash function and the both `key' and `context' will be saved to the
507 * hash table. This function quarantees that the entry is always added
508 * to the hash table reliably (it is collision resistant).
510 * The `hash' and `hash_user_context' are application specified hash
511 * function. If not provided the hash table's default is used.
514 SilcBool silc_hash_table_add_ext(SilcHashTable ht,
515 void *key, void *context,
516 SilcHashFunction hash,
517 void *hash_user_context);
519 /****f* silcutil/silc_hash_table_set_ext
523 * SilcBool silc_hash_table_set_ext(SilcHashTable ht, void *key,
525 * SilcHashFunction hash,
526 * void *hash_user_context);
530 * Same as silc_hash_table_add_ext but if the `key' already exists in the
531 * hash table the old key and the old context will be replaced with the
532 * `key' and the `context. The destructor function will be called for the
533 * replaced key and context.
535 * The `hash' and `hash_user_context' are application specified hash
536 * function. If not provided the hash table's default is used.
539 SilcBool silc_hash_table_set_ext(SilcHashTable ht,
540 void *key, void *context,
541 SilcHashFunction hash,
542 void *hash_user_context);
544 /****f* silcutil/silc_hash_table_del_ext
548 * SilcBool silc_hash_table_del_ext(SilcHashTable ht, void *key,
549 * SilcHashFunction hash,
550 * void *hash_user_context,
551 * SilcHashCompare compare,
552 * void *compare_user_context,
553 * SilcHashDestructor destructor,
554 * void *destructor_user_context);
558 * Removes the entry from the hash table by the provided `key'. This will
559 * call the destructor funtion for the found entry. Return TRUE if the
560 * entry was removed successfully and FALSE otherwise.
562 * The `hash' and `hash_user_context' are application specified hash
563 * function. If not provided the hash table's default is used.
564 * The `compare' and `compare_user_context' are application specified
565 * comparing function. If not provided the hash table's default is used.
566 * The `destructor' and `destructor_user_context' are application
567 * specific destructor function.
570 SilcBool silc_hash_table_del_ext(SilcHashTable ht, void *key,
571 SilcHashFunction hash,
572 void *hash_user_context,
573 SilcHashCompare compare,
574 void *compare_user_context,
575 SilcHashDestructor destructor,
576 void *destructor_user_context);
578 /****f* silcutil/silc_hash_table_del_by_context_ext
583 * silc_hash_table_del_by_context_ext(SilcHashTable ht, void *key,
585 * SilcHashFunction hash,
586 * void *hash_user_context,
587 * SilcHashCompare compare,
588 * void *compare_user_context,
589 * SilcHashDestructor destructor,
590 * void *destructor_user_context);
594 * Same as silc_hash_table_del but verifies that the context associated
595 * with the `key' matches the `context'. This is handy to use with hash
596 * tables that may have duplicate keys. In that case the `context' may
597 * be used to check whether the correct entry is being deleted.
599 * The `hash' and `hash_user_context' are application specified hash
600 * function. If not provided the hash table's default is used.
601 * The `compare' and `compare_user_context' are application specified
602 * comparing function. If not provided the hash table's default is used.
603 * The `destructor' and `destructor_user_context' are application
604 * specific destructor function.
607 SilcBool silc_hash_table_del_by_context_ext(SilcHashTable ht, void *key,
609 SilcHashFunction hash,
610 void *hash_user_context,
611 SilcHashCompare compare,
612 void *compare_user_context,
613 SilcHashDestructor destructor,
614 void *destructor_user_context);
616 /****f* silcutil/silc_hash_table_find_ext
620 * SilcBool silc_hash_table_find_ext(SilcHashTable ht, void *key,
621 * void **ret_key, void **ret_context,
622 * SilcHashFunction hash,
623 * void *hash_user_context,
624 * SilcHashCompare compare,
625 * void *compare_user_context);
629 * Finds the entry in the hash table by the provided `key' as fast as
630 * possible. Return TRUE if the entry was found and FALSE otherwise.
631 * The found entry is returned to the `ret_key' and `ret_context',
632 * respectively. If the `ret_key and `ret_context' are NULL then this
633 * maybe used only to check whether given key exists in the table.
635 * The `hash' and `hash_user_context' are application specified hash
636 * function. If not provided the hash table's default is used.
637 * The `compare' and `compare_user_context' are application specified
638 * comparing function. If not provided the hash table's default is used.
641 SilcBool silc_hash_table_find_ext(SilcHashTable ht, void *key,
642 void **ret_key, void **ret_context,
643 SilcHashFunction hash,
644 void *hash_user_context,
645 SilcHashCompare compare,
646 void *compare_user_context);
648 /****f* silcutil/silc_hash_table_find_by_context_ext
653 * silc_hash_table_find_by_context_ext(SilcHashTable ht, void *key,
654 * void *context, void **ret_key,
655 * SilcHashFunction hash,
656 * void *hash_user_context,
657 * SilcHashCompare compare,
658 * void *compare_user_context);
662 * Finds the entry in the hash table by the provided `key' and
663 * `context' as fast as possible. This is handy function when there
664 * can be multiple same keys in the hash table. By using this function
665 * the specific key with specific context can be found. Return
666 * TRUE if the entry with the key and context was found and FALSE
667 * otherwise. The function returns only the key to `ret_key' since
668 * the caller already knows the context.
670 * The `hash' and `hash_user_context' are application specified hash
671 * function. If not provided the hash table's default is used.
672 * The `compare' and `compare_user_context' are application specified
673 * comparing function. If not provided the hash table's default is used.
676 SilcBool silc_hash_table_find_by_context_ext(SilcHashTable ht, void *key,
677 void *context, void **ret_key,
678 SilcHashFunction hash,
679 void *hash_user_context,
680 SilcHashCompare compare,
681 void *compare_user_context);
683 /****f* silcutil/silc_hash_table_find_foreach_ext
687 * void silc_hash_table_find_foreach_ext(SilcHashTable ht, void *key,
688 * SilcHashFunction hash,
689 * void *hash_user_context,
690 * SilcHashCompare compare,
691 * void *compare_user_context,
692 * SilcHashForeach foreach,
693 * void *foreach_user_context);
697 * As the hash table is collision resistant it is possible to save duplicate
698 * keys to the hash table. This function can be used to find all keys
699 * and contexts from the hash table that are found using the `key'. The
700 * `foreach' is called for every found key. If no entries can be found
701 * the `foreach' will be called once with the context set NULL and
702 * `key' and `user_context' sent to the function.
704 * The `hash' and `hash_user_context' are application specified hash
705 * function. If not provided the hash table's default is used.
706 * The `compare' and `compare_user_context' are application specified
707 * comparing function. If not provided the hash table's default is used.
711 * The hash table will not be rehashed during the traversing of the table,
712 * even if the table was marked as auto rehashable. The caller also must
713 * not call silc_hash_table_rehash while traversing the table.
716 void silc_hash_table_find_foreach_ext(SilcHashTable ht, void *key,
717 SilcHashFunction hash,
718 void *hash_user_context,
719 SilcHashCompare compare,
720 void *compare_user_context,
721 SilcHashForeach foreach,
722 void *foreach_user_context);
724 /****f* silcutil/silc_hash_table_rehash_ext
728 * void silc_hash_table_rehash_ext(SilcHashTable ht, SilcUInt32 new_size,
729 * SilcHashFunction hash,
730 * void *hash_user_context);
734 * Rehashs the hash table. The size of the new hash table is provided
735 * as `new_size'. If the `new_size' is zero then this routine will make
736 * the new table of a suitable size. Note that this operation may be
739 * The `hash' and `hash_user_context' are application specified hash
740 * function. If not provided the hash table's default is used.
743 void silc_hash_table_rehash_ext(SilcHashTable ht, SilcUInt32 new_size,
744 SilcHashFunction hash,
745 void *hash_user_context);
749 /****f* silcutil/silc_hash_string
753 * SilcUInt32 silc_hash_string(void *key, void *user_context);
757 * Basic hash function to hash strings. May be used with the SilcHashTable.
758 * This uses Bob Jenkin's one-at-a-time (described in Wikipedia) hash
762 SilcUInt32 silc_hash_string(void *key, void *user_context);
764 /****f* silcutil/silc_hash_string_case
768 * SilcUInt32 silc_hash_string_case(void *key, void *user_context);
772 * Basic hash function to hash strings. May be used with the SilcHashTable.
773 * This ignores the string's case, ie. 'Foo' and 'foo' will hash to same
774 * value. This uses Bob Jenkin's one-at-a-time (described in Wikipedia)
778 SilcUInt32 silc_hash_string_case(void *key, void *user_context);
780 /****f* silcutil/silc_hash_utf8_string
784 * SilcUInt32 silc_hash_utf8_string(void *key, void *user_context);
788 * Basic has function to hash UTF-8 strings. May be used with the
789 * SilcHashTable. Used with identifier strings. The key is
790 * expected to be casefolded.
793 SilcUInt32 silc_hash_utf8_string(void *key, void *user_context);
795 /****f* silcutil/silc_hash_uint
799 * SilcUInt32 silc_hash_uint(void *key, void *user_context);
803 * Basic hash function to hash integers. May be used with the SilcHashTable.
804 * Comparison function is not needed, the SilcHashTable will automatically
805 * compare integer values.
808 SilcUInt32 silc_hash_uint(void *key, void *user_context);
810 /****f* silcutil/silc_hash_ptr
814 * SilcUInt32 silc_hash_ptr(void *key, void *user_context);
818 * Basic hash funtion to hash pointers. May be used with the SilcHashTable.
819 * Comparison function is not needed, the SilcHashTable will automatically
820 * compare pointer values.
823 SilcUInt32 silc_hash_ptr(void *key, void *user_context);
825 /****f* silcutil/silc_hash_data
829 * SilcUInt32 silc_hash_data(void *key, void *user_context);
833 * Hash binary data. The `user_context' is the data length. This uses Bob
834 * Jenkin's one-at-a-time (described in Wikipedia) hash function.
837 SilcUInt32 silc_hash_data(void *key, void *user_context);
839 /* Comparison functions */
841 /****f* silcutil/silc_hash_string_compare
845 * SilcBool silc_hash_string_compare(void *key1, void *key2,
846 * void *user_context);
850 * Compares two strings. It may be used as SilcHashTable comparison
854 SilcBool silc_hash_string_compare(void *key1, void *key2, void *user_context);
856 /****f* silcutil/silc_hash_string_case_compare
860 * SilcBool silc_hash_string_case_compare(void *key1, void *key2,
861 * void *user_context);
865 * Compares two strings. This ignores the case while comparing. It may
866 * be used as SilcHashTable comparison function.
869 SilcBool silc_hash_string_case_compare(void *key1, void *key2,
872 /****f* silcutil/silc_hash_utf8_compare
876 * SilcBool silc_hash_utf8_compare(void *key1, void *key2,
877 * void *user_context);
881 * Compares UTF-8 strings. Casefolded and NULL terminated strings are
882 * expected. May be used as SilcHashTable comparison function.
885 SilcBool silc_hash_utf8_compare(void *key1, void *key2, void *user_context);
887 /****f* silcutil/silc_hash_data_compare
891 * SilcBool silc_hash_data_compare(void *key1, void *key2,
892 * void *user_context);
896 * Compares binary data. May be used as SilcHashTable comparison function.
899 SilcBool silc_hash_data_compare(void *key1, void *key2, void *user_context);
901 /* Destructor functions */
903 /****f* silcutil/silc_hash_destructor
907 * void silc_hash_destructor(void *key, void *context, void *user_context);
911 * A generic destructor for SilcHashTable. This will call silc_free for
912 * `key' and `context'.
915 void silc_hash_destructor(void *key, void *context, void *user_context);