149 lines
3.8 KiB
C
149 lines
3.8 KiB
C
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include <stdint.h>
|
|
#include <errno.h>
|
|
#include <assert.h>
|
|
|
|
#include "treetrie.h"
|
|
#include "critbit.h"
|
|
#include "route.h"
|
|
|
|
static inline tt_node_ptr_t rseq(tt_arena_t *a, tt_atom_t s, tt_node_ptr_t r) {
|
|
if (TT_EMPTY_P(r)) {
|
|
return TT_EMPTY;
|
|
}
|
|
assert(s != TT_WILD);
|
|
return tt_cons_branch(a, TT_EMPTY, RET_IF_NO_PTR(tt_dict_singleton(a, s, r)));
|
|
}
|
|
|
|
static inline tt_node_ptr_t rwild(tt_arena_t *a, tt_node_ptr_t r) {
|
|
if (TT_EMPTY_P(r)) {
|
|
return TT_EMPTY;
|
|
}
|
|
return tt_cons_branch(a, r, TT_EMPTY_DICT);
|
|
}
|
|
|
|
static inline tt_node_ptr_t rbranch(tt_arena_t *a,
|
|
tt_node_ptr_t wild, /* trie */
|
|
tt_node_ptr_t others) /* dict */
|
|
{
|
|
if (TT_EMPTY_P(wild) && TT_EMPTY_DICT_P(others)) {
|
|
return TT_EMPTY;
|
|
}
|
|
return tt_cons_branch(a, wild, others);
|
|
}
|
|
|
|
static inline tt_node_ptr_t rwildseq(tt_arena_t *a, tt_node_ptr_t r) {
|
|
if (TT_EMPTY_P(r)) {
|
|
return TT_EMPTY;
|
|
}
|
|
return tt_cons_tail(a, r);
|
|
}
|
|
|
|
static inline tt_node_ptr_t runwildseq(tt_arena_t *a, tt_node_ptr_t r) {
|
|
if (tt_ptr_tag(r) == TT_TAG_TAIL) {
|
|
return TT_TAIL_TRIE(a,r);
|
|
} else {
|
|
return TT_EMPTY;
|
|
}
|
|
}
|
|
|
|
static inline tt_node_ptr_t rlookup(tt_arena_t *a,
|
|
tt_node_ptr_t r,
|
|
tt_atom_t key)
|
|
{
|
|
tt_node_ptr_t result;
|
|
assert(tt_ptr_tag(r) == TT_TAG_BRANCH);
|
|
result = tt_dict_get(a, TT_BRANCH_OTHERS(a,r), key);
|
|
if (!TT_NO_PTR_P(result)) {
|
|
return result;
|
|
}
|
|
result = TT_BRANCH_WILDCARD(a,r);
|
|
switch (key) {
|
|
case TT_BOS: return rwildseq(a, result);
|
|
case TT_EOS: return runwildseq(a, result);
|
|
default: return result;
|
|
}
|
|
}
|
|
|
|
static inline tt_node_ptr_t rupdate(tt_arena_t *a,
|
|
tt_node_ptr_t r0, /* branch */
|
|
tt_atom_t key,
|
|
tt_node_ptr_t k) /* trie */
|
|
{
|
|
assert(key != TT_WILD);
|
|
if (TT_EMPTY_P(r0)) {
|
|
return rseq(a, key, k);
|
|
} else {
|
|
tt_node_ptr_t old_wild;
|
|
tt_node_ptr_t old_others;
|
|
assert(tt_ptr_tag(r0) == TT_TAG_BRANCH);
|
|
old_wild = TT_BRANCH_WILDCARD(a,r0);
|
|
old_others = TT_BRANCH_OTHERS(a,r0);
|
|
|
|
#define R0_SANS_KEY() (rbranch(a, old_wild, RET_IF_NO_PTR(tt_dict_remove(a, old_others, key))))
|
|
#define R0_WITH_KEY() (rbranch(a, old_wild, RET_IF_NO_PTR(tt_dict_set(a, old_others, key, k))))
|
|
|
|
switch (key) {
|
|
case TT_BOS:
|
|
if (tt_ptr_tag(k) == TT_TAG_TAIL) {
|
|
return (TT_TAIL_TRIE(a,k) == old_wild) ? R0_SANS_KEY() : R0_WITH_KEY();
|
|
} else {
|
|
return TT_EMPTY_P(k) ? R0_SANS_KEY() : R0_WITH_KEY();
|
|
}
|
|
case TT_EOS:
|
|
if (tt_ptr_tag(old_wild) == TT_TAG_TAIL) {
|
|
return (TT_TAIL_TRIE(a,old_wild) == k) ? R0_SANS_KEY() : R0_WITH_KEY();
|
|
} else {
|
|
return TT_EMPTY_P(k) ? R0_SANS_KEY() : R0_WITH_KEY();
|
|
}
|
|
default:
|
|
return (k == old_wild) ? R0_SANS_KEY() : R0_WITH_KEY();
|
|
}
|
|
|
|
#undef R0_SANS_KEY
|
|
#undef R0_WITH_KEY
|
|
|
|
}
|
|
}
|
|
|
|
/* static tt_node_ptr_t combine(tt_arena_t *a, */
|
|
/* tt_node_ptr_t r1, */
|
|
/* tt_node_ptr_t r2, */
|
|
/* int left_empty_keep, */
|
|
/* int right_empty_keep, */
|
|
/* int left_base_keep, */
|
|
/* int right_base_keep, */
|
|
/* void *f_context, */
|
|
/* tt_node_ptr_t (*f)(void *f_context, tt_node_ptr_t r1, tt_node_ptr_t r2)) */
|
|
/* { */
|
|
/* tt_node_ptr_t g(tt_node_ptr_t r1, tt_node_ptr_t r2) { */
|
|
/* tt_tag_t t1, t2; */
|
|
|
|
/* if (TT_EMPTY_P(r1)) { */
|
|
/* return left_empty_keep ? r2 : TT_EMPTY; */
|
|
/* } */
|
|
/* if (TT_EMPTY_P(r2)) { */
|
|
/* return right_empty_keep ? r1 : TT_EMPTY; */
|
|
/* } */
|
|
|
|
/* t1 = tt_ptr_tag(r1); */
|
|
/* t2 = tt_ptr_tag(r2); */
|
|
|
|
/* if (t1 == TT_TAG_TAIL) { */
|
|
/* if (t2 == TT_TAG_TAIL) { */
|
|
/* return rwildseq(a, RET_IF_NO_PTR(g(TT_TAIL_TRIE(a,r1), TT_TAIL_TRIE(a,r2)))); */
|
|
/* } else { */
|
|
/* ....HERE */
|
|
/* } */
|
|
|
|
/* switch (tt_ptr_tag(r1)) { */
|
|
/* default: */
|
|
/* abort(); */
|
|
/* } */
|
|
/* } */
|
|
|
|
/* return g(r1, r2); */
|
|
/* } */
|