collapsing; fixes; more tests
This commit is contained in:
parent
7bfbb3f8c9
commit
0082983809
142
main.c
142
main.c
|
@ -99,6 +99,21 @@ int main1(int argc, char *argv[]) {
|
|||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static tt_node_ptr_t make_path(tt_arena_t *a, tt_node_ptr_t ok_dict, int n, tt_atom_t const *atoms)
|
||||
{
|
||||
int i;
|
||||
tt_node_ptr_t result = tt_begin_path(a, ok_dict);
|
||||
for (i = n - 1; i >= 0; i--) {
|
||||
result = tt_prepend_path(a, atoms[i], result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#define MAKE_PATH(a, ok_dict, elts...) ({ \
|
||||
tt_atom_t __atoms[] = elts; \
|
||||
make_path(a, ok_dict, sizeof(__atoms)/sizeof(tt_atom_t), __atoms); \
|
||||
})
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
tt_arena_t a;
|
||||
tt_node_ptr_t a_set;
|
||||
|
@ -112,21 +127,11 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
printf("\n============================================================ 1\n");
|
||||
{
|
||||
tt_node_ptr_t A =
|
||||
tt_grab(&a,
|
||||
tt_prepend_path(&a, TT_BOS,
|
||||
tt_prepend_path(&a, 'A',
|
||||
tt_prepend_path(&a, TT_EOS,
|
||||
tt_begin_path(&a, a_set)))));
|
||||
tt_node_ptr_t A = tt_grab(&a, MAKE_PATH(&a, a_set, {TT_BOS, 'A', TT_EOS}));
|
||||
printf("\nA node: %u/%u\n", tt_ptr_idx(A), tt_ptr_tag(A));
|
||||
tt_arena_flush(&a);
|
||||
tt_dump_arena_dot("A", A, &a);
|
||||
tt_node_ptr_t B =
|
||||
tt_grab(&a,
|
||||
tt_prepend_path(&a, TT_BOS,
|
||||
tt_prepend_path(&a, 'B',
|
||||
tt_prepend_path(&a, TT_EOS,
|
||||
tt_begin_path(&a, b_set)))));
|
||||
tt_node_ptr_t B = tt_grab(&a, MAKE_PATH(&a, b_set, {TT_BOS, 'B', TT_EOS}));
|
||||
printf("\nB node: %u/%u\n", tt_ptr_idx(B), tt_ptr_tag(B));
|
||||
tt_dump_arena_dot("B", B, &a);
|
||||
tt_node_ptr_t C = tt_trie_union(&a, A, B);
|
||||
|
@ -147,21 +152,11 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
printf("\n============================================================ 2\n");
|
||||
{
|
||||
tt_node_ptr_t A =
|
||||
tt_grab(&a,
|
||||
tt_prepend_path(&a, TT_BOS,
|
||||
tt_prepend_path(&a, 'A',
|
||||
tt_prepend_path(&a, TT_EOS,
|
||||
tt_begin_path(&a, a_set)))));
|
||||
tt_node_ptr_t A = tt_grab(&a, MAKE_PATH(&a, a_set, {TT_BOS, 'A', TT_EOS}));
|
||||
printf("\nA node: %u/%u\n", tt_ptr_idx(A), tt_ptr_tag(A));
|
||||
tt_arena_flush(&a);
|
||||
tt_dump_arena_dot("A", A, &a);
|
||||
tt_node_ptr_t B =
|
||||
tt_grab(&a,
|
||||
tt_prepend_path(&a, TT_BOS,
|
||||
tt_prepend_path(&a, TT_WILD,
|
||||
tt_prepend_path(&a, TT_EOS,
|
||||
tt_begin_path(&a, b_set)))));
|
||||
tt_node_ptr_t B = tt_grab(&a, MAKE_PATH(&a, b_set, {TT_BOS, TT_WILD, TT_EOS}));
|
||||
printf("\nB node: %u/%u\n", tt_ptr_idx(B), tt_ptr_tag(B));
|
||||
tt_dump_arena_dot("B", B, &a);
|
||||
tt_node_ptr_t C = tt_trie_union(&a, A, B);
|
||||
|
@ -179,16 +174,11 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
printf("\n============================================================ 3\n");
|
||||
{
|
||||
tt_node_ptr_t A =
|
||||
tt_grab(&a,
|
||||
tt_prepend_path(&a, TT_BOS,
|
||||
tt_prepend_path(&a, 'A',
|
||||
tt_prepend_path(&a, TT_EOS,
|
||||
tt_begin_path(&a, a_set)))));
|
||||
tt_node_ptr_t A = tt_grab(&a, MAKE_PATH(&a, a_set, {TT_BOS, 'A', TT_EOS}));
|
||||
printf("\nA node: %u/%u\n", tt_ptr_idx(A), tt_ptr_tag(A));
|
||||
tt_arena_flush(&a);
|
||||
tt_dump_arena_dot("A", A, &a);
|
||||
tt_node_ptr_t B = tt_grab(&a, tt_prepend_path(&a, TT_WILD, tt_begin_path(&a, b_set)));
|
||||
tt_node_ptr_t B = tt_grab(&a, MAKE_PATH(&a, b_set, {TT_WILD}));
|
||||
printf("\nB node: %u/%u\n", tt_ptr_idx(B), tt_ptr_tag(B));
|
||||
tt_dump_arena_dot("B", B, &a);
|
||||
tt_node_ptr_t C = tt_trie_union(&a, A, B);
|
||||
|
@ -206,17 +196,11 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
printf("\n============================================================ 4\n");
|
||||
{
|
||||
tt_node_ptr_t A =
|
||||
tt_grab(&a,
|
||||
tt_prepend_path(&a, TT_BOS,
|
||||
tt_prepend_path(&a, 'A',
|
||||
tt_prepend_path(&a, TT_EOS,
|
||||
/* NB b_set below */
|
||||
tt_begin_path(&a, b_set)))));
|
||||
tt_node_ptr_t A = tt_grab(&a, MAKE_PATH(&a, b_set /* !!! */, {TT_BOS, 'A', TT_EOS}));
|
||||
printf("\nA node: %u/%u\n", tt_ptr_idx(A), tt_ptr_tag(A));
|
||||
tt_arena_flush(&a);
|
||||
tt_dump_arena_dot("A", A, &a);
|
||||
tt_node_ptr_t B = tt_grab(&a, tt_prepend_path(&a, TT_WILD, tt_begin_path(&a, b_set)));
|
||||
tt_node_ptr_t B = tt_grab(&a, MAKE_PATH(&a, b_set, {TT_WILD}));
|
||||
printf("\nB node: %u/%u\n", tt_ptr_idx(B), tt_ptr_tag(B));
|
||||
tt_dump_arena_dot("B", B, &a);
|
||||
tt_node_ptr_t C = tt_trie_union(&a, A, B);
|
||||
|
@ -232,6 +216,86 @@ int main(int argc, char *argv[]) {
|
|||
tt_drop(&a, C);
|
||||
}
|
||||
|
||||
printf("\n============================================================ 5\n");
|
||||
{
|
||||
tt_node_ptr_t A = tt_grab(&a, MAKE_PATH(&a, a_set, {TT_BOS, 'A', 'B', TT_EOS}));
|
||||
printf("\nA node: %u/%u\n", tt_ptr_idx(A), tt_ptr_tag(A));
|
||||
tt_arena_flush(&a);
|
||||
tt_dump_arena_dot("A", A, &a);
|
||||
tt_node_ptr_t B = tt_grab(&a, MAKE_PATH(&a, b_set, {TT_BOS, TT_WILD, TT_EOS}));
|
||||
printf("\nB node: %u/%u\n", tt_ptr_idx(B), tt_ptr_tag(B));
|
||||
tt_dump_arena_dot("B", B, &a);
|
||||
tt_node_ptr_t C = tt_trie_union(&a, A, B);
|
||||
tt_arena_flush(&a);
|
||||
tt_dump_arena_dot("Cpredrop", C, &a);
|
||||
tt_drop(&a, A);
|
||||
tt_drop(&a, B);
|
||||
printf("\nC node: %u/%u\n", tt_ptr_idx(C), tt_ptr_tag(C));
|
||||
tt_arena_flush(&a);
|
||||
tt_dump_arena_dot("Cpostdrop", C, &a);
|
||||
putchar('\n');
|
||||
tt_dump_routingtable(&a, C, 0);
|
||||
tt_drop(&a, C);
|
||||
}
|
||||
|
||||
printf("\n============================================================ 6\n");
|
||||
{
|
||||
tt_node_ptr_t A = tt_grab(&a, MAKE_PATH(&a, a_set, {TT_BOS, 'A', 'B', TT_EOS}));
|
||||
printf("\nA node: %u/%u\n", tt_ptr_idx(A), tt_ptr_tag(A));
|
||||
tt_arena_flush(&a);
|
||||
tt_dump_arena_dot("A", A, &a);
|
||||
tt_node_ptr_t B = tt_grab(&a, MAKE_PATH(&a, b_set, {TT_BOS, TT_WILD, TT_WILD, TT_EOS}));
|
||||
printf("\nB node: %u/%u\n", tt_ptr_idx(B), tt_ptr_tag(B));
|
||||
tt_dump_arena_dot("B", B, &a);
|
||||
tt_node_ptr_t C = tt_trie_union(&a, A, B);
|
||||
tt_arena_flush(&a);
|
||||
tt_dump_arena_dot("Cpredrop", C, &a);
|
||||
tt_drop(&a, A);
|
||||
tt_drop(&a, B);
|
||||
printf("\nC node: %u/%u\n", tt_ptr_idx(C), tt_ptr_tag(C));
|
||||
tt_arena_flush(&a);
|
||||
tt_dump_arena_dot("Cpostdrop", C, &a);
|
||||
putchar('\n');
|
||||
tt_dump_routingtable(&a, C, 0);
|
||||
tt_drop(&a, C);
|
||||
}
|
||||
|
||||
printf("\n============================================================ 7\n");
|
||||
{
|
||||
tt_node_ptr_t A = tt_grab(&a, MAKE_PATH(&a, a_set, {TT_BOS, 'A', TT_WILD, TT_EOS}));
|
||||
printf("\nA node: %u/%u\n", tt_ptr_idx(A), tt_ptr_tag(A));
|
||||
tt_arena_flush(&a);
|
||||
tt_dump_arena_dot("A", A, &a);
|
||||
tt_node_ptr_t B = tt_grab(&a, MAKE_PATH(&a, b_set, {TT_BOS, TT_WILD, 'B', TT_EOS}));
|
||||
printf("\nB node: %u/%u\n", tt_ptr_idx(B), tt_ptr_tag(B));
|
||||
tt_dump_arena_dot("B", B, &a);
|
||||
tt_node_ptr_t C = tt_trie_union(&a, A, B);
|
||||
tt_arena_flush(&a);
|
||||
tt_dump_arena_dot("Cpredrop", C, &a);
|
||||
tt_drop(&a, A);
|
||||
tt_drop(&a, B);
|
||||
printf("\nC node: %u/%u\n", tt_ptr_idx(C), tt_ptr_tag(C));
|
||||
tt_arena_flush(&a);
|
||||
tt_dump_arena_dot("Cpostdrop", C, &a);
|
||||
putchar('\n');
|
||||
tt_dump_routingtable(&a, C, 0);
|
||||
|
||||
tt_node_ptr_t D = tt_trie_union(&a, C, C);
|
||||
tt_drop(&a, C);
|
||||
tt_arena_flush(&a);
|
||||
tt_dump_arena_dot("D", D, &a);
|
||||
tt_dump_routingtable(&a, D, 0);
|
||||
|
||||
tt_node_ptr_t E = tt_grab(&a, MAKE_PATH(&a, b_set, {TT_WILD}));
|
||||
tt_node_ptr_t F = tt_trie_union(&a, D, E);
|
||||
tt_drop(&a, D);
|
||||
tt_drop(&a, E);
|
||||
tt_arena_flush(&a);
|
||||
tt_dump_arena_dot("F", F, &a);
|
||||
tt_dump_routingtable(&a, F, 0);
|
||||
tt_drop(&a, F);
|
||||
}
|
||||
|
||||
tt_arena_flush(&a);
|
||||
tt_dump_arena_dot("afterAll", TT_NO_PTR, &a); /* expect a_set and b_set here */
|
||||
|
||||
|
|
97
route.c
97
route.c
|
@ -2,6 +2,7 @@
|
|||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
||||
|
@ -28,8 +29,12 @@ 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;
|
||||
if (TT_EMPTY_DICT_P(others)) {
|
||||
if (TT_EMPTY_P(wild)) {
|
||||
return TT_EMPTY;
|
||||
} else if (tt_ptr_tag(wild) == TT_TAG_TAIL) {
|
||||
return wild;
|
||||
}
|
||||
}
|
||||
return tt_cons_branch(a, wild, others);
|
||||
}
|
||||
|
@ -83,6 +88,14 @@ static inline tt_node_ptr_t rupdate_dict(tt_arena_t *a,
|
|||
{
|
||||
assert(key != TT_WILD);
|
||||
assert(TT_EMPTY_DICT_P(old_others) || tt_ptr_tag(old_others) == TT_TAG_DICT);
|
||||
/* printf("rupdate_dict key %d k %u/%u old_wild %u/%u old_others %u/%u\n", */
|
||||
/* key, */
|
||||
/* tt_ptr_idx(k), */
|
||||
/* tt_ptr_tag(k), */
|
||||
/* tt_ptr_idx(old_wild), */
|
||||
/* tt_ptr_tag(old_wild), */
|
||||
/* tt_ptr_idx(old_others), */
|
||||
/* tt_ptr_tag(old_others)); */
|
||||
|
||||
#define OTHERS_SANS_KEY() (tt_dict_remove(a, old_others, key))
|
||||
#define OTHERS_WITH_KEY() (tt_dict_set(a, old_others, key, k))
|
||||
|
@ -108,27 +121,45 @@ static inline tt_node_ptr_t rupdate_dict(tt_arena_t *a,
|
|||
#undef OTHERS_WITH_KEY
|
||||
}
|
||||
|
||||
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 new_others;
|
||||
assert(tt_ptr_tag(r0) == TT_TAG_BRANCH);
|
||||
new_others = rupdate_dict(a, TT_BRANCH_WILDCARD(a,r0), TT_BRANCH_OTHERS(a,r0), key, k);
|
||||
return rbranch(a, TT_BRANCH_WILDCARD(a,r0), RET_IF_NO_PTR(new_others));
|
||||
}
|
||||
}
|
||||
/* 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 new_others; */
|
||||
/* assert(tt_ptr_tag(r0) == TT_TAG_BRANCH); */
|
||||
/* new_others = rupdate_dict(a, TT_BRANCH_WILDCARD(a,r0), TT_BRANCH_OTHERS(a,r0), key, k); */
|
||||
/* return rbranch(a, TT_BRANCH_WILDCARD(a,r0), RET_IF_NO_PTR(new_others)); */
|
||||
/* } */
|
||||
/* } */
|
||||
|
||||
static inline tt_node_ptr_t expand(tt_arena_t *a, tt_node_ptr_t tailnode) {
|
||||
tt_node_ptr_t others = RET_IF_NO_PTR(tt_dict_singleton(a, TT_EOS, TT_TAIL_TRIE(a,tailnode)));
|
||||
return rbranch(a, tailnode, others);
|
||||
}
|
||||
|
||||
static inline tt_node_ptr_t collapse(tt_arena_t *a, tt_node_ptr_t n) {
|
||||
if (tt_ptr_tag(n) == TT_TAG_BRANCH) {
|
||||
tt_node_ptr_t w = TT_BRANCH_WILDCARD(a,n);
|
||||
tt_node_ptr_t o = TT_BRANCH_OTHERS(a,n);
|
||||
if (tt_ptr_tag(w) == TT_TAG_TAIL &&
|
||||
tt_ptr_tag(o) == TT_TAG_DICT &&
|
||||
TT_DICT_SIZE(a,o) == 1) {
|
||||
tt_node_ptr_t root = TT_DICT_ROOT(a,o);
|
||||
assert(tt_ptr_tag(root) == TT_TAG_LEAF);
|
||||
if (TT_LEAF_ATOM(a,root) == TT_EOS &&
|
||||
TT_LEAF_TRIE(a,root) == TT_TAIL_TRIE(a,w)) {
|
||||
return w;
|
||||
}
|
||||
}
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/* N.B. Returns a tt_grab'd result. */
|
||||
tt_node_ptr_t tt_trie_combine(tt_arena_t *a,
|
||||
tt_node_ptr_t r1,
|
||||
|
@ -187,12 +218,22 @@ tt_node_ptr_t tt_trie_combine(tt_arena_t *a,
|
|||
if (TT_NO_PTR_P(new_result_others)) return 0;
|
||||
tt_drop(a, result_others);
|
||||
result_others = new_result_others;
|
||||
/* printf("after update key %d, result_others %u/%u\n", */
|
||||
/* key, */
|
||||
/* tt_ptr_idx(result_others), */
|
||||
/* tt_ptr_tag(result_others)); */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* printf("{{{ combining %u/%u with %u/%u\n", */
|
||||
/* tt_ptr_idx(r1), */
|
||||
/* tt_ptr_tag(r1), */
|
||||
/* tt_ptr_idx(r2), */
|
||||
/* tt_ptr_tag(r2)); */
|
||||
if (!TT_EMPTY_P(w1) && !TT_EMPTY_P(w2)) {
|
||||
/* Two wildcards - worst case. Must loop over both dictionaries. */
|
||||
result_wild = g(w1, w2);
|
||||
ok = !TT_NO_PTR_P(result_wild);
|
||||
ok = ok && tt_dict_foreach(a, dict1, NULL, examine_key);
|
||||
ok = ok && tt_dict_foreach(a, dict2, NULL, examine_key);
|
||||
} else if ((!TT_EMPTY_P(w1)) ||
|
||||
|
@ -211,7 +252,15 @@ tt_node_ptr_t tt_trie_combine(tt_arena_t *a,
|
|||
|
||||
if (ok) {
|
||||
result = tt_grab(a, rbranch(a, result_wild, result_others));
|
||||
if (!TT_NO_PTR_P(result)) {
|
||||
tt_node_ptr_t collapsed = tt_grab(a, collapse(a, result));
|
||||
tt_drop(a, result);
|
||||
result = collapsed;
|
||||
}
|
||||
}
|
||||
/* printf("}}} result %u/%u\n", */
|
||||
/* tt_ptr_idx(result), */
|
||||
/* tt_ptr_tag(result)); */
|
||||
|
||||
tt_drop(a, result_wild);
|
||||
tt_drop(a, result_others);
|
||||
|
@ -286,6 +335,18 @@ void print_indent(int spaces) {
|
|||
}
|
||||
}
|
||||
|
||||
static size_t gross_approximate_utf8_strlen(char const *c) {
|
||||
size_t count = 0;
|
||||
while (*c) {
|
||||
unsigned char b = *c;
|
||||
if (b < 0x80 || b >= 0xc0) {
|
||||
count++;
|
||||
}
|
||||
c++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
void tt_dump_routingtable(tt_arena_t *a, tt_node_ptr_t r, int initial_indent) {
|
||||
void walk(int indent, tt_node_ptr_t r) {
|
||||
switch (tt_ptr_tag(r)) {
|
||||
|
@ -330,7 +391,7 @@ void tt_dump_routingtable(tt_arena_t *a, tt_node_ptr_t r, int initial_indent) {
|
|||
snprintf(keystr, sizeof(keystr) - 1, " %d", key);
|
||||
}
|
||||
fputs(keystr, stdout);
|
||||
walk(indent + strlen(keystr), node);
|
||||
walk(indent + gross_approximate_utf8_strlen(keystr), node);
|
||||
return 1;
|
||||
}
|
||||
if (!TT_EMPTY_P(TT_BRANCH_WILDCARD(a, r))) {
|
||||
|
|
Loading…
Reference in New Issue