ref: 5479f0fb4283ca4a5a58c9b7b50c5b86bde13aa1
dir: /trie.c/
#include <u.h>
#include <libc.h>
#include "dat.h"
#include "fns.h"
int trieallocs;
int triedebug;
#define dprint if(triedebug) print
Trie *
triealloc(void)
{
Trie *t;
t = emalloc(sizeof(Trie));
trieallocs++;
return t;
}
void
triefree(Trie *t)
{
Trie *c, *n;
for(c = t->child; c != nil; c = n){
n = c->next;
triefree(c);
}
free(t);
trieallocs--;
}
void
triewalk(Trie *t, Triewalk *w, Rune *key, int keysize)
{
w->root = t;
w->curr = nil;
w->key = key;
w->keysize = keysize;
w->depth = 0;
}
void *
trienext(Triewalk *w)
{
Trie *t;
int d;
if(w->curr == nil){
w->curr = w->root;
w->depth = 0;
w->key[0] = 0;
if(w->root->value != nil)
return w->root->value;
}
t = w->curr;
d = w->depth;
do{
if(t->child != nil && d < w->keysize-1){
t = t->child;
d++;
}
else if(t->next != nil)
t = t->next;
else {
while(t->next == nil && t != w->root){
t = t->parent;
d--;
}
if(t->next != nil)
t = t->next;
else {
assert(t == w->root);
w->curr = nil;
return nil;
}
}
w->key[d-1] = t->rune;
} while(t->value == nil);
w->key[d] = 0;
w->curr = t;
w->depth = d;
return t->value;
}
static Trie *
getchild(Trie *t, Rune r)
{
dprint(" getchild %C: ", r);
for(t = t->child; t != nil; t = t->next)
if(t->rune == r)
break;
dprint("%s\n", t != nil ? "found" : "not found");
return t;
}
static Trie *
addchild(Trie *t, Rune r)
{
Trie *c, *n, *prev;
dprint(" addchild %C\n", r);
c = triealloc();
c->rune = r;
c->parent = t;
prev = nil;
for(n = t->child; n != nil; n = n->next){
if((prev == nil || prev->rune < r) && r < n->rune)
break;
assert(r > n->rune);
prev = n;
}
if(prev == nil)
t->child = c;
else
prev->next = c;
c->next = n;
return c;
}
static int
delchild(Trie *t, Rune r)
{
Trie *c, *prev;
dprint(" delchild %C\n", r);
prev = nil;
for(c = t->child; c != nil; c = c->next){
if(c->rune == r)
break;
prev = c;
}
if(c == nil)
return 0;
if(c->child != nil)
return 0;
if(prev == nil)
t->child = c->next;
else
prev->next = c->next;
triefree(c);
return 1;
}
void *
trieadd(Trie *t, Rune *key, void *val)
{
Trie *c;
void *v;
if(val == nil)
return nil;
while(*key){
c = getchild(t, *key);
if(c == nil)
break;
t = c;
key++;
}
while(*key)
t = addchild(t, *key++);
v = t->value;
t->value = val;
return v;
}
static Trie *
find(Trie *t, Rune *key)
{
Trie *c;
while(*key){
c = getchild(t, *key);
if(c == nil)
break;
t = c;
key++;
}
if(*key)
return nil;
return t;
}
void *
triedel(Trie *t, Rune *key)
{
Rune *r;
void *v;
t = find(t, key);
if(t == nil)
return nil;
/* only non-leaves and root can have empty value */
if(t->value == nil){
assert(t->child != nil || t->parent == nil);
return nil;
}
v = t->value;
t->value = nil;
if(t->child != nil || t->parent == nil)
return v;
r = runestrchr(key, 0);
while(t->child == nil && t->value == nil && --r >= key){
t = t->parent;
assert(t != nil);
assert(delchild(t, *r));
}
return v;
}
void *
trieget(Trie *t, Rune *key)
{
t = find(t, key);
if(t == nil)
return nil;
return t->value;
}