Skip to content

Instantly share code, notes, and snippets.

@alyx
Created June 22, 2012 05:45
Show Gist options
  • Save alyx/2970572 to your computer and use it in GitHub Desktop.
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.
#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