This commit is contained in:
Adrien Gallouët
2016-12-05 14:47:22 +00:00
parent 0645f0d4d0
commit 0d97df6b50
7 changed files with 272 additions and 220 deletions

View File

@@ -3,56 +3,57 @@
#include "db.h"
#include "str.h"
#define CBIT(X) (1&(intptr_t)(X))
#define CBIT_PTR(X) (uint8_t *)(1|(intptr_t)(X))
#define CBIT_NODE(X) (struct node *)(1^(intptr_t)(X))
#define CBIT(X) (1 & (intptr_t)(X))
#define CBIT_PTR(X) (uint8_t *)(1 | (intptr_t)(X))
#define CBIT_NODE(X) (struct node *)(1 ^ (intptr_t)(X))
struct node {
uint8_t *child[2];
uint32_t point;
};
_pure_
static inline size_t db_size (const uint8_t *a)
_pure_ static inline size_t
db_size(const uint8_t *a)
{
return (a[0]?:str_len((char *)a+1))+1;
return (a[0] ?: str_len((char *)a + 1)) + 1;
}
_pure_
static inline size_t db_cmp (const uint8_t *a, const uint8_t *b)
_pure_ static inline size_t
db_cmp(const uint8_t *a, const uint8_t *b)
{
const size_t size = a[0];
if (size!=b[0])
if (size != b[0])
return 1;
if (!size) {
size_t i = str_cmp((char *)a+1, (char *)b+1);
return i?i+1:0;
size_t i = str_cmp((char *)a + 1, (char *)b + 1);
return i ? i + 1 : 0;
}
for (size_t i=1; i<=size; i++) {
if (a[i]!=b[i])
return i+1;
for (size_t i = 1; i <= size; i++) {
if (a[i] != b[i])
return i + 1;
}
return 0;
}
_pure_
static inline int db_dir (const uint32_t point, uint8_t *data, const size_t size)
_pure_ static inline int
db_dir(const uint32_t point, uint8_t *data, const size_t size)
{
const size_t pos = point>>8;
const size_t pos = point >> 8;
if (pos>=size)
if (pos >= size)
return 0;
return ((point|data[pos])&255)==255;
return ((point | data[pos]) & 255) == 255;
}
uint8_t *db_search (uint8_t **p, uint8_t *data)
uint8_t *
db_search(uint8_t **p, uint8_t *data)
{
if _0_(!*p)
if (_0_(!*p))
return NULL;
uint8_t *r = *p;
@@ -69,12 +70,13 @@ uint8_t *db_search (uint8_t **p, uint8_t *data)
return NULL;
}
uint8_t *db_insert (uint8_t **p, uint8_t *data)
uint8_t *
db_insert(uint8_t **p, uint8_t *data)
{
if _0_(CBIT(data))
if (_0_(CBIT(data)))
return NULL;
if _0_(!*p) {
if (_0_(!*p)) {
*p = data;
return data;
}
@@ -89,31 +91,31 @@ uint8_t *db_insert (uint8_t **p, uint8_t *data)
const size_t diff = db_cmp(r, data);
if _0_(!diff)
if (_0_(!diff))
return r;
const size_t pos = diff-1;
const uint8_t mask = ~((1u<<31)>>CLZ(r[pos]^data[pos]));
const size_t point = (pos<<8)|mask;
const size_t pos = diff - 1;
const uint8_t mask = ~((1u << 31) >> CLZ(r[pos] ^ data[pos]));
const size_t point = (pos << 8) | mask;
while (CBIT(*p)) {
struct node *node = CBIT_NODE(*p);
if (node->point>point)
if (node->point > point)
break;
p = node->child+db_dir(node->point, data, size);
p = node->child + db_dir(node->point, data, size);
}
struct node *node = malloc(sizeof(struct node));
if _0_(!node)
if (_0_(!node))
return NULL;
const int dir = (mask|r[pos])==255;
const int dir = (mask | r[pos]) == 255;
node->child[dir] = *p;
node->child[1-dir] = data;
node->child[1 - dir] = data;
node->point = point;
*p = CBIT_PTR(node);
@@ -121,9 +123,10 @@ uint8_t *db_insert (uint8_t **p, uint8_t *data)
return data;
}
uint8_t *db_remove (uint8_t **p, uint8_t *data)
uint8_t *
db_remove(uint8_t **p, uint8_t *data)
{
if _0_(!*p)
if (_0_(!*p))
return NULL;
const size_t size = db_size(data);
@@ -136,16 +139,16 @@ uint8_t *db_remove (uint8_t **p, uint8_t *data)
p_old = p;
node = CBIT_NODE(*p);
dir = db_dir(node->point, data, size);
p = node->child+dir;
p = node->child + dir;
}
if _0_(db_cmp(data, *p))
if (_0_(db_cmp(data, *p)))
return NULL;
uint8_t *r = *p;
if (p_old) {
*p_old = node->child[1-dir];
*p_old = node->child[1 - dir];
free(node);
} else {
*p = NULL;