Created
June 22, 2012 05:45
-
-
Save alyx/2970572 to your computer and use it in GitHub Desktop.
A (failed) attempt to make the code from agl's repo actually readable.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdint.h> | |
#include <string.h> | |
#include <stdlib.h> | |
#include <sys/types.h> | |
#include <errno.h> | |
typedef struct | |
{ | |
void *child[2]; | |
uint32_t byte; | |
uint8_t otherbits; | |
} cb_node; | |
typedef struct | |
{ | |
void *root; | |
} cb_tree; | |
int cb_contains(cb_tree *t, const char *str) | |
{ | |
uint8_t *bytes, *root, c; | |
cb_node *node; | |
size_t len; | |
int dir, ndir; | |
bytes = (void *)str; | |
len = strlen(str); | |
root = t->root; | |
if (!root) | |
return 0; | |
while (1&(intptr_t)root) // I'm just going to leave that there... | |
{ | |
node = (void *)(root-1); | |
if (node->byte < len) | |
c = bytes[node->byte]; | |
int dir = (1 + (node->otherbits | c)) >> 8; | |
root = node->child[dir]; | |
} | |
return (strcmp(str, (const char *)root) == 0); | |
} | |
int cb_insert(cb_tree *t, const char *str) | |
{ | |
uint8_t *bytes, *ptr, c; | |
uint32_t newbyte, newobits; | |
size_t len; | |
char *buf, *b2; | |
int status, dir, ndir; | |
cb_node *node, *nnode; | |
void **wherep; | |
bytes = (void *)str; | |
len = strlen(str); | |
ptr = t->root; | |
if (!ptr) | |
{ | |
status = posix_memalign((void **)&buf, sizeof(void*), len+1); | |
if (status) | |
return 0; | |
memcpy(buf, str, len+1); | |
t->root = buf; | |
return 2; | |
} | |
while(1&(intptr_t)ptr) | |
{ | |
node = (void *)(ptr - 1); | |
c = 0; | |
if (node->byte < len) | |
c = bytes[node->byte]; | |
dir = (1 + (node->otherbits | c)) >> 8; | |
ptr = node->child[dir]; | |
} | |
for (newbyte = 0; newbyte < len; ++newbyte) | |
{ | |
if (ptr[newbyte] != bytes[newbyte]) | |
{ | |
newobits = ptr[newbyte] ^ bytes[newbyte]; | |
goto diff_byte; | |
} | |
} | |
if (ptr[newbyte] != 0) | |
{ | |
newobits = ptr[newbyte]; | |
goto diff_byte; | |
} | |
return 1; | |
diff_byte: | |
newobits |= newobits >> 1; | |
newobits |= newobits >> 2; | |
newobits |= newobits >> 4; | |
newobits |= (newobits & ~(newobits >> 1)) ^ 255; | |
c = ptr[newbyte]; | |
ndir = (1 + (newobits | c)) >> 8; | |
if (posix_memalign((void **)&nnode, sizeof(void *), sizeof(cb_node))) | |
return 0; | |
if (posix_memalign((void **)&b2, sizeof(void *), len+1)) | |
{ | |
free(nnode); | |
return 0; | |
} | |
memcpy(b2, bytes, len+1); | |
nnode->byte = newbyte; | |
nnode->otherbits = newobits; | |
nnode->child[1 - ndir] = b2; | |
wherep = &t->root; | |
for (;;) | |
{ | |
*ptr = *wherep; | |
if (!(1&(intptr_t)ptr)) | |
break; | |
node = (void *)(ptr - 1); | |
if (node->byte > newbyte) | |
break; | |
if (node->byte == newbyte && node->otherbits > newobits) | |
break; | |
c = 0; | |
if (node->byte < len) | |
c = bytes[node->byte]; | |
dir = (1 + (node->otherbits | c)) >> 8; | |
wherep = node->child+dir; | |
} | |
nnode->child[ndir] = *wherep; | |
*wherep = (void *)(1 + (char *)nnode); | |
return 2; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment