#include /* size_t, uintptr_t */ #include /* for uint8_t, uint32_t */ #include #include #include "critbit.h" typedef struct { void* child[2]; uint32_t byte; uint8_t otherbits; } critbit0_node; #if 0 typedef struct{ void* root; } critbit0_tree; #endif int critbit0_contains(critbit0_tree* t,const char* u) { const uint8_t* ubytes= (void*)u; const size_t ulen= strlen(u); uint8_t* p= t->root; if (!p) return 0; while ((uintptr_t)p & 1) { critbit0_node* q = (void*)(p-1); uint8_t c = 0; if (q->bytebyte]; const int direction = (1+(q->otherbits|c))>>8; p = q->child[direction]; } return 0==strcmp(u,(const char*)p); } int critbit0_insert(critbit0_tree* t,const char* u) { const uint8_t* const ubytes = (void*)u; const size_t ulen = strlen(u); uint8_t* p = t->root; if (!p) { char* x = malloc(ulen+1); if (!x) return 0; memcpy(x,u,ulen+1); t->root= x; return 2; } while (1&(intptr_t)p) { critbit0_node* q = (void*)(p-1); uint8_t c = 0; if (q->bytebyte]; const int direction = (1+(q->otherbits|c))>>8; p = q->child[direction]; } uint32_t newbyte; uint32_t newotherbits; for (newbyte = 0; newbyte < ulen; ++newbyte) { if (p[newbyte] != ubytes[newbyte]) { newotherbits = p[newbyte]^ubytes[newbyte]; goto different_byte_found; } } if (p[newbyte]!=0) { newotherbits = p[newbyte]; goto different_byte_found; } return 1; different_byte_found: newotherbits |= newotherbits>>1; newotherbits |= newotherbits>>2; newotherbits |= newotherbits>>4; newotherbits = (newotherbits&~(newotherbits>>1))^255; uint8_t c = p[newbyte]; int newdirection = (1+(newotherbits|c))>>8; critbit0_node* newnode; if (!(newnode=malloc(sizeof(critbit0_node)))) return 0; char* x; if (!(x = malloc(ulen+1))) { free(newnode); return 0; } memcpy(x,ubytes,ulen+1); newnode->byte= newbyte; newnode->otherbits= newotherbits; newnode->child[1-newdirection]= x; void** wherep= &t->root; for(;;) { uint8_t* p = *wherep; if (!((intptr_t)p&1)) break; critbit0_node* q = (void*)(p-1); if (q->byte > newbyte)break; if (q->byte==newbyte && q->otherbits>newotherbits)break; uint8_t c = 0; if (q->bytebyte]; const int direction = (1+(q->otherbits|c))>>8; wherep = q->child+direction; } newnode->child[newdirection]= *wherep; *wherep= (void*)(1+(char*)newnode); // gcc -fanalyze false positive return 2; } int critbit0_delete(critbit0_tree* t,const char* u) { const uint8_t* ubytes = (void*)u; const size_t ulen = strlen(u); uint8_t* p = t->root; void** wherep = &t->root; void** whereq = 0; critbit0_node* q = 0; int direction = 0; if (!p) return 0; while ((intptr_t)p&1) { whereq = wherep; q = (void*)(p-1); uint8_t c = 0; if (q->bytebyte]; direction = (1+(q->otherbits|c))>>8; wherep = q->child+direction; p = *wherep; } if (0!=strcmp(u,(const char*)p)) return 0; free(p); if (!whereq) { t->root = 0; return 1; } *whereq = q->child[1-direction]; free(q); return 1; } static void traverse(void* top) { uint8_t* p = top; if ((intptr_t)p&1) { critbit0_node* q = (void*)(p-1); traverse(q->child[0]); traverse(q->child[1]); free(q); } else { free(p); } } void critbit0_clear(critbit0_tree* t) { if (t->root) traverse(t->root); t->root = NULL; } static int allprefixed_traverse(uint8_t* top,int(*handle)(const char*,void*),void* arg) { if ((uintptr_t)top&1) { critbit0_node* q = (void*)(top-1); int direction; for (direction=0; direction<2; ++direction) switch (allprefixed_traverse(q->child[direction],handle,arg)) { case 1: break; case 0: return 0; default: return-1; } return 1; } return handle((const char*)top,arg); } int critbit0_allprefixed(critbit0_tree* t,const char* prefix,int(*handle)(const char*,void*),void* arg) { const uint8_t* ubytes = (void*)prefix; const size_t ulen = strlen(prefix); uint8_t* p = t->root; uint8_t* top = p; if (!p) return 1; while ((uintptr_t)p&1) { critbit0_node* q = (void*)(p-1); uint8_t c = 0; if (q->bytebyte]; const int direction = (1+(q->otherbits|c))>>8; p = q->child[direction]; if (q->byte