ghash.h
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:5k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * include/linux/ghash.h -- generic hashing with fuzzy retrieval
  3.  *
  4.  * (C) 1997 Thomas Schoebel-Theuer
  5.  *
  6.  * The algorithms implemented here seem to be a completely new invention,
  7.  * and I'll publish the fundamentals in a paper.
  8.  */
  9. #ifndef _GHASH_H
  10. #define _GHASH_H
  11. /* HASHSIZE _must_ be a power of two!!! */
  12. #define DEF_HASH_FUZZY_STRUCTS(NAME,HASHSIZE,TYPE) 
  13. struct NAME##_table {
  14. TYPE * hashtable[HASHSIZE];
  15. TYPE * sorted_list;
  16. int nr_entries;
  17. };
  18. struct NAME##_ptrs {
  19. TYPE * next_hash;
  20. TYPE * prev_hash;
  21. TYPE * next_sorted;
  22. TYPE * prev_sorted;
  23. };
  24. #define DEF_HASH_FUZZY(LINKAGE,NAME,HASHSIZE,TYPE,PTRS,KEYTYPE,KEY,KEYCMP,KEYEQ,HASHFN)
  25. LINKAGE void insert_##NAME##_hash(struct NAME##_table * tbl, TYPE * elem)
  26. {
  27. int ix = HASHFN(elem->KEY);
  28. TYPE ** base = &tbl->hashtable[ix];
  29. TYPE * ptr = *base;
  30. TYPE * prev = NULL;
  31. tbl->nr_entries++;
  32. while(ptr && KEYCMP(ptr->KEY, elem->KEY)) {
  33. base = &ptr->PTRS.next_hash;
  34. prev = ptr;
  35. ptr = *base;
  36. }
  37. elem->PTRS.next_hash = ptr;
  38. elem->PTRS.prev_hash = prev;
  39. if(ptr) {
  40. ptr->PTRS.prev_hash = elem;
  41. }
  42. *base = elem;
  43. ptr = prev;
  44. if(!ptr) {
  45. ptr = tbl->sorted_list;
  46. prev = NULL;
  47. } else {
  48. prev = ptr->PTRS.prev_sorted;
  49. }
  50. while(ptr) {
  51. TYPE * next = ptr->PTRS.next_hash;
  52. if(next && KEYCMP(next->KEY, elem->KEY)) {
  53. prev = ptr;
  54. ptr = next;
  55. } else if(KEYCMP(ptr->KEY, elem->KEY)) {
  56. prev = ptr;
  57. ptr = ptr->PTRS.next_sorted;
  58. } else
  59. break;
  60. }
  61. elem->PTRS.next_sorted = ptr;
  62. elem->PTRS.prev_sorted = prev;
  63. if(ptr) {
  64. ptr->PTRS.prev_sorted = elem;
  65. }
  66. if(prev) {
  67. prev->PTRS.next_sorted = elem;
  68. } else {
  69. tbl->sorted_list = elem;
  70. }
  71. }
  72. LINKAGE void remove_##NAME##_hash(struct NAME##_table * tbl, TYPE * elem)
  73. {
  74. TYPE * next = elem->PTRS.next_hash;
  75. TYPE * prev = elem->PTRS.prev_hash;
  76. tbl->nr_entries--;
  77. if(next)
  78. next->PTRS.prev_hash = prev;
  79. if(prev)
  80. prev->PTRS.next_hash = next;
  81. else {
  82. int ix = HASHFN(elem->KEY);
  83. tbl->hashtable[ix] = next;
  84. }
  85. next = elem->PTRS.next_sorted;
  86. prev = elem->PTRS.prev_sorted;
  87. if(next)
  88. next->PTRS.prev_sorted = prev;
  89. if(prev)
  90. prev->PTRS.next_sorted = next;
  91. else
  92. tbl->sorted_list = next;
  93. }
  94. LINKAGE TYPE * find_##NAME##_hash(struct NAME##_table * tbl, KEYTYPE pos)
  95. {
  96. int ix = hashfn(pos);
  97. TYPE * ptr = tbl->hashtable[ix];
  98. while(ptr && KEYCMP(ptr->KEY, pos))
  99. ptr = ptr->PTRS.next_hash;
  100. if(ptr && !KEYEQ(ptr->KEY, pos))
  101. ptr = NULL;
  102. return ptr;
  103. }
  104. LINKAGE TYPE * find_##NAME##_hash_fuzzy(struct NAME##_table * tbl, KEYTYPE pos)
  105. {
  106. int ix;
  107. int offset;
  108. TYPE * ptr;
  109. TYPE * next;
  110. ptr = tbl->sorted_list;
  111. if(!ptr || KEYCMP(pos, ptr->KEY))
  112. return NULL;
  113. ix = HASHFN(pos);
  114. offset = HASHSIZE;
  115. do {
  116. offset >>= 1;
  117. next = tbl->hashtable[(ix+offset) & ((HASHSIZE)-1)];
  118. if(next && (KEYCMP(next->KEY, pos) || KEYEQ(next->KEY, pos))
  119.    && KEYCMP(ptr->KEY, next->KEY))
  120. ptr = next;
  121. } while(offset);
  122. for(;;) {
  123. next = ptr->PTRS.next_hash;
  124. if(next) {
  125. if(KEYCMP(next->KEY, pos)) {
  126. ptr = next;
  127. continue;
  128. }
  129. }
  130. next = ptr->PTRS.next_sorted;
  131. if(next && KEYCMP(next->KEY, pos)) {
  132. ptr = next;
  133. continue;
  134. }
  135. return ptr;
  136. }
  137. return NULL;
  138. }
  139. #define DEF_HASH_STRUCTS(NAME,HASHSIZE,TYPE) 
  140. struct NAME##_table {
  141. TYPE * hashtable[HASHSIZE];
  142. int nr_entries;
  143. };
  144. struct NAME##_ptrs {
  145. TYPE * next_hash;
  146. TYPE * prev_hash;
  147. };
  148. #define DEF_HASH(LINKAGE,NAME,HASHSIZE,TYPE,PTRS,KEYTYPE,KEY,KEYCMP,KEYEQ,HASHFN)
  149. LINKAGE void insert_##NAME##_hash(struct NAME##_table * tbl, TYPE * elem)
  150. {
  151. int ix = HASHFN(elem->KEY);
  152. TYPE ** base = &tbl->hashtable[ix];
  153. TYPE * ptr = *base;
  154. TYPE * prev = NULL;
  155. tbl->nr_entries++;
  156. while(ptr && KEYCMP(ptr->KEY, elem->KEY)) {
  157. base = &ptr->PTRS.next_hash;
  158. prev = ptr;
  159. ptr = *base;
  160. }
  161. elem->PTRS.next_hash = ptr;
  162. elem->PTRS.prev_hash = prev;
  163. if(ptr) {
  164. ptr->PTRS.prev_hash = elem;
  165. }
  166. *base = elem;
  167. }
  168. LINKAGE void remove_##NAME##_hash(struct NAME##_table * tbl, TYPE * elem)
  169. {
  170. TYPE * next = elem->PTRS.next_hash;
  171. TYPE * prev = elem->PTRS.prev_hash;
  172. tbl->nr_entries--;
  173. if(next)
  174. next->PTRS.prev_hash = prev;
  175. if(prev)
  176. prev->PTRS.next_hash = next;
  177. else {
  178. int ix = HASHFN(elem->KEY);
  179. tbl->hashtable[ix] = next;
  180. }
  181. }
  182. LINKAGE TYPE * find_##NAME##_hash(struct NAME##_table * tbl, KEYTYPE pos)
  183. {
  184. int ix = hashfn(pos);
  185. TYPE * ptr = tbl->hashtable[ix];
  186. while(ptr && KEYCMP(ptr->KEY, pos))
  187. ptr = ptr->PTRS.next_hash;
  188. if(ptr && !KEYEQ(ptr->KEY, pos))
  189. ptr = NULL;
  190. return ptr;
  191. }
  192. #endif