46#define BAL_MASK ((intptr_t)3)
47#define PARENT(node) ((hb_node*) ((node)->bal & ~BAL_MASK))
48#define BAL_POS(node) ((node)->bal & 1)
49#define BAL_NEG(node) ((node)->bal & 2)
58_Static_assert(
sizeof(intptr_t) ==
sizeof(
hb_node*),
59 "hb_node tags a parent pointer stored in an intptr_t");
61 "hb_node must be layout-compatible with tree_node_base");
63 "hb_node must be layout-compatible with tree_node_base");
65 "hb_node must be layout-compatible with tree_node_base");
67 "hb_node must be layout-compatible with tree_node_base");
69 "hb_node must be layout-compatible with tree_node_base");
90static bool vt_hb_tree_select(
void* obj,
size_t n,
const void** key,
void** datum) {
return hb_tree_select(obj, n, key, datum); }
91static bool vt_hb_tree_verify(
const void* obj) {
return hb_tree_verify(obj); }
92static bool vt_hb_itor_next(
void* itor) {
return hb_itor_next(itor); }
93static bool vt_hb_itor_prev(
void* itor) {
return hb_itor_prev(itor); }
94static bool vt_hb_itor_nextn(
void* itor,
size_t count) {
return hb_itor_nextn(itor, count); }
95static bool vt_hb_itor_prevn(
void* itor,
size_t count) {
return hb_itor_prevn(itor, count); }
96static bool vt_hb_itor_remove(
void* itor) {
return hb_itor_remove(itor); }
139static hb_node* node_new(
void* key);
142 unsigned* height,
size_t *count,
143 const void* lower,
const void* upper);
169 dct->
_vtable = &hb_tree_vtable;
192 if (delete_func) delete_func(node->
key, node->
datum);
217 q->bal = (intptr_t)qr | (qr_bal == 0);
218 if ((q->rlink = qrl) != NULL)
219 qrl->bal = (intptr_t)q | (qrl->bal &
BAL_MASK);
222 qr->bal = (intptr_t)qp | ((qr_bal == 0) << 1);
226 return (qr_bal == 0);
242 q->bal = (intptr_t)ql | ((ql_bal == 0) << 1);
243 if ((q->llink = qlr) != NULL)
244 qlr->bal = (intptr_t)q | (qlr->bal &
BAL_MASK);
247 ql->bal = (intptr_t)qp | (ql_bal == 0);
251 return (ql_bal == 0);
265 const int qrl_bal = qrl->bal &
BAL_MASK;
270 qrl->
bal = (intptr_t)qp;
276 q->bal = (intptr_t)qrl | ((qrl_bal == 1) << 1);
277 if ((q->rlink = qrll) != NULL)
278 qrll->bal = (intptr_t)q | (qrll->bal &
BAL_MASK);
281 qr->bal = (intptr_t)qrl | (qrl_bal == 2);
282 if ((qr->llink = qrlr) != NULL)
283 qrlr->bal = (intptr_t)qr | (qrlr->bal &
BAL_MASK);
297 const int qlr_bal = qlr->bal &
BAL_MASK;
302 qlr->
bal = (intptr_t)qp;
308 q->bal = (intptr_t)qlr | (qlr_bal == 2);
309 if ((q->llink = qlrr) != NULL)
310 qlrr->bal = (intptr_t)q | (qlrr->bal &
BAL_MASK);
313 ql->bal = (intptr_t)qlr | ((qlr_bal == 1) << 1);
314 if ((ql->rlink = qlrl) != NULL)
315 qlrl->bal = (intptr_t)ql | (qlrl->bal &
BAL_MASK);
329 parent = node; node = node->
llink;
330 }
else if (cmp > 0) {
331 parent = node; node = node->
rlink;
338 hb_node*
const add = node = node_new(key);
342 if (!(node->
pptr = parent)) {
348 parent->
llink = node;
350 parent->
rlink = node;
352 while (parent != q) {
354 if (parent->
llink == node)
363 if (q->
llink == node) {
410 SWAP(node->
key, out->key, tmp);
419 bool left = p && (p->
llink == node);
437 unsigned rotations = 0;
447 if (rotate_l(
tree, p))
break;
466 if (rotate_r(
tree, p))
482 if (p->
llink == node) {
499 remove_node(
tree, node);
514 if (!visit(node->
key, node->
datum, user_data))
535 node = node_prev(node);
539 node = node_next(node);
544 *datum = node->
datum;
562 if ((((uintptr_t) node) & 3) != 0) {
563 fprintf(stderr,
"%s:%d (%s) dict_malloc_func returned a pointer "
564 "that is not 4-byte aligned: %p\n",
565 __FILE__, __LINE__, __func__, (
void*) node);
583 while (parent && parent->
llink == node) {
596 while (parent && parent->
rlink == node) {
605 unsigned* height,
size_t *count,
const void* lower,
const void* upper)
630 }
else if (bal == 1) {
634 unsigned lheight, rheight;
635 if (!node_verify(
tree, node, node->
llink, &lheight, count, lower, node->
key) ||
636 !node_verify(
tree, node, node->
rlink, &rheight, count, node->
key, upper))
638 VERIFY(bal == (
int)rheight - (
int)lheight);
640 *height =
MAX(lheight, rheight) + 1;
656 if (!node_verify(
tree, NULL,
tree->
root, NULL, &count, NULL, NULL))
682 itor->
_vtable = &hb_tree_itor_vtable;
694 return itor->
node != NULL;
700 return itor->
node != NULL;
704 while (itor->
node && count--)
706 return itor->
node != NULL;
710 while (itor->
node && count--)
712 return itor->
node != NULL;
731 remove_node(itor->
tree, itor->
node);
int(* dict_compare_func)(const void *, const void *)
A pointer to a function that compares two keys.
void(* dict_delete_func)(void *, void *)
A pointer to a function that is called when a key-value pair gets removed from a dictionary.
bool(* dict_visit_func)(const void *, void *, void *)
A pointer to a function used for iterating over dictionary contents.
bool hb_itor_search(hb_itor *itor, const void *key)
Position |itor| on |key| and return true, or unposition it and return false if |key| is not present.
dict_itor * hb_dict_itor_new(hb_tree *tree)
Like hb_itor_new(), but wrapped in a generic dict_itor for use with the dict_itor_* macros.
size_t hb_tree_clear(hb_tree *tree, dict_delete_func delete_func)
Remove every element, calling |delete_func|(key, datum) for each unless |delete_func| is NULL.
bool hb_itor_search_gt(hb_itor *itor, const void *key)
Position |itor| on the least key greater than |key| and return true, or unposition it and return fals...
void ** hb_tree_search_lt(hb_tree *tree, const void *key)
Return the address of the datum of the greatest key less than |key|, or NULL if there is none.
void ** hb_tree_search(hb_tree *tree, const void *key)
Return the address of the datum stored for |key|, or NULL if |key| is not present.
bool hb_tree_select(hb_tree *tree, size_t n, const void **key, void **datum)
Store the key and datum of the |n|th element in key order (0-based) through |key| and |datum| and ret...
dict * hb_dict_new(dict_compare_func cmp_func)
Like hb_tree_new(), but wrapped in a generic dict for use with the dict_* macros.
bool hb_itor_search_ge(hb_itor *itor, const void *key)
Position |itor| on the least key greater than or equal to |key| and return true, or unposition it and...
void hb_itor_free(hb_itor *itor)
Free an iterator.
hb_itor * hb_itor_new(hb_tree *tree)
Create an iterator over |tree| that is not positioned on any element yet.
bool hb_itor_search_lt(hb_itor *itor, const void *key)
Position |itor| on the greatest key less than |key| and return true, or unposition it and return fals...
bool hb_itor_prev(hb_itor *itor)
Move |itor| to the previous element in key order and return true, or unposition it and return false i...
void ** hb_tree_search_gt(hb_tree *tree, const void *key)
Return the address of the datum of the least key greater than |key|, or NULL if there is none.
hb_tree * hb_tree_new(dict_compare_func cmp_func)
Create an empty tree that orders keys with |cmp_func| (must not be NULL).
void hb_itor_invalidate(hb_itor *itor)
Unposition |itor|, so that it is not positioned on any element.
size_t hb_tree_count(const hb_tree *tree)
Return the number of elements.
bool hb_itor_valid(const hb_itor *itor)
Return whether |itor| is positioned on an element.
size_t hb_tree_min_path_length(const hb_tree *tree)
Return the shallowest depth at which a child link is absent, the root being at depth 1,...
dict_insert_result hb_tree_insert(hb_tree *tree, void *key)
Insert |key| unless an equal key is present.
void ** hb_tree_search_ge(hb_tree *tree, const void *key)
Return the address of the datum of the least key greater than or equal to |key|, or NULL if there is ...
bool hb_itor_nextn(hb_itor *itor, size_t count)
Move |itor| |count| elements forward and return whether it is still positioned.
bool hb_itor_remove(hb_itor *itor)
Remove the element |itor| is positioned on and unposition |itor|; return false if it was not position...
size_t hb_tree_free(hb_tree *tree, dict_delete_func delete_func)
Remove every element, calling |delete_func|(key, datum) for each unless |delete_func| is NULL,...
dict_remove_result hb_tree_remove(hb_tree *tree, const void *key)
Remove the element with key |key|.
size_t hb_tree_max_path_length(const hb_tree *tree)
Return the greatest depth of any node, the root being at depth 1, or 0 for an empty tree: the height ...
int hb_itor_compare(const hb_itor *i1, const hb_itor *i2)
Compare the positions of two iterators over the same tree: return a negative value,...
bool hb_itor_last(hb_itor *itor)
Position |itor| on the last element in key order and return true, or unposition it and return false i...
bool hb_itor_prevn(hb_itor *itor, size_t count)
Move |itor| |count| elements back and return whether it is still positioned.
void ** hb_itor_datum(hb_itor *itor)
Return the address of the datum |itor| is positioned on, through which it can be read or replaced,...
bool hb_itor_next(hb_itor *itor)
Move |itor| to the next element in key order and return true, or unposition it and return false if th...
const void * hb_itor_key(const hb_itor *itor)
Return the key |itor| is positioned on, or NULL if it is not positioned.
bool hb_itor_search_le(hb_itor *itor, const void *key)
Position |itor| on the greatest key less than or equal to |key| and return true, or unposition it and...
bool hb_tree_verify(const hb_tree *tree)
Check the internal invariants of the tree and return true if they hold, or print the first failed che...
bool hb_itor_first(hb_itor *itor)
Position |itor| on the first element in key order and return true, or unposition it and return false ...
size_t hb_tree_traverse(hb_tree *tree, dict_visit_func visit, void *user_data)
Call |visit|(key, datum, |user_data|) for each element in key order, stopping early if |visit| return...
void ** hb_tree_search_le(hb_tree *tree, const void *key)
Return the address of the datum of the greatest key less than or equal to |key|, or NULL if there is ...
size_t hb_tree_total_path_length(const hb_tree *tree)
Return the sum of the depths of all nodes, the root being at depth 1, or 0 for an empty tree.
Height-balanced (AVL) tree.
const itor_vtable * _vtable
The operations of one container type.
const dict_vtable * _vtable
dict_compare_func cmp_func
bool tree_iterator_last(void *Iterator)
void ** tree_iterator_datum(void *Iterator)
void * tree_node_max(void *Node)
void tree_iterator_invalidate(void *Iterator)
void ** tree_search_gt(void *Tree, const void *key)
int tree_iterator_compare(const void *Iterator1, const void *Iterator2)
void * tree_search_node(void *Tree, const void *key)
bool tree_iterator_search_le(void *Iterator, const void *key)
bool tree_iterator_valid(const void *Iterator)
size_t tree_count(const void *Tree)
void ** tree_search_lt(void *Tree, const void *key)
const void * tree_iterator_key(const void *Iterator)
size_t tree_min_path_length(const void *Tree)
void * tree_node_min(void *Node)
void ** tree_search(void *Tree, const void *key)
size_t tree_total_path_length(const void *Tree)
bool tree_iterator_first(void *Iterator)
void tree_iterator_free(void *Iterator)
bool tree_iterator_search_lt(void *Iterator, const void *key)
bool tree_iterator_search_ge(void *Iterator, const void *key)
size_t tree_max_path_length(const void *Tree)
void * tree_iterator_key_vt(void *Iterator)
int tree_iterator_compare_vt(void *Iterator1, void *Iterator2)
bool tree_iterator_search_gt(void *Iterator, const void *key)
void ** tree_search_ge(void *Tree, const void *key)
void ** tree_search_le(void *Tree, const void *key)
bool tree_iterator_search(void *Iterator, const void *key)
#define TREE_ITERATOR_FIELDS(tree_type, node_type)
#define TREE_FIELDS(node_type)