int hattrie_find_leq (hattrie_t* T, const char* key, size_t len, value_t** dst) { /* create node stack for traceback */ size_t sp = 0; node_ptr bs[NODESTACK_INIT]; /* base stack (will be enough mostly) */ node_ptr *ns = bs; /* generic ptr, could point to new mem */ ns[sp] = T->root; /* find node for given key */ int ret = 1; /* no node on the left matches */ node_ptr node = hattrie_find_ns(&ns, &sp, NODESTACK_INIT, &key, &len); if (node.flag == NULL) { *dst = hattrie_walk_left(ns, sp, key, hattrie_find_rightmost); if (ns != bs) free(ns); if (*dst) { return -1; /* found previous */ } return 1; /* no previous key found */ } /* assign value from trie or find in table */ if (*node.flag & NODE_TYPE_TRIE) { *dst = &node.t->val; ret = 0; /* found exact match */ } else { *dst = hhash_find(node.b, key, len); if (*dst) { ret = 0; /* found exact match */ } else { /* look for previous in hashtable */ ret = hhash_find_leq(node.b, key, len, dst); } } /* return if found equal or left in hashtable */ if (*dst == 0) { /* we're retracing from pure bucket, pop the key */ if (*node.flag & NODE_TYPE_PURE_BUCKET) { --key; } /* walk up the stack of visited nodes and find closest match on the left */ *dst = hattrie_walk_left(ns, sp, key, hattrie_find_rightmost); if (*dst) { ret = -1; /* found previous */ } else { ret = 1; /* no previous key found */ } } if (ns != bs) free(ns); return ret; }
int hattrie_find_lpr (hattrie_t* T, const char* key, size_t len, value_t** dst) { /* create node stack for traceback */ int ret = -1; size_t sp = 0; node_ptr bs[NODESTACK_INIT]; /* base stack (will be enough mostly) */ node_ptr *ns = bs; /* generic ptr, could point to new mem */ ns[sp] = T->root; *dst = NULL; /* consume trie nodes for key (thus building prefix chain) */ node_ptr node = hattrie_find_ns(&ns, &sp, NODESTACK_INIT, &key, &len); if (node.flag == NULL) { if (sp == 0) { /* empty trie, no prefix match */ if (ns != bs) free(ns); return -1; } node = ns[--sp]; /* dead end, pop node */ } /* search for suffix in current node */ size_t suffix = len; /* suffix length */ if (*node.flag & NODE_TYPE_TRIE) { *dst = &node.t->val; /* use current trie node value */ } else { while (*dst == NULL) { /* find remainder in current ahtable */ *dst = ahtable_tryget(node.b, key, suffix); if (suffix == 0) break; --suffix; } } /* not in current node, need to traceback node stack */ while (*dst == NULL) { node = ns[sp]; /* parent node, always a trie node type */ if (*node.flag & NODE_HAS_VAL) *dst = &node.t->val; if (sp == 0) break; --sp; } if (*dst) { /* prefix found? */ ret = 0; } if (ns != bs) free(ns); return ret; }
int hattrie_find_next (hattrie_t* T, const char* key, size_t len, value_t **dst) { /* create node stack for traceback */ size_t sp = 0; node_ptr bs[NODESTACK_INIT]; /* base stack (will be enough mostly) */ node_ptr *ns = bs; /* generic ptr, could point to new mem */ ns[sp] = T->root; /* find node for given key */ node_ptr ptr = hattrie_find_ns(&ns, &sp, NODESTACK_INIT, &key, &len); if (ptr.flag == NULL) { *dst = hattrie_walk_right(ns, sp, key, hattrie_find_leftmost); if (ns != bs) free(ns); if (*dst) { return 0; /* found next. */ } else { return 1; /* no next key found. */ } } int ret = 0; if (*ptr.flag & NODE_TYPE_TRIE) { /* Get next using walk. */ ret = 1; } else { ret = hhash_find_next(ptr.b, key, len, dst); } if (ret == 1) { /* we're retracing from pure bucket, pop the key. */ if (*ptr.flag & NODE_TYPE_PURE_BUCKET) { --key; } *dst = hattrie_walk_right(ns, sp, key, hattrie_find_leftmost); if (ns != bs) free(ns); if (*dst) { ret = 0; /* found next. */ } else { ret = 1; /* no next key found. */ } } return ret; }
/* find node in trie */ static inline node_ptr hattrie_find(node_ptr *parent, const char **key, size_t *len) { size_t sp = 0; return hattrie_find_ns(&parent, &sp, 0, key, len); }