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