2 * Dictionary Abstract Data Type
3 * Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net>
5 * Free Software License:
7 * All rights are reserved by the author, with the following exceptions:
8 * Permission is granted to freely reproduce and distribute this software,
9 * possibly in exchange for a fee, provided that this copyright notice appears
10 * intact. Permission is also granted to adapt this software to produce
11 * derivative works, as long as the modified versions carry this copyright
12 * notice and additional notices stating that the work has been modified.
13 * This source code may be translated into executable form and incorporated
14 * into proprietary software; there is no requirement for such software to
15 * contain a copyright notice related to this source.
17 * $Id: dict.c,v 1.40.2.7 2000/11/13 01:36:44 kaz Exp $
18 * $Name: kazlib_1_20 $
24 #define EXT2FS_ATTR(x) __attribute__(x)
26 #define EXT2FS_ATTR(x)
32 #define DICT_IMPLEMENTATION
36 static const char rcsid[] = "$Id: dict.c,v 1.40.2.7 2000/11/13 01:36:44 kaz Exp $";
40 * These macros provide short convenient names for structure members,
41 * which are embellished with dict_ prefixes so that they are
42 * properly confined to the documented namespace. It's legal for a
43 * program which uses dict to define, for instance, a macro called ``parent''.
44 * Such a macro would interfere with the dnode_t struct definition.
45 * In general, highly portable and reusable C modules which expose their
46 * structures need to confine structure member names to well-defined spaces.
47 * The resulting identifiers aren't necessarily convenient to use, nor
48 * readable, in the implementation, however!
51 #define left dict_left
52 #define right dict_right
53 #define parent dict_parent
54 #define color dict_color
56 #define data dict_data
58 #define nilnode dict_nilnode
59 #define nodecount dict_nodecount
60 #define maxcount dict_maxcount
61 #define compare dict_compare
62 #define allocnode dict_allocnode
63 #define freenode dict_freenode
64 #define context dict_context
65 #define dupes dict_dupes
67 #define dictptr dict_dictptr
69 #define dict_root(D) ((D)->nilnode.left)
70 #define dict_nil(D) (&(D)->nilnode)
71 #define DICT_DEPTH_MAX 64
73 static dnode_t *dnode_alloc(void *context);
74 static void dnode_free(dnode_t *node, void *context);
77 * Perform a ``left rotation'' adjustment on the tree. The given node P and
78 * its right child C are rearranged so that the P instead becomes the left
79 * child of C. The left subtree of C is inherited as the new right subtree
80 * for P. The ordering of the keys within the tree is thus preserved.
83 static void rotate_left(dnode_t *upper)
85 dnode_t *lower, *lowleft, *upparent;
88 upper->right = lowleft = lower->left;
89 lowleft->parent = upper;
91 lower->parent = upparent = upper->parent;
93 /* don't need to check for root node here because root->parent is
94 the sentinel nil node, and root->parent->left points back to root */
96 if (upper == upparent->left) {
97 upparent->left = lower;
99 assert (upper == upparent->right);
100 upparent->right = lower;
104 upper->parent = lower;
108 * This operation is the ``mirror'' image of rotate_left. It is
109 * the same procedure, but with left and right interchanged.
112 static void rotate_right(dnode_t *upper)
114 dnode_t *lower, *lowright, *upparent;
117 upper->left = lowright = lower->right;
118 lowright->parent = upper;
120 lower->parent = upparent = upper->parent;
122 if (upper == upparent->right) {
123 upparent->right = lower;
125 assert (upper == upparent->left);
126 upparent->left = lower;
129 lower->right = upper;
130 upper->parent = lower;
134 * Do a postorder traversal of the tree rooted at the specified
135 * node and free everything under it. Used by dict_free().
138 static void free_nodes(dict_t *dict, dnode_t *node, dnode_t *nil)
142 free_nodes(dict, node->left, nil);
143 free_nodes(dict, node->right, nil);
144 dict->freenode(node, dict->context);
148 * This procedure performs a verification that the given subtree is a binary
149 * search tree. It performs an inorder traversal of the tree using the
150 * dict_next() successor function, verifying that the key of each node is
151 * strictly lower than that of its successor, if duplicates are not allowed,
152 * or lower or equal if duplicates are allowed. This function is used for
153 * debugging purposes.
156 static int verify_bintree(dict_t *dict)
158 dnode_t *first, *next;
160 first = dict_first(dict);
163 while (first && (next = dict_next(dict, first))) {
164 if (dict->compare(first->key, next->key) > 0)
169 while (first && (next = dict_next(dict, first))) {
170 if (dict->compare(first->key, next->key) >= 0)
179 * This function recursively verifies that the given binary subtree satisfies
180 * three of the red black properties. It checks that every red node has only
181 * black children. It makes sure that each node is either red or black. And it
182 * checks that every path has the same count of black nodes from root to leaf.
183 * It returns the blackheight of the given subtree; this allows blackheights to
184 * be computed recursively and compared for left and right siblings for
185 * mismatches. It does not check for every nil node being black, because there
186 * is only one sentinel nil node. The return value of this function is the
187 * black height of the subtree rooted at the node ``root'', or zero if the
188 * subtree is not red-black.
191 static unsigned int verify_redblack(dnode_t *nil, dnode_t *root)
193 unsigned height_left, height_right;
196 height_left = verify_redblack(nil, root->left);
197 height_right = verify_redblack(nil, root->right);
198 if (height_left == 0 || height_right == 0)
200 if (height_left != height_right)
202 if (root->color == dnode_red) {
203 if (root->left->color != dnode_black)
205 if (root->right->color != dnode_black)
209 if (root->color != dnode_black)
211 return height_left + 1;
217 * Compute the actual count of nodes by traversing the tree and
218 * return it. This could be compared against the stored count to
222 static dictcount_t verify_node_count(dnode_t *nil, dnode_t *root)
227 return 1 + verify_node_count(nil, root->left)
228 + verify_node_count(nil, root->right);
233 * Verify that the tree contains the given node. This is done by
234 * traversing all of the nodes and comparing their pointers to the
235 * given pointer. Returns 1 if the node is found, otherwise
236 * returns zero. It is intended for debugging purposes.
239 static int verify_dict_has_node(dnode_t *nil, dnode_t *root, dnode_t *node)
243 || verify_dict_has_node(nil, root->left, node)
244 || verify_dict_has_node(nil, root->right, node);
250 #ifdef E2FSCK_NOTUSED
252 * Dynamically allocate and initialize a dictionary object.
255 dict_t *dict_create(dictcount_t maxcount, dict_comp_t comp)
257 dict_t *new = malloc(sizeof *new);
261 new->allocnode = dnode_alloc;
262 new->freenode = dnode_free;
265 new->maxcount = maxcount;
266 new->nilnode.left = &new->nilnode;
267 new->nilnode.right = &new->nilnode;
268 new->nilnode.parent = &new->nilnode;
269 new->nilnode.color = dnode_black;
274 #endif /* E2FSCK_NOTUSED */
277 * Select a different set of node allocator routines.
280 void dict_set_allocator(dict_t *dict, dnode_alloc_t al,
281 dnode_free_t fr, void *context)
283 assert (dict_count(dict) == 0);
284 assert ((al == NULL && fr == NULL) || (al != NULL && fr != NULL));
286 dict->allocnode = al ? al : dnode_alloc;
287 dict->freenode = fr ? fr : dnode_free;
288 dict->context = context;
291 #ifdef E2FSCK_NOTUSED
293 * Free a dynamically allocated dictionary object. Removing the nodes
294 * from the tree before deleting it is required.
297 void dict_destroy(dict_t *dict)
299 assert (dict_isempty(dict));
305 * Free all the nodes in the dictionary by using the dictionary's
306 * installed free routine. The dictionary is emptied.
309 void dict_free_nodes(dict_t *dict)
311 dnode_t *nil = dict_nil(dict), *root = dict_root(dict);
312 free_nodes(dict, root, nil);
314 dict->nilnode.left = &dict->nilnode;
315 dict->nilnode.right = &dict->nilnode;
318 #ifdef E2FSCK_NOTUSED
320 * Obsolescent function, equivalent to dict_free_nodes
322 void dict_free(dict_t *dict)
324 #ifdef KAZLIB_OBSOLESCENT_DEBUG
325 assert ("call to obsolescent function dict_free()" && 0);
327 dict_free_nodes(dict);
332 * Initialize a user-supplied dictionary object.
335 dict_t *dict_init(dict_t *dict, dictcount_t maxcount, dict_comp_t comp)
337 dict->compare = comp;
338 dict->allocnode = dnode_alloc;
339 dict->freenode = dnode_free;
340 dict->context = NULL;
342 dict->maxcount = maxcount;
343 dict->nilnode.left = &dict->nilnode;
344 dict->nilnode.right = &dict->nilnode;
345 dict->nilnode.parent = &dict->nilnode;
346 dict->nilnode.color = dnode_black;
351 #ifdef E2FSCK_NOTUSED
353 * Initialize a dictionary in the likeness of another dictionary
356 void dict_init_like(dict_t *dict, const dict_t *template)
358 dict->compare = template->compare;
359 dict->allocnode = template->allocnode;
360 dict->freenode = template->freenode;
361 dict->context = template->context;
363 dict->maxcount = template->maxcount;
364 dict->nilnode.left = &dict->nilnode;
365 dict->nilnode.right = &dict->nilnode;
366 dict->nilnode.parent = &dict->nilnode;
367 dict->nilnode.color = dnode_black;
368 dict->dupes = template->dupes;
370 assert (dict_similar(dict, template));
374 * Remove all nodes from the dictionary (without freeing them in any way).
377 static void dict_clear(dict_t *dict)
380 dict->nilnode.left = &dict->nilnode;
381 dict->nilnode.right = &dict->nilnode;
382 dict->nilnode.parent = &dict->nilnode;
383 assert (dict->nilnode.color == dnode_black);
388 * Verify the integrity of the dictionary structure. This is provided for
389 * debugging purposes, and should be placed in assert statements. Just because
390 * this function succeeds doesn't mean that the tree is not corrupt. Certain
391 * corruptions in the tree may simply cause undefined behavior.
394 int dict_verify(dict_t *dict)
397 dnode_t *nil = dict_nil(dict), *root = dict_root(dict);
399 /* check that the sentinel node and root node are black */
400 if (root->color != dnode_black)
402 if (nil->color != dnode_black)
404 if (nil->right != nil)
406 /* nil->left is the root node; check that its parent pointer is nil */
407 if (nil->left->parent != nil)
409 /* perform a weak test that the tree is a binary search tree */
410 if (!verify_bintree(dict))
412 /* verify that the tree is a red-black tree */
413 if (!verify_redblack(nil, root))
415 if (verify_node_count(nil, root) != dict_count(dict))
422 * Determine whether two dictionaries are similar: have the same comparison and
423 * allocator functions, and same status as to whether duplicates are allowed.
426 int dict_similar(const dict_t *left, const dict_t *right)
428 if (left->compare != right->compare)
431 if (left->allocnode != right->allocnode)
434 if (left->freenode != right->freenode)
437 if (left->context != right->context)
440 if (left->dupes != right->dupes)
445 #endif /* E2FSCK_NOTUSED */
448 * Locate a node in the dictionary having the given key.
449 * If the node is not found, a null a pointer is returned (rather than
450 * a pointer that dictionary's nil sentinel node), otherwise a pointer to the
451 * located node is returned.
454 dnode_t *dict_lookup(dict_t *dict, const void *key)
456 dnode_t *root = dict_root(dict);
457 dnode_t *nil = dict_nil(dict);
461 /* simple binary search adapted for trees that contain duplicate keys */
463 while (root != nil) {
464 result = dict->compare(key, root->key);
470 if (!dict->dupes) { /* no duplicates, return match */
472 } else { /* could be dupes, find leftmost one */
476 while (root != nil && dict->compare(key, root->key))
478 } while (root != nil);
487 #ifdef E2FSCK_NOTUSED
489 * Look for the node corresponding to the lowest key that is equal to or
490 * greater than the given key. If there is no such node, return null.
493 dnode_t *dict_lower_bound(dict_t *dict, const void *key)
495 dnode_t *root = dict_root(dict);
496 dnode_t *nil = dict_nil(dict);
497 dnode_t *tentative = 0;
499 while (root != nil) {
500 int result = dict->compare(key, root->key);
504 } else if (result < 0) {
521 * Look for the node corresponding to the greatest key that is equal to or
522 * lower than the given key. If there is no such node, return null.
525 dnode_t *dict_upper_bound(dict_t *dict, const void *key)
527 dnode_t *root = dict_root(dict);
528 dnode_t *nil = dict_nil(dict);
529 dnode_t *tentative = 0;
531 while (root != nil) {
532 int result = dict->compare(key, root->key);
536 } else if (result > 0) {
554 * Insert a node into the dictionary. The node should have been
555 * initialized with a data field. All other fields are ignored.
556 * The behavior is undefined if the user attempts to insert into
557 * a dictionary that is already full (for which the dict_isfull()
558 * function returns true).
561 void dict_insert(dict_t *dict, dnode_t *node, const void *key)
563 dnode_t *where = dict_root(dict), *nil = dict_nil(dict);
564 dnode_t *parent = nil, *uncle, *grandpa;
569 assert (!dict_isfull(dict));
570 assert (!dict_contains(dict, node));
571 assert (!dnode_is_in_a_dict(node));
573 /* basic binary tree insert */
575 while (where != nil) {
577 result = dict->compare(key, where->key);
578 /* trap attempts at duplicate key insertion unless it's explicitly allowed */
579 assert (dict->dupes || result != 0);
583 where = where->right;
586 assert (where == nil);
591 parent->right = node;
593 node->parent = parent;
599 /* red black adjustments */
601 node->color = dnode_red;
603 while (parent->color == dnode_red) {
604 grandpa = parent->parent;
605 if (parent == grandpa->left) {
606 uncle = grandpa->right;
607 if (uncle->color == dnode_red) { /* red parent, red uncle */
608 parent->color = dnode_black;
609 uncle->color = dnode_black;
610 grandpa->color = dnode_red;
612 parent = grandpa->parent;
613 } else { /* red parent, black uncle */
614 if (node == parent->right) {
617 assert (grandpa == parent->parent);
618 /* rotation between parent and child preserves grandpa */
620 parent->color = dnode_black;
621 grandpa->color = dnode_red;
622 rotate_right(grandpa);
625 } else { /* symmetric cases: parent == parent->parent->right */
626 uncle = grandpa->left;
627 if (uncle->color == dnode_red) {
628 parent->color = dnode_black;
629 uncle->color = dnode_black;
630 grandpa->color = dnode_red;
632 parent = grandpa->parent;
634 if (node == parent->left) {
635 rotate_right(parent);
637 assert (grandpa == parent->parent);
639 parent->color = dnode_black;
640 grandpa->color = dnode_red;
641 rotate_left(grandpa);
647 dict_root(dict)->color = dnode_black;
649 assert (dict_verify(dict));
652 #ifdef E2FSCK_NOTUSED
654 * Delete the given node from the dictionary. If the given node does not belong
655 * to the given dictionary, undefined behavior results. A pointer to the
656 * deleted node is returned.
659 dnode_t *dict_delete(dict_t *dict, dnode_t *delete)
661 dnode_t *nil = dict_nil(dict), *child, *delparent = delete->parent;
665 assert (!dict_isempty(dict));
666 assert (dict_contains(dict, delete));
669 * If the node being deleted has two children, then we replace it with its
670 * successor (i.e. the leftmost node in the right subtree.) By doing this,
671 * we avoid the traditional algorithm under which the successor's key and
672 * value *only* move to the deleted node and the successor is spliced out
673 * from the tree. We cannot use this approach because the user may hold
674 * pointers to the successor, or nodes may be inextricably tied to some
675 * other structures by way of embedding, etc. So we must splice out the
676 * node we are given, not some other node, and must not move contents from
677 * one node to another behind the user's back.
680 if (delete->left != nil && delete->right != nil) {
681 dnode_t *next = dict_next(dict, delete);
682 dnode_t *nextparent = next->parent;
683 dnode_color_t nextcolor = next->color;
685 assert (next != nil);
686 assert (next->parent != nil);
687 assert (next->left == nil);
690 * First, splice out the successor from the tree completely, by
691 * moving up its right child into its place.
695 child->parent = nextparent;
697 if (nextparent->left == next) {
698 nextparent->left = child;
700 assert (nextparent->right == next);
701 nextparent->right = child;
705 * Now that the successor has been extricated from the tree, install it
706 * in place of the node that we want deleted.
709 next->parent = delparent;
710 next->left = delete->left;
711 next->right = delete->right;
712 next->left->parent = next;
713 next->right->parent = next;
714 next->color = delete->color;
715 delete->color = nextcolor;
717 if (delparent->left == delete) {
718 delparent->left = next;
720 assert (delparent->right == delete);
721 delparent->right = next;
725 assert (delete != nil);
726 assert (delete->left == nil || delete->right == nil);
728 child = (delete->left != nil) ? delete->left : delete->right;
730 child->parent = delparent = delete->parent;
732 if (delete == delparent->left) {
733 delparent->left = child;
735 assert (delete == delparent->right);
736 delparent->right = child;
740 delete->parent = NULL;
741 delete->right = NULL;
746 assert (verify_bintree(dict));
748 /* red-black adjustments */
750 if (delete->color == dnode_black) {
751 dnode_t *parent, *sister;
753 dict_root(dict)->color = dnode_red;
755 while (child->color == dnode_black) {
756 parent = child->parent;
757 if (child == parent->left) {
758 sister = parent->right;
759 assert (sister != nil);
760 if (sister->color == dnode_red) {
761 sister->color = dnode_black;
762 parent->color = dnode_red;
764 sister = parent->right;
765 assert (sister != nil);
767 if (sister->left->color == dnode_black
768 && sister->right->color == dnode_black) {
769 sister->color = dnode_red;
772 if (sister->right->color == dnode_black) {
773 assert (sister->left->color == dnode_red);
774 sister->left->color = dnode_black;
775 sister->color = dnode_red;
776 rotate_right(sister);
777 sister = parent->right;
778 assert (sister != nil);
780 sister->color = parent->color;
781 sister->right->color = dnode_black;
782 parent->color = dnode_black;
786 } else { /* symmetric case: child == child->parent->right */
787 assert (child == parent->right);
788 sister = parent->left;
789 assert (sister != nil);
790 if (sister->color == dnode_red) {
791 sister->color = dnode_black;
792 parent->color = dnode_red;
793 rotate_right(parent);
794 sister = parent->left;
795 assert (sister != nil);
797 if (sister->right->color == dnode_black
798 && sister->left->color == dnode_black) {
799 sister->color = dnode_red;
802 if (sister->left->color == dnode_black) {
803 assert (sister->right->color == dnode_red);
804 sister->right->color = dnode_black;
805 sister->color = dnode_red;
807 sister = parent->left;
808 assert (sister != nil);
810 sister->color = parent->color;
811 sister->left->color = dnode_black;
812 parent->color = dnode_black;
813 rotate_right(parent);
819 child->color = dnode_black;
820 dict_root(dict)->color = dnode_black;
823 assert (dict_verify(dict));
827 #endif /* E2FSCK_NOTUSED */
830 * Allocate a node using the dictionary's allocator routine, give it
834 int dict_alloc_insert(dict_t *dict, const void *key, void *data)
836 dnode_t *node = dict->allocnode(dict->context);
839 dnode_init(node, data);
840 dict_insert(dict, node, key);
846 #ifdef E2FSCK_NOTUSED
847 void dict_delete_free(dict_t *dict, dnode_t *node)
849 dict_delete(dict, node);
850 dict->freenode(node, dict->context);
855 * Return the node with the lowest (leftmost) key. If the dictionary is empty
856 * (that is, dict_isempty(dict) returns 1) a null pointer is returned.
859 dnode_t *dict_first(dict_t *dict)
861 dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *left;
864 while ((left = root->left) != nil)
867 return (root == nil) ? NULL : root;
871 * Return the node with the highest (rightmost) key. If the dictionary is empty
872 * (that is, dict_isempty(dict) returns 1) a null pointer is returned.
875 dnode_t *dict_last(dict_t *dict)
877 dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *right;
880 while ((right = root->right) != nil)
883 return (root == nil) ? NULL : root;
887 * Return the given node's successor node---the node which has the
888 * next key in the the left to right ordering. If the node has
889 * no successor, a null pointer is returned rather than a pointer to
893 dnode_t *dict_next(dict_t *dict, dnode_t *curr)
895 dnode_t *nil = dict_nil(dict), *parent, *left;
897 if (curr->right != nil) {
899 while ((left = curr->left) != nil)
904 parent = curr->parent;
906 while (parent != nil && curr == parent->right) {
908 parent = curr->parent;
911 return (parent == nil) ? NULL : parent;
915 * Return the given node's predecessor, in the key order.
916 * The nil sentinel node is returned if there is no predecessor.
919 dnode_t *dict_prev(dict_t *dict, dnode_t *curr)
921 dnode_t *nil = dict_nil(dict), *parent, *right;
923 if (curr->left != nil) {
925 while ((right = curr->right) != nil)
930 parent = curr->parent;
932 while (parent != nil && curr == parent->left) {
934 parent = curr->parent;
937 return (parent == nil) ? NULL : parent;
940 void dict_allow_dupes(dict_t *dict)
952 dictcount_t dict_count(dict_t *dict)
954 return dict->nodecount;
957 int dict_isempty(dict_t *dict)
959 return dict->nodecount == 0;
962 int dict_isfull(dict_t *dict)
964 return dict->nodecount == dict->maxcount;
967 int dict_contains(dict_t *dict, dnode_t *node)
969 return verify_dict_has_node(dict_nil(dict), dict_root(dict), node);
972 static dnode_t *dnode_alloc(void *context EXT2FS_ATTR((unused)))
974 return malloc(sizeof *dnode_alloc(NULL));
977 static void dnode_free(dnode_t *node, void *context EXT2FS_ATTR((unused)))
982 dnode_t *dnode_create(void *data)
984 dnode_t *new = malloc(sizeof *new);
994 dnode_t *dnode_init(dnode_t *dnode, void *data)
997 dnode->parent = NULL;
1003 void dnode_destroy(dnode_t *dnode)
1005 assert (!dnode_is_in_a_dict(dnode));
1009 void *dnode_get(dnode_t *dnode)
1014 const void *dnode_getkey(dnode_t *dnode)
1019 #ifdef E2FSCK_NOTUSED
1020 void dnode_put(dnode_t *dnode, void *data)
1025 int dnode_is_in_a_dict(dnode_t *dnode)
1027 return (dnode->parent && dnode->left && dnode->right);
1030 void dict_process(dict_t *dict, void *context, dnode_process_t function)
1032 dnode_t *node = dict_first(dict), *next;
1034 while (node != NULL) {
1035 /* check for callback function deleting */
1036 /* the next node from under us */
1037 assert (dict_contains(dict, node));
1038 next = dict_next(dict, node);
1039 function(dict, node, context);
1044 static void load_begin_internal(dict_load_t *load, dict_t *dict)
1046 load->dictptr = dict;
1047 load->nilnode.left = &load->nilnode;
1048 load->nilnode.right = &load->nilnode;
1051 void dict_load_begin(dict_load_t *load, dict_t *dict)
1053 assert (dict_isempty(dict));
1054 load_begin_internal(load, dict);
1057 void dict_load_next(dict_load_t *load, dnode_t *newnode, const void *key)
1059 dict_t *dict = load->dictptr;
1060 dnode_t *nil = &load->nilnode;
1062 assert (!dnode_is_in_a_dict(newnode));
1063 assert (dict->nodecount < dict->maxcount);
1066 if (dict->nodecount > 0) {
1068 assert (dict->compare(nil->left->key, key) <= 0);
1070 assert (dict->compare(nil->left->key, key) < 0);
1075 nil->right->left = newnode;
1076 nil->right = newnode;
1077 newnode->left = nil;
1081 void dict_load_end(dict_load_t *load)
1083 dict_t *dict = load->dictptr;
1084 dnode_t *tree[DICT_DEPTH_MAX] = { 0 };
1085 dnode_t *curr, *dictnil = dict_nil(dict), *loadnil = &load->nilnode, *next;
1086 dnode_t *complete = 0;
1087 dictcount_t fullcount = DICTCOUNT_T_MAX, nodecount = dict->nodecount;
1088 dictcount_t botrowcount;
1089 unsigned baselevel = 0, level = 0, i;
1091 assert (dnode_red == 0 && dnode_black == 1);
1093 while (fullcount >= nodecount && fullcount)
1096 botrowcount = nodecount - fullcount;
1098 for (curr = loadnil->left; curr != loadnil; curr = next) {
1101 if (complete == NULL && botrowcount-- == 0) {
1102 assert (baselevel == 0);
1103 assert (level == 0);
1104 baselevel = level = 1;
1107 if (complete != 0) {
1109 complete->right = dictnil;
1110 while (tree[level] != 0) {
1111 tree[level]->right = complete;
1112 complete->parent = tree[level];
1113 complete = tree[level];
1119 if (complete == NULL) {
1120 curr->left = dictnil;
1121 curr->right = dictnil;
1122 curr->color = level % 2;
1125 assert (level == baselevel);
1126 while (tree[level] != 0) {
1127 tree[level]->right = complete;
1128 complete->parent = tree[level];
1129 complete = tree[level];
1133 curr->left = complete;
1134 curr->color = (level + 1) % 2;
1135 complete->parent = curr;
1142 if (complete == NULL)
1145 for (i = 0; i < DICT_DEPTH_MAX; i++) {
1147 tree[i]->right = complete;
1148 complete->parent = tree[i];
1153 dictnil->color = dnode_black;
1154 dictnil->right = dictnil;
1155 complete->parent = dictnil;
1156 complete->color = dnode_black;
1157 dict_root(dict) = complete;
1159 assert (dict_verify(dict));
1162 void dict_merge(dict_t *dest, dict_t *source)
1165 dnode_t *leftnode = dict_first(dest), *rightnode = dict_first(source);
1167 assert (dict_similar(dest, source));
1172 dest->nodecount = 0;
1173 load_begin_internal(&load, dest);
1176 if (leftnode != NULL && rightnode != NULL) {
1177 if (dest->compare(leftnode->key, rightnode->key) < 0)
1181 } else if (leftnode != NULL) {
1183 } else if (rightnode != NULL) {
1186 assert (leftnode == NULL && rightnode == NULL);
1192 dnode_t *next = dict_next(dest, leftnode);
1194 leftnode->left = NULL; /* suppress assertion in dict_load_next */
1196 dict_load_next(&load, leftnode, leftnode->key);
1203 dnode_t *next = dict_next(source, rightnode);
1205 rightnode->left = NULL;
1207 dict_load_next(&load, rightnode, rightnode->key);
1214 dict_load_end(&load);
1216 #endif /* E2FSCK_NOTUSED */
1218 #ifdef KAZLIB_TEST_MAIN
1225 typedef char input_t[256];
1227 static int tokenize(char *string, ...)
1233 va_start(arglist, string);
1234 tokptr = va_arg(arglist, char **);
1236 while (*string && isspace((unsigned char) *string))
1241 while (*string && !isspace((unsigned char) *string))
1243 tokptr = va_arg(arglist, char **);
1254 static int comparef(const void *key1, const void *key2)
1256 return strcmp(key1, key2);
1259 static char *dupstring(char *str)
1261 int sz = strlen(str) + 1;
1262 char *new = malloc(sz);
1264 memcpy(new, str, sz);
1268 static dnode_t *new_node(void *c)
1270 static dnode_t few[5];
1274 return few + count++;
1279 static void del_node(dnode_t *n, void *c)
1283 static int prompt = 0;
1285 static void construct(dict_t *d)
1291 char *tok1, *tok2, *val;
1294 "p turn prompt on\n"
1295 "q finish construction\n"
1296 "a <key> <val> add new entry\n";
1298 if (!dict_isempty(d))
1299 puts("warning: dictionary not empty!");
1301 dict_load_begin(&dl, d);
1308 if (!fgets(in, sizeof(input_t), stdin))
1322 if (tokenize(in+1, &tok1, &tok2, (char **) 0) != 2) {
1326 key = dupstring(tok1);
1327 val = dupstring(tok2);
1328 dn = dnode_create(val);
1330 if (!key || !val || !dn) {
1331 puts("out of memory");
1338 dict_load_next(&dl, dn, key);
1354 dict_t *d = &darray[0];
1357 char *tok1, *tok2, *val;
1361 "a <key> <val> add value to dictionary\n"
1362 "d <key> delete value from dictionary\n"
1363 "l <key> lookup value in dictionary\n"
1364 "( <key> lookup lower bound\n"
1365 ") <key> lookup upper bound\n"
1366 "# <num> switch to alternate dictionary (0-9)\n"
1367 "j <num> <num> merge two dictionaries\n"
1368 "f free the whole dictionary\n"
1369 "k allow duplicate keys\n"
1370 "c show number of entries\n"
1371 "t dump whole dictionary in sort order\n"
1372 "m make dictionary out of sorted items\n"
1373 "p turn prompt on\n"
1374 "s switch to non-functioning allocator\n"
1377 for (i = 0; i < sizeof darray / sizeof *darray; i++)
1378 dict_init(&darray[i], DICTCOUNT_T_MAX, comparef);
1385 if (!fgets(in, sizeof(input_t), stdin))
1393 if (tokenize(in+1, &tok1, &tok2, (char **) 0) != 2) {
1397 key = dupstring(tok1);
1398 val = dupstring(tok2);
1401 puts("out of memory");
1406 if (!dict_alloc_insert(d, key, val)) {
1407 puts("dict_alloc_insert failed");
1414 if (tokenize(in+1, &tok1, (char **) 0) != 1) {
1418 dn = dict_lookup(d, tok1);
1420 puts("dict_lookup failed");
1423 val = dnode_get(dn);
1424 key = dnode_getkey(dn);
1425 dict_delete_free(d, dn);
1436 if (tokenize(in+1, &tok1, (char **) 0) != 1) {
1443 dn = dict_lookup(d, tok1);
1446 dn = dict_lower_bound(d, tok1);
1449 dn = dict_upper_bound(d, tok1);
1453 puts("lookup failed");
1456 val = dnode_get(dn);
1463 dict_allow_dupes(d);
1466 printf("%lu\n", (unsigned long) dict_count(d));
1469 for (dn = dict_first(d); dn; dn = dict_next(d, dn)) {
1470 printf("%s\t%s\n", (char *) dnode_getkey(dn),
1471 (char *) dnode_get(dn));
1483 dict_set_allocator(d, new_node, del_node, NULL);
1486 if (tokenize(in+1, &tok1, (char **) 0) != 1) {
1490 int dictnum = atoi(tok1);
1491 if (dictnum < 0 || dictnum > 9) {
1492 puts("invalid number");
1495 d = &darray[dictnum];
1499 if (tokenize(in+1, &tok1, &tok2, (char **) 0) != 2) {
1503 int dict1 = atoi(tok1), dict2 = atoi(tok2);
1504 if (dict1 < 0 || dict1 > 9 || dict2 < 0 || dict2 > 9) {
1505 puts("invalid number");
1508 dict_merge(&darray[dict1], &darray[dict2]);