erlang各种有用的函数包括一些有用nif封装,还有一些性能测试case。
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

240 lines
9.1 KiB

5 years ago
  1. /*
  2. * Hash Table Data Type
  3. * Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net>
  4. *
  5. * Free Software License:
  6. *
  7. * All rights are reserved by the author, with the following exceptions:
  8. * Permission is granted to freely reproduce and distribute this software,
  9. * possibly in exchange for a fee, provided that this copyright notice appears
  10. * intact. Permission is also granted to adapt this software to produce
  11. * derivative works, as long as the modified versions carry this copyright
  12. * notice and additional notices stating that the work has been modified.
  13. * This source code may be translated into executable form and incorporated
  14. * into proprietary software; there is no requirement for such software to
  15. * contain a copyright notice related to this source.
  16. *
  17. * $Id: hash.h,v 1.22.2.7 2000/11/13 01:36:45 kaz Exp $
  18. * $Name: kazlib_1_20 $
  19. */
  20. #ifndef HASH_H
  21. #define HASH_H
  22. #include <limits.h>
  23. #ifdef KAZLIB_SIDEEFFECT_DEBUG
  24. #include "sfx.h"
  25. #endif
  26. /*
  27. * Blurb for inclusion into C++ translation units
  28. */
  29. #ifdef __cplusplus
  30. extern "C" {
  31. #endif
  32. typedef unsigned long hashcount_t;
  33. #define HASHCOUNT_T_MAX ULONG_MAX
  34. typedef unsigned long hash_val_t;
  35. #define HASH_VAL_T_MAX ULONG_MAX
  36. extern int hash_val_t_bit;
  37. #ifndef HASH_VAL_T_BIT
  38. #define HASH_VAL_T_BIT ((int) hash_val_t_bit)
  39. #endif
  40. /*
  41. * Hash chain node structure.
  42. * Notes:
  43. * 1. This preprocessing directive is for debugging purposes. The effect is
  44. * that if the preprocessor symbol KAZLIB_OPAQUE_DEBUG is defined prior to the
  45. * inclusion of this header, then the structure shall be declared as having
  46. * the single member int __OPAQUE__. This way, any attempts by the
  47. * client code to violate the principles of information hiding (by accessing
  48. * the structure directly) can be diagnosed at translation time. However,
  49. * note the resulting compiled unit is not suitable for linking.
  50. * 2. This is a pointer to the next node in the chain. In the last node of a
  51. * chain, this pointer is null.
  52. * 3. The key is a pointer to some user supplied data that contains a unique
  53. * identifier for each hash node in a given table. The interpretation of
  54. * the data is up to the user. When creating or initializing a hash table,
  55. * the user must supply a pointer to a function for comparing two keys,
  56. * and a pointer to a function for hashing a key into a numeric value.
  57. * 4. The value is a user-supplied pointer to void which may refer to
  58. * any data object. It is not interpreted in any way by the hashing
  59. * module.
  60. * 5. The hashed key is stored in each node so that we don't have to rehash
  61. * each key when the table must grow or shrink.
  62. */
  63. typedef struct hnode_t {
  64. #if defined(HASH_IMPLEMENTATION) || !defined(KAZLIB_OPAQUE_DEBUG) /* 1 */
  65. struct hnode_t *hash_next; /* 2 */
  66. const void *hash_key; /* 3 */
  67. void *hash_data; /* 4 */
  68. hash_val_t hash_hkey; /* 5 */
  69. #else
  70. int hash_dummy;
  71. #endif
  72. } hnode_t;
  73. /*
  74. * The comparison function pointer type. A comparison function takes two keys
  75. * and produces a value of -1 if the left key is less than the right key, a
  76. * value of 0 if the keys are equal, and a value of 1 if the left key is
  77. * greater than the right key.
  78. */
  79. typedef int (*hash_comp_t)(const void *, const void *);
  80. /*
  81. * The hashing function performs some computation on a key and produces an
  82. * integral value of type hash_val_t based on that key. For best results, the
  83. * function should have a good randomness properties in *all* significant bits
  84. * over the set of keys that are being inserted into a given hash table. In
  85. * particular, the most significant bits of hash_val_t are most significant to
  86. * the hash module. Only as the hash table expands are less significant bits
  87. * examined. Thus a function that has good distribution in its upper bits but
  88. * not lower is preferrable to one that has poor distribution in the upper bits
  89. * but not the lower ones.
  90. */
  91. typedef hash_val_t (*hash_fun_t)(const void *);
  92. /*
  93. * allocator functions
  94. */
  95. typedef hnode_t *(*hnode_alloc_t)(void *);
  96. typedef void (*hnode_free_t)(hnode_t *, void *);
  97. /*
  98. * This is the hash table control structure. It keeps track of information
  99. * about a hash table, as well as the hash table itself.
  100. * Notes:
  101. * 1. Pointer to the hash table proper. The table is an array of pointers to
  102. * hash nodes (of type hnode_t). If the table is empty, every element of
  103. * this table is a null pointer. A non-null entry points to the first
  104. * element of a chain of nodes.
  105. * 2. This member keeps track of the size of the hash table---that is, the
  106. * number of chain pointers.
  107. * 3. The count member maintains the number of elements that are presently
  108. * in the hash table.
  109. * 4. The maximum count is the greatest number of nodes that can populate this
  110. * table. If the table contains this many nodes, no more can be inserted,
  111. * and the hash_isfull() function returns true.
  112. * 5. The high mark is a population threshold, measured as a number of nodes,
  113. * which, if exceeded, will trigger a table expansion. Only dynamic hash
  114. * tables are subject to this expansion.
  115. * 6. The low mark is a minimum population threshold, measured as a number of
  116. * nodes. If the table population drops below this value, a table shrinkage
  117. * will occur. Only dynamic tables are subject to this reduction. No table
  118. * will shrink beneath a certain absolute minimum number of nodes.
  119. * 7. This is the a pointer to the hash table's comparison function. The
  120. * function is set once at initialization or creation time.
  121. * 8. Pointer to the table's hashing function, set once at creation or
  122. * initialization time.
  123. * 9. The current hash table mask. If the size of the hash table is 2^N,
  124. * this value has its low N bits set to 1, and the others clear. It is used
  125. * to select bits from the result of the hashing function to compute an
  126. * index into the table.
  127. * 10. A flag which indicates whether the table is to be dynamically resized. It
  128. * is set to 1 in dynamically allocated tables, 0 in tables that are
  129. * statically allocated.
  130. */
  131. typedef struct hash_t {
  132. #if defined(HASH_IMPLEMENTATION) || !defined(KAZLIB_OPAQUE_DEBUG)
  133. struct hnode_t **hash_table; /* 1 */
  134. hashcount_t hash_nchains; /* 2 */
  135. hashcount_t hash_nodecount; /* 3 */
  136. hashcount_t hash_maxcount; /* 4 */
  137. hashcount_t hash_highmark; /* 5 */
  138. hashcount_t hash_lowmark; /* 6 */
  139. hash_comp_t hash_compare; /* 7 */
  140. hash_fun_t hash_function; /* 8 */
  141. hnode_alloc_t hash_allocnode;
  142. hnode_free_t hash_freenode;
  143. void *hash_context;
  144. hash_val_t hash_mask; /* 9 */
  145. int hash_dynamic; /* 10 */
  146. #else
  147. int hash_dummy;
  148. #endif
  149. } hash_t;
  150. /*
  151. * Hash scanner structure, used for traversals of the data structure.
  152. * Notes:
  153. * 1. Pointer to the hash table that is being traversed.
  154. * 2. Reference to the current chain in the table being traversed (the chain
  155. * that contains the next node that shall be retrieved).
  156. * 3. Pointer to the node that will be retrieved by the subsequent call to
  157. * hash_scan_next().
  158. */
  159. typedef struct hscan_t {
  160. #if defined(HASH_IMPLEMENTATION) || !defined(KAZLIB_OPAQUE_DEBUG)
  161. hash_t *hash_table; /* 1 */
  162. hash_val_t hash_chain; /* 2 */
  163. hnode_t *hash_next; /* 3 */
  164. #else
  165. int hash_dummy;
  166. #endif
  167. } hscan_t;
  168. extern hash_t *kl_hash_create(hashcount_t, hash_comp_t, hash_fun_t);
  169. extern void kl_hash_set_allocator(hash_t *, hnode_alloc_t, hnode_free_t, void *);
  170. extern void kl_hash_destroy(hash_t *);
  171. extern void kl_hash_free_nodes(hash_t *);
  172. extern void kl_hash_free(hash_t *);
  173. extern hash_t *kl_hash_init(hash_t *, hashcount_t, hash_comp_t,
  174. hash_fun_t, hnode_t **, hashcount_t);
  175. extern void kl_hash_insert(hash_t *, hnode_t *, const void *);
  176. extern hnode_t *kl_hash_lookup(hash_t *, const void *);
  177. extern hnode_t *kl_hash_delete(hash_t *, hnode_t *);
  178. extern int kl_hash_alloc_insert(hash_t *, const void *, void *);
  179. extern void kl_hash_delete_free(hash_t *, hnode_t *);
  180. extern void kl_hnode_put(hnode_t *, void *);
  181. extern void *kl_hnode_get(hnode_t *);
  182. extern const void *kl_hnode_getkey(hnode_t *);
  183. extern hashcount_t kl_hash_count(hash_t *);
  184. extern hashcount_t kl_hash_size(hash_t *);
  185. extern int kl_hash_isfull(hash_t *);
  186. extern int kl_hash_isempty(hash_t *);
  187. extern void kl_hash_scan_begin(hscan_t *, hash_t *);
  188. extern hnode_t *kl_hash_scan_next(hscan_t *);
  189. extern hnode_t *kl_hash_scan_delete(hash_t *, hnode_t *);
  190. extern void kl_hash_scan_delfree(hash_t *, hnode_t *);
  191. extern int kl_hash_verify(hash_t *);
  192. extern hnode_t *kl_hnode_create(void *);
  193. extern hnode_t *kl_hnode_init(hnode_t *, void *);
  194. extern void kl_hnode_destroy(hnode_t *);
  195. #if defined(HASH_IMPLEMENTATION) || !defined(KAZLIB_OPAQUE_DEBUG)
  196. #ifdef KAZLIB_SIDEEFFECT_DEBUG
  197. #define kl_hash_isfull(H) (SFX_CHECK(H)->hash_nodecount == (H)->hash_maxcount)
  198. #else
  199. #define kl_hash_isfull(H) ((H)->hash_nodecount == (H)->hash_maxcount)
  200. #endif
  201. #define kl_hash_isempty(H) ((H)->hash_nodecount == 0)
  202. #define kl_hash_count(H) ((H)->hash_nodecount)
  203. #define kl_hash_size(H) ((H)->hash_nchains)
  204. #define kl_hnode_get(N) ((N)->hash_data)
  205. #define kl_hnode_getkey(N) ((N)->hash_key)
  206. #define kl_hnode_put(N, V) ((N)->hash_data = (V))
  207. #endif
  208. #ifdef __cplusplus
  209. }
  210. #endif
  211. #endif