value_t* hattrie_get(hattrie_t* T, const char* key, size_t len) { node_ptr parent = T->root; assert(*parent.flag & NODE_TYPE_TRIE); if (len == 0) return &parent.t->val; /* consume all trie nodes, now parent must be trie and child anything */ node_ptr node = hattrie_consume(&parent, &key, &len, 0); assert(*parent.flag & NODE_TYPE_TRIE); /* if the key has been consumed on a trie node, use its value */ if (len == 0) { if (*node.flag & NODE_TYPE_TRIE) { return hattrie_useval(T, node); } else if (*node.flag & NODE_TYPE_HYBRID_BUCKET) { return hattrie_useval(T, parent); } } /* preemptively split the bucket if it is full */ while (ahtable_size(node.b) >= MAX_BUCKET_SIZE) { hattrie_split(T, parent, node); /* after the split, the node pointer is invalidated, so we search from * the parent again. */ node = hattrie_consume(&parent, &key, &len, 0); /* if the key has been consumed on a trie node, use its value */ if (len == 0) { if (*node.flag & NODE_TYPE_TRIE) { return hattrie_useval(T, node); } else if (*node.flag & NODE_TYPE_HYBRID_BUCKET) { return hattrie_useval(T, parent); } } } assert(*node.flag & NODE_TYPE_PURE_BUCKET || *node.flag & NODE_TYPE_HYBRID_BUCKET); assert(len > 0); size_t m_old = node.b->m; value_t* val; if (*node.flag & NODE_TYPE_PURE_BUCKET) { val = ahtable_get(node.b, key + 1, len - 1); } else { val = ahtable_get(node.b, key, len); } T->m += (node.b->m - m_old); return val; }
static value_t *find_below(hattrie_t *T, node_ptr parent, const char *key, size_t len) { /* consume all trie nodes, now parent must be trie and child anything */ node_ptr node = hattrie_consume(&parent, &key, &len, 0); assert(*parent.flag & NODE_TYPE_TRIE); /* if the key has been consumed on a trie node, use its value */ if (len == 0) { if (*node.flag & NODE_TYPE_TRIE) { return hattrie_useval(T, node); } else if (*node.flag & NODE_TYPE_HYBRID_BUCKET) { return hattrie_useval(T, parent); } } #ifdef HHASH_MAX_FILL /* preemptively split the bucket if fill is over threshold */ if (node.b->weight >= node.b->size * HHASH_MAX_FILL) { node_split(T, parent, node); return find_below(T, parent, key, len); } #endif /* attempt to fit new element and split if it doesn't fit */ value_t *val = NULL; assert(len > 0); if (*node.flag & NODE_TYPE_PURE_BUCKET) { val = hhash_map(node.b, key + 1, len - 1, HHASH_INSERT); } else { val = hhash_map(node.b, key, len, HHASH_INSERT); } /* not inserted, recursively split */ if (val == NULL) { node_split(T, parent, node); val = find_below(T, parent, key, len); } return val; }