static uint32_t node_insert(struct cc_trie* tp, uint32_t node_pos, char c) { struct cc_node* node = pos2node(tp, node_pos); int idx = c2idx(c); uint32_t pos = node->childs[idx]; if(pos == 0) { pos = pool_get(tp); node = pos2node(tp, node_pos); node->childs[idx] = pos; assert(node->count < _CHAR_COUNT); node->list[node->count++] = idx; } return pos; }
static struct cc_node* node_next(struct cc_trie* tp, struct cc_node* node, char c) { int idx = c2idx(c); if(idx<0) return NULL; uint32_t pos = node->childs[idx]; if(pos == 0) return NULL; return pos2node(tp, pos); }
void cc_trie_match(struct cc_trie* tp, const char* prefix, trie_visit func, void* ud) { char c; struct cc_node* cur = pos2node(tp, tp->root); for(; (prefix && (c=*prefix++)); ) { struct cc_node* next = node_next(tp, cur, c); if(!next) return; cur = next; } // dump _dump_node(tp, cur, func, ud); }
static void _dump_node(struct cc_trie* tp, struct cc_node* root, trie_visit func, void* ud) { int i; if(root->has_ud) { func(root->ud, ud); } for(i=0; i<root->count; i++){ int idx = root->list[i]; struct cc_node* next = pos2node(tp, root->childs[idx]); _dump_node(tp, next, func, ud); } }
static void _dump_node(struct cc_trie* tp, struct cc_node* root, trie_visit func, void* ud) { int i; for(i=0; i<root->ud_slot.pos; i++) { unsigned int *p = root->ud_slot.p; unsigned int v = (p)?(p[i]):(root->ud_slot.tmp); func(v, ud); } for(i=0; i<root->count; i++) { int idx = root->list[i]; struct cc_node* next = pos2node(tp, root->childs[idx]); _dump_node(tp, next, func, ud); } }
void cc_trie_insert(struct cc_trie* tp, const char* str, unsigned int ud) { if(str == NULL) return; char c; uint32_t cur_pos = tp->root; for(; (c=*str++); ) { if(c2idx(c) >= 0) { cur_pos = node_insert(tp, cur_pos, c); } } struct cc_node* node = pos2node(tp, cur_pos); node_addud(node, ud); }
// for test static void _tdump(struct cc_trie* tp, struct cc_node* node, uint32_t pos) { printf("pos[%d] count[%d] ud[%d] has_ud[%d]\n", pos, node->count, node->ud, node->has_ud); int i=0; for(i=0; i<node->count; i++) { int idx = node->list[i]; printf(" %c -> pos[%d]\n", idx2char[idx], node->childs[idx]); } for(i=0; i<node->count; i++) { int idx = node->list[i]; uint32_t pos = node->childs[idx]; _tdump(tp, pos2node(tp, pos), pos); } }
void trie_dump(struct cc_trie* tp) { _tdump(tp, pos2node(tp, tp->root), tp->root); }