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 * A collision resistant hash table API. This is a hash table that provides
25 * a reliable hash table (what you add there stays there, and duplicate keys
26 * are allowed) with as fast reference to the key as possible. If there are
27 * a lot of duplicate keys in the hash table the lookup slows down. However,
28 * this is reliable and no data is lost at any point. If you know that you
29 * never have duplicate keys then this is as fast as any simple hash table.
31 * The interface provides many ways to search the hash table including
32 * an extended interface where caller can specify their own hash and comparison
33 * functions. The interface also supports SilcStack and all memory allocated
34 * by the hash table can be allocated from SilcStack.
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.
42 * The interface also provides many utility hashing and comparison functions
43 * that caller may use with SilcHashTable.
45 * The hash table is not thread safe. If same SilcHashtable context is used
46 * in multi thread environment concurrency control must be employed.
50 #ifndef SILCHASHTABLE_H
51 #define SILCHASHTABLE_H
53 /****s* silcutil/SilcHashTable
57 * typedef struct SilcHashTableStruct *SilcHashTable;
61 * This context is the actual hash table and is allocated
62 * by silc_hash_table_alloc and given as argument usually to
63 * all silc_hash_table_* functions. It is freed by the
64 * silc_hash_table_free function.
67 typedef struct SilcHashTableStruct *SilcHashTable;
69 /****s* silcutil/SilcHashTableList
73 * typedef struct SilcHashTableListStruct SilcHashTableList;
77 * This structure is used to tarverse the hash table. This structure
78 * is given as argument to the silc_hash_table_list function to
79 * initialize it and then used to traverse the hash table with the
80 * silc_hash_table_get function. It needs not be allocated or freed.
84 * SilcHashTableList htl;
85 * silc_hash_table_list(hash_table, &htl);
86 * while (silc_hash_table_get(&htl, (void *)&key, (void *)&context))
88 * silc_hash_table_list_reset(&htl);
92 typedef struct SilcHashTableListStruct SilcHashTableList;
94 /* List structure to traverse the hash table. */
95 struct SilcHashTableListStruct {
98 unsigned int index : 31;
99 unsigned int auto_rehash : 1;
103 /****f* silcutil/SilcHashFunction
107 * typedef SilcUInt32 (*SilcHashFunction)(void *key, void *user_context);
111 * A type for the hash function. This function is used to hash the
112 * provided key value `key' and return the index for the hash table.
113 * The `user_context' is application specific context and is delivered
117 typedef SilcUInt32 (*SilcHashFunction)(void *key, void *user_context);
119 /****f* silcutil/SilcHashCompare
123 * typedef SilcBool (*SilcHashCompare)(void *key1, void *key2,
124 * void *user_context);
128 * A comparison funtion that is called to compare the two keys `key1' and
129 * `key2'. If they are equal this must return TRUE or FALSE otherwise.
130 * The application provides this function when allocating a new hash table.
131 * The `user_context' is application specific context and is delivered
135 typedef SilcBool (*SilcHashCompare)(void *key1, void *key2,
138 /****f* silcutil/SilcHashDestructor
142 * typedef void (*SilcHashDestructor)(void *key, void *context,
143 * void *user_context);
147 * A destructor callback that the library will call to destroy the
148 * `key' and `context'. The application provides the function when
149 * allocating a new hash table. The `user_context' is application
150 * specific context and is delivered to the callback.
153 typedef void (*SilcHashDestructor)(void *key, void *context,
156 /****f* silcutil/SilcHashForeach
160 * typedef void (*SilcHashForeach)(void *key, void *context,
161 * void *user_context);
165 * Foreach function. This is called when traversing the entrys in the
166 * hash table using silc_hash_table_foreach. The `user_context' is
167 * application specific context and is delivered to the callback.
170 typedef void (*SilcHashForeach)(void *key, void *context, void *user_context);
172 /* Simple hash table interface */
174 /****f* silcutil/silc_hash_table_alloc
178 * SilcHashTable silc_hash_table_alloc(SilcStack stack,
179 * SilcUInt32 table_size,
180 * SilcHashFunction hash,
181 * void *hash_user_context,
182 * SilcHashCompare compare,
183 * void *compare_user_context,
184 * SilcHashDestructor destructor,
185 * void *destructor_user_context,
186 * SilcBool auto_rehash);
190 * Allocates new hash table and returns it. If the `stack' is non-NULL
191 * the hash table is allocated from `stack'. If the `table_size' is not
192 * zero then the hash table size is the size provided. If zero then the
193 * default size will be used. Note that if the `table_size' is provided
194 * it should be a prime. The `hash', `compare' and `destructor' are
195 * the hash function, the key comparison function and key and context
196 * destructor function, respectively. The `hash' is mandatory, the others
197 * are optional. Returns NULL if system is out of memory.
200 SilcHashTable silc_hash_table_alloc(SilcStack stack,
201 SilcUInt32 table_size,
202 SilcHashFunction hash,
203 void *hash_user_context,
204 SilcHashCompare compare,
205 void *compare_user_context,
206 SilcHashDestructor destructor,
207 void *destructor_user_context,
208 SilcBool auto_rehash);
210 /****f* silcutil/silc_hash_table_free
214 * void silc_hash_table_free(SilcHashTable ht);
218 * Frees the hash table. The destructor function provided in the
219 * silc_hash_table_alloc will be called for all keys in the hash table.
221 * If the SilcStack was given to silc_hash_table_alloc this call will
222 * release all memory allocated during the life time of the `ht' back
226 void silc_hash_table_free(SilcHashTable ht);
228 /****f* silcutil/silc_hash_table_size
232 * SilcUInt32 silc_hash_table_size(SilcHashTable ht);
236 * Returns the size of the hash table. This is the true size of the
240 SilcUInt32 silc_hash_table_size(SilcHashTable ht);
242 /****f* silcutil/silc_hash_table_count
246 * SilcUInt32 silc_hash_table_count(SilcHashTable ht);
250 * Returns the number of the entires in the hash table. If there is more
251 * entries in the table thatn the size of the hash table calling the
252 * silc_hash_table_rehash is recommended.
255 SilcUInt32 silc_hash_table_count(SilcHashTable ht);
257 /****f* silcutil/silc_hash_table_add
261 * SilcBool silc_hash_table_add(SilcHashTable ht, void *key, void *context);
265 * Adds new entry to the hash table. The `key' is hashed using the
266 * hash function and the both `key' and `context' will be saved to the
267 * hash table. This function quarantees that the entry is always added
268 * to the hash table reliably (it is collision resistant).
271 SilcBool silc_hash_table_add(SilcHashTable ht, void *key, void *context);
273 /****f* silcutil/silc_hash_table_set
277 * SilcBool silc_hash_table_set(SilcHashTable ht, void *key,
282 * Same as silc_hash_table_add but if the `key' already exists in the
283 * hash table the old key and the old context will be replaced with the
284 * `key' and the `context. The destructor function will be called for the
285 * replaced key and context.
288 SilcBool silc_hash_table_set(SilcHashTable ht, void *key, void *context);
290 /****f* silcutil/silc_hash_table_del
294 * SilcBool silc_hash_table_del(SilcHashTable ht, void *key);
298 * Removes the entry from the hash table by the provided `key'. This will
299 * call the destructor funtion for the found entry. Return TRUE if the
300 * entry was removed successfully and FALSE otherwise.
303 SilcBool silc_hash_table_del(SilcHashTable ht, void *key);
305 /****f* silcutil/silc_hash_table_del_by_context
309 * SilcBool silc_hash_table_del_by_context(SilcHashTable ht, void *key,
314 * Same as silc_hash_table_del but verifies that the context associated
315 * with the `key' matches the `context'. This is handy to use with hash
316 * tables that may have duplicate keys. In that case the `context' may
317 * be used to check whether the correct entry is being deleted.
320 SilcBool silc_hash_table_del_by_context(SilcHashTable ht, void *key,
323 /****f* silcutil/silc_hash_table_find
327 * SilcBool silc_hash_table_find(SilcHashTable ht, void *key,
328 * void **ret_key, void **ret_context);
332 * Finds the entry in the hash table by the provided `key' as fast as
333 * possible. Return TRUE if the entry was found and FALSE otherwise.
334 * The found entry is returned to the `ret_key' and `ret_context',
335 * respectively. If the `ret_key and `ret_context' are NULL then this
336 * maybe used only to check whether given key exists in the table.
339 SilcBool silc_hash_table_find(SilcHashTable ht, void *key,
340 void **ret_key, void **ret_context);
342 /****f* silcutil/silc_hash_table_find_by_context
346 * SilcBool silc_hash_table_find_by_context(SilcHashTable ht, void *key,
347 * void *context, void **ret_key);
351 * Finds the entry in the hash table by the provided `key' and
352 * `context' as fast as possible. This is handy function when there
353 * can be multiple same keys in the hash table. By using this function
354 * the specific key with specific context can be found. Return
355 * TRUE if the entry with the key and context was found and FALSE
356 * otherwise. The function returns only the key to `ret_key' since
357 * the caller already knows the context.
360 SilcBool silc_hash_table_find_by_context(SilcHashTable ht, void *key,
361 void *context, void **ret_key);
363 /****f* silcutil/silc_hash_table_find_foreach
367 * void silc_hash_table_find_foreach(SilcHashTable ht, void *key,
368 * SilcHashForeach foreach,
369 * void *user_context);
373 * As the hash table is collision resistant it is possible to save duplicate
374 * keys to the hash table. This function can be used to find all keys
375 * and contexts from the hash table that are found using the `key'. The
376 * `foreach' is called for every found key. If no entries can be found
377 * the `foreach' will be called once with the context set NULL and
378 * `key' and `user_context' sent to the function.
382 * The hash table will not be rehashed during the traversing of the table,
383 * even if the table was marked as auto rehashable. The caller also must
384 * not call silc_hash_table_rehash while traversing the table.
387 void silc_hash_table_find_foreach(SilcHashTable ht, void *key,
388 SilcHashForeach foreach, void *user_context);
390 /****f* silcutil/silc_hash_table_foreach
394 * void silc_hash_table_foreach(SilcHashTable ht, SilcHashForeach foreach,
395 * void *user_context);
399 * Traverse all entrys in the hash table and call the `foreach' for
400 * every entry with the `user_context' context.
404 * The hash table will not be rehashed during the traversing of the table,
405 * even if the table was marked as auto rehashable. The caller also must
406 * not call silc_hash_table_rehash while traversing the table.
409 void silc_hash_table_foreach(SilcHashTable ht, SilcHashForeach foreach,
412 /****f* silcutil/silc_hash_table_rehash
416 * void silc_hash_table_rehash(SilcHashTable ht, SilcUInt32 new_size);
420 * Rehashs the hash table. The size of the new hash table is provided
421 * as `new_size'. If the `new_size' is zero then this routine will make
422 * the new table of a suitable size. Note that this operation may be
426 void silc_hash_table_rehash(SilcHashTable ht, SilcUInt32 new_size);
428 /****f* silcutil/silc_hash_table_list
432 * void silc_hash_table_list(SilcHashTable ht, SilcHashTableList *htl);
436 * Prepares the `htl' SilcHashTableList sent as argument to be used in the
437 * hash table traversing with the silc_hash_table_get. After the hash
438 * table traversing is completed the silc_hash_table_list_reset must be
443 * The hash table will not be rehashed during the traversing of the list,
444 * even if the table was marked as auto rehashable. The caller also must
445 * not call silc_hash_table_rehash while traversing the list.
448 void silc_hash_table_list(SilcHashTable ht, SilcHashTableList *htl);
450 /****f* silcutil/silc_hash_table_list_reset
454 * void silc_hash_table_list_reset(SilcHashTableList *htl);
458 * Resets the `htl' SilcHashTableList. This must be called after the
459 * hash table traversing is completed.
462 void silc_hash_table_list_reset(SilcHashTableList *htl);
464 /****f* silcutil/silc_hash_table_get
468 * SilcBool silc_hash_table_get(SilcHashTableList *htl, void **key,
473 * Returns always the next entry in the hash table into the `key' and
474 * `context' and TRUE. If this returns FALSE then there are no more
479 * SilcHashTableList htl;
480 * silc_hash_table_list(hash_table, &htl);
481 * while (silc_hash_table_get(&htl, (void *)&key, (void *)&context))
483 * silc_hash_table_list_reset(&htl);
486 SilcBool silc_hash_table_get(SilcHashTableList *htl,
487 void **key, void **context);
490 /* Extended hash table interface (same as above but with specific
491 hash and comparison functions). */
493 /****f* silcutil/silc_hash_table_add_ext
497 * SilcBool silc_hash_table_add_ext(SilcHashTable ht, void *key,
499 * SilcHashFunction hash,
500 * void *hash_user_context);
504 * Adds new entry to the hash table. The `key' is hashed using the
505 * hash function and the both `key' and `context' will be saved to the
506 * hash table. This function quarantees that the entry is always added
507 * to the hash table reliably (it is collision resistant).
509 * The `hash' and `hash_user_context' are application specified hash
510 * function. If not provided the hash table's default is used.
513 SilcBool silc_hash_table_add_ext(SilcHashTable ht,
514 void *key, void *context,
515 SilcHashFunction hash,
516 void *hash_user_context);
518 /****f* silcutil/silc_hash_table_set_ext
522 * SilcBool silc_hash_table_set_ext(SilcHashTable ht, void *key,
524 * SilcHashFunction hash,
525 * void *hash_user_context);
529 * Same as silc_hash_table_add_ext but if the `key' already exists in the
530 * hash table the old key and the old context will be replaced with the
531 * `key' and the `context. The destructor function will be called for the
532 * replaced key and context.
534 * The `hash' and `hash_user_context' are application specified hash
535 * function. If not provided the hash table's default is used.
538 SilcBool silc_hash_table_set_ext(SilcHashTable ht,
539 void *key, void *context,
540 SilcHashFunction hash,
541 void *hash_user_context);
543 /****f* silcutil/silc_hash_table_del_ext
547 * SilcBool silc_hash_table_del_ext(SilcHashTable ht, void *key,
548 * SilcHashFunction hash,
549 * void *hash_user_context,
550 * SilcHashCompare compare,
551 * void *compare_user_context,
552 * SilcHashDestructor destructor,
553 * void *destructor_user_context);
557 * Removes the entry from the hash table by the provided `key'. This will
558 * call the destructor funtion for the found entry. Return TRUE if the
559 * entry was removed successfully and FALSE otherwise.
561 * The `hash' and `hash_user_context' are application specified hash
562 * function. If not provided the hash table's default is used.
563 * The `compare' and `compare_user_context' are application specified
564 * comparing function. If not provided the hash table's default is used.
565 * The `destructor' and `destructor_user_context' are application
566 * specific destructor function.
569 SilcBool silc_hash_table_del_ext(SilcHashTable ht, void *key,
570 SilcHashFunction hash,
571 void *hash_user_context,
572 SilcHashCompare compare,
573 void *compare_user_context,
574 SilcHashDestructor destructor,
575 void *destructor_user_context);
577 /****f* silcutil/silc_hash_table_del_by_context_ext
582 * silc_hash_table_del_by_context_ext(SilcHashTable ht, void *key,
584 * SilcHashFunction hash,
585 * void *hash_user_context,
586 * SilcHashCompare compare,
587 * void *compare_user_context,
588 * SilcHashDestructor destructor,
589 * void *destructor_user_context);
593 * Same as silc_hash_table_del but verifies that the context associated
594 * with the `key' matches the `context'. This is handy to use with hash
595 * tables that may have duplicate keys. In that case the `context' may
596 * be used to check whether the correct entry is being deleted.
598 * The `hash' and `hash_user_context' are application specified hash
599 * function. If not provided the hash table's default is used.
600 * The `compare' and `compare_user_context' are application specified
601 * comparing function. If not provided the hash table's default is used.
602 * The `destructor' and `destructor_user_context' are application
603 * specific destructor function.
606 SilcBool silc_hash_table_del_by_context_ext(SilcHashTable ht, void *key,
608 SilcHashFunction hash,
609 void *hash_user_context,
610 SilcHashCompare compare,
611 void *compare_user_context,
612 SilcHashDestructor destructor,
613 void *destructor_user_context);
615 /****f* silcutil/silc_hash_table_find_ext
619 * SilcBool silc_hash_table_find_ext(SilcHashTable ht, void *key,
620 * void **ret_key, void **ret_context,
621 * SilcHashFunction hash,
622 * void *hash_user_context,
623 * SilcHashCompare compare,
624 * void *compare_user_context);
628 * Finds the entry in the hash table by the provided `key' as fast as
629 * possible. Return TRUE if the entry was found and FALSE otherwise.
630 * The found entry is returned to the `ret_key' and `ret_context',
631 * respectively. If the `ret_key and `ret_context' are NULL then this
632 * maybe used only to check whether given key exists in the table.
634 * The `hash' and `hash_user_context' are application specified hash
635 * function. If not provided the hash table's default is used.
636 * The `compare' and `compare_user_context' are application specified
637 * comparing function. If not provided the hash table's default is used.
640 SilcBool silc_hash_table_find_ext(SilcHashTable ht, void *key,
641 void **ret_key, void **ret_context,
642 SilcHashFunction hash,
643 void *hash_user_context,
644 SilcHashCompare compare,
645 void *compare_user_context);
647 /****f* silcutil/silc_hash_table_find_by_context_ext
652 * silc_hash_table_find_by_context_ext(SilcHashTable ht, void *key,
653 * void *context, void **ret_key,
654 * SilcHashFunction hash,
655 * void *hash_user_context,
656 * SilcHashCompare compare,
657 * void *compare_user_context);
661 * Finds the entry in the hash table by the provided `key' and
662 * `context' as fast as possible. This is handy function when there
663 * can be multiple same keys in the hash table. By using this function
664 * the specific key with specific context can be found. Return
665 * TRUE if the entry with the key and context was found and FALSE
666 * otherwise. The function returns only the key to `ret_key' since
667 * the caller already knows the context.
669 * The `hash' and `hash_user_context' are application specified hash
670 * function. If not provided the hash table's default is used.
671 * The `compare' and `compare_user_context' are application specified
672 * comparing function. If not provided the hash table's default is used.
675 SilcBool silc_hash_table_find_by_context_ext(SilcHashTable ht, void *key,
676 void *context, void **ret_key,
677 SilcHashFunction hash,
678 void *hash_user_context,
679 SilcHashCompare compare,
680 void *compare_user_context);
682 /****f* silcutil/silc_hash_table_find_foreach_ext
686 * void silc_hash_table_find_foreach_ext(SilcHashTable ht, void *key,
687 * SilcHashFunction hash,
688 * void *hash_user_context,
689 * SilcHashCompare compare,
690 * void *compare_user_context,
691 * SilcHashForeach foreach,
692 * void *foreach_user_context);
696 * As the hash table is collision resistant it is possible to save duplicate
697 * keys to the hash table. This function can be used to find all keys
698 * and contexts from the hash table that are found using the `key'. The
699 * `foreach' is called for every found key. If no entries can be found
700 * the `foreach' will be called once with the context set NULL and
701 * `key' and `user_context' sent to the function.
703 * The `hash' and `hash_user_context' are application specified hash
704 * function. If not provided the hash table's default is used.
705 * The `compare' and `compare_user_context' are application specified
706 * comparing function. If not provided the hash table's default is used.
710 * The hash table will not be rehashed during the traversing of the table,
711 * even if the table was marked as auto rehashable. The caller also must
712 * not call silc_hash_table_rehash while traversing the table.
715 void silc_hash_table_find_foreach_ext(SilcHashTable ht, void *key,
716 SilcHashFunction hash,
717 void *hash_user_context,
718 SilcHashCompare compare,
719 void *compare_user_context,
720 SilcHashForeach foreach,
721 void *foreach_user_context);
723 /****f* silcutil/silc_hash_table_rehash_ext
727 * void silc_hash_table_rehash_ext(SilcHashTable ht, SilcUInt32 new_size,
728 * SilcHashFunction hash,
729 * void *hash_user_context);
733 * Rehashs the hash table. The size of the new hash table is provided
734 * as `new_size'. If the `new_size' is zero then this routine will make
735 * the new table of a suitable size. Note that this operation may be
738 * The `hash' and `hash_user_context' are application specified hash
739 * function. If not provided the hash table's default is used.
742 void silc_hash_table_rehash_ext(SilcHashTable ht, SilcUInt32 new_size,
743 SilcHashFunction hash,
744 void *hash_user_context);
748 /****f* silcutil/silc_hash_string
752 * SilcUInt32 silc_hash_string(void *key, void *user_context);
756 * Basic hash function to hash strings. May be used with the SilcHashTable.
757 * This uses Bob Jenkin's one-at-a-time (described in Wikipedia) hash
761 SilcUInt32 silc_hash_string(void *key, void *user_context);
763 /****f* silcutil/silc_hash_string_case
767 * SilcUInt32 silc_hash_string_case(void *key, void *user_context);
771 * Basic hash function to hash strings. May be used with the SilcHashTable.
772 * This ignores the string's case, ie. 'Foo' and 'foo' will hash to same
773 * value. This uses Bob Jenkin's one-at-a-time (described in Wikipedia)
777 SilcUInt32 silc_hash_string_case(void *key, void *user_context);
779 /****f* silcutil/silc_hash_utf8_string
783 * SilcUInt32 silc_hash_utf8_string(void *key, void *user_context);
787 * Basic has function to hash UTF-8 strings. May be used with the
788 * SilcHashTable. Used with identifier strings. The key is
789 * expected to be casefolded.
792 SilcUInt32 silc_hash_utf8_string(void *key, void *user_context);
794 /****f* silcutil/silc_hash_uint
798 * SilcUInt32 silc_hash_uint(void *key, void *user_context);
802 * Basic hash function to hash integers. May be used with the SilcHashTable.
803 * Comparison function is not needed, the SilcHashTable will automatically
804 * compare integer values.
807 SilcUInt32 silc_hash_uint(void *key, void *user_context);
809 /****f* silcutil/silc_hash_ptr
813 * SilcUInt32 silc_hash_ptr(void *key, void *user_context);
817 * Basic hash funtion to hash pointers. May be used with the SilcHashTable.
818 * Comparison function is not needed, the SilcHashTable will automatically
819 * compare pointer values.
822 SilcUInt32 silc_hash_ptr(void *key, void *user_context);
824 /****f* silcutil/silc_hash_data
828 * SilcUInt32 silc_hash_data(void *key, void *user_context);
832 * Hash binary data. The `user_context' is the data length. This uses Bob
833 * Jenkin's one-at-a-time (described in Wikipedia) hash function.
836 SilcUInt32 silc_hash_data(void *key, void *user_context);
838 /* Comparison functions */
840 /****f* silcutil/silc_hash_string_compare
844 * SilcBool silc_hash_string_compare(void *key1, void *key2,
845 * void *user_context);
849 * Compares two strings. It may be used as SilcHashTable comparison
853 SilcBool silc_hash_string_compare(void *key1, void *key2, void *user_context);
855 /****f* silcutil/silc_hash_string_case_compare
859 * SilcBool silc_hash_string_case_compare(void *key1, void *key2,
860 * void *user_context);
864 * Compares two strings. This ignores the case while comparing. It may
865 * be used as SilcHashTable comparison function.
868 SilcBool silc_hash_string_case_compare(void *key1, void *key2,
871 /****f* silcutil/silc_hash_utf8_compare
875 * SilcBool silc_hash_utf8_compare(void *key1, void *key2,
876 * void *user_context);
880 * Compares UTF-8 strings. Casefolded and NULL terminated strings are
881 * expected. May be used as SilcHashTable comparison function.
884 SilcBool silc_hash_utf8_compare(void *key1, void *key2, void *user_context);
886 /****f* silcutil/silc_hash_data_compare
890 * SilcBool silc_hash_data_compare(void *key1, void *key2,
891 * void *user_context);
895 * Compares binary data. May be used as SilcHashTable comparison function.
898 SilcBool silc_hash_data_compare(void *key1, void *key2, void *user_context);
900 /* Destructor functions */
902 /****f* silcutil/silc_hash_destructor
906 * void silc_hash_destructor(void *key, void *context, void *user_context);
910 * A generic destructor for SilcHashTable. This will call silc_free for
911 * `key' and `context'.
914 void silc_hash_destructor(void *key, void *context, void *user_context);