Start on route.{c,h}

This commit is contained in:
Tony Garnock-Jones 2015-07-01 14:27:03 -04:00
parent 22c9a2d5a0
commit 96fd6c455e
2 changed files with 132 additions and 0 deletions

109
route.c Normal file
View File

@ -0,0 +1,109 @@
#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
}
}

23
route.h Normal file
View File

@ -0,0 +1,23 @@
#ifndef ROUTE_H_c2d88c54_f18d_4b71_9fce_5d43c0723360
#define ROUTE_H_c2d88c54_f18d_4b71_9fce_5d43c0723360
/* Sticking to odd-numbered constants, since the plan is for most
bindings to use odd-numbered atoms for immediates and even-numbered
atoms for heap-allocated complex values. TODO: make this a proper
part of the interface? */
#define TT_WILD ((tt_atom_t) -1) /* Wildcard */
#define TT_BOS ((tt_atom_t) -3) /* Beginning of sequence */
#define TT_EOS ((tt_atom_t) -5) /* End of sequence */
#define TT_BOC ((tt_atom_t) -7) /* Beginning of capture */
#define TT_EOC ((tt_atom_t) -9) /* End of capture */
// TODO move to the right place
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif