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.
25 #define DICT_IMPLEMENTATION
29 static const char rcsid
[] = "Id: dict.c,v 1.40.2.7 2000/11/13 01:36:44 kaz";
33 * These macros provide short convenient names for structure members,
34 * which are embellished with dict_ prefixes so that they are
35 * properly confined to the documented namespace. It's legal for a
36 * program which uses dict to define, for instance, a macro called ``parent''.
37 * Such a macro would interfere with the dnode_t struct definition.
38 * In general, highly portable and reusable C modules which expose their
39 * structures need to confine structure member names to well-defined spaces.
40 * The resulting identifiers aren't necessarily convenient to use, nor
41 * readable, in the implementation, however!
44 #define left dict_left
45 #define right dict_right
46 #define parent dict_parent
47 #define color dict_color
49 #define data dict_data
51 #define nilnode dict_nilnode
52 #define nodecount dict_nodecount
53 #define maxcount dict_maxcount
54 #define compare dict_compare
55 #define allocnode dict_allocnode
56 #define freenode dict_freenode
57 #define context dict_context
58 #define dupes dict_dupes
60 #define dictptr dict_dictptr
62 #define dict_root(D) ((D)->nilnode.left)
63 #define dict_nil(D) (&(D)->nilnode)
64 #define DICT_DEPTH_MAX 64
66 static dnode_t
*dnode_alloc(void *context
);
67 static void dnode_free(dnode_t
*node
, void *context
);
70 * Perform a ``left rotation'' adjustment on the tree. The given node P and
71 * its right child C are rearranged so that the P instead becomes the left
72 * child of C. The left subtree of C is inherited as the new right subtree
73 * for P. The ordering of the keys within the tree is thus preserved.
76 static void rotate_left(dnode_t
*upper
)
78 dnode_t
*lower
, *lowleft
, *upparent
;
81 upper
->right
= lowleft
= lower
->left
;
82 lowleft
->parent
= upper
;
84 lower
->parent
= upparent
= upper
->parent
;
86 /* don't need to check for root node here because root->parent is
87 the sentinel nil node, and root->parent->left points back to root */
89 if (upper
== upparent
->left
) {
90 upparent
->left
= lower
;
92 assert (upper
== upparent
->right
);
93 upparent
->right
= lower
;
97 upper
->parent
= lower
;
101 * This operation is the ``mirror'' image of rotate_left. It is
102 * the same procedure, but with left and right interchanged.
105 static void rotate_right(dnode_t
*upper
)
107 dnode_t
*lower
, *lowright
, *upparent
;
110 upper
->left
= lowright
= lower
->right
;
111 lowright
->parent
= upper
;
113 lower
->parent
= upparent
= upper
->parent
;
115 if (upper
== upparent
->right
) {
116 upparent
->right
= lower
;
118 assert (upper
== upparent
->left
);
119 upparent
->left
= lower
;
122 lower
->right
= upper
;
123 upper
->parent
= lower
;
127 * Do a postorder traversal of the tree rooted at the specified
128 * node and free everything under it. Used by dict_free().
131 static void free_nodes(dict_t
*dict
, dnode_t
*node
, dnode_t
*nil
)
135 free_nodes(dict
, node
->left
, nil
);
136 free_nodes(dict
, node
->right
, nil
);
137 dict
->freenode(node
, dict
->context
);
141 * This procedure performs a verification that the given subtree is a binary
142 * search tree. It performs an inorder traversal of the tree using the
143 * dict_next() successor function, verifying that the key of each node is
144 * strictly lower than that of its successor, if duplicates are not allowed,
145 * or lower or equal if duplicates are allowed. This function is used for
146 * debugging purposes.
149 static int verify_bintree(dict_t
*dict
)
151 dnode_t
*first
, *next
;
153 first
= dict_first(dict
);
156 while (first
&& (next
= dict_next(dict
, first
))) {
157 if (dict
->compare(first
->key
, next
->key
) > 0)
162 while (first
&& (next
= dict_next(dict
, first
))) {
163 if (dict
->compare(first
->key
, next
->key
) >= 0)
173 * This function recursively verifies that the given binary subtree satisfies
174 * three of the red black properties. It checks that every red node has only
175 * black children. It makes sure that each node is either red or black. And it
176 * checks that every path has the same count of black nodes from root to leaf.
177 * It returns the blackheight of the given subtree; this allows blackheights to
178 * be computed recursively and compared for left and right siblings for
179 * mismatches. It does not check for every nil node being black, because there
180 * is only one sentinel nil node. The return value of this function is the
181 * black height of the subtree rooted at the node ``root'', or zero if the
182 * subtree is not red-black.
185 static unsigned int verify_redblack(dnode_t
*nil
, dnode_t
*root
)
187 unsigned height_left
, height_right
;
190 height_left
= verify_redblack(nil
, root
->left
);
191 height_right
= verify_redblack(nil
, root
->right
);
192 if (height_left
== 0 || height_right
== 0)
194 if (height_left
!= height_right
)
196 if (root
->color
== dnode_red
) {
197 if (root
->left
->color
!= dnode_black
)
199 if (root
->right
->color
!= dnode_black
)
203 if (root
->color
!= dnode_black
)
205 return height_left
+ 1;
211 * Compute the actual count of nodes by traversing the tree and
212 * return it. This could be compared against the stored count to
216 static dictcount_t
verify_node_count(dnode_t
*nil
, dnode_t
*root
)
221 return 1 + verify_node_count(nil
, root
->left
)
222 + verify_node_count(nil
, root
->right
);
226 * Verify that the tree contains the given node. This is done by
227 * traversing all of the nodes and comparing their pointers to the
228 * given pointer. Returns 1 if the node is found, otherwise
229 * returns zero. It is intended for debugging purposes.
232 static int verify_dict_has_node(dnode_t
*nil
, dnode_t
*root
, dnode_t
*node
)
236 || verify_dict_has_node(nil
, root
->left
, node
)
237 || verify_dict_has_node(nil
, root
->right
, node
);
244 * Dynamically allocate and initialize a dictionary object.
247 dict_t
*dict_create(dictcount_t maxcount
, dict_comp_t comp
)
249 dict_t
*new = malloc(sizeof *new);
253 new->allocnode
= dnode_alloc
;
254 new->freenode
= dnode_free
;
257 new->maxcount
= maxcount
;
258 new->nilnode
.left
= &new->nilnode
;
259 new->nilnode
.right
= &new->nilnode
;
260 new->nilnode
.parent
= &new->nilnode
;
261 new->nilnode
.color
= dnode_black
;
268 * Select a different set of node allocator routines.
271 void dict_set_allocator(dict_t
*dict
, dnode_alloc_t al
,
272 dnode_free_t fr
, void *context
)
274 assert (dict_count(dict
) == 0);
275 assert ((al
== NULL
&& fr
== NULL
) || (al
!= NULL
&& fr
!= NULL
));
277 dict
->allocnode
= al
? al
: dnode_alloc
;
278 dict
->freenode
= fr
? fr
: dnode_free
;
279 dict
->context
= context
;
283 * Free a dynamically allocated dictionary object. Removing the nodes
284 * from the tree before deleting it is required.
287 void dict_destroy(dict_t
*dict
)
289 assert (dict_isempty(dict
));
294 * Free all the nodes in the dictionary by using the dictionary's
295 * installed free routine. The dictionary is emptied.
298 void dict_free_nodes(dict_t
*dict
)
300 dnode_t
*nil
= dict_nil(dict
), *root
= dict_root(dict
);
301 free_nodes(dict
, root
, nil
);
303 dict
->nilnode
.left
= &dict
->nilnode
;
304 dict
->nilnode
.right
= &dict
->nilnode
;
308 * Obsolescent function, equivalent to dict_free_nodes
311 void dict_free(dict_t
*dict
)
313 #ifdef KAZLIB_OBSOLESCENT_DEBUG
314 assert ("call to obsolescent function dict_free()" && 0);
316 dict_free_nodes(dict
);
320 * Initialize a user-supplied dictionary object.
323 dict_t
*dict_init(dict_t
*dict
, dictcount_t maxcount
, dict_comp_t comp
)
325 dict
->compare
= comp
;
326 dict
->allocnode
= dnode_alloc
;
327 dict
->freenode
= dnode_free
;
328 dict
->context
= NULL
;
330 dict
->maxcount
= maxcount
;
331 dict
->nilnode
.left
= &dict
->nilnode
;
332 dict
->nilnode
.right
= &dict
->nilnode
;
333 dict
->nilnode
.parent
= &dict
->nilnode
;
334 dict
->nilnode
.color
= dnode_black
;
340 * Initialize a dictionary in the likeness of another dictionary
343 void dict_init_like(dict_t
*dict
, const dict_t
*template)
345 dict
->compare
= template->compare
;
346 dict
->allocnode
= template->allocnode
;
347 dict
->freenode
= template->freenode
;
348 dict
->context
= template->context
;
350 dict
->maxcount
= template->maxcount
;
351 dict
->nilnode
.left
= &dict
->nilnode
;
352 dict
->nilnode
.right
= &dict
->nilnode
;
353 dict
->nilnode
.parent
= &dict
->nilnode
;
354 dict
->nilnode
.color
= dnode_black
;
355 dict
->dupes
= template->dupes
;
357 assert (dict_similar(dict
, template));
361 * Remove all nodes from the dictionary (without freeing them in any way).
364 static void dict_clear(dict_t
*dict
)
367 dict
->nilnode
.left
= &dict
->nilnode
;
368 dict
->nilnode
.right
= &dict
->nilnode
;
369 dict
->nilnode
.parent
= &dict
->nilnode
;
370 assert (dict
->nilnode
.color
== dnode_black
);
375 * Verify the integrity of the dictionary structure. This is provided for
376 * debugging purposes, and should be placed in assert statements. Just because
377 * this function succeeds doesn't mean that the tree is not corrupt. Certain
378 * corruptions in the tree may simply cause undefined behavior.
381 int dict_verify(dict_t
*dict
)
383 dnode_t
*nil
= dict_nil(dict
), *root
= dict_root(dict
);
385 /* check that the sentinel node and root node are black */
386 if (root
->color
!= dnode_black
)
388 if (nil
->color
!= dnode_black
)
390 if (nil
->right
!= nil
)
392 /* nil->left is the root node; check that its parent pointer is nil */
393 if (nil
->left
->parent
!= nil
)
395 /* perform a weak test that the tree is a binary search tree */
396 if (!verify_bintree(dict
))
398 /* verify that the tree is a red-black tree */
399 if (!verify_redblack(nil
, root
))
401 if (verify_node_count(nil
, root
) != dict_count(dict
))
407 * Determine whether two dictionaries are similar: have the same comparison and
408 * allocator functions, and same status as to whether duplicates are allowed.
411 int dict_similar(const dict_t
*left
, const dict_t
*right
)
413 if (left
->compare
!= right
->compare
)
416 if (left
->allocnode
!= right
->allocnode
)
419 if (left
->freenode
!= right
->freenode
)
422 if (left
->context
!= right
->context
)
425 if (left
->dupes
!= right
->dupes
)
432 * Locate a node in the dictionary having the given key.
433 * If the node is not found, a null a pointer is returned (rather than
434 * a pointer that dictionary's nil sentinel node), otherwise a pointer to the
435 * located node is returned.
438 dnode_t
*dict_lookup(dict_t
*dict
, const void *key
)
440 dnode_t
*root
= dict_root(dict
);
441 dnode_t
*nil
= dict_nil(dict
);
445 /* simple binary search adapted for trees that contain duplicate keys */
447 while (root
!= nil
) {
448 result
= dict
->compare(key
, root
->key
);
454 if (!dict
->dupes
) { /* no duplicates, return match */
456 } else { /* could be dupes, find leftmost one */
460 while (root
!= nil
&& dict
->compare(key
, root
->key
))
462 } while (root
!= nil
);
472 * Look for the node corresponding to the lowest key that is equal to or
473 * greater than the given key. If there is no such node, return null.
476 dnode_t
*dict_lower_bound(dict_t
*dict
, const void *key
)
478 dnode_t
*root
= dict_root(dict
);
479 dnode_t
*nil
= dict_nil(dict
);
480 dnode_t
*tentative
= 0;
482 while (root
!= nil
) {
483 int result
= dict
->compare(key
, root
->key
);
487 } else if (result
< 0) {
504 * Look for the node corresponding to the greatest key that is equal to or
505 * lower than the given key. If there is no such node, return null.
508 dnode_t
*dict_upper_bound(dict_t
*dict
, const void *key
)
510 dnode_t
*root
= dict_root(dict
);
511 dnode_t
*nil
= dict_nil(dict
);
512 dnode_t
*tentative
= 0;
514 while (root
!= nil
) {
515 int result
= dict
->compare(key
, root
->key
);
519 } else if (result
> 0) {
536 * Insert a node into the dictionary. The node should have been
537 * initialized with a data field. All other fields are ignored.
538 * The behavior is undefined if the user attempts to insert into
539 * a dictionary that is already full (for which the dict_isfull()
540 * function returns true).
543 void dict_insert(dict_t
*dict
, dnode_t
*node
, const void *key
)
545 dnode_t
*where
= dict_root(dict
), *nil
= dict_nil(dict
);
546 dnode_t
*parent
= nil
, *uncle
, *grandpa
;
551 assert (!dict_isfull(dict
));
552 assert (!dict_contains(dict
, node
));
553 assert (!dnode_is_in_a_dict(node
));
555 /* basic binary tree insert */
557 while (where
!= nil
) {
559 result
= dict
->compare(key
, where
->key
);
560 /* trap attempts at duplicate key insertion unless it's explicitly allowed */
561 assert (dict
->dupes
|| result
!= 0);
565 where
= where
->right
;
568 assert (where
== nil
);
573 parent
->right
= node
;
575 node
->parent
= parent
;
581 /* red black adjustments */
583 node
->color
= dnode_red
;
585 while (parent
->color
== dnode_red
) {
586 grandpa
= parent
->parent
;
587 if (parent
== grandpa
->left
) {
588 uncle
= grandpa
->right
;
589 if (uncle
->color
== dnode_red
) { /* red parent, red uncle */
590 parent
->color
= dnode_black
;
591 uncle
->color
= dnode_black
;
592 grandpa
->color
= dnode_red
;
594 parent
= grandpa
->parent
;
595 } else { /* red parent, black uncle */
596 if (node
== parent
->right
) {
599 assert (grandpa
== parent
->parent
);
600 /* rotation between parent and child preserves grandpa */
602 parent
->color
= dnode_black
;
603 grandpa
->color
= dnode_red
;
604 rotate_right(grandpa
);
607 } else { /* symmetric cases: parent == parent->parent->right */
608 uncle
= grandpa
->left
;
609 if (uncle
->color
== dnode_red
) {
610 parent
->color
= dnode_black
;
611 uncle
->color
= dnode_black
;
612 grandpa
->color
= dnode_red
;
614 parent
= grandpa
->parent
;
616 if (node
== parent
->left
) {
617 rotate_right(parent
);
619 assert (grandpa
== parent
->parent
);
621 parent
->color
= dnode_black
;
622 grandpa
->color
= dnode_red
;
623 rotate_left(grandpa
);
629 dict_root(dict
)->color
= dnode_black
;
631 assert (dict_verify(dict
));
635 * Delete the given node from the dictionary. If the given node does not belong
636 * to the given dictionary, undefined behavior results. A pointer to the
637 * deleted node is returned.
640 dnode_t
*dict_delete(dict_t
*dict
, dnode_t
*delete)
642 dnode_t
*nil
= dict_nil(dict
), *child
, *delparent
= delete->parent
;
646 assert (!dict_isempty(dict
));
647 assert (dict_contains(dict
, delete));
650 * If the node being deleted has two children, then we replace it with its
651 * successor (i.e. the leftmost node in the right subtree.) By doing this,
652 * we avoid the traditional algorithm under which the successor's key and
653 * value *only* move to the deleted node and the successor is spliced out
654 * from the tree. We cannot use this approach because the user may hold
655 * pointers to the successor, or nodes may be inextricably tied to some
656 * other structures by way of embedding, etc. So we must splice out the
657 * node we are given, not some other node, and must not move contents from
658 * one node to another behind the user's back.
661 if (delete->left
!= nil
&& delete->right
!= nil
) {
662 dnode_t
*next
= dict_next(dict
, delete);
663 dnode_t
*nextparent
= next
->parent
;
664 dnode_color_t nextcolor
= next
->color
;
666 assert (next
!= nil
);
667 assert (next
->parent
!= nil
);
668 assert (next
->left
== nil
);
671 * First, splice out the successor from the tree completely, by
672 * moving up its right child into its place.
676 child
->parent
= nextparent
;
678 if (nextparent
->left
== next
) {
679 nextparent
->left
= child
;
681 assert (nextparent
->right
== next
);
682 nextparent
->right
= child
;
686 * Now that the successor has been extricated from the tree, install it
687 * in place of the node that we want deleted.
690 next
->parent
= delparent
;
691 next
->left
= delete->left
;
692 next
->right
= delete->right
;
693 next
->left
->parent
= next
;
694 next
->right
->parent
= next
;
695 next
->color
= delete->color
;
696 delete->color
= nextcolor
;
698 if (delparent
->left
== delete) {
699 delparent
->left
= next
;
701 assert (delparent
->right
== delete);
702 delparent
->right
= next
;
706 assert (delete != nil
);
707 assert (delete->left
== nil
|| delete->right
== nil
);
709 child
= (delete->left
!= nil
) ? delete->left
: delete->right
;
711 child
->parent
= delparent
= delete->parent
;
713 if (delete == delparent
->left
) {
714 delparent
->left
= child
;
716 assert (delete == delparent
->right
);
717 delparent
->right
= child
;
721 delete->parent
= NULL
;
722 delete->right
= NULL
;
727 assert (verify_bintree(dict
));
729 /* red-black adjustments */
731 if (delete->color
== dnode_black
) {
732 dnode_t
*parent
, *sister
;
734 dict_root(dict
)->color
= dnode_red
;
736 while (child
->color
== dnode_black
) {
737 parent
= child
->parent
;
738 if (child
== parent
->left
) {
739 sister
= parent
->right
;
740 assert (sister
!= nil
);
741 if (sister
->color
== dnode_red
) {
742 sister
->color
= dnode_black
;
743 parent
->color
= dnode_red
;
745 sister
= parent
->right
;
746 assert (sister
!= nil
);
748 if (sister
->left
->color
== dnode_black
749 && sister
->right
->color
== dnode_black
) {
750 sister
->color
= dnode_red
;
753 if (sister
->right
->color
== dnode_black
) {
754 assert (sister
->left
->color
== dnode_red
);
755 sister
->left
->color
= dnode_black
;
756 sister
->color
= dnode_red
;
757 rotate_right(sister
);
758 sister
= parent
->right
;
759 assert (sister
!= nil
);
761 sister
->color
= parent
->color
;
762 sister
->right
->color
= dnode_black
;
763 parent
->color
= dnode_black
;
767 } else { /* symmetric case: child == child->parent->right */
768 assert (child
== parent
->right
);
769 sister
= parent
->left
;
770 assert (sister
!= nil
);
771 if (sister
->color
== dnode_red
) {
772 sister
->color
= dnode_black
;
773 parent
->color
= dnode_red
;
774 rotate_right(parent
);
775 sister
= parent
->left
;
776 assert (sister
!= nil
);
778 if (sister
->right
->color
== dnode_black
779 && sister
->left
->color
== dnode_black
) {
780 sister
->color
= dnode_red
;
783 if (sister
->left
->color
== dnode_black
) {
784 assert (sister
->right
->color
== dnode_red
);
785 sister
->right
->color
= dnode_black
;
786 sister
->color
= dnode_red
;
788 sister
= parent
->left
;
789 assert (sister
!= nil
);
791 sister
->color
= parent
->color
;
792 sister
->left
->color
= dnode_black
;
793 parent
->color
= dnode_black
;
794 rotate_right(parent
);
800 child
->color
= dnode_black
;
801 dict_root(dict
)->color
= dnode_black
;
804 assert (dict_verify(dict
));
810 * Allocate a node using the dictionary's allocator routine, give it
814 int dict_alloc_insert(dict_t
*dict
, const void *key
, void *data
)
816 dnode_t
*node
= dict
->allocnode(dict
->context
);
819 dnode_init(node
, data
);
820 dict_insert(dict
, node
, key
);
826 void dict_delete_free(dict_t
*dict
, dnode_t
*node
)
828 dict_delete(dict
, node
);
829 dict
->freenode(node
, dict
->context
);
833 * Return the node with the lowest (leftmost) key. If the dictionary is empty
834 * (that is, dict_isempty(dict) returns 1) a null pointer is returned.
837 dnode_t
*dict_first(dict_t
*dict
)
839 dnode_t
*nil
= dict_nil(dict
), *root
= dict_root(dict
), *left
;
842 while ((left
= root
->left
) != nil
)
845 return (root
== nil
) ? NULL
: root
;
849 * Return the node with the highest (rightmost) key. If the dictionary is empty
850 * (that is, dict_isempty(dict) returns 1) a null pointer is returned.
853 dnode_t
*dict_last(dict_t
*dict
)
855 dnode_t
*nil
= dict_nil(dict
), *root
= dict_root(dict
), *right
;
858 while ((right
= root
->right
) != nil
)
861 return (root
== nil
) ? NULL
: root
;
865 * Return the given node's successor node---the node which has the
866 * next key in the the left to right ordering. If the node has
867 * no successor, a null pointer is returned rather than a pointer to
871 dnode_t
*dict_next(dict_t
*dict
, dnode_t
*curr
)
873 dnode_t
*nil
= dict_nil(dict
), *parent
, *left
;
875 if (curr
->right
!= nil
) {
877 while ((left
= curr
->left
) != nil
)
882 parent
= curr
->parent
;
884 while (parent
!= nil
&& curr
== parent
->right
) {
886 parent
= curr
->parent
;
889 return (parent
== nil
) ? NULL
: parent
;
893 * Return the given node's predecessor, in the key order.
894 * The nil sentinel node is returned if there is no predecessor.
897 dnode_t
*dict_prev(dict_t
*dict
, dnode_t
*curr
)
899 dnode_t
*nil
= dict_nil(dict
), *parent
, *right
;
901 if (curr
->left
!= nil
) {
903 while ((right
= curr
->right
) != nil
)
908 parent
= curr
->parent
;
910 while (parent
!= nil
&& curr
== parent
->left
) {
912 parent
= curr
->parent
;
915 return (parent
== nil
) ? NULL
: parent
;
918 void dict_allow_dupes(dict_t
*dict
)
930 dictcount_t
dict_count(dict_t
*dict
)
932 return dict
->nodecount
;
935 int dict_isempty(dict_t
*dict
)
937 return dict
->nodecount
== 0;
940 int dict_isfull(dict_t
*dict
)
942 return dict
->nodecount
== dict
->maxcount
;
945 int dict_contains(dict_t
*dict
, dnode_t
*node
)
947 return verify_dict_has_node(dict_nil(dict
), dict_root(dict
), node
);
950 static dnode_t
*dnode_alloc(void *context
)
952 return malloc(sizeof *dnode_alloc(NULL
));
955 static void dnode_free(dnode_t
*node
, void *context
)
960 dnode_t
*dnode_create(void *data
)
962 dnode_t
*new = malloc(sizeof *new);
972 dnode_t
*dnode_init(dnode_t
*dnode
, void *data
)
975 dnode
->parent
= NULL
;
981 void dnode_destroy(dnode_t
*dnode
)
983 assert (!dnode_is_in_a_dict(dnode
));
987 void *dnode_get(dnode_t
*dnode
)
992 const void *dnode_getkey(dnode_t
*dnode
)
997 void dnode_put(dnode_t
*dnode
, void *data
)
1002 int dnode_is_in_a_dict(dnode_t
*dnode
)
1004 return (dnode
->parent
&& dnode
->left
&& dnode
->right
);
1007 void dict_process(dict_t
*dict
, void *context
, dnode_process_t function
)
1009 dnode_t
*node
= dict_first(dict
), *next
;
1011 while (node
!= NULL
) {
1012 /* check for callback function deleting */
1013 /* the next node from under us */
1014 assert (dict_contains(dict
, node
));
1015 next
= dict_next(dict
, node
);
1016 function(dict
, node
, context
);
1021 static void load_begin_internal(dict_load_t
*load
, dict_t
*dict
)
1023 load
->dictptr
= dict
;
1024 load
->nilnode
.left
= &load
->nilnode
;
1025 load
->nilnode
.right
= &load
->nilnode
;
1028 void dict_load_begin(dict_load_t
*load
, dict_t
*dict
)
1030 assert (dict_isempty(dict
));
1031 load_begin_internal(load
, dict
);
1034 void dict_load_next(dict_load_t
*load
, dnode_t
*newnode
, const void *key
)
1036 dict_t
*dict
= load
->dictptr
;
1037 dnode_t
*nil
= &load
->nilnode
;
1039 assert (!dnode_is_in_a_dict(newnode
));
1040 assert (dict
->nodecount
< dict
->maxcount
);
1043 if (dict
->nodecount
> 0) {
1045 assert (dict
->compare(nil
->left
->key
, key
) <= 0);
1047 assert (dict
->compare(nil
->left
->key
, key
) < 0);
1052 nil
->right
->left
= newnode
;
1053 nil
->right
= newnode
;
1054 newnode
->left
= nil
;
1058 void dict_load_end(dict_load_t
*load
)
1060 dict_t
*dict
= load
->dictptr
;
1061 dnode_t
*tree
[DICT_DEPTH_MAX
] = { 0 };
1062 dnode_t
*curr
, *dictnil
= dict_nil(dict
), *loadnil
= &load
->nilnode
, *next
;
1063 dnode_t
*complete
= 0;
1064 dictcount_t fullcount
= DICTCOUNT_T_MAX
, nodecount
= dict
->nodecount
;
1065 dictcount_t botrowcount
;
1066 unsigned baselevel
= 0, level
= 0, i
;
1068 assert (dnode_red
== 0 && dnode_black
== 1);
1070 while (fullcount
>= nodecount
&& fullcount
)
1073 botrowcount
= nodecount
- fullcount
;
1075 for (curr
= loadnil
->left
; curr
!= loadnil
; curr
= next
) {
1078 if (complete
== NULL
&& botrowcount
-- == 0) {
1079 assert (baselevel
== 0);
1080 assert (level
== 0);
1081 baselevel
= level
= 1;
1084 if (complete
!= 0) {
1086 complete
->right
= dictnil
;
1087 while (tree
[level
] != 0) {
1088 tree
[level
]->right
= complete
;
1089 complete
->parent
= tree
[level
];
1090 complete
= tree
[level
];
1096 if (complete
== NULL
) {
1097 curr
->left
= dictnil
;
1098 curr
->right
= dictnil
;
1099 curr
->color
= level
% 2;
1102 assert (level
== baselevel
);
1103 while (tree
[level
] != 0) {
1104 tree
[level
]->right
= complete
;
1105 complete
->parent
= tree
[level
];
1106 complete
= tree
[level
];
1110 curr
->left
= complete
;
1111 curr
->color
= (level
+ 1) % 2;
1112 complete
->parent
= curr
;
1119 if (complete
== NULL
)
1122 for (i
= 0; i
< DICT_DEPTH_MAX
; i
++) {
1124 tree
[i
]->right
= complete
;
1125 complete
->parent
= tree
[i
];
1130 dictnil
->color
= dnode_black
;
1131 dictnil
->right
= dictnil
;
1132 complete
->parent
= dictnil
;
1133 complete
->color
= dnode_black
;
1134 dict_root(dict
) = complete
;
1136 assert (dict_verify(dict
));
1139 void dict_merge(dict_t
*dest
, dict_t
*source
)
1142 dnode_t
*leftnode
= dict_first(dest
), *rightnode
= dict_first(source
);
1144 assert (dict_similar(dest
, source
));
1149 dest
->nodecount
= 0;
1150 load_begin_internal(&load
, dest
);
1153 if (leftnode
!= NULL
&& rightnode
!= NULL
) {
1154 if (dest
->compare(leftnode
->key
, rightnode
->key
) < 0)
1158 } else if (leftnode
!= NULL
) {
1160 } else if (rightnode
!= NULL
) {
1163 assert (leftnode
== NULL
&& rightnode
== NULL
);
1169 dnode_t
*next
= dict_next(dest
, leftnode
);
1171 leftnode
->left
= NULL
; /* suppress assertion in dict_load_next */
1173 dict_load_next(&load
, leftnode
, leftnode
->key
);
1180 dnode_t
*next
= dict_next(source
, rightnode
);
1182 rightnode
->left
= NULL
;
1184 dict_load_next(&load
, rightnode
, rightnode
->key
);
1191 dict_load_end(&load
);
1194 #ifdef KAZLIB_TEST_MAIN
1201 typedef char input_t
[256];
1203 static int tokenize(char *string
, ...)
1209 va_start(arglist
, string
);
1210 tokptr
= va_arg(arglist
, char **);
1212 while (*string
&& isspace((unsigned char) *string
))
1217 while (*string
&& !isspace((unsigned char) *string
))
1219 tokptr
= va_arg(arglist
, char **);
1230 static int comparef(const void *key1
, const void *key2
)
1232 return strcmp(key1
, key2
);
1235 static char *dupstring(char *str
)
1237 int sz
= strlen(str
) + 1;
1238 char *new = malloc(sz
);
1240 memcpy(new, str
, sz
);
1244 static dnode_t
*new_node(void *c
)
1246 static dnode_t few
[5];
1250 return few
+ count
++;
1255 static void del_node(dnode_t
*n
, void *c
)
1259 static int prompt
= 0;
1261 static void construct(dict_t
*d
)
1267 char *tok1
, *tok2
, *val
;
1270 "p turn prompt on\n"
1271 "q finish construction\n"
1272 "a <key> <val> add new entry\n";
1274 if (!dict_isempty(d
))
1275 puts("warning: dictionary not empty!");
1277 dict_load_begin(&dl
, d
);
1284 if (!fgets(in
, sizeof(input_t
), stdin
))
1298 if (tokenize(in
+1, &tok1
, &tok2
, (char **) 0) != 2) {
1302 key
= dupstring(tok1
);
1303 val
= dupstring(tok2
);
1304 dn
= dnode_create(val
);
1306 if (!key
|| !val
|| !dn
) {
1307 puts("out of memory");
1314 dict_load_next(&dl
, dn
, key
);
1330 dict_t
*d
= &darray
[0];
1333 char *tok1
, *tok2
, *val
;
1337 "a <key> <val> add value to dictionary\n"
1338 "d <key> delete value from dictionary\n"
1339 "l <key> lookup value in dictionary\n"
1340 "( <key> lookup lower bound\n"
1341 ") <key> lookup upper bound\n"
1342 "# <num> switch to alternate dictionary (0-9)\n"
1343 "j <num> <num> merge two dictionaries\n"
1344 "f free the whole dictionary\n"
1345 "k allow duplicate keys\n"
1346 "c show number of entries\n"
1347 "t dump whole dictionary in sort order\n"
1348 "m make dictionary out of sorted items\n"
1349 "p turn prompt on\n"
1350 "s switch to non-functioning allocator\n"
1353 for (i
= 0; i
< sizeof darray
/ sizeof *darray
; i
++)
1354 dict_init(&darray
[i
], DICTCOUNT_T_MAX
, comparef
);
1361 if (!fgets(in
, sizeof(input_t
), stdin
))
1369 if (tokenize(in
+1, &tok1
, &tok2
, (char **) 0) != 2) {
1373 key
= dupstring(tok1
);
1374 val
= dupstring(tok2
);
1377 puts("out of memory");
1382 if (!dict_alloc_insert(d
, key
, val
)) {
1383 puts("dict_alloc_insert failed");
1390 if (tokenize(in
+1, &tok1
, (char **) 0) != 1) {
1394 dn
= dict_lookup(d
, tok1
);
1396 puts("dict_lookup failed");
1399 val
= dnode_get(dn
);
1400 key
= dnode_getkey(dn
);
1401 dict_delete_free(d
, dn
);
1412 if (tokenize(in
+1, &tok1
, (char **) 0) != 1) {
1419 dn
= dict_lookup(d
, tok1
);
1422 dn
= dict_lower_bound(d
, tok1
);
1425 dn
= dict_upper_bound(d
, tok1
);
1429 puts("lookup failed");
1432 val
= dnode_get(dn
);
1439 dict_allow_dupes(d
);
1442 printf("%lu\n", (unsigned long) dict_count(d
));
1445 for (dn
= dict_first(d
); dn
; dn
= dict_next(d
, dn
)) {
1446 printf("%s\t%s\n", (char *) dnode_getkey(dn
),
1447 (char *) dnode_get(dn
));
1459 dict_set_allocator(d
, new_node
, del_node
, NULL
);
1462 if (tokenize(in
+1, &tok1
, (char **) 0) != 1) {
1466 int dictnum
= atoi(tok1
);
1467 if (dictnum
< 0 || dictnum
> 9) {
1468 puts("invalid number");
1471 d
= &darray
[dictnum
];
1475 if (tokenize(in
+1, &tok1
, &tok2
, (char **) 0) != 2) {
1479 int dict1
= atoi(tok1
), dict2
= atoi(tok2
);
1480 if (dict1
< 0 || dict1
> 9 || dict2
< 0 || dict2
> 9) {
1481 puts("invalid number");
1484 dict_merge(&darray
[dict1
], &darray
[dict2
]);