Mirror of :pserver:cvs@cvs.fefe.de:/cvs libowfat https://www.fefe.de/libowfat/
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.
 
 
 
 

228 lines
4.5 KiB

  1. #include <stddef.h> /* size_t, uintptr_t */
  2. #include <stdint.h> /* for uint8_t, uint32_t */
  3. #include <string.h>
  4. #include <stdlib.h>
  5. #include "critbit.h"
  6. typedef struct {
  7. void* child[2];
  8. uint32_t byte;
  9. uint8_t otherbits;
  10. } critbit0_node;
  11. #if 0
  12. typedef struct{
  13. void* root;
  14. } critbit0_tree;
  15. #endif
  16. int critbit0_contains(critbit0_tree* t,const char* u) {
  17. const uint8_t* ubytes= (void*)u;
  18. const size_t ulen= strlen(u);
  19. uint8_t* p= t->root;
  20. if (!p) return 0;
  21. while ((uintptr_t)p & 1) {
  22. critbit0_node* q = (void*)(p-1);
  23. uint8_t c = 0;
  24. if (q->byte<ulen)
  25. c = ubytes[q->byte];
  26. const int direction = (1+(q->otherbits|c))>>8;
  27. p = q->child[direction];
  28. }
  29. return 0==strcmp(u,(const char*)p);
  30. }
  31. int critbit0_insert(critbit0_tree* t,const char* u) {
  32. const uint8_t* const ubytes = (void*)u;
  33. const size_t ulen = strlen(u);
  34. uint8_t* p = t->root;
  35. if (!p) {
  36. char* x = malloc(ulen+1);
  37. if (!x) return 0;
  38. memcpy(x,u,ulen+1);
  39. t->root= x;
  40. return 2;
  41. }
  42. while (1&(intptr_t)p) {
  43. critbit0_node* q = (void*)(p-1);
  44. uint8_t c = 0;
  45. if (q->byte<ulen)
  46. c = ubytes[q->byte];
  47. const int direction = (1+(q->otherbits|c))>>8;
  48. p = q->child[direction];
  49. }
  50. uint32_t newbyte;
  51. uint32_t newotherbits;
  52. for (newbyte = 0; newbyte < ulen; ++newbyte) {
  53. if (p[newbyte] != ubytes[newbyte]) {
  54. newotherbits = p[newbyte]^ubytes[newbyte];
  55. goto different_byte_found;
  56. }
  57. }
  58. if (p[newbyte]!=0) {
  59. newotherbits = p[newbyte];
  60. goto different_byte_found;
  61. }
  62. return 1;
  63. different_byte_found:
  64. newotherbits |= newotherbits>>1;
  65. newotherbits |= newotherbits>>2;
  66. newotherbits |= newotherbits>>4;
  67. newotherbits = (newotherbits&~(newotherbits>>1))^255;
  68. uint8_t c = p[newbyte];
  69. int newdirection = (1+(newotherbits|c))>>8;
  70. critbit0_node* newnode;
  71. if (!(newnode=malloc(sizeof(critbit0_node))))
  72. return 0;
  73. char* x;
  74. if (!(x = malloc(ulen+1))) {
  75. free(newnode);
  76. return 0;
  77. }
  78. memcpy(x,ubytes,ulen+1);
  79. newnode->byte= newbyte;
  80. newnode->otherbits= newotherbits;
  81. newnode->child[1-newdirection]= x;
  82. void** wherep= &t->root;
  83. for(;;) {
  84. uint8_t* p = *wherep;
  85. if (!((intptr_t)p&1))
  86. break;
  87. critbit0_node* q = (void*)(p-1);
  88. if (q->byte > newbyte)break;
  89. if (q->byte==newbyte && q->otherbits>newotherbits)break;
  90. uint8_t c = 0;
  91. if (q->byte<ulen)
  92. c = ubytes[q->byte];
  93. const int direction = (1+(q->otherbits|c))>>8;
  94. wherep = q->child+direction;
  95. }
  96. newnode->child[newdirection]= *wherep;
  97. *wherep= (void*)(1+(char*)newnode);
  98. return 2;
  99. }
  100. int critbit0_delete(critbit0_tree* t,const char* u) {
  101. const uint8_t* ubytes = (void*)u;
  102. const size_t ulen = strlen(u);
  103. uint8_t* p = t->root;
  104. void** wherep = &t->root;
  105. void** whereq = 0;
  106. critbit0_node* q = 0;
  107. int direction = 0;
  108. if (!p) return 0;
  109. while ((intptr_t)p&1) {
  110. whereq = wherep;
  111. q = (void*)(p-1);
  112. uint8_t c = 0;
  113. if (q->byte<ulen)
  114. c = ubytes[q->byte];
  115. direction = (1+(q->otherbits|c))>>8;
  116. wherep = q->child+direction;
  117. p = *wherep;
  118. }
  119. if (0!=strcmp(u,(const char*)p))
  120. return 0;
  121. free(p);
  122. if (!whereq) {
  123. t->root = 0;
  124. return 1;
  125. }
  126. *whereq = q->child[1-direction];
  127. free(q);
  128. return 1;
  129. }
  130. static void traverse(void* top) {
  131. uint8_t* p = top;
  132. if ((intptr_t)p&1) {
  133. critbit0_node* q = (void*)(p-1);
  134. traverse(q->child[0]);
  135. traverse(q->child[1]);
  136. free(q);
  137. } else {
  138. free(p);
  139. }
  140. }
  141. void critbit0_clear(critbit0_tree* t) {
  142. if (t->root)
  143. traverse(t->root);
  144. t->root = NULL;
  145. }
  146. static int allprefixed_traverse(uint8_t* top,int(*handle)(const char*,void*),void* arg) {
  147. if ((uintptr_t)top&1) {
  148. critbit0_node* q = (void*)(top-1);
  149. int direction;
  150. for (direction=0; direction<2; ++direction)
  151. switch (allprefixed_traverse(q->child[direction],handle,arg)) {
  152. case 1: break;
  153. case 0: return 0;
  154. default: return-1;
  155. }
  156. return 1;
  157. }
  158. return handle((const char*)top,arg);
  159. }
  160. int critbit0_allprefixed(critbit0_tree* t,const char* prefix,int(*handle)(const char*,void*),void* arg) {
  161. const uint8_t* ubytes = (void*)prefix;
  162. const size_t ulen = strlen(prefix);
  163. uint8_t* p = t->root;
  164. uint8_t* top = p;
  165. if (!p) return 1;
  166. while ((uintptr_t)p&1) {
  167. critbit0_node* q = (void*)(p-1);
  168. uint8_t c = 0;
  169. if (q->byte<ulen)
  170. c=ubytes[q->byte];
  171. const int direction = (1+(q->otherbits|c))>>8;
  172. p = q->child[direction];
  173. if (q->byte<ulen)
  174. top = p;
  175. }
  176. size_t i;
  177. for (i=0; i<ulen; ++i) {
  178. if (p[i]!=ubytes[i])
  179. return 1;
  180. }
  181. return allprefixed_traverse(top,handle,arg);
  182. }