#ifndef TREETRIE_H_f55a3f6d_ef43_45d3_bec3_496a196b5db1 #define TREETRIE_H_f55a3f6d_ef43_45d3_bec3_496a196b5db1 #ifdef __cplusplus extern "C" { #endif typedef enum tt_tag_t { TT_TAG_TAIL = 0, TT_TAG_BRANCH, TT_TAG_LEAF, /* only case where one of node a or b points to non-node */ TT_TAG_NODE } tt_tag_t; typedef enum tt_reserved_node_idx_t { TT_NO_IDX = 0, /* invalid node index, means "no node at all", not even empty */ TT_EMPTY_IDX, /* empty treetrie */ TT_OK_IDX, /* terminal marker */ TT_FIRST_VALID_NODE_IDX } tt_reserved_node_idx_t; #define TT_NO_PTR (tt_mkptr(TT_NO_IDX, 0)) #define TT_EMPTY (tt_mkptr(TT_EMPTY_IDX, 0)) #define TT_OK (tt_mkptr(TT_OK_IDX, 0)) #define TT_FIRST_VALID_NODE_PTR (tt_mkptr(TT_FIRST_VALID_NODE_IDX, 0)) typedef uint32_t tt_node_idx_t; /* N.B. tt_reserved_node_idx_t */ typedef uint32_t tt_node_ptr_t; /* An index shifted left 2 with tag or'd in low bits */ typedef uint32_t tt_atom_t; /* Atom number 0 is the wildcard atom. */ typedef union tt_header_t { tt_node_idx_t next_free; struct { uint32_t refcount : 24; uint32_t index : 8; /* this really doesn't need to be more than 5 or 6 bits wide */ } inuse; } tt_header_t; #define TT_REFCOUNT_LIMIT ((1 << 24) - 1) typedef struct tt_node_t { tt_node_ptr_t a; /* always a real node ptr */ tt_node_ptr_t b; /* a real node ptr unless corresponding tag is TT_TAG_LEAF */ } tt_node_t; typedef struct tt_free_chain_t { tt_node_idx_t head; /* remove links from here */ tt_node_idx_t tail; /* append links here */ } tt_free_chain_t; typedef struct tt_arena_t { /* Fields for the Robin Hood hashset used for hashconsing of tt_nodes */ unsigned int max_probe; unsigned int table_length; tt_node_ptr_t *table; tt_header_t *headers; tt_node_t *nodes; unsigned int free_count; tt_free_chain_t free_chain; } tt_arena_t; static inline tt_node_ptr_t tt_mkptr(tt_node_idx_t i, tt_tag_t tag) { return (i << 2) | tag; } static inline tt_node_idx_t tt_ptr_idx(tt_node_ptr_t p) { return p >> 2; } static inline tt_tag_t tt_ptr_tag(tt_node_ptr_t p) { return p & 3; } extern int tt_arena_init(tt_arena_t *a); extern void tt_arena_done(tt_arena_t *a); extern void tt_dump_arena_summary(tt_arena_t *a); extern void tt_dump_arena(tt_arena_t *a); extern void tt_arena_flush(tt_arena_t *a); /* Returns 0 if consing failed (because of out-of-memory). Otherwise, returns a nonzero index. Grabs na and nb (according to tag) IF it needs to allocate a new node, otherwise does not. DOES NOT increase the reference count of the returned node. */ extern tt_node_ptr_t tt_arena_cons(tt_arena_t *a, uint32_t tag, uint32_t index, tt_node_ptr_t na, tt_node_ptr_t nb); extern tt_node_ptr_t tt_grab(tt_arena_t *a, tt_node_ptr_t i); extern void tt_drop(tt_arena_t *a, tt_node_ptr_t i); #ifdef __cplusplus } #endif #endif