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 $
19 * The work has been modified.
25 #define EXT2FS_ATTR(x) __attribute__(x)
27 #define EXT2FS_ATTR(x)
34 #define dict_assert(x)
37 #define dict_assert(x) assert(x)
39 #define DICT_IMPLEMENTATION
43 static const char rcsid[] = "$Id: dict.c,v 1.40.2.7 2000/11/13 01:36:44 kaz Exp $";
47 * These macros provide short convenient names for structure members,
48 * which are embellished with dict_ prefixes so that they are
49 * properly confined to the documented namespace. It's legal for a
50 * program which uses dict to define, for instance, a macro called ``parent''.
51 * Such a macro would interfere with the dnode_t struct definition.
52 * In general, highly portable and reusable C modules which expose their
53 * structures need to confine structure member names to well-defined spaces.
54 * The resulting identifiers aren't necessarily convenient to use, nor
55 * readable, in the implementation, however!
58 #define left dict_left
59 #define right dict_right
60 #define parent dict_parent
61 #define color dict_color
63 #define data dict_data
65 #define nilnode dict_nilnode
66 #define nodecount dict_nodecount
67 #define maxcount dict_maxcount
68 #define compare dict_compare
69 #define allocnode dict_allocnode
70 #define freenode dict_freenode
71 #define context dict_context
72 #define dupes dict_dupes
74 #define dictptr dict_dictptr
76 #define dict_root(D) ((D)->nilnode.left)
77 #define dict_nil(D) (&(D)->nilnode)
78 #define DICT_DEPTH_MAX 64
80 static dnode_t *dnode_alloc(void *context);
81 static void dnode_free(dnode_t *node, void *context);
84 * Perform a ``left rotation'' adjustment on the tree. The given node P and
85 * its right child C are rearranged so that the P instead becomes the left
86 * child of C. The left subtree of C is inherited as the new right subtree
87 * for P. The ordering of the keys within the tree is thus preserved.
90 static void rotate_left(dnode_t *upper)
92 dnode_t *lower, *lowleft, *upparent;
95 upper->right = lowleft = lower->left;
96 lowleft->parent = upper;
98 lower->parent = upparent = upper->parent;
100 /* don't need to check for root node here because root->parent is
101 the sentinel nil node, and root->parent->left points back to root */
103 if (upper == upparent->left) {
104 upparent->left = lower;
106 dict_assert (upper == upparent->right);
107 upparent->right = lower;
111 upper->parent = lower;
115 * This operation is the ``mirror'' image of rotate_left. It is
116 * the same procedure, but with left and right interchanged.
119 static void rotate_right(dnode_t *upper)
121 dnode_t *lower, *lowright, *upparent;
124 upper->left = lowright = lower->right;
125 lowright->parent = upper;
127 lower->parent = upparent = upper->parent;
129 if (upper == upparent->right) {
130 upparent->right = lower;
132 dict_assert (upper == upparent->left);
133 upparent->left = lower;
136 lower->right = upper;
137 upper->parent = lower;
141 * Do a postorder traversal of the tree rooted at the specified
142 * node and free everything under it. Used by dict_free().
145 static void free_nodes(dict_t *dict, dnode_t *node, dnode_t *nil)
149 free_nodes(dict, node->left, nil);
150 free_nodes(dict, node->right, nil);
151 dict->freenode(node, dict->context);
155 * This procedure performs a verification that the given subtree is a binary
156 * search tree. It performs an inorder traversal of the tree using the
157 * dict_next() successor function, verifying that the key of each node is
158 * strictly lower than that of its successor, if duplicates are not allowed,
159 * or lower or equal if duplicates are allowed. This function is used for
160 * debugging purposes.
163 static int verify_bintree(dict_t *dict)
165 dnode_t *first, *next;
167 first = dict_first(dict);
170 while (first && (next = dict_next(dict, first))) {
171 if (dict->compare(first->key, next->key) > 0)
176 while (first && (next = dict_next(dict, first))) {
177 if (dict->compare(first->key, next->key) >= 0)
186 * This function recursively verifies that the given binary subtree satisfies
187 * three of the red black properties. It checks that every red node has only
188 * black children. It makes sure that each node is either red or black. And it
189 * checks that every path has the same count of black nodes from root to leaf.
190 * It returns the blackheight of the given subtree; this allows blackheights to
191 * be computed recursively and compared for left and right siblings for
192 * mismatches. It does not check for every nil node being black, because there
193 * is only one sentinel nil node. The return value of this function is the
194 * black height of the subtree rooted at the node ``root'', or zero if the
195 * subtree is not red-black.
198 static unsigned int verify_redblack(dnode_t *nil, dnode_t *root)
200 unsigned height_left, height_right;
203 height_left = verify_redblack(nil, root->left);
204 height_right = verify_redblack(nil, root->right);
205 if (height_left == 0 || height_right == 0)
207 if (height_left != height_right)
209 if (root->color == dnode_red) {
210 if (root->left->color != dnode_black)
212 if (root->right->color != dnode_black)
216 if (root->color != dnode_black)
218 return height_left + 1;
224 * Compute the actual count of nodes by traversing the tree and
225 * return it. This could be compared against the stored count to
229 static dictcount_t verify_node_count(dnode_t *nil, dnode_t *root)
234 return 1 + verify_node_count(nil, root->left)
235 + verify_node_count(nil, root->right);
240 * Verify that the tree contains the given node. This is done by
241 * traversing all of the nodes and comparing their pointers to the
242 * given pointer. Returns 1 if the node is found, otherwise
243 * returns zero. It is intended for debugging purposes.
246 static int verify_dict_has_node(dnode_t *nil, dnode_t *root, dnode_t *node)
250 || verify_dict_has_node(nil, root->left, node)
251 || verify_dict_has_node(nil, root->right, node);
257 #ifdef E2FSCK_NOTUSED
259 * Dynamically allocate and initialize a dictionary object.
262 dict_t *dict_create(dictcount_t maxcount, dict_comp_t comp)
264 dict_t *new = malloc(sizeof *new);
268 new->allocnode = dnode_alloc;
269 new->freenode = dnode_free;
273 new->maxcount = maxcount;
274 new->nilnode.left = &new->nilnode;
275 new->nilnode.right = &new->nilnode;
276 new->nilnode.parent = &new->nilnode;
277 new->nilnode.color = dnode_black;
282 #endif /* E2FSCK_NOTUSED */
285 * Select a different set of node allocator routines.
288 void dict_set_allocator(dict_t *dict, dnode_alloc_t al,
289 dnode_free_t fr, void *context)
291 dict_assert (dict_count(dict) == 0);
292 dict_assert ((al == NULL && fr == NULL) || (al != NULL && fr != NULL));
294 dict->allocnode = al ? al : dnode_alloc;
295 dict->freenode = fr ? fr : dnode_free;
296 dict->context = context;
299 void dict_set_cmp_context(dict_t *dict, const void *cmp_ctx)
301 dict_assert (!dict->cmp_ctx);
302 dict_assert (dict_count(dict) == 0);
304 dict->cmp_ctx = cmp_ctx;
307 #ifdef E2FSCK_NOTUSED
309 * Free a dynamically allocated dictionary object. Removing the nodes
310 * from the tree before deleting it is required.
313 void dict_destroy(dict_t *dict)
315 dict_assert (dict_isempty(dict));
321 * Free all the nodes in the dictionary by using the dictionary's
322 * installed free routine. The dictionary is emptied.
325 void dict_free_nodes(dict_t *dict)
327 dnode_t *nil = dict_nil(dict), *root = dict_root(dict);
328 free_nodes(dict, root, nil);
330 dict->nilnode.left = &dict->nilnode;
331 dict->nilnode.right = &dict->nilnode;
334 #ifdef E2FSCK_NOTUSED
336 * Obsolescent function, equivalent to dict_free_nodes
338 void dict_free(dict_t *dict)
340 #ifdef KAZLIB_OBSOLESCENT_DEBUG
341 dict_assert ("call to obsolescent function dict_free()" && 0);
343 dict_free_nodes(dict);
348 * Initialize a user-supplied dictionary object.
351 dict_t *dict_init(dict_t *dict, dictcount_t maxcount, dict_comp_t comp)
353 dict->compare = comp;
354 dict->allocnode = dnode_alloc;
355 dict->freenode = dnode_free;
356 dict->context = NULL;
358 dict->maxcount = maxcount;
359 dict->nilnode.left = &dict->nilnode;
360 dict->nilnode.right = &dict->nilnode;
361 dict->nilnode.parent = &dict->nilnode;
362 dict->nilnode.color = dnode_black;
367 #ifdef E2FSCK_NOTUSED
369 * Initialize a dictionary in the likeness of another dictionary
372 void dict_init_like(dict_t *dict, const dict_t *template)
374 dict->compare = template->compare;
375 dict->allocnode = template->allocnode;
376 dict->freenode = template->freenode;
377 dict->context = template->context;
379 dict->maxcount = template->maxcount;
380 dict->nilnode.left = &dict->nilnode;
381 dict->nilnode.right = &dict->nilnode;
382 dict->nilnode.parent = &dict->nilnode;
383 dict->nilnode.color = dnode_black;
384 dict->dupes = template->dupes;
386 dict_assert (dict_similar(dict, template));
390 * Remove all nodes from the dictionary (without freeing them in any way).
393 static void dict_clear(dict_t *dict)
396 dict->nilnode.left = &dict->nilnode;
397 dict->nilnode.right = &dict->nilnode;
398 dict->nilnode.parent = &dict->nilnode;
399 dict_assert (dict->nilnode.color == dnode_black);
401 #endif /* E2FSCK_NOTUSED */
405 * Verify the integrity of the dictionary structure. This is provided for
406 * debugging purposes, and should be placed in assert statements. Just because
407 * this function succeeds doesn't mean that the tree is not corrupt. Certain
408 * corruptions in the tree may simply cause undefined behavior.
411 int dict_verify(dict_t *dict)
413 dnode_t *nil = dict_nil(dict), *root = dict_root(dict);
415 /* check that the sentinel node and root node are black */
416 if (root->color != dnode_black)
418 if (nil->color != dnode_black)
420 if (nil->right != nil)
422 /* nil->left is the root node; check that its parent pointer is nil */
423 if (nil->left->parent != nil)
425 /* perform a weak test that the tree is a binary search tree */
426 if (!verify_bintree(dict))
428 /* verify that the tree is a red-black tree */
429 if (!verify_redblack(nil, root))
431 if (verify_node_count(nil, root) != dict_count(dict))
435 #endif /* DICT_NODEBUG */
437 #ifdef E2FSCK_NOTUSED
439 * Determine whether two dictionaries are similar: have the same comparison and
440 * allocator functions, and same status as to whether duplicates are allowed.
442 int dict_similar(const dict_t *left, const dict_t *right)
444 if (left->compare != right->compare)
447 if (left->allocnode != right->allocnode)
450 if (left->freenode != right->freenode)
453 if (left->context != right->context)
456 if (left->dupes != right->dupes)
461 #endif /* E2FSCK_NOTUSED */
464 * Locate a node in the dictionary having the given key.
465 * If the node is not found, a null a pointer is returned (rather than
466 * a pointer that dictionary's nil sentinel node), otherwise a pointer to the
467 * located node is returned.
470 dnode_t *dict_lookup(dict_t *dict, const void *key)
472 dnode_t *root = dict_root(dict);
473 dnode_t *nil = dict_nil(dict);
477 /* simple binary search adapted for trees that contain duplicate keys */
479 while (root != nil) {
480 result = dict->compare(dict->cmp_ctx, key, root->key);
486 if (!dict->dupes) { /* no duplicates, return match */
488 } else { /* could be dupes, find leftmost one */
493 && dict->compare(dict->cmp_ctx, key, root->key))
495 } while (root != nil);
504 #ifdef E2FSCK_NOTUSED
506 * Look for the node corresponding to the lowest key that is equal to or
507 * greater than the given key. If there is no such node, return null.
510 dnode_t *dict_lower_bound(dict_t *dict, const void *key)
512 dnode_t *root = dict_root(dict);
513 dnode_t *nil = dict_nil(dict);
514 dnode_t *tentative = 0;
516 while (root != nil) {
517 int result = dict->compare(dict->cmp_ctx, key, root->key);
521 } else if (result < 0) {
538 * Look for the node corresponding to the greatest key that is equal to or
539 * lower than the given key. If there is no such node, return null.
542 dnode_t *dict_upper_bound(dict_t *dict, const void *key)
544 dnode_t *root = dict_root(dict);
545 dnode_t *nil = dict_nil(dict);
546 dnode_t *tentative = 0;
548 while (root != nil) {
549 int result = dict->compare(dict->cmp_ctx, key, root->key);
553 } else if (result > 0) {
571 * Insert a node into the dictionary. The node should have been
572 * initialized with a data field. All other fields are ignored.
573 * The behavior is undefined if the user attempts to insert into
574 * a dictionary that is already full (for which the dict_isfull()
575 * function returns true).
578 void dict_insert(dict_t *dict, dnode_t *node, const void *key)
580 dnode_t *where = dict_root(dict), *nil = dict_nil(dict);
581 dnode_t *parent = nil, *uncle, *grandpa;
586 dict_assert (!dict_isfull(dict));
587 dict_assert (!dict_contains(dict, node));
588 dict_assert (!dnode_is_in_a_dict(node));
590 /* basic binary tree insert */
592 while (where != nil) {
594 result = dict->compare(dict->cmp_ctx, key, where->key);
595 /* trap attempts at duplicate key insertion unless it's explicitly allowed */
596 dict_assert (dict->dupes || result != 0);
600 where = where->right;
603 dict_assert (where == nil);
608 parent->right = node;
610 node->parent = parent;
616 /* red black adjustments */
618 node->color = dnode_red;
620 while (parent->color == dnode_red) {
621 grandpa = parent->parent;
622 if (parent == grandpa->left) {
623 uncle = grandpa->right;
624 if (uncle->color == dnode_red) { /* red parent, red uncle */
625 parent->color = dnode_black;
626 uncle->color = dnode_black;
627 grandpa->color = dnode_red;
629 parent = grandpa->parent;
630 } else { /* red parent, black uncle */
631 if (node == parent->right) {
634 dict_assert (grandpa == parent->parent);
635 /* rotation between parent and child preserves grandpa */
637 parent->color = dnode_black;
638 grandpa->color = dnode_red;
639 rotate_right(grandpa);
642 } else { /* symmetric cases: parent == parent->parent->right */
643 uncle = grandpa->left;
644 if (uncle->color == dnode_red) {
645 parent->color = dnode_black;
646 uncle->color = dnode_black;
647 grandpa->color = dnode_red;
649 parent = grandpa->parent;
651 if (node == parent->left) {
652 rotate_right(parent);
654 dict_assert (grandpa == parent->parent);
656 parent->color = dnode_black;
657 grandpa->color = dnode_red;
658 rotate_left(grandpa);
664 dict_root(dict)->color = dnode_black;
666 dict_assert (dict_verify(dict));
669 #ifdef E2FSCK_NOTUSED
671 * Delete the given node from the dictionary. If the given node does not belong
672 * to the given dictionary, undefined behavior results. A pointer to the
673 * deleted node is returned.
676 dnode_t *dict_delete(dict_t *dict, dnode_t *delete)
678 dnode_t *nil = dict_nil(dict), *child, *delparent = delete->parent;
682 dict_assert (!dict_isempty(dict));
683 dict_assert (dict_contains(dict, delete));
686 * If the node being deleted has two children, then we replace it with its
687 * successor (i.e. the leftmost node in the right subtree.) By doing this,
688 * we avoid the traditional algorithm under which the successor's key and
689 * value *only* move to the deleted node and the successor is spliced out
690 * from the tree. We cannot use this approach because the user may hold
691 * pointers to the successor, or nodes may be inextricably tied to some
692 * other structures by way of embedding, etc. So we must splice out the
693 * node we are given, not some other node, and must not move contents from
694 * one node to another behind the user's back.
697 if (delete->left != nil && delete->right != nil) {
698 dnode_t *next = dict_next(dict, delete);
699 dnode_t *nextparent = next->parent;
700 dnode_color_t nextcolor = next->color;
702 dict_assert (next != nil);
703 dict_assert (next->parent != nil);
704 dict_assert (next->left == nil);
707 * First, splice out the successor from the tree completely, by
708 * moving up its right child into its place.
712 child->parent = nextparent;
714 if (nextparent->left == next) {
715 nextparent->left = child;
717 dict_assert (nextparent->right == next);
718 nextparent->right = child;
722 * Now that the successor has been extricated from the tree, install it
723 * in place of the node that we want deleted.
726 next->parent = delparent;
727 next->left = delete->left;
728 next->right = delete->right;
729 next->left->parent = next;
730 next->right->parent = next;
731 next->color = delete->color;
732 delete->color = nextcolor;
734 if (delparent->left == delete) {
735 delparent->left = next;
737 dict_assert (delparent->right == delete);
738 delparent->right = next;
742 dict_assert (delete != nil);
743 dict_assert (delete->left == nil || delete->right == nil);
745 child = (delete->left != nil) ? delete->left : delete->right;
747 child->parent = delparent = delete->parent;
749 if (delete == delparent->left) {
750 delparent->left = child;
752 dict_assert (delete == delparent->right);
753 delparent->right = child;
757 delete->parent = NULL;
758 delete->right = NULL;
763 dict_assert (verify_bintree(dict));
765 /* red-black adjustments */
767 if (delete->color == dnode_black) {
768 dnode_t *parent, *sister;
770 dict_root(dict)->color = dnode_red;
772 while (child->color == dnode_black) {
773 parent = child->parent;
774 if (child == parent->left) {
775 sister = parent->right;
776 dict_assert (sister != nil);
777 if (sister->color == dnode_red) {
778 sister->color = dnode_black;
779 parent->color = dnode_red;
781 sister = parent->right;
782 dict_assert (sister != nil);
784 if (sister->left->color == dnode_black
785 && sister->right->color == dnode_black) {
786 sister->color = dnode_red;
789 if (sister->right->color == dnode_black) {
790 dict_assert (sister->left->color == dnode_red);
791 sister->left->color = dnode_black;
792 sister->color = dnode_red;
793 rotate_right(sister);
794 sister = parent->right;
795 dict_assert (sister != nil);
797 sister->color = parent->color;
798 sister->right->color = dnode_black;
799 parent->color = dnode_black;
803 } else { /* symmetric case: child == child->parent->right */
804 dict_assert (child == parent->right);
805 sister = parent->left;
806 dict_assert (sister != nil);
807 if (sister->color == dnode_red) {
808 sister->color = dnode_black;
809 parent->color = dnode_red;
810 rotate_right(parent);
811 sister = parent->left;
812 dict_assert (sister != nil);
814 if (sister->right->color == dnode_black
815 && sister->left->color == dnode_black) {
816 sister->color = dnode_red;
819 if (sister->left->color == dnode_black) {
820 dict_assert (sister->right->color == dnode_red);
821 sister->right->color = dnode_black;
822 sister->color = dnode_red;
824 sister = parent->left;
825 dict_assert (sister != nil);
827 sister->color = parent->color;
828 sister->left->color = dnode_black;
829 parent->color = dnode_black;
830 rotate_right(parent);
836 child->color = dnode_black;
837 dict_root(dict)->color = dnode_black;
840 dict_assert (dict_verify(dict));
844 #endif /* E2FSCK_NOTUSED */
847 * Allocate a node using the dictionary's allocator routine, give it
851 int dict_alloc_insert(dict_t *dict, const void *key, void *data)
853 dnode_t *node = dict->allocnode(dict->context);
856 dnode_init(node, data);
857 dict_insert(dict, node, key);
863 #ifdef E2FSCK_NOTUSED
864 void dict_delete_free(dict_t *dict, dnode_t *node)
866 dict_delete(dict, node);
867 dict->freenode(node, dict->context);
872 * Return the node with the lowest (leftmost) key. If the dictionary is empty
873 * (that is, dict_isempty(dict) returns 1) a null pointer is returned.
876 dnode_t *dict_first(dict_t *dict)
878 dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *left;
881 while ((left = root->left) != nil)
884 return (root == nil) ? NULL : root;
888 * Return the node with the highest (rightmost) key. If the dictionary is empty
889 * (that is, dict_isempty(dict) returns 1) a null pointer is returned.
892 dnode_t *dict_last(dict_t *dict)
894 dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *right;
897 while ((right = root->right) != nil)
900 return (root == nil) ? NULL : root;
904 * Return the given node's successor node---the node which has the
905 * next key in the the left to right ordering. If the node has
906 * no successor, a null pointer is returned rather than a pointer to
910 dnode_t *dict_next(dict_t *dict, dnode_t *curr)
912 dnode_t *nil = dict_nil(dict), *parent, *left;
914 if (curr->right != nil) {
916 while ((left = curr->left) != nil)
921 parent = curr->parent;
923 while (parent != nil && curr == parent->right) {
925 parent = curr->parent;
928 return (parent == nil) ? NULL : parent;
932 * Return the given node's predecessor, in the key order.
933 * The nil sentinel node is returned if there is no predecessor.
936 dnode_t *dict_prev(dict_t *dict, dnode_t *curr)
938 dnode_t *nil = dict_nil(dict), *parent, *right;
940 if (curr->left != nil) {
942 while ((right = curr->right) != nil)
947 parent = curr->parent;
949 while (parent != nil && curr == parent->left) {
951 parent = curr->parent;
954 return (parent == nil) ? NULL : parent;
957 void dict_allow_dupes(dict_t *dict)
969 dictcount_t dict_count(dict_t *dict)
971 return dict->nodecount;
974 int dict_isempty(dict_t *dict)
976 return dict->nodecount == 0;
979 int dict_isfull(dict_t *dict)
981 return dict->nodecount == dict->maxcount;
984 int dict_contains(dict_t *dict, dnode_t *node)
986 return verify_dict_has_node(dict_nil(dict), dict_root(dict), node);
989 static dnode_t *dnode_alloc(void *context EXT2FS_ATTR((unused)))
991 return malloc(sizeof *dnode_alloc(NULL));
994 static void dnode_free(dnode_t *node, void *context EXT2FS_ATTR((unused)))
999 dnode_t *dnode_create(void *data)
1001 dnode_t *new = malloc(sizeof *new);
1011 dnode_t *dnode_init(dnode_t *dnode, void *data)
1014 dnode->parent = NULL;
1016 dnode->right = NULL;
1020 void dnode_destroy(dnode_t *dnode)
1022 dict_assert (!dnode_is_in_a_dict(dnode));
1026 void *dnode_get(dnode_t *dnode)
1031 const void *dnode_getkey(dnode_t *dnode)
1036 #ifdef E2FSCK_NOTUSED
1037 void dnode_put(dnode_t *dnode, void *data)
1043 #ifndef DICT_NODEBUG
1044 int dnode_is_in_a_dict(dnode_t *dnode)
1046 return (dnode->parent && dnode->left && dnode->right);
1050 #ifdef E2FSCK_NOTUSED
1051 void dict_process(dict_t *dict, void *context, dnode_process_t function)
1053 dnode_t *node = dict_first(dict), *next;
1055 while (node != NULL) {
1056 /* check for callback function deleting */
1057 /* the next node from under us */
1058 dict_assert (dict_contains(dict, node));
1059 next = dict_next(dict, node);
1060 function(dict, node, context);
1065 static void load_begin_internal(dict_load_t *load, dict_t *dict)
1067 load->dictptr = dict;
1068 load->nilnode.left = &load->nilnode;
1069 load->nilnode.right = &load->nilnode;
1072 void dict_load_begin(dict_load_t *load, dict_t *dict)
1074 dict_assert (dict_isempty(dict));
1075 load_begin_internal(load, dict);
1078 void dict_load_next(dict_load_t *load, dnode_t *newnode, const void *key)
1080 dict_t *dict = load->dictptr;
1081 dnode_t *nil = &load->nilnode;
1083 dict_assert (!dnode_is_in_a_dict(newnode));
1084 dict_assert (dict->nodecount < dict->maxcount);
1086 #ifndef DICT_NODEBUG
1087 if (dict->nodecount > 0) {
1089 dict_assert (dict->compare(nil->left->key, key) <= 0);
1091 dict_assert (dict->compare(nil->left->key, key) < 0);
1096 nil->right->left = newnode;
1097 nil->right = newnode;
1098 newnode->left = nil;
1102 void dict_load_end(dict_load_t *load)
1104 dict_t *dict = load->dictptr;
1105 dnode_t *tree[DICT_DEPTH_MAX] = { 0 };
1106 dnode_t *curr, *dictnil = dict_nil(dict), *loadnil = &load->nilnode, *next;
1107 dnode_t *complete = 0;
1108 dictcount_t fullcount = DICTCOUNT_T_MAX, nodecount = dict->nodecount;
1109 dictcount_t botrowcount;
1110 unsigned baselevel = 0, level = 0, i;
1112 dict_assert (dnode_red == 0 && dnode_black == 1);
1114 while (fullcount >= nodecount && fullcount)
1117 botrowcount = nodecount - fullcount;
1119 for (curr = loadnil->left; curr != loadnil; curr = next) {
1122 if (complete == NULL && botrowcount-- == 0) {
1123 dict_assert (baselevel == 0);
1124 dict_assert (level == 0);
1125 baselevel = level = 1;
1128 if (complete != 0) {
1130 complete->right = dictnil;
1131 while (tree[level] != 0) {
1132 tree[level]->right = complete;
1133 complete->parent = tree[level];
1134 complete = tree[level];
1140 if (complete == NULL) {
1141 curr->left = dictnil;
1142 curr->right = dictnil;
1143 curr->color = level % 2;
1146 dict_assert (level == baselevel);
1147 while (tree[level] != 0) {
1148 tree[level]->right = complete;
1149 complete->parent = tree[level];
1150 complete = tree[level];
1154 curr->left = complete;
1155 curr->color = (level + 1) % 2;
1156 complete->parent = curr;
1163 if (complete == NULL)
1166 for (i = 0; i < DICT_DEPTH_MAX; i++) {
1168 tree[i]->right = complete;
1169 complete->parent = tree[i];
1174 dictnil->color = dnode_black;
1175 dictnil->right = dictnil;
1176 complete->parent = dictnil;
1177 complete->color = dnode_black;
1178 dict_root(dict) = complete;
1180 dict_assert (dict_verify(dict));
1183 void dict_merge(dict_t *dest, dict_t *source)
1186 dnode_t *leftnode = dict_first(dest), *rightnode = dict_first(source);
1188 dict_assert (dict_similar(dest, source));
1193 dest->nodecount = 0;
1194 load_begin_internal(&load, dest);
1197 if (leftnode != NULL && rightnode != NULL) {
1198 if (dest->compare(leftnode->key, rightnode->key) < 0)
1202 } else if (leftnode != NULL) {
1204 } else if (rightnode != NULL) {
1207 dict_assert (leftnode == NULL && rightnode == NULL);
1213 dnode_t *next = dict_next(dest, leftnode);
1214 #ifndef DICT_NODEBUG
1215 leftnode->left = NULL; /* suppress assertion in dict_load_next */
1217 dict_load_next(&load, leftnode, leftnode->key);
1224 dnode_t *next = dict_next(source, rightnode);
1225 #ifndef DICT_NODEBUG
1226 rightnode->left = NULL;
1228 dict_load_next(&load, rightnode, rightnode->key);
1235 dict_load_end(&load);
1237 #endif /* E2FSCK_NOTUSED */
1239 #ifdef KAZLIB_TEST_MAIN
1246 typedef char input_t[256];
1248 static int tokenize(char *string, ...)
1254 va_start(arglist, string);
1255 tokptr = va_arg(arglist, char **);
1257 while (*string && isspace((unsigned char) *string))
1262 while (*string && !isspace((unsigned char) *string))
1264 tokptr = va_arg(arglist, char **);
1275 static int comparef(const void *cmp_ctx, const void *key1, const void *key2)
1277 return strcmp(key1, key2);
1280 static char *dupstring(char *str)
1282 int sz = strlen(str) + 1;
1283 char *new = malloc(sz);
1285 memcpy(new, str, sz);
1289 static dnode_t *new_node(void *c)
1291 static dnode_t few[5];
1295 return few + count++;
1300 static void del_node(dnode_t *n, void *c)
1304 static int prompt = 0;
1306 static void construct(dict_t *d)
1312 char *tok1, *tok2, *val;
1315 "p turn prompt on\n"
1316 "q finish construction\n"
1317 "a <key> <val> add new entry\n";
1319 if (!dict_isempty(d))
1320 puts("warning: dictionary not empty!");
1322 dict_load_begin(&dl, d);
1329 if (!fgets(in, sizeof(input_t), stdin))
1343 if (tokenize(in+1, &tok1, &tok2, (char **) 0) != 2) {
1347 key = dupstring(tok1);
1348 val = dupstring(tok2);
1349 dn = dnode_create(val);
1351 if (!key || !val || !dn) {
1352 puts("out of memory");
1359 dict_load_next(&dl, dn, key);
1375 dict_t *d = &darray[0];
1378 char *tok1, *tok2, *val;
1382 "a <key> <val> add value to dictionary\n"
1383 "d <key> delete value from dictionary\n"
1384 "l <key> lookup value in dictionary\n"
1385 "( <key> lookup lower bound\n"
1386 ") <key> lookup upper bound\n"
1387 "# <num> switch to alternate dictionary (0-9)\n"
1388 "j <num> <num> merge two dictionaries\n"
1389 "f free the whole dictionary\n"
1390 "k allow duplicate keys\n"
1391 "c show number of entries\n"
1392 "t dump whole dictionary in sort order\n"
1393 "m make dictionary out of sorted items\n"
1394 "p turn prompt on\n"
1395 "s switch to non-functioning allocator\n"
1398 for (i = 0; i < sizeof darray / sizeof *darray; i++)
1399 dict_init(&darray[i], DICTCOUNT_T_MAX, comparef);
1406 if (!fgets(in, sizeof(input_t), stdin))
1414 if (tokenize(in+1, &tok1, &tok2, (char **) 0) != 2) {
1418 key = dupstring(tok1);
1419 val = dupstring(tok2);
1422 puts("out of memory");
1427 if (!dict_alloc_insert(d, key, val)) {
1428 puts("dict_alloc_insert failed");
1435 if (tokenize(in+1, &tok1, (char **) 0) != 1) {
1439 dn = dict_lookup(d, tok1);
1441 puts("dict_lookup failed");
1444 val = dnode_get(dn);
1445 key = dnode_getkey(dn);
1446 dict_delete_free(d, dn);
1457 if (tokenize(in+1, &tok1, (char **) 0) != 1) {
1464 dn = dict_lookup(d, tok1);
1467 dn = dict_lower_bound(d, tok1);
1470 dn = dict_upper_bound(d, tok1);
1474 puts("lookup failed");
1477 val = dnode_get(dn);
1484 dict_allow_dupes(d);
1487 printf("%lu\n", (unsigned long) dict_count(d));
1490 for (dn = dict_first(d); dn; dn = dict_next(d, dn)) {
1491 printf("%s\t%s\n", (char *) dnode_getkey(dn),
1492 (char *) dnode_get(dn));
1504 dict_set_allocator(d, new_node, del_node, NULL);
1507 if (tokenize(in+1, &tok1, (char **) 0) != 1) {
1511 int dictnum = atoi(tok1);
1512 if (dictnum < 0 || dictnum > 9) {
1513 puts("invalid number");
1516 d = &darray[dictnum];
1520 if (tokenize(in+1, &tok1, &tok2, (char **) 0) != 2) {
1524 int dict1 = atoi(tok1), dict2 = atoi(tok2);
1525 if (dict1 < 0 || dict1 > 9 || dict2 < 0 || dict2 > 9) {
1526 puts("invalid number");
1529 dict_merge(&darray[dict1], &darray[dict2]);