12 unsigned char header[32];
16static node *ptroff_get(
const void *base,
const unsigned char *data) {
17 const ptrdiff_t offset = (ptrdiff_t)(
18 (uint64_t)data[0] << 56 | (uint64_t)data[1] << 48 |
19 (uint64_t)data[2] << 40 | (uint64_t)data[3] << 32 |
20 (uint64_t)data[4] << 24 | (uint64_t)data[5] << 16 |
21 (uint64_t)data[6] << 8 | (uint64_t)data[7]);
22 if (offset == 0)
return nullptr;
23 return (
node*)((
char*)base + offset - 1);
25static void ptroff_set(
const void *base,
unsigned char *data,
const node *ptr) {
28 offset = (uint64_t)((
char*)ptr - (
char*)base) + 1;
32 data[0] = (
unsigned char)(offset >> 56); data[1] = (
unsigned char)(offset >> 48);
33 data[2] = (
unsigned char)(offset >> 40); data[3] = (
unsigned char)(offset >> 32);
34 data[4] = (
unsigned char)(offset >> 24); data[5] = (
unsigned char)(offset >> 16);
35 data[6] = (
unsigned char)(offset >> 8 ); data[7] = (
unsigned char)offset;
37static void copy(
void *dst,
const void *src,
const size_t n) {
38 if (dst == src)
return;
40 assert_fatal(CLOD_DEBUG, (
char*)dst + n <= (
char*)src || (
char*)dst >= (
char*)src + n,
41 "Copying key/value in tree has buffers that overlap. This implies serious implementation bug.");
43 for (
size_t i = 0; i < n; i++) {
44 ((
char*)dst)[i] = ((
char*)src)[i];
48#define KEY_SIZE (tree->key_size)
49#define VAL_SIZE (tree->val_size)
50#define INTL_CAPACITY ((tree->node_size - (int)sizeof(node) - 8) / (tree->key_size + 8))
51#define LEAF_CAPACITY ((tree->node_size - (int)sizeof(node)) / (tree->key_size + tree->val_size))
53#define checksum_get(node) (\
54 (uint32_t)(node)->header[0] << 24 |\
55 (uint32_t)(node)->header[1] << 16 |\
56 (uint32_t)(node)->header[2] << 8 |\
57 (uint32_t)(node)->header[3])
59#define checksum_set(node, val) (\
60 (node)->header[0] = (unsigned char)((val) >> 24),\
61 (node)->header[1] = (unsigned char)((val) >> 16),\
62 (node)->header[2] = (unsigned char)((val) >> 8),\
63 (node)->header[3] = (unsigned char)((val)))
65#define type_get(n) ((n)->header[4])
66#define type_set(n, val) ((n)->header[4] = (val))
67#define length_get(n) ((n)->header[6] << 8 | (n)->header[7])
68#define length_set(n, val) ((n)->header[6] = (unsigned char)((val) >> 8), (n)->header[7] = (unsigned char)(val))
69#define parent_get(n) (node*)ptroff_get(tree->root, (n)->header + 8)
70#define parent_set(n, val) ptroff_set(tree->root, (n)->header + 8, val)
71#define next_get(n) (node*)ptroff_get(tree->root, (n)->header + 16)
72#define next_set(n, val) ptroff_set(tree->root, (n)->header + 16, val)
73#define prev_get(n) (node*)ptroff_get(tree->root, (n)->header + 24)
74#define prev_set(n, val) ptroff_set(tree->root, (n)->header + 24, val)
76#define key_get(n, index) (\
77 assert_fatal(CLOD_DEBUG, index >= 0 && index < length_get(n),\
78 "Key index %i out of bounds for node %ptr with %i keys.",\
79 index, (void*)n, length_get(n)),\
80 ((n)->keys + (index) * KEY_SIZE))
82#define key_set(n, index, val) \
83 assert_fatal(CLOD_DEBUG, index >= 0 && index < (type_get(n) == TYPE_LEAF ? LEAF_CAPACITY : INTL_CAPACITY),\
84 "Key index %i out of bounds for node %ptr with maximum %i keys.",\
85 index, (void*)n, type_get(n) == TYPE_LEAF ? LEAF_CAPACITY : INTL_CAPACITY),\
86 copy(((n)->keys + (index) * KEY_SIZE), (val), KEY_SIZE);
88#define val_get(n, index) (\
89 assert_fatal(CLOD_DEBUG, index >= 0 && index < length_get(n),\
90 "Value index %i out of bounds for node %ptr with %i keys.",\
91 index, (void*)n, length_get(n)),\
92 ((n)->keys + LEAF_CAPACITY * KEY_SIZE + (index) * VAL_SIZE))
94#define val_set(n, index, val) \
95 assert_fatal(CLOD_DEBUG, index >= 0 && index < LEAF_CAPACITY,\
96 "Value index %i out of bounds for node %ptr with maximum %i values.",\
97 index, (void*)n, LEAF_CAPACITY),\
98 copy(((n)->keys + LEAF_CAPACITY * KEY_SIZE + (index) * VAL_SIZE), (val), VAL_SIZE);
100#define branch_get(n, index) (\
101 assert_fatal(CLOD_DEBUG, index >= 0 && index <= length_get(n),\
102 "Branch index %i out of bounds for node %ptr with %i keys.",\
103 index, (void*)n, length_get(n)),\
104 (node*)ptroff_get(tree->root, (unsigned char*)(n)->keys + INTL_CAPACITY * KEY_SIZE + (index) * 8))
106#define branch_set(n, index, val) \
107 assert_fatal(CLOD_DEBUG, index >= 0 && index <= INTL_CAPACITY,\
108 "Branch index %i out of bounds for node %ptr with maximum %i branches.",\
109 index, (void*)n, INTL_CAPACITY + 1),\
110 ptroff_set(tree->root, (unsigned char*)(n)->keys + INTL_CAPACITY * KEY_SIZE + (index) * 8, val)
114void clod_tree_debug_print(
const struct clod_tree *tree,
const node *n,
const int depth) {
116 clod_stream_format(clod_stderr,
CLOD_STRING_C(
"\n==== Begin Tree Debug ====\n"));
119 clod_stream_format(clod_stderr,
CLOD_STRING_C(
"Tree is too deep to print. Skipping...\n"));
121 for (
int i = 0; i < depth; i++)
129 if (((uintptr_t)n & 0xFFFF700000000000ull) != 0x0000700000000000ull) {
130 clod_stream_format(clod_stderr,
CLOD_STRING_C(
"Node %ptr is not a valid node!\n"), (
void*)n);
134 if (type_get(n) == TYPE_LEAF) {
135 clod_stream_format(clod_stderr,
CLOD_STRING_C(
"Leaf %ptr (Parent: %ptr, Next: %ptr, Prev: %ptr, Keys: %i)\n"),
136 (
void*)n, (
void*)parent_get(n), (
void*)next_get(n), (
void*)prev_get(n), length_get(n));
138 for (
int i = 0; i <= depth; i++)
140 for (
int i = 0; i < length_get(n); i++) {
141 clod_stream_format(clod_stderr,
CLOD_STRING_C(
"| [%u]: %i -> %i "), i, *(
int*)key_get(n, i), *(
int*)val_get(n, i));
146 clod_stream_format(clod_stderr,
CLOD_STRING_C(
"Intl %ptr (Parent: %ptr, Keys: %i)\n"),
147 (
void*)n, (
void*)parent_get(n), length_get(n));
149 for (
int i = 0; i <= depth; i++)
152 for (
int i = 0; i < length_get(n); i++) {
153 clod_stream_format(clod_stderr,
CLOD_STRING_C(
"| Branch: %ptr | Key: %i "), branch_get(n, i), *(
int*)key_get(n, i));
155 clod_stream_format(clod_stderr,
CLOD_STRING_C(
"| Branch: %ptr |\n"), branch_get(n, length_get(n)));
158 for (
int i = 0; i < length_get(n); i++) {
159 clod_tree_debug_print(tree, branch_get(n, i), depth + 1);
161 for (
int k = 0; k < depth; k++)
163 clod_stream_format(clod_stderr,
CLOD_STRING_C(
"Key: %i\n"), *(
int*)key_get(n, i));
166 clod_tree_debug_print(tree, branch_get(n, length_get(n)), depth + 1);
170 clod_stream_format(clod_stderr,
CLOD_STRING_C(
"==== End Tree Debug ====\n\n"));
176static bool search(
const struct clod_tree *tree,
const node *n,
const void *key,
int *index) {
177 int l = 0, h = length_get(n);
179 const int m = (l + h) / 2;
183 }
else if (cmp > 0) {
196static node *parent_branch_get(
const struct clod_tree *tree,
const node *n,
int *parent_index) {
197 node *parent = parent_get(n);
202 for (
int i = 0; i <= length_get(parent); i++) {
203 if (branch_get(parent, i) == n) {
204 if (parent_index) *parent_index = i;
209 assert_fatal(CLOD_DEBUG,
false,
"Parent of %ptr does not contain it! Invalid tree.", (
void*)n);
213static void leaf_insert(
const struct clod_tree *tree,
node *n,
int index,
const void *key,
const void *val) {
214 const int len = length_get(n);
215 assert_fatal(CLOD_DEBUG, index <= len,
216 "Index %i out of bounds for inserting into node %ptr with %i keys.",
217 index, (
void*)n, len);
219 for (
int i = len; i > index; i--) key_set(n, i, key_get(n, i - 1));
220 for (
int i = len; i > index; i--) val_set(n, i, val_get(n, i - 1));
222 length_set(n, len + 1);
223 key_set(n, index, key);
224 val_set(n, index, val);
230 node *parent = parent_branch_get(tree, n, &index);
231 while (parent && index == length_get(parent)) {
232 parent = parent_branch_get(tree, parent, &index);
236 key_set(parent, index, key_get(n, len));
241static void intl_insert_left(
const struct clod_tree *tree,
node *n,
const int index,
const void *key,
node *
branch) {
242 for (
int i = length_get(n) + 1; i > index; i--) branch_set(n, i, branch_get(n, i - 1));
243 for (
int i = length_get(n); i > index; i--) key_set(n, i, key_get(n, i - 1));
245 length_set(n, length_get(n) + 1);
246 key_set(n, index, key);
247 branch_set(n, index,
branch);
252static void intl_insert_right(
const struct clod_tree *tree,
node *n,
const int index,
const void *key,
node *
branch) {
253 for (
int i = length_get(n) + 1; i > index + 1; i--) branch_set(n, i, branch_get(n, i - 1));
254 for (
int i = length_get(n); i > index; i--) key_set(n, i, key_get(n, i - 1));
256 length_set(n, length_get(n) + 1);
257 key_set(n, index, key);
258 branch_set(n, index + 1,
branch);
264static void leaf_remove(
const struct clod_tree *tree,
node *
const n,
int index) {
265 const int len = length_get(n);
266 for (
int i = index; i < len - 1; i++) val_set(n, i, val_get(n, i + 1));
267 for (
int i = index; i < len - 1; i++) key_set(n, i, key_get(n, i + 1));
268 length_set(n, len - 1);
270 if (index != len - 1) {
274 node *parent = parent_branch_get(tree, n, &index);
275 while (parent && index == length_get(parent)) {
276 parent = parent_branch_get(tree, parent, &index);
280 key_set(parent, index, key_get(n, len - 2));
285static void intl_remove_left(
const struct clod_tree *tree,
node *
const n,
const int index) {
286 for (
int i = index; i < length_get(n); i++) branch_set(n, i, branch_get(n, i + 1));
287 for (
int i = index; i < length_get(n) - 1; i++) key_set(n, i, key_get(n, i + 1));
288 length_set(n, length_get(n) - 1);
292static void intl_remove_right(
const struct clod_tree *tree,
node *
const n,
const int index) {
293 for (
int i = index + 1; i < length_get(n); i++) branch_set(n, i, branch_get(n, i + 1));
294 for (
int i = index; i < length_get(n) - 1; i++) key_set(n, i, key_get(n, i + 1));
295 length_set(n, length_get(n) - 1);
301 const int keys = length_get(n);
302 const int left_size = (keys + 1) / 2;
303 const int right_size = keys - left_size;
305 assert_fatal(CLOD_DEBUG, keys >= LEAF_CAPACITY / 2,
306 "Refusing to split leaf node %ptr with %i keys. Nodes may never be less than half full.",
310 node *
const parent = parent_branch_get(tree, n, &parent_index);
311 assert_fatal(CLOD_DEBUG, !parent || length_get(parent) < INTL_CAPACITY,
312 "Cannot split leaf node %ptr when its parent %ptr has %i out of %i keys occupied.",
313 (
void*)n, (
void*)parent, length_get(parent), INTL_CAPACITY);
315 type_set(left, TYPE_LEAF);
316 type_set(right, TYPE_LEAF);
317 parent_set(left, parent);
318 parent_set(right, parent);
319 const node *n_next = next_get(n), *n_prev = prev_get(n);
320 next_set(left, right);
321 next_set(right, n_next);
322 prev_set(left, n_prev);
323 prev_set(right, left);
326 branch_set(parent, parent_index, left);
327 intl_insert_right(tree, parent, parent_index, key_get(n, left_size - 1), right);
331 for (
int i = 0; i < right_size; i++) key_set(right, i, key_get(n, i + left_size));
332 for (
int i = 0; i < right_size; i++) val_set(right, i, val_get(n, i + left_size));
334 for (
int i = 0; i < left_size; i++) key_set(left, i, key_get(n, i));
335 for (
int i = 0; i < right_size; i++) key_set(right, i, key_get(n, i + left_size));
336 for (
int i = 0; i < left_size; i++) val_set(left, i, val_get(n, i));
337 for (
int i = 0; i < right_size; i++) val_set(right, i, val_get(n, i + left_size));
340 length_set(left, left_size);
341 length_set(right, right_size);
342 return left_size - 1;
348 const int keys = length_get(n);
349 const int left_size = keys / 2;
350 const int right_size = keys - left_size - 1;
352 assert_fatal(CLOD_DEBUG, keys >= INTL_CAPACITY / 2,
353 "Refusing to split internal node %ptr with %i keys. Nodes may never be less than half full.",
357 node *
const parent = parent_branch_get(tree, n, &parent_index);
358 assert_fatal(CLOD_DEBUG, !parent || length_get(parent) < INTL_CAPACITY,
359 "Cannot split leaf node when its parent %ptr has no space.", (
void*)parent);
361 type_set(left, TYPE_INTL);
362 type_set(right, TYPE_INTL);
363 parent_set(left, parent);
364 parent_set(right, parent);
366 branch_set(parent, parent_index, left);
367 intl_insert_right(tree, parent, parent_index, key_get(n, left_size), right);
371 for (
int i = 0; i < right_size; i++) key_set(right, i, key_get(n, i + left_size + 1));
372 for (
int i = 0; i <= right_size; i++) branch_set(right, i, branch_get(n, i + left_size + 1));
374 for (
int i = 0; i < left_size; i++) key_set(left, i, key_get(n, i));
375 for (
int i = 0; i < right_size; i++) key_set(right, i, key_get(n, i + left_size + 1));
376 for (
int i = 0; i <= left_size; i++) branch_set(left, i, branch_get(n, i));
377 for (
int i = 0; i <= right_size; i++) branch_set(right, i, branch_get(n, i + left_size + 1));
380 length_set(left, left_size);
381 length_set(right, right_size);
382 for (
int i = 0; i <= left_size; i++) parent_set(branch_get(left, i), left);
383 for (
int i = 0; i <= right_size; i++) parent_set(branch_get(right, i), right);
390 const int left_len = length_get(left);
391 const int right_len = length_get(right);
393 assert_fatal(CLOD_DEBUG, left_len + right_len <= LEAF_CAPACITY,
394 "Cannot merge leaf nodes %ptr and %ptr because their combined elements %i + %i = %i is larger than the maximum %i.",
395 (
void*)left, (
void*)right, left_len, right_len, left_len + right_len, LEAF_CAPACITY);
398 node *parent = parent_branch_get(tree, left, &parent_index);
399 assert_fatal(CLOD_DEBUG, parent == parent_get(right),
400 "Cannot merge leaf nodes %ptr and %ptr that belong to different parents %ptr and %ptr.",
401 (
void*)left, (
void*)right, (
void*)parent_get(left), (
void*)parent_get(right));
403 type_set(n, TYPE_LEAF);
404 length_set(n, left_len + right_len);
405 parent_set(n, parent);
406 next_set(n, next_get(right));
407 prev_set(n, prev_get(left));
409 intl_remove_right(tree, parent, parent_index);
410 branch_set(parent, parent_index, n);
413 for (
int i = 0; i < right_len; i++) key_set(n, i + left_len, key_get(right, i));
414 for (
int i = 0; i < right_len; i++) val_set(n, i + left_len, val_get(right, i));
416 for (
int i = right_len - 1; i >= 0; i--) key_set(n, i + left_len, key_get(right, i));
417 for (
int i = 0; i < left_len; i++) key_set(n, i, key_get(left, i));
418 for (
int i = right_len - 1; i >= 0; i--) val_set(n, i + left_len, val_get(right, i));
419 for (
int i = 0; i < left_len; i++) val_set(n, i, val_get(left, i));
426 const int left_len = length_get(left);
427 const int right_len = length_get(right);
429 assert_fatal(CLOD_DEBUG, left_len + right_len <= INTL_CAPACITY,
430 "Cannot merge internal nodes %ptr and %ptr because their combined elements %i + %i = %i is larger than the maximum %i.",
431 (
void*)left, (
void*)right, left_len, right_len, left_len + right_len, INTL_CAPACITY);
434 node *parent = parent_branch_get(tree, left, &parent_index);
435 assert_fatal(CLOD_DEBUG, parent == parent_get(right),
436 "Cannot merge internal nodes %ptr and %ptr that belong to different parents %ptr and %ptr.",
437 (
void*)left, (
void*)right, (
void*)parent_get(left), (
void*)parent_get(right));
439 type_set(n, TYPE_INTL);
440 length_set(n, left_len + right_len + 1);
441 parent_set(n, parent);
443 intl_remove_right(tree, parent, parent_index);
444 branch_set(parent, parent_index, n);
447 for (
int i = 0; i < right_len; i++) key_set(n, i + left_len + 1, key_get(right, i));
448 for (
int i = 0; i <= right_len; i++) branch_set(n, i + left_len + 1, branch_get(right, i));
450 for (
int i = right_len - 1; i >= 0; i--) key_set(n, i + left_len + 1, key_get(right, i));
451 for (
int i = 0; i < left_len; i++) key_set(n, i, key_get(left, i));
452 for (
int i = right_len - 1; i >= 0; i--) branch_set(n, i + left_len + 1, branch_get(right, i));
453 for (
int i = 0; i <= left_len; i++) branch_set(n, i, branch_get(left, i));
456 for (
int i = 0; i <= length_get(n); i++) parent_set(branch_get(n, i), n);
464 node *parent = parent_branch_get(tree, n, &index);
466 debug(CLOD_DEBUG,
"Cannot balance root node.");
473 right = branch_get(parent, 1);
475 left = branch_get(parent, index - 1);
478 const int left_len = length_get(left), right_len = length_get(right);
480 if (type_get(n) == TYPE_LEAF) {
481 if (left_len + right_len <= LEAF_CAPACITY) {
483 leaf_merge(tree, left, left, right);
486 }
else if (left_len < right_len) {
488 leaf_insert(tree, left, left_len, key_get(right, 0), val_get(right, 0));
489 leaf_remove(tree, right, 0);
491 }
else if (right_len < left_len) {
493 leaf_insert(tree, right, 0, key_get(left, left_len - 1), val_get(left, left_len - 1));
494 leaf_remove(tree, left, left_len - 1);
497 }
else if (type_get(n) == TYPE_INTL) {
499 if (left_len + right_len <= INTL_CAPACITY) {
501 intl_merge(tree, left, left, right);
504 }
else if (left_len < right_len) {
506 intl_insert_right(tree, left, left_len, key_get(parent, index), branch_get(right, 0));
507 key_set(parent, index, key_get(right, 0));
508 intl_remove_left(tree, right, 0);
510 }
else if (right_len < left_len) {
512 intl_insert_left(tree, right, 0, key_get(parent, index), branch_get(left, left_len - 1));
513 key_set(parent, index, key_get(left, left_len - 1));
514 intl_remove_right(tree, left, left_len - 1);
523 debug(CLOD_DEBUG,
"Tree key size cannot be zero.");
529 debug(CLOD_DEBUG,
"Tree node size of %i is too small. Need %i for a key and value size of %i and %i.",
535 debug(CLOD_DEBUG,
"Tree compare function cannot be null.");
541 debug(CLOD_DEBUG,
"Tree allocator methods cannot be null.");
547 debug(CLOD_DEBUG,
"Failed to allocate root node.");
551 type_set(tree->
root, TYPE_LEAF);
552 length_set(tree->
root, 0);
553 parent_set(tree->
root,
nullptr);
560 if (!tree->
root)
return;
563 const int len = length_get(n);
566 type_get(n) == TYPE_LEAF ||
567 (length_get(n) == 0 && branch_get(n, 0) ==
nullptr)
569 node *tmp = parent_get(n);
575 node *next = branch_get(n, len);
576 branch_set(n, len,
nullptr);
578 length_set(n, len - 1);
583 tree->
root =
nullptr;
590 while (type_get(n) == TYPE_INTL) {
591 search(tree, n, key, &index);
592 n = branch_get(n, index);
595 if (search(tree, n, key, &index)) {
596 if (key_out) copy(key_out, key_get(n, index), tree->
key_size);
597 if (val_out) copy(val_out, val_get(n, index), tree->
val_size);
601 if (length_get(n) < LEAF_CAPACITY) {
602 leaf_insert(tree, n, index, key, val);
606 while (parent_get(n) && length_get(parent_get(n)) >= INTL_CAPACITY) {
608 node *parent = parent_branch_get(tree, n, &parent_index);
610 if (parent_index > 0 && length_get(branch_get(parent, parent_index - 1)) < INTL_CAPACITY) {
611 node *left = branch_get(parent, parent_index - 1);
612 intl_insert_right(tree, left, length_get(left), key_get(parent, parent_index - 1), branch_get(n, 0));
613 key_set(parent, parent_index - 1, key_get(n, 0));
614 intl_remove_left(tree, n, 0);
616 search(tree, parent, key, &index);
617 n = branch_get(parent, index);
618 search(tree, n, key, &index);
619 n = branch_get(n, index);
623 if (parent_index < length_get(parent) - 1 && length_get(branch_get(parent, parent_index + 1)) < INTL_CAPACITY) {
624 node *right = branch_get(parent, parent_index + 1);
625 intl_insert_left(tree, right, 0, key_get(parent, parent_index), branch_get(n, length_get(n)));
626 key_set(parent, parent_index, key_get(n, length_get(n) - 1));
627 intl_remove_right(tree, n, length_get(n) - 1);
629 search(tree, parent, key, &index);
630 n = branch_get(parent, index);
631 search(tree, n, key, &index);
632 n = branch_get(n, index);
639 if (parent_get(n) ==
nullptr) {
642 if (!left || !right) {
643 debug(CLOD_DEBUG,
"Failed to allocate new internal node.");
649 if (type_get(n) == TYPE_LEAF) {
650 const int split = leaf_split(tree, n, left, right);
652 type_set(n, TYPE_INTL);
653 key_set(n, 0, key_get(n, split));
655 branch_set(n, 0, left);
656 branch_set(n, 1, right);
658 parent_set(right, n);
660 search(tree, n, key, &index);
661 n = branch_get(n, index);
662 search(tree, n, key, &index);
663 leaf_insert(tree, n, index, key, val);
667 if (type_get(n) == TYPE_INTL) {
668 const int split = intl_split(tree, n, left, right);
670 type_set(n, TYPE_INTL);
671 key_set(n, 0, key_get(n, split));
673 branch_set(n, 0, left);
674 branch_set(n, 1, right);
676 parent_set(right, n);
678 search(tree, n, key, &index);
679 n = branch_get(n, index);
680 search(tree, n, key, &index);
681 n = branch_get(n, index);
685 while (type_get(n) == TYPE_INTL) {
688 debug(CLOD_DEBUG,
"Failed to allocate new internal node.");
692 search(tree, n, key, &index);
693 const int split = intl_split(tree, n, n,
new);
695 n = branch_get(n, index);
697 n = branch_get(
new, index - split - 1);
703 debug(CLOD_DEBUG,
"Failed to allocate new leaf node.");
707 search(tree, n, key, &index);
708 const int split = leaf_split(tree, n, n,
new);
709 if (index >= split) {
711 index = index - split - 1;
714 leaf_insert(tree, n, index, key, val);
721 while (type_get(n) == TYPE_INTL) {
722 search(tree, n, key, &index);
723 n = branch_get(n, index);
726 if (search(tree, n, key, &index)) {
727 if (key_out) copy(key_out, key_get(n, index), tree->
key_size);
728 if (val_out) copy(val_out, val_get(n, index), tree->
val_size);
737 while (type_get(n) == TYPE_INTL) {
738 search(tree, n, key, &index);
739 n = branch_get(n, index);
742 if (!search(tree, n, key, &index)) {
746 if (key_out) copy(key_out, key_get(n, index), tree->
key_size);
747 if (val_out) copy(val_out, val_get(n, index), tree->
val_size);
748 leaf_remove(tree, n, index);
750 while (n && length_get(n) < LEAF_CAPACITY / 2) {
#define CLOD_STRING_C(cstr)
String literal constant.
void * self
Value passed to invocations of allocate and free.
void(* free)(void *ptr, void *self)
void *(* allocate)(size_t size, void *self)
int(* compare)(const void *key1, const void *key2, void *user)
Comparison function.
unsigned char val_size
Size of values in the tree.
unsigned short node_size
Size of each node in the tree.
void * compare_user
User variable passed to invocations of compare.
unsigned char key_size
Size of keys in the tree.
struct clod_tree_node * root
Pointer to the root node.
bool clod_tree_create(struct clod_tree *tree)
bool clod_tree_del(const struct clod_tree *tree, const void *key, void *key_out, void *val_out)
void clod_tree_destroy(struct clod_tree *tree)
bool clod_tree_get(const struct clod_tree *tree, const void *key, void *key_out, void *val_out)
bool clod_tree_add(const struct clod_tree *tree, const void *key, const void *val, void *key_out, void *val_out)