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