blob: 4c787ac589078191333f7b0ac4c114e0c4d540fa [file] [log] [blame]
jardineb5d44e2003-12-23 08:09:43 +00001/*
2 * Dictionary Abstract Data Type
3 * Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net>
4 *
5 * Free Software License:
6 *
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.
16 *
17 * $Id: dict.c,v 1.1 2003/12/23 08:09:47 jardin Exp $
18 * $Name: $
19 */
20
21#include <stdlib.h>
22#include <stddef.h>
23#include <assert.h>
24#define DICT_IMPLEMENTATION
25#include "dict.h"
26
27#ifdef KAZLIB_RCSID
28static const char rcsid[] = "$Id: dict.c,v 1.1 2003/12/23 08:09:47 jardin Exp $";
29#endif
30
31/*
32 * These macros provide short convenient names for structure members,
33 * which are embellished with dict_ prefixes so that they are
34 * properly confined to the documented namespace. It's legal for a
35 * program which uses dict to define, for instance, a macro called ``parent''.
36 * Such a macro would interfere with the dnode_t struct definition.
37 * In general, highly portable and reusable C modules which expose their
38 * structures need to confine structure member names to well-defined spaces.
39 * The resulting identifiers aren't necessarily convenient to use, nor
40 * readable, in the implementation, however!
41 */
42
43#define left dict_left
44#define right dict_right
45#define parent dict_parent
46#define color dict_color
47#define key dict_key
48#define data dict_data
49
50#define nilnode dict_nilnode
51#define nodecount dict_nodecount
52#define maxcount dict_maxcount
53#define compare dict_compare
54#define allocnode dict_allocnode
55#define freenode dict_freenode
56#define context dict_context
57#define dupes dict_dupes
58
59#define dictptr dict_dictptr
60
61#define dict_root(D) ((D)->nilnode.left)
62#define dict_nil(D) (&(D)->nilnode)
63#define DICT_DEPTH_MAX 64
64
65static dnode_t *dnode_alloc(void *context);
66static void dnode_free(dnode_t *node, void *context);
67
68/*
69 * Perform a ``left rotation'' adjustment on the tree. The given node P and
70 * its right child C are rearranged so that the P instead becomes the left
71 * child of C. The left subtree of C is inherited as the new right subtree
72 * for P. The ordering of the keys within the tree is thus preserved.
73 */
74
75static void rotate_left(dnode_t *upper)
76{
77 dnode_t *lower, *lowleft, *upparent;
78
79 lower = upper->right;
80 upper->right = lowleft = lower->left;
81 lowleft->parent = upper;
82
83 lower->parent = upparent = upper->parent;
84
85 /* don't need to check for root node here because root->parent is
86 the sentinel nil node, and root->parent->left points back to root */
87
88 if (upper == upparent->left) {
89 upparent->left = lower;
90 } else {
91 assert (upper == upparent->right);
92 upparent->right = lower;
93 }
94
95 lower->left = upper;
96 upper->parent = lower;
97}
98
99/*
100 * This operation is the ``mirror'' image of rotate_left. It is
101 * the same procedure, but with left and right interchanged.
102 */
103
104static void rotate_right(dnode_t *upper)
105{
106 dnode_t *lower, *lowright, *upparent;
107
108 lower = upper->left;
109 upper->left = lowright = lower->right;
110 lowright->parent = upper;
111
112 lower->parent = upparent = upper->parent;
113
114 if (upper == upparent->right) {
115 upparent->right = lower;
116 } else {
117 assert (upper == upparent->left);
118 upparent->left = lower;
119 }
120
121 lower->right = upper;
122 upper->parent = lower;
123}
124
125/*
126 * Do a postorder traversal of the tree rooted at the specified
127 * node and free everything under it. Used by dict_free().
128 */
129
130static void free_nodes(dict_t *dict, dnode_t *node, dnode_t *nil)
131{
132 if (node == nil)
133 return;
134 free_nodes(dict, node->left, nil);
135 free_nodes(dict, node->right, nil);
136 dict->freenode(node, dict->context);
137}
138
139/*
140 * This procedure performs a verification that the given subtree is a binary
141 * search tree. It performs an inorder traversal of the tree using the
142 * dict_next() successor function, verifying that the key of each node is
143 * strictly lower than that of its successor, if duplicates are not allowed,
144 * or lower or equal if duplicates are allowed. This function is used for
145 * debugging purposes.
146 */
147
148static int verify_bintree(dict_t *dict)
149{
150 dnode_t *first, *next;
151
152 first = dict_first(dict);
153
154 if (dict->dupes) {
155 while (first && (next = dict_next(dict, first))) {
156 if (dict->compare(first->key, next->key) > 0)
157 return 0;
158 first = next;
159 }
160 } else {
161 while (first && (next = dict_next(dict, first))) {
162 if (dict->compare(first->key, next->key) >= 0)
163 return 0;
164 first = next;
165 }
166 }
167 return 1;
168}
169
170
171/*
172 * This function recursively verifies that the given binary subtree satisfies
173 * three of the red black properties. It checks that every red node has only
174 * black children. It makes sure that each node is either red or black. And it
175 * checks that every path has the same count of black nodes from root to leaf.
176 * It returns the blackheight of the given subtree; this allows blackheights to
177 * be computed recursively and compared for left and right siblings for
178 * mismatches. It does not check for every nil node being black, because there
179 * is only one sentinel nil node. The return value of this function is the
180 * black height of the subtree rooted at the node ``root'', or zero if the
181 * subtree is not red-black.
182 */
183
184static unsigned int verify_redblack(dnode_t *nil, dnode_t *root)
185{
186 unsigned height_left, height_right;
187
188 if (root != nil) {
189 height_left = verify_redblack(nil, root->left);
190 height_right = verify_redblack(nil, root->right);
191 if (height_left == 0 || height_right == 0)
192 return 0;
193 if (height_left != height_right)
194 return 0;
195 if (root->color == dnode_red) {
196 if (root->left->color != dnode_black)
197 return 0;
198 if (root->right->color != dnode_black)
199 return 0;
200 return height_left;
201 }
202 if (root->color != dnode_black)
203 return 0;
204 return height_left + 1;
205 }
206 return 1;
207}
208
209/*
210 * Compute the actual count of nodes by traversing the tree and
211 * return it. This could be compared against the stored count to
212 * detect a mismatch.
213 */
214
215static dictcount_t verify_node_count(dnode_t *nil, dnode_t *root)
216{
217 if (root == nil)
218 return 0;
219 else
220 return 1 + verify_node_count(nil, root->left)
221 + verify_node_count(nil, root->right);
222}
223
224/*
225 * Verify that the tree contains the given node. This is done by
226 * traversing all of the nodes and comparing their pointers to the
227 * given pointer. Returns 1 if the node is found, otherwise
228 * returns zero. It is intended for debugging purposes.
229 */
230
231static int verify_dict_has_node(dnode_t *nil, dnode_t *root, dnode_t *node)
232{
233 if (root != nil) {
234 return root == node
235 || verify_dict_has_node(nil, root->left, node)
236 || verify_dict_has_node(nil, root->right, node);
237 }
238 return 0;
239}
240
241
242/*
243 * Dynamically allocate and initialize a dictionary object.
244 */
245
246dict_t *dict_create(dictcount_t maxcount, dict_comp_t comp)
247{
248 dict_t *new = malloc(sizeof *new);
249
250 if (new) {
251 new->compare = comp;
252 new->allocnode = dnode_alloc;
253 new->freenode = dnode_free;
254 new->context = NULL;
255 new->nodecount = 0;
256 new->maxcount = maxcount;
257 new->nilnode.left = &new->nilnode;
258 new->nilnode.right = &new->nilnode;
259 new->nilnode.parent = &new->nilnode;
260 new->nilnode.color = dnode_black;
261 new->dupes = 0;
262 }
263 return new;
264}
265
266/*
267 * Select a different set of node allocator routines.
268 */
269
270void dict_set_allocator(dict_t *dict, dnode_alloc_t al,
271 dnode_free_t fr, void *context)
272{
273 assert (dict_count(dict) == 0);
274 assert ((al == NULL && fr == NULL) || (al != NULL && fr != NULL));
275
276 dict->allocnode = al ? al : dnode_alloc;
277 dict->freenode = fr ? fr : dnode_free;
278 dict->context = context;
279}
280
281/*
282 * Free a dynamically allocated dictionary object. Removing the nodes
283 * from the tree before deleting it is required.
284 */
285
286void dict_destroy(dict_t *dict)
287{
288 assert (dict_isempty(dict));
289 free(dict);
290}
291
292/*
293 * Free all the nodes in the dictionary by using the dictionary's
294 * installed free routine. The dictionary is emptied.
295 */
296
297void dict_free_nodes(dict_t *dict)
298{
299 dnode_t *nil = dict_nil(dict), *root = dict_root(dict);
300 free_nodes(dict, root, nil);
301 dict->nodecount = 0;
302 dict->nilnode.left = &dict->nilnode;
303 dict->nilnode.right = &dict->nilnode;
304}
305
306/*
307 * Obsolescent function, equivalent to dict_free_nodes
308 */
309
310void dict_free(dict_t *dict)
311{
312#ifdef KAZLIB_OBSOLESCENT_DEBUG
313 assert ("call to obsolescent function dict_free()" && 0);
314#endif
315 dict_free_nodes(dict);
316}
317
318/*
319 * Initialize a user-supplied dictionary object.
320 */
321
322dict_t *dict_init(dict_t *dict, dictcount_t maxcount, dict_comp_t comp)
323{
324 dict->compare = comp;
325 dict->allocnode = dnode_alloc;
326 dict->freenode = dnode_free;
327 dict->context = NULL;
328 dict->nodecount = 0;
329 dict->maxcount = maxcount;
330 dict->nilnode.left = &dict->nilnode;
331 dict->nilnode.right = &dict->nilnode;
332 dict->nilnode.parent = &dict->nilnode;
333 dict->nilnode.color = dnode_black;
334 dict->dupes = 0;
335 return dict;
336}
337
338/*
339 * Initialize a dictionary in the likeness of another dictionary
340 */
341
342void dict_init_like(dict_t *dict, const dict_t *template)
343{
344 dict->compare = template->compare;
345 dict->allocnode = template->allocnode;
346 dict->freenode = template->freenode;
347 dict->context = template->context;
348 dict->nodecount = 0;
349 dict->maxcount = template->maxcount;
350 dict->nilnode.left = &dict->nilnode;
351 dict->nilnode.right = &dict->nilnode;
352 dict->nilnode.parent = &dict->nilnode;
353 dict->nilnode.color = dnode_black;
354 dict->dupes = template->dupes;
355
356 assert (dict_similar(dict, template));
357}
358
359/*
360 * Remove all nodes from the dictionary (without freeing them in any way).
361 */
362
363static void dict_clear(dict_t *dict)
364{
365 dict->nodecount = 0;
366 dict->nilnode.left = &dict->nilnode;
367 dict->nilnode.right = &dict->nilnode;
368 dict->nilnode.parent = &dict->nilnode;
369 assert (dict->nilnode.color == dnode_black);
370}
371
372
373/*
374 * Verify the integrity of the dictionary structure. This is provided for
375 * debugging purposes, and should be placed in assert statements. Just because
376 * this function succeeds doesn't mean that the tree is not corrupt. Certain
377 * corruptions in the tree may simply cause undefined behavior.
378 */
379
380int dict_verify(dict_t *dict)
381{
382 dnode_t *nil = dict_nil(dict), *root = dict_root(dict);
383
384 /* check that the sentinel node and root node are black */
385 if (root->color != dnode_black)
386 return 0;
387 if (nil->color != dnode_black)
388 return 0;
389 if (nil->right != nil)
390 return 0;
391 /* nil->left is the root node; check that its parent pointer is nil */
392 if (nil->left->parent != nil)
393 return 0;
394 /* perform a weak test that the tree is a binary search tree */
395 if (!verify_bintree(dict))
396 return 0;
397 /* verify that the tree is a red-black tree */
398 if (!verify_redblack(nil, root))
399 return 0;
400 if (verify_node_count(nil, root) != dict_count(dict))
401 return 0;
402 return 1;
403}
404
405/*
406 * Determine whether two dictionaries are similar: have the same comparison and
407 * allocator functions, and same status as to whether duplicates are allowed.
408 */
409
410int dict_similar(const dict_t *left, const dict_t *right)
411{
412 if (left->compare != right->compare)
413 return 0;
414
415 if (left->allocnode != right->allocnode)
416 return 0;
417
418 if (left->freenode != right->freenode)
419 return 0;
420
421 if (left->context != right->context)
422 return 0;
423
424 if (left->dupes != right->dupes)
425 return 0;
426
427 return 1;
428}
429
430/*
431 * Locate a node in the dictionary having the given key.
432 * If the node is not found, a null a pointer is returned (rather than
433 * a pointer that dictionary's nil sentinel node), otherwise a pointer to the
434 * located node is returned.
435 */
436
437dnode_t *dict_lookup(dict_t *dict, const void *key)
438{
439 dnode_t *root = dict_root(dict);
440 dnode_t *nil = dict_nil(dict);
441 dnode_t *saved;
442 int result;
443
444 /* simple binary search adapted for trees that contain duplicate keys */
445
446 while (root != nil) {
447 result = dict->compare(key, root->key);
448 if (result < 0)
449 root = root->left;
450 else if (result > 0)
451 root = root->right;
452 else {
453 if (!dict->dupes) { /* no duplicates, return match */
454 return root;
455 } else { /* could be dupes, find leftmost one */
456 do {
457 saved = root;
458 root = root->left;
459 while (root != nil && dict->compare(key, root->key))
460 root = root->right;
461 } while (root != nil);
462 return saved;
463 }
464 }
465 }
466
467 return NULL;
468}
469
470/*
471 * Look for the node corresponding to the lowest key that is equal to or
472 * greater than the given key. If there is no such node, return null.
473 */
474
475dnode_t *dict_lower_bound(dict_t *dict, const void *key)
476{
477 dnode_t *root = dict_root(dict);
478 dnode_t *nil = dict_nil(dict);
479 dnode_t *tentative = 0;
480
481 while (root != nil) {
482 int result = dict->compare(key, root->key);
483
484 if (result > 0) {
485 root = root->right;
486 } else if (result < 0) {
487 tentative = root;
488 root = root->left;
489 } else {
490 if (!dict->dupes) {
491 return root;
492 } else {
493 tentative = root;
494 root = root->left;
495 }
496 }
497 }
498
499 return tentative;
500}
501
502/*
503 * Look for the node corresponding to the greatest key that is equal to or
504 * lower than the given key. If there is no such node, return null.
505 */
506
507dnode_t *dict_upper_bound(dict_t *dict, const void *key)
508{
509 dnode_t *root = dict_root(dict);
510 dnode_t *nil = dict_nil(dict);
511 dnode_t *tentative = 0;
512
513 while (root != nil) {
514 int result = dict->compare(key, root->key);
515
516 if (result < 0) {
517 root = root->left;
518 } else if (result > 0) {
519 tentative = root;
520 root = root->right;
521 } else {
522 if (!dict->dupes) {
523 return root;
524 } else {
525 tentative = root;
526 root = root->right;
527 }
528 }
529 }
530
531 return tentative;
532}
533
534/*
535 * Insert a node into the dictionary. The node should have been
536 * initialized with a data field. All other fields are ignored.
537 * The behavior is undefined if the user attempts to insert into
538 * a dictionary that is already full (for which the dict_isfull()
539 * function returns true).
540 */
541
542void dict_insert(dict_t *dict, dnode_t *node, const void *key)
543{
544 dnode_t *where = dict_root(dict), *nil = dict_nil(dict);
545 dnode_t *parent = nil, *uncle, *grandpa;
546 int result = -1;
547
548 node->key = key;
549
550 assert (!dict_isfull(dict));
551 assert (!dict_contains(dict, node));
552 assert (!dnode_is_in_a_dict(node));
553
554 /* basic binary tree insert */
555
556 while (where != nil) {
557 parent = where;
558 result = dict->compare(key, where->key);
559 /* trap attempts at duplicate key insertion unless it's explicitly allowed */
560 assert (dict->dupes || result != 0);
561 if (result < 0)
562 where = where->left;
563 else
564 where = where->right;
565 }
566
567 assert (where == nil);
568
569 if (result < 0)
570 parent->left = node;
571 else
572 parent->right = node;
573
574 node->parent = parent;
575 node->left = nil;
576 node->right = nil;
577
578 dict->nodecount++;
579
580 /* red black adjustments */
581
582 node->color = dnode_red;
583
584 while (parent->color == dnode_red) {
585 grandpa = parent->parent;
586 if (parent == grandpa->left) {
587 uncle = grandpa->right;
588 if (uncle->color == dnode_red) { /* red parent, red uncle */
589 parent->color = dnode_black;
590 uncle->color = dnode_black;
591 grandpa->color = dnode_red;
592 node = grandpa;
593 parent = grandpa->parent;
594 } else { /* red parent, black uncle */
595 if (node == parent->right) {
596 rotate_left(parent);
597 parent = node;
598 assert (grandpa == parent->parent);
599 /* rotation between parent and child preserves grandpa */
600 }
601 parent->color = dnode_black;
602 grandpa->color = dnode_red;
603 rotate_right(grandpa);
604 break;
605 }
606 } else { /* symmetric cases: parent == parent->parent->right */
607 uncle = grandpa->left;
608 if (uncle->color == dnode_red) {
609 parent->color = dnode_black;
610 uncle->color = dnode_black;
611 grandpa->color = dnode_red;
612 node = grandpa;
613 parent = grandpa->parent;
614 } else {
615 if (node == parent->left) {
616 rotate_right(parent);
617 parent = node;
618 assert (grandpa == parent->parent);
619 }
620 parent->color = dnode_black;
621 grandpa->color = dnode_red;
622 rotate_left(grandpa);
623 break;
624 }
625 }
626 }
627
628 dict_root(dict)->color = dnode_black;
629
630 assert (dict_verify(dict));
631}
632
633/*
634 * Delete the given node from the dictionary. If the given node does not belong
635 * to the given dictionary, undefined behavior results. A pointer to the
636 * deleted node is returned.
637 */
638
639dnode_t *dict_delete(dict_t *dict, dnode_t *delete)
640{
641 dnode_t *nil = dict_nil(dict), *child, *delparent = delete->parent;
642
643 /* basic deletion */
644
645 assert (!dict_isempty(dict));
646 assert (dict_contains(dict, delete));
647
648 /*
649 * If the node being deleted has two children, then we replace it with its
650 * successor (i.e. the leftmost node in the right subtree.) By doing this,
651 * we avoid the traditional algorithm under which the successor's key and
652 * value *only* move to the deleted node and the successor is spliced out
653 * from the tree. We cannot use this approach because the user may hold
654 * pointers to the successor, or nodes may be inextricably tied to some
655 * other structures by way of embedding, etc. So we must splice out the
656 * node we are given, not some other node, and must not move contents from
657 * one node to another behind the user's back.
658 */
659
660 if (delete->left != nil && delete->right != nil) {
661 dnode_t *next = dict_next(dict, delete);
662 dnode_t *nextparent = next->parent;
663 dnode_color_t nextcolor = next->color;
664
665 assert (next != nil);
666 assert (next->parent != nil);
667 assert (next->left == nil);
668
669 /*
670 * First, splice out the successor from the tree completely, by
671 * moving up its right child into its place.
672 */
673
674 child = next->right;
675 child->parent = nextparent;
676
677 if (nextparent->left == next) {
678 nextparent->left = child;
679 } else {
680 assert (nextparent->right == next);
681 nextparent->right = child;
682 }
683
684 /*
685 * Now that the successor has been extricated from the tree, install it
686 * in place of the node that we want deleted.
687 */
688
689 next->parent = delparent;
690 next->left = delete->left;
691 next->right = delete->right;
692 next->left->parent = next;
693 next->right->parent = next;
694 next->color = delete->color;
695 delete->color = nextcolor;
696
697 if (delparent->left == delete) {
698 delparent->left = next;
699 } else {
700 assert (delparent->right == delete);
701 delparent->right = next;
702 }
703
704 } else {
705 assert (delete != nil);
706 assert (delete->left == nil || delete->right == nil);
707
708 child = (delete->left != nil) ? delete->left : delete->right;
709
710 child->parent = delparent = delete->parent;
711
712 if (delete == delparent->left) {
713 delparent->left = child;
714 } else {
715 assert (delete == delparent->right);
716 delparent->right = child;
717 }
718 }
719
720 delete->parent = NULL;
721 delete->right = NULL;
722 delete->left = NULL;
723
724 dict->nodecount--;
725
726 assert (verify_bintree(dict));
727
728 /* red-black adjustments */
729
730 if (delete->color == dnode_black) {
731 dnode_t *parent, *sister;
732
733 dict_root(dict)->color = dnode_red;
734
735 while (child->color == dnode_black) {
736 parent = child->parent;
737 if (child == parent->left) {
738 sister = parent->right;
739 assert (sister != nil);
740 if (sister->color == dnode_red) {
741 sister->color = dnode_black;
742 parent->color = dnode_red;
743 rotate_left(parent);
744 sister = parent->right;
745 assert (sister != nil);
746 }
747 if (sister->left->color == dnode_black
748 && sister->right->color == dnode_black) {
749 sister->color = dnode_red;
750 child = parent;
751 } else {
752 if (sister->right->color == dnode_black) {
753 assert (sister->left->color == dnode_red);
754 sister->left->color = dnode_black;
755 sister->color = dnode_red;
756 rotate_right(sister);
757 sister = parent->right;
758 assert (sister != nil);
759 }
760 sister->color = parent->color;
761 sister->right->color = dnode_black;
762 parent->color = dnode_black;
763 rotate_left(parent);
764 break;
765 }
766 } else { /* symmetric case: child == child->parent->right */
767 assert (child == parent->right);
768 sister = parent->left;
769 assert (sister != nil);
770 if (sister->color == dnode_red) {
771 sister->color = dnode_black;
772 parent->color = dnode_red;
773 rotate_right(parent);
774 sister = parent->left;
775 assert (sister != nil);
776 }
777 if (sister->right->color == dnode_black
778 && sister->left->color == dnode_black) {
779 sister->color = dnode_red;
780 child = parent;
781 } else {
782 if (sister->left->color == dnode_black) {
783 assert (sister->right->color == dnode_red);
784 sister->right->color = dnode_black;
785 sister->color = dnode_red;
786 rotate_left(sister);
787 sister = parent->left;
788 assert (sister != nil);
789 }
790 sister->color = parent->color;
791 sister->left->color = dnode_black;
792 parent->color = dnode_black;
793 rotate_right(parent);
794 break;
795 }
796 }
797 }
798
799 child->color = dnode_black;
800 dict_root(dict)->color = dnode_black;
801 }
802
803 assert (dict_verify(dict));
804
805 return delete;
806}
807
808/*
809 * Allocate a node using the dictionary's allocator routine, give it
810 * the data item.
811 */
812
813int dict_alloc_insert(dict_t *dict, const void *key, void *data)
814{
815 dnode_t *node = dict->allocnode(dict->context);
816
817 if (node) {
818 dnode_init(node, data);
819 dict_insert(dict, node, key);
820 return 1;
821 }
822 return 0;
823}
824
825void dict_delete_free(dict_t *dict, dnode_t *node)
826{
827 dict_delete(dict, node);
828 dict->freenode(node, dict->context);
829}
830
831/*
832 * Return the node with the lowest (leftmost) key. If the dictionary is empty
833 * (that is, dict_isempty(dict) returns 1) a null pointer is returned.
834 */
835
836dnode_t *dict_first(dict_t *dict)
837{
838 dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *left;
839
840 if (root != nil)
841 while ((left = root->left) != nil)
842 root = left;
843
844 return (root == nil) ? NULL : root;
845}
846
847/*
848 * Return the node with the highest (rightmost) key. If the dictionary is empty
849 * (that is, dict_isempty(dict) returns 1) a null pointer is returned.
850 */
851
852dnode_t *dict_last(dict_t *dict)
853{
854 dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *right;
855
856 if (root != nil)
857 while ((right = root->right) != nil)
858 root = right;
859
860 return (root == nil) ? NULL : root;
861}
862
863/*
864 * Return the given node's successor node---the node which has the
865 * next key in the the left to right ordering. If the node has
866 * no successor, a null pointer is returned rather than a pointer to
867 * the nil node.
868 */
869
870dnode_t *dict_next(dict_t *dict, dnode_t *curr)
871{
872 dnode_t *nil = dict_nil(dict), *parent, *left;
873
874 if (curr->right != nil) {
875 curr = curr->right;
876 while ((left = curr->left) != nil)
877 curr = left;
878 return curr;
879 }
880
881 parent = curr->parent;
882
883 while (parent != nil && curr == parent->right) {
884 curr = parent;
885 parent = curr->parent;
886 }
887
888 return (parent == nil) ? NULL : parent;
889}
890
891/*
892 * Return the given node's predecessor, in the key order.
893 * The nil sentinel node is returned if there is no predecessor.
894 */
895
896dnode_t *dict_prev(dict_t *dict, dnode_t *curr)
897{
898 dnode_t *nil = dict_nil(dict), *parent, *right;
899
900 if (curr->left != nil) {
901 curr = curr->left;
902 while ((right = curr->right) != nil)
903 curr = right;
904 return curr;
905 }
906
907 parent = curr->parent;
908
909 while (parent != nil && curr == parent->left) {
910 curr = parent;
911 parent = curr->parent;
912 }
913
914 return (parent == nil) ? NULL : parent;
915}
916
917void dict_allow_dupes(dict_t *dict)
918{
919 dict->dupes = 1;
920}
921
922#undef dict_count
923#undef dict_isempty
924#undef dict_isfull
925#undef dnode_get
926#undef dnode_put
927#undef dnode_getkey
928
929dictcount_t dict_count(dict_t *dict)
930{
931 return dict->nodecount;
932}
933
934int dict_isempty(dict_t *dict)
935{
936 return dict->nodecount == 0;
937}
938
939int dict_isfull(dict_t *dict)
940{
941 return dict->nodecount == dict->maxcount;
942}
943
944int dict_contains(dict_t *dict, dnode_t *node)
945{
946 return verify_dict_has_node(dict_nil(dict), dict_root(dict), node);
947}
948
949static dnode_t *dnode_alloc(void *context)
950{
951 return malloc(sizeof *dnode_alloc(NULL));
952}
953
954static void dnode_free(dnode_t *node, void *context)
955{
956 free(node);
957}
958
959dnode_t *dnode_create(void *data)
960{
961 dnode_t *new = malloc(sizeof *new);
962 if (new) {
963 new->data = data;
964 new->parent = NULL;
965 new->left = NULL;
966 new->right = NULL;
967 }
968 return new;
969}
970
971dnode_t *dnode_init(dnode_t *dnode, void *data)
972{
973 dnode->data = data;
974 dnode->parent = NULL;
975 dnode->left = NULL;
976 dnode->right = NULL;
977 return dnode;
978}
979
980void dnode_destroy(dnode_t *dnode)
981{
982 assert (!dnode_is_in_a_dict(dnode));
983 free(dnode);
984}
985
986void *dnode_get(dnode_t *dnode)
987{
988 return dnode->data;
989}
990
991const void *dnode_getkey(dnode_t *dnode)
992{
993 return dnode->key;
994}
995
996void dnode_put(dnode_t *dnode, void *data)
997{
998 dnode->data = data;
999}
1000
1001int dnode_is_in_a_dict(dnode_t *dnode)
1002{
1003 return (dnode->parent && dnode->left && dnode->right);
1004}
1005
1006void dict_process(dict_t *dict, void *context, dnode_process_t function)
1007{
1008 dnode_t *node = dict_first(dict), *next;
1009
1010 while (node != NULL) {
1011 /* check for callback function deleting */
1012 /* the next node from under us */
1013 assert (dict_contains(dict, node));
1014 next = dict_next(dict, node);
1015 function(dict, node, context);
1016 node = next;
1017 }
1018}
1019
1020static void load_begin_internal(dict_load_t *load, dict_t *dict)
1021{
1022 load->dictptr = dict;
1023 load->nilnode.left = &load->nilnode;
1024 load->nilnode.right = &load->nilnode;
1025}
1026
1027void dict_load_begin(dict_load_t *load, dict_t *dict)
1028{
1029 assert (dict_isempty(dict));
1030 load_begin_internal(load, dict);
1031}
1032
1033void dict_load_next(dict_load_t *load, dnode_t *newnode, const void *key)
1034{
1035 dict_t *dict = load->dictptr;
1036 dnode_t *nil = &load->nilnode;
1037
1038 assert (!dnode_is_in_a_dict(newnode));
1039 assert (dict->nodecount < dict->maxcount);
1040
1041 #ifndef NDEBUG
1042 if (dict->nodecount > 0) {
1043 if (dict->dupes)
1044 assert (dict->compare(nil->left->key, key) <= 0);
1045 else
1046 assert (dict->compare(nil->left->key, key) < 0);
1047 }
1048 #endif
1049
1050 newnode->key = key;
1051 nil->right->left = newnode;
1052 nil->right = newnode;
1053 newnode->left = nil;
1054 dict->nodecount++;
1055}
1056
1057void dict_load_end(dict_load_t *load)
1058{
1059 dict_t *dict = load->dictptr;
1060 dnode_t *tree[DICT_DEPTH_MAX] = { 0 };
1061 dnode_t *curr, *dictnil = dict_nil(dict), *loadnil = &load->nilnode, *next;
1062 dnode_t *complete = 0;
1063 dictcount_t fullcount = DICTCOUNT_T_MAX, nodecount = dict->nodecount;
1064 dictcount_t botrowcount;
1065 unsigned baselevel = 0, level = 0, i;
1066
1067 assert (dnode_red == 0 && dnode_black == 1);
1068
1069 while (fullcount >= nodecount && fullcount)
1070 fullcount >>= 1;
1071
1072 botrowcount = nodecount - fullcount;
1073
1074 for (curr = loadnil->left; curr != loadnil; curr = next) {
1075 next = curr->left;
1076
1077 if (complete == NULL && botrowcount-- == 0) {
1078 assert (baselevel == 0);
1079 assert (level == 0);
1080 baselevel = level = 1;
1081 complete = tree[0];
1082
1083 if (complete != 0) {
1084 tree[0] = 0;
1085 complete->right = dictnil;
1086 while (tree[level] != 0) {
1087 tree[level]->right = complete;
1088 complete->parent = tree[level];
1089 complete = tree[level];
1090 tree[level++] = 0;
1091 }
1092 }
1093 }
1094
1095 if (complete == NULL) {
1096 curr->left = dictnil;
1097 curr->right = dictnil;
1098 curr->color = level % 2;
1099 complete = curr;
1100
1101 assert (level == baselevel);
1102 while (tree[level] != 0) {
1103 tree[level]->right = complete;
1104 complete->parent = tree[level];
1105 complete = tree[level];
1106 tree[level++] = 0;
1107 }
1108 } else {
1109 curr->left = complete;
1110 curr->color = (level + 1) % 2;
1111 complete->parent = curr;
1112 tree[level] = curr;
1113 complete = 0;
1114 level = baselevel;
1115 }
1116 }
1117
1118 if (complete == NULL)
1119 complete = dictnil;
1120
1121 for (i = 0; i < DICT_DEPTH_MAX; i++) {
1122 if (tree[i] != 0) {
1123 tree[i]->right = complete;
1124 complete->parent = tree[i];
1125 complete = tree[i];
1126 }
1127 }
1128
1129 dictnil->color = dnode_black;
1130 dictnil->right = dictnil;
1131 complete->parent = dictnil;
1132 complete->color = dnode_black;
1133 dict_root(dict) = complete;
1134
1135 assert (dict_verify(dict));
1136}
1137
1138void dict_merge(dict_t *dest, dict_t *source)
1139{
1140 dict_load_t load;
1141 dnode_t *leftnode = dict_first(dest), *rightnode = dict_first(source);
1142
1143 assert (dict_similar(dest, source));
1144
1145 if (source == dest)
1146 return;
1147
1148 dest->nodecount = 0;
1149 load_begin_internal(&load, dest);
1150
1151 for (;;) {
1152 if (leftnode != NULL && rightnode != NULL) {
1153 if (dest->compare(leftnode->key, rightnode->key) < 0)
1154 goto copyleft;
1155 else
1156 goto copyright;
1157 } else if (leftnode != NULL) {
1158 goto copyleft;
1159 } else if (rightnode != NULL) {
1160 goto copyright;
1161 } else {
1162 assert (leftnode == NULL && rightnode == NULL);
1163 break;
1164 }
1165
1166 copyleft:
1167 {
1168 dnode_t *next = dict_next(dest, leftnode);
1169 #ifndef NDEBUG
1170 leftnode->left = NULL; /* suppress assertion in dict_load_next */
1171 #endif
1172 dict_load_next(&load, leftnode, leftnode->key);
1173 leftnode = next;
1174 continue;
1175 }
1176
1177 copyright:
1178 {
1179 dnode_t *next = dict_next(source, rightnode);
1180 #ifndef NDEBUG
1181 rightnode->left = NULL;
1182 #endif
1183 dict_load_next(&load, rightnode, rightnode->key);
1184 rightnode = next;
1185 continue;
1186 }
1187 }
1188
1189 dict_clear(source);
1190 dict_load_end(&load);
1191}
1192
1193#ifdef KAZLIB_TEST_MAIN
1194
1195#include <stdio.h>
1196#include <string.h>
1197#include <ctype.h>
1198#include <stdarg.h>
1199
1200typedef char input_t[256];
1201
1202static int tokenize(char *string, ...)
1203{
1204 char **tokptr;
1205 va_list arglist;
1206 int tokcount = 0;
1207
1208 va_start(arglist, string);
1209 tokptr = va_arg(arglist, char **);
1210 while (tokptr) {
1211 while (*string && isspace((unsigned char) *string))
1212 string++;
1213 if (!*string)
1214 break;
1215 *tokptr = string;
1216 while (*string && !isspace((unsigned char) *string))
1217 string++;
1218 tokptr = va_arg(arglist, char **);
1219 tokcount++;
1220 if (!*string)
1221 break;
1222 *string++ = 0;
1223 }
1224 va_end(arglist);
1225
1226 return tokcount;
1227}
1228
1229static int comparef(const void *key1, const void *key2)
1230{
1231 return strcmp(key1, key2);
1232}
1233
1234static char *dupstring(char *str)
1235{
1236 int sz = strlen(str) + 1;
1237 char *new = malloc(sz);
1238 if (new)
1239 memcpy(new, str, sz);
1240 return new;
1241}
1242
1243static dnode_t *new_node(void *c)
1244{
1245 static dnode_t few[5];
1246 static int count;
1247
1248 if (count < 5)
1249 return few + count++;
1250
1251 return NULL;
1252}
1253
1254static void del_node(dnode_t *n, void *c)
1255{
1256}
1257
1258static int prompt = 0;
1259
1260static void construct(dict_t *d)
1261{
1262 input_t in;
1263 int done = 0;
1264 dict_load_t dl;
1265 dnode_t *dn;
1266 char *tok1, *tok2, *val;
1267 const char *key;
1268 char *help =
1269 "p turn prompt on\n"
1270 "q finish construction\n"
1271 "a <key> <val> add new entry\n";
1272
1273 if (!dict_isempty(d))
1274 puts("warning: dictionary not empty!");
1275
1276 dict_load_begin(&dl, d);
1277
1278 while (!done) {
1279 if (prompt)
1280 putchar('>');
1281 fflush(stdout);
1282
1283 if (!fgets(in, sizeof(input_t), stdin))
1284 break;
1285
1286 switch (in[0]) {
1287 case '?':
1288 puts(help);
1289 break;
1290 case 'p':
1291 prompt = 1;
1292 break;
1293 case 'q':
1294 done = 1;
1295 break;
1296 case 'a':
1297 if (tokenize(in+1, &tok1, &tok2, (char **) 0) != 2) {
1298 puts("what?");
1299 break;
1300 }
1301 key = dupstring(tok1);
1302 val = dupstring(tok2);
1303 dn = dnode_create(val);
1304
1305 if (!key || !val || !dn) {
1306 puts("out of memory");
1307 free((void *) key);
1308 free(val);
1309 if (dn)
1310 dnode_destroy(dn);
1311 }
1312
1313 dict_load_next(&dl, dn, key);
1314 break;
1315 default:
1316 putchar('?');
1317 putchar('\n');
1318 break;
1319 }
1320 }
1321
1322 dict_load_end(&dl);
1323}
1324
1325int main(void)
1326{
1327 input_t in;
1328 dict_t darray[10];
1329 dict_t *d = &darray[0];
1330 dnode_t *dn;
1331 int i;
1332 char *tok1, *tok2, *val;
1333 const char *key;
1334
1335 char *help =
1336 "a <key> <val> add value to dictionary\n"
1337 "d <key> delete value from dictionary\n"
1338 "l <key> lookup value in dictionary\n"
1339 "( <key> lookup lower bound\n"
1340 ") <key> lookup upper bound\n"
1341 "# <num> switch to alternate dictionary (0-9)\n"
1342 "j <num> <num> merge two dictionaries\n"
1343 "f free the whole dictionary\n"
1344 "k allow duplicate keys\n"
1345 "c show number of entries\n"
1346 "t dump whole dictionary in sort order\n"
1347 "m make dictionary out of sorted items\n"
1348 "p turn prompt on\n"
1349 "s switch to non-functioning allocator\n"
1350 "q quit";
1351
1352 for (i = 0; i < sizeof darray / sizeof *darray; i++)
1353 dict_init(&darray[i], DICTCOUNT_T_MAX, comparef);
1354
1355 for (;;) {
1356 if (prompt)
1357 putchar('>');
1358 fflush(stdout);
1359
1360 if (!fgets(in, sizeof(input_t), stdin))
1361 break;
1362
1363 switch(in[0]) {
1364 case '?':
1365 puts(help);
1366 break;
1367 case 'a':
1368 if (tokenize(in+1, &tok1, &tok2, (char **) 0) != 2) {
1369 puts("what?");
1370 break;
1371 }
1372 key = dupstring(tok1);
1373 val = dupstring(tok2);
1374
1375 if (!key || !val) {
1376 puts("out of memory");
1377 free((void *) key);
1378 free(val);
1379 }
1380
1381 if (!dict_alloc_insert(d, key, val)) {
1382 puts("dict_alloc_insert failed");
1383 free((void *) key);
1384 free(val);
1385 break;
1386 }
1387 break;
1388 case 'd':
1389 if (tokenize(in+1, &tok1, (char **) 0) != 1) {
1390 puts("what?");
1391 break;
1392 }
1393 dn = dict_lookup(d, tok1);
1394 if (!dn) {
1395 puts("dict_lookup failed");
1396 break;
1397 }
1398 val = dnode_get(dn);
1399 key = dnode_getkey(dn);
1400 dict_delete_free(d, dn);
1401
1402 free(val);
1403 free((void *) key);
1404 break;
1405 case 'f':
1406 dict_free(d);
1407 break;
1408 case 'l':
1409 case '(':
1410 case ')':
1411 if (tokenize(in+1, &tok1, (char **) 0) != 1) {
1412 puts("what?");
1413 break;
1414 }
1415 dn = 0;
1416 switch (in[0]) {
1417 case 'l':
1418 dn = dict_lookup(d, tok1);
1419 break;
1420 case '(':
1421 dn = dict_lower_bound(d, tok1);
1422 break;
1423 case ')':
1424 dn = dict_upper_bound(d, tok1);
1425 break;
1426 }
1427 if (!dn) {
1428 puts("lookup failed");
1429 break;
1430 }
1431 val = dnode_get(dn);
1432 puts(val);
1433 break;
1434 case 'm':
1435 construct(d);
1436 break;
1437 case 'k':
1438 dict_allow_dupes(d);
1439 break;
1440 case 'c':
1441 printf("%lu\n", (unsigned long) dict_count(d));
1442 break;
1443 case 't':
1444 for (dn = dict_first(d); dn; dn = dict_next(d, dn)) {
1445 printf("%s\t%s\n", (char *) dnode_getkey(dn),
1446 (char *) dnode_get(dn));
1447 }
1448 break;
1449 case 'q':
1450 exit(0);
1451 break;
1452 case '\0':
1453 break;
1454 case 'p':
1455 prompt = 1;
1456 break;
1457 case 's':
1458 dict_set_allocator(d, new_node, del_node, NULL);
1459 break;
1460 case '#':
1461 if (tokenize(in+1, &tok1, (char **) 0) != 1) {
1462 puts("what?");
1463 break;
1464 } else {
1465 int dictnum = atoi(tok1);
1466 if (dictnum < 0 || dictnum > 9) {
1467 puts("invalid number");
1468 break;
1469 }
1470 d = &darray[dictnum];
1471 }
1472 break;
1473 case 'j':
1474 if (tokenize(in+1, &tok1, &tok2, (char **) 0) != 2) {
1475 puts("what?");
1476 break;
1477 } else {
1478 int dict1 = atoi(tok1), dict2 = atoi(tok2);
1479 if (dict1 < 0 || dict1 > 9 || dict2 < 0 || dict2 > 9) {
1480 puts("invalid number");
1481 break;
1482 }
1483 dict_merge(&darray[dict1], &darray[dict2]);
1484 }
1485 break;
1486 default:
1487 putchar('?');
1488 putchar('\n');
1489 break;
1490 }
1491 }
1492
1493 return 0;
1494}
1495
1496#endif