]> git.proxmox.com Git - mirror_frr.git/blame - isisd/dict.c
Add user `frr` into group `frrvty`
[mirror_frr.git] / isisd / dict.c
CommitLineData
eb5d44eb 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.
eb5d44eb 16 */
17
238497fc 18#include "zebra.h"
cee3df1e 19#include "zassert.h"
3f045a08 20#include "memory.h"
4a1ab8e4 21#include "isis_memory.h"
eb5d44eb 22#include "dict.h"
23
eb5d44eb 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
ffe543af 58static dnode_t *dnode_alloc(void *context);
59static void dnode_free(dnode_t *node, void *context);
eb5d44eb 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
ffe543af 68static void rotate_left(dnode_t *upper)
eb5d44eb 69{
ffe543af 70 dnode_t *lower, *lowleft, *upparent;
eb5d44eb 71
ffe543af 72 lower = upper->right;
73 upper->right = lowleft = lower->left;
74 lowleft->parent = upper;
eb5d44eb 75
ffe543af 76 lower->parent = upparent = upper->parent;
eb5d44eb 77
ffe543af 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 */
eb5d44eb 80
ffe543af 81 if (upper == upparent->left) {
82 upparent->left = lower;
83 } else {
84 assert (upper == upparent->right);
85 upparent->right = lower;
eb5d44eb 86 }
87
ffe543af 88 lower->left = upper;
89 upper->parent = lower;
eb5d44eb 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
ffe543af 97static void rotate_right(dnode_t *upper)
eb5d44eb 98{
ffe543af 99 dnode_t *lower, *lowright, *upparent;
eb5d44eb 100
ffe543af 101 lower = upper->left;
102 upper->left = lowright = lower->right;
103 lowright->parent = upper;
eb5d44eb 104
ffe543af 105 lower->parent = upparent = upper->parent;
eb5d44eb 106
ffe543af 107 if (upper == upparent->right) {
108 upparent->right = lower;
109 } else {
110 assert (upper == upparent->left);
111 upparent->left = lower;
eb5d44eb 112 }
113
ffe543af 114 lower->right = upper;
115 upper->parent = lower;
eb5d44eb 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
ffe543af 123static void free_nodes(dict_t *dict, dnode_t *node, dnode_t *nil)
eb5d44eb 124{
ffe543af 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);
eb5d44eb 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
ffe543af 141static int verify_bintree(dict_t *dict)
eb5d44eb 142{
ffe543af 143 dnode_t *first, *next;
eb5d44eb 144
ffe543af 145 first = dict_first(dict);
eb5d44eb 146
ffe543af 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;
eb5d44eb 152 }
ffe543af 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;
eb5d44eb 158 }
159 }
ffe543af 160 return 1;
eb5d44eb 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
ffe543af 177static unsigned int verify_redblack(dnode_t *nil, dnode_t *root)
eb5d44eb 178{
ffe543af 179 unsigned height_left, height_right;
eb5d44eb 180
ffe543af 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)
eb5d44eb 185 return 0;
ffe543af 186 if (height_left != height_right)
eb5d44eb 187 return 0;
ffe543af 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;
eb5d44eb 194 }
ffe543af 195 if (root->color != dnode_black)
196 return 0;
197 return height_left + 1;
198 }
199 return 1;
eb5d44eb 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
ffe543af 208static dictcount_t verify_node_count(dnode_t *nil, dnode_t *root)
eb5d44eb 209{
ffe543af 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);
eb5d44eb 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
ffe543af 224static int verify_dict_has_node(dnode_t *nil, dnode_t *root, dnode_t *node)
eb5d44eb 225{
ffe543af 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);
eb5d44eb 230 }
ffe543af 231 return 0;
eb5d44eb 232}
233
ffe543af 234
eb5d44eb 235/*
236 * Dynamically allocate and initialize a dictionary object.
237 */
238
ffe543af 239dict_t *dict_create(dictcount_t maxcount, dict_comp_t comp)
eb5d44eb 240{
3f045a08 241 dict_t *new = XCALLOC(MTYPE_ISIS_DICT, sizeof(dict_t));
ffe543af 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;
eb5d44eb 255 }
ffe543af 256 return new;
eb5d44eb 257}
258
259/*
260 * Select a different set of node allocator routines.
261 */
262
ffe543af 263void dict_set_allocator(dict_t *dict, dnode_alloc_t al,
264 dnode_free_t fr, void *context)
eb5d44eb 265{
ffe543af 266 assert (dict_count(dict) == 0);
267 assert ((al == NULL && fr == NULL) || (al != NULL && fr != NULL));
eb5d44eb 268
ffe543af 269 dict->allocnode = al ? al : dnode_alloc;
270 dict->freenode = fr ? fr : dnode_free;
271 dict->context = context;
eb5d44eb 272}
273
274/*
275 * Free a dynamically allocated dictionary object. Removing the nodes
276 * from the tree before deleting it is required.
277 */
278
ffe543af 279void dict_destroy(dict_t *dict)
eb5d44eb 280{
ffe543af 281 assert (dict_isempty(dict));
3f045a08 282 XFREE(MTYPE_ISIS_DICT, dict);
eb5d44eb 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
ffe543af 290void dict_free_nodes(dict_t *dict)
eb5d44eb 291{
ffe543af 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;
eb5d44eb 297}
298
299/*
300 * Obsolescent function, equivalent to dict_free_nodes
301 */
302
ffe543af 303void dict_free(dict_t *dict)
eb5d44eb 304{
ffe543af 305 dict_free_nodes(dict);
eb5d44eb 306}
307
308/*
309 * Initialize a user-supplied dictionary object.
310 */
311
ffe543af 312dict_t *dict_init(dict_t *dict, dictcount_t maxcount, dict_comp_t comp)
eb5d44eb 313{
ffe543af 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;
eb5d44eb 326}
327
328/*
329 * Initialize a dictionary in the likeness of another dictionary
330 */
331
ffe543af 332void dict_init_like(dict_t *dict, const dict_t *template)
eb5d44eb 333{
ffe543af 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));
eb5d44eb 347}
348
349/*
350 * Remove all nodes from the dictionary (without freeing them in any way).
351 */
352
ffe543af 353static void dict_clear(dict_t *dict)
eb5d44eb 354{
ffe543af 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);
eb5d44eb 360}
361
ffe543af 362
eb5d44eb 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.
ffe543af 368 */
eb5d44eb 369
ffe543af 370int dict_verify(dict_t *dict)
eb5d44eb 371{
ffe543af 372 dnode_t *nil = dict_nil(dict), *root = dict_root(dict);
eb5d44eb 373
ffe543af 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;
eb5d44eb 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
ffe543af 400int dict_similar(const dict_t *left, const dict_t *right)
eb5d44eb 401{
ffe543af 402 if (left->compare != right->compare)
403 return 0;
eb5d44eb 404
ffe543af 405 if (left->allocnode != right->allocnode)
406 return 0;
eb5d44eb 407
ffe543af 408 if (left->freenode != right->freenode)
409 return 0;
eb5d44eb 410
ffe543af 411 if (left->context != right->context)
412 return 0;
eb5d44eb 413
ffe543af 414 if (left->dupes != right->dupes)
415 return 0;
eb5d44eb 416
ffe543af 417 return 1;
eb5d44eb 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
ffe543af 427dnode_t *dict_lookup(dict_t *dict, const void *key)
eb5d44eb 428{
ffe543af 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 return root;
445 } else { /* could be dupes, find leftmost one */
446 do {
447 saved = root;
448 root = root->left;
449 while (root != nil && dict->compare(key, root->key))
450 root = root->right;
451 } while (root != nil);
452 return saved;
eb5d44eb 453 }
454 }
455 }
456
ffe543af 457 return NULL;
eb5d44eb 458}
459
460/*
461 * Look for the node corresponding to the lowest key that is equal to or
462 * greater than the given key. If there is no such node, return null.
463 */
464
ffe543af 465dnode_t *dict_lower_bound(dict_t *dict, const void *key)
eb5d44eb 466{
ffe543af 467 dnode_t *root = dict_root(dict);
468 dnode_t *nil = dict_nil(dict);
469 dnode_t *tentative = 0;
470
471 while (root != nil) {
472 int result = dict->compare(key, root->key);
473
474 if (result > 0) {
475 root = root->right;
476 } else if (result < 0) {
477 tentative = root;
478 root = root->left;
479 } else {
480 if (!dict->dupes) {
481 return root;
482 } else {
483 tentative = root;
484 root = root->left;
eb5d44eb 485 }
ffe543af 486 }
eb5d44eb 487 }
ffe543af 488
489 return tentative;
eb5d44eb 490}
491
492/*
493 * Look for the node corresponding to the greatest key that is equal to or
494 * lower than the given key. If there is no such node, return null.
495 */
496
ffe543af 497dnode_t *dict_upper_bound(dict_t *dict, const void *key)
eb5d44eb 498{
ffe543af 499 dnode_t *root = dict_root(dict);
500 dnode_t *nil = dict_nil(dict);
501 dnode_t *tentative = 0;
502
503 while (root != nil) {
504 int result = dict->compare(key, root->key);
505
506 if (result < 0) {
507 root = root->left;
508 } else if (result > 0) {
509 tentative = root;
510 root = root->right;
511 } else {
512 if (!dict->dupes) {
513 return root;
514 } else {
515 tentative = root;
516 root = root->right;
eb5d44eb 517 }
ffe543af 518 }
eb5d44eb 519 }
ffe543af 520
521 return tentative;
eb5d44eb 522}
523
524/*
525 * Insert a node into the dictionary. The node should have been
526 * initialized with a data field. All other fields are ignored.
527 * The behavior is undefined if the user attempts to insert into
528 * a dictionary that is already full (for which the dict_isfull()
529 * function returns true).
530 */
531
ffe543af 532void dict_insert(dict_t *dict, dnode_t *node, const void *key)
eb5d44eb 533{
ffe543af 534 dnode_t *where = dict_root(dict), *nil = dict_nil(dict);
535 dnode_t *parent = nil, *uncle, *grandpa;
536 int result = -1;
537
538 node->key = key;
539
540 assert (!dict_isfull(dict));
541 assert (!dict_contains(dict, node));
542 assert (!dnode_is_in_a_dict(node));
543
544 /* basic binary tree insert */
545
546 while (where != nil) {
547 parent = where;
548 result = dict->compare(key, where->key);
549 /* trap attempts at duplicate key insertion unless it's explicitly allowed */
550 assert (dict->dupes || result != 0);
551 if (result < 0)
552 where = where->left;
553 else
554 where = where->right;
eb5d44eb 555 }
556
ffe543af 557 assert (where == nil);
558
559 if (result < 0)
560 parent->left = node;
561 else
562 parent->right = node;
563
564 node->parent = parent;
565 node->left = nil;
566 node->right = nil;
567
568 dict->nodecount++;
569
570 /* red black adjustments */
571
572 node->color = dnode_red;
573
574 while (parent->color == dnode_red) {
575 grandpa = parent->parent;
576 if (parent == grandpa->left) {
577 uncle = grandpa->right;
578 if (uncle->color == dnode_red) { /* red parent, red uncle */
579 parent->color = dnode_black;
580 uncle->color = dnode_black;
581 grandpa->color = dnode_red;
582 node = grandpa;
583 parent = grandpa->parent;
584 } else { /* red parent, black uncle */
585 if (node == parent->right) {
586 rotate_left(parent);
587 parent = node;
588 assert (grandpa == parent->parent);
589 /* rotation between parent and child preserves grandpa */
eb5d44eb 590 }
ffe543af 591 parent->color = dnode_black;
592 grandpa->color = dnode_red;
593 rotate_right(grandpa);
594 break;
eb5d44eb 595 }
ffe543af 596 } else { /* symmetric cases: parent == parent->parent->right */
597 uncle = grandpa->left;
598 if (uncle->color == dnode_red) {
599 parent->color = dnode_black;
600 uncle->color = dnode_black;
601 grandpa->color = dnode_red;
602 node = grandpa;
603 parent = grandpa->parent;
604 } else {
605 if (node == parent->left) {
606 rotate_right(parent);
607 parent = node;
608 assert (grandpa == parent->parent);
eb5d44eb 609 }
ffe543af 610 parent->color = dnode_black;
611 grandpa->color = dnode_red;
612 rotate_left(grandpa);
613 break;
eb5d44eb 614 }
615 }
616 }
617
ffe543af 618 dict_root(dict)->color = dnode_black;
eb5d44eb 619
ffe543af 620 assert (dict_verify(dict));
eb5d44eb 621}
622
623/*
624 * Delete the given node from the dictionary. If the given node does not belong
625 * to the given dictionary, undefined behavior results. A pointer to the
626 * deleted node is returned.
627 */
628
ffe543af 629dnode_t *dict_delete(dict_t *dict, dnode_t *delete)
eb5d44eb 630{
ffe543af 631 dnode_t *nil = dict_nil(dict), *child, *delparent = delete->parent;
632
633 /* basic deletion */
634
635 assert (!dict_isempty(dict));
636 assert (dict_contains(dict, delete));
637
638 /*
639 * If the node being deleted has two children, then we replace it with its
640 * successor (i.e. the leftmost node in the right subtree.) By doing this,
641 * we avoid the traditional algorithm under which the successor's key and
642 * value *only* move to the deleted node and the successor is spliced out
643 * from the tree. We cannot use this approach because the user may hold
644 * pointers to the successor, or nodes may be inextricably tied to some
645 * other structures by way of embedding, etc. So we must splice out the
646 * node we are given, not some other node, and must not move contents from
647 * one node to another behind the user's back.
648 */
649
650 if (delete->left != nil && delete->right != nil) {
651 dnode_t *next = dict_next(dict, delete);
f7535236 652 assert (next);
ffe543af 653 dnode_t *nextparent = next->parent;
654 dnode_color_t nextcolor = next->color;
655
656 assert (next != nil);
657 assert (next->parent != nil);
658 assert (next->left == nil);
659
660 /*
661 * First, splice out the successor from the tree completely, by
662 * moving up its right child into its place.
663 */
664
665 child = next->right;
666 child->parent = nextparent;
667
668 if (nextparent->left == next) {
669 nextparent->left = child;
670 } else {
671 assert (nextparent->right == next);
672 nextparent->right = child;
eb5d44eb 673 }
674
ffe543af 675 /*
676 * Now that the successor has been extricated from the tree, install it
677 * in place of the node that we want deleted.
678 */
679
680 next->parent = delparent;
681 next->left = delete->left;
682 next->right = delete->right;
683 next->left->parent = next;
684 next->right->parent = next;
685 next->color = delete->color;
686 delete->color = nextcolor;
687
688 if (delparent->left == delete) {
689 delparent->left = next;
690 } else {
691 assert (delparent->right == delete);
692 delparent->right = next;
eb5d44eb 693 }
694
ffe543af 695 } else {
696 assert (delete != nil);
697 assert (delete->left == nil || delete->right == nil);
eb5d44eb 698
ffe543af 699 child = (delete->left != nil) ? delete->left : delete->right;
eb5d44eb 700
ffe543af 701 child->parent = delparent = delete->parent;
eb5d44eb 702
ffe543af 703 if (delete == delparent->left) {
704 delparent->left = child;
705 } else {
706 assert (delete == delparent->right);
707 delparent->right = child;
eb5d44eb 708 }
709 }
710
ffe543af 711 delete->parent = NULL;
712 delete->right = NULL;
713 delete->left = NULL;
eb5d44eb 714
ffe543af 715 dict->nodecount--;
eb5d44eb 716
ffe543af 717 assert (verify_bintree(dict));
eb5d44eb 718
ffe543af 719 /* red-black adjustments */
eb5d44eb 720
ffe543af 721 if (delete->color == dnode_black) {
722 dnode_t *parent, *sister;
eb5d44eb 723
ffe543af 724 dict_root(dict)->color = dnode_red;
eb5d44eb 725
ffe543af 726 while (child->color == dnode_black) {
727 parent = child->parent;
728 if (child == parent->left) {
729 sister = parent->right;
730 assert (sister != nil);
731 if (sister->color == dnode_red) {
732 sister->color = dnode_black;
733 parent->color = dnode_red;
734 rotate_left(parent);
735 sister = parent->right;
736 assert (sister != nil);
eb5d44eb 737 }
ffe543af 738 if (sister->left->color == dnode_black
739 && sister->right->color == dnode_black) {
740 sister->color = dnode_red;
741 child = parent;
742 } else {
743 if (sister->right->color == dnode_black) {
744 assert (sister->left->color == dnode_red);
745 sister->left->color = dnode_black;
746 sister->color = dnode_red;
747 rotate_right(sister);
748 sister = parent->right;
749 assert (sister != nil);
eb5d44eb 750 }
ffe543af 751 sister->color = parent->color;
752 sister->right->color = dnode_black;
753 parent->color = dnode_black;
754 rotate_left(parent);
755 break;
eb5d44eb 756 }
ffe543af 757 } else { /* symmetric case: child == child->parent->right */
758 assert (child == parent->right);
759 sister = parent->left;
760 assert (sister != nil);
761 if (sister->color == dnode_red) {
762 sister->color = dnode_black;
763 parent->color = dnode_red;
764 rotate_right(parent);
765 sister = parent->left;
766 assert (sister != nil);
eb5d44eb 767 }
ffe543af 768 if (sister->right->color == dnode_black
769 && sister->left->color == dnode_black) {
770 sister->color = dnode_red;
771 child = parent;
772 } else {
773 if (sister->left->color == dnode_black) {
774 assert (sister->right->color == dnode_red);
775 sister->right->color = dnode_black;
776 sister->color = dnode_red;
777 rotate_left(sister);
778 sister = parent->left;
779 assert (sister != nil);
eb5d44eb 780 }
ffe543af 781 sister->color = parent->color;
782 sister->left->color = dnode_black;
783 parent->color = dnode_black;
784 rotate_right(parent);
785 break;
eb5d44eb 786 }
787 }
788 }
789
ffe543af 790 child->color = dnode_black;
791 dict_root(dict)->color = dnode_black;
eb5d44eb 792 }
793
ffe543af 794 assert (dict_verify(dict));
eb5d44eb 795
ffe543af 796 return delete;
eb5d44eb 797}
798
799/*
800 * Allocate a node using the dictionary's allocator routine, give it
801 * the data item.
802 */
803
ffe543af 804int dict_alloc_insert(dict_t *dict, const void *key, void *data)
eb5d44eb 805{
3f045a08 806 dnode_t *node = dict->allocnode (dict->context);
eb5d44eb 807
ffe543af 808 if (node) {
809 dnode_init(node, data);
810 dict_insert(dict, node, key);
811 return 1;
eb5d44eb 812 }
ffe543af 813 return 0;
eb5d44eb 814}
815
ffe543af 816void dict_delete_free(dict_t *dict, dnode_t *node)
eb5d44eb 817{
ffe543af 818 dict_delete(dict, node);
819 dict->freenode(node, dict->context);
eb5d44eb 820}
821
822/*
823 * Return the node with the lowest (leftmost) key. If the dictionary is empty
824 * (that is, dict_isempty(dict) returns 1) a null pointer is returned.
825 */
826
ffe543af 827dnode_t *dict_first(dict_t *dict)
eb5d44eb 828{
ffe543af 829 dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *left;
eb5d44eb 830
ffe543af 831 if (root != nil)
832 while ((left = root->left) != nil)
833 root = left;
eb5d44eb 834
ffe543af 835 return (root == nil) ? NULL : root;
eb5d44eb 836}
837
838/*
839 * Return the node with the highest (rightmost) key. If the dictionary is empty
840 * (that is, dict_isempty(dict) returns 1) a null pointer is returned.
841 */
842
ffe543af 843dnode_t *dict_last(dict_t *dict)
eb5d44eb 844{
ffe543af 845 dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *right;
eb5d44eb 846
ffe543af 847 if (root != nil)
848 while ((right = root->right) != nil)
849 root = right;
eb5d44eb 850
ffe543af 851 return (root == nil) ? NULL : root;
eb5d44eb 852}
853
854/*
855 * Return the given node's successor node---the node which has the
856 * next key in the the left to right ordering. If the node has
857 * no successor, a null pointer is returned rather than a pointer to
858 * the nil node.
859 */
860
ffe543af 861dnode_t *dict_next(dict_t *dict, dnode_t *curr)
eb5d44eb 862{
ffe543af 863 dnode_t *nil = dict_nil(dict), *parent, *left;
864
865 if (curr->right != nil) {
866 curr = curr->right;
867 while ((left = curr->left) != nil)
868 curr = left;
869 return curr;
eb5d44eb 870 }
871
ffe543af 872 parent = curr->parent;
eb5d44eb 873
ffe543af 874 while (parent != nil && curr == parent->right) {
875 curr = parent;
876 parent = curr->parent;
eb5d44eb 877 }
878
ffe543af 879 return (parent == nil) ? NULL : parent;
eb5d44eb 880}
881
882/*
883 * Return the given node's predecessor, in the key order.
884 * The nil sentinel node is returned if there is no predecessor.
885 */
886
ffe543af 887dnode_t *dict_prev(dict_t *dict, dnode_t *curr)
eb5d44eb 888{
ffe543af 889 dnode_t *nil = dict_nil(dict), *parent, *right;
890
891 if (curr->left != nil) {
892 curr = curr->left;
893 while ((right = curr->right) != nil)
894 curr = right;
895 return curr;
eb5d44eb 896 }
897
ffe543af 898 parent = curr->parent;
eb5d44eb 899
ffe543af 900 while (parent != nil && curr == parent->left) {
901 curr = parent;
902 parent = curr->parent;
eb5d44eb 903 }
904
ffe543af 905 return (parent == nil) ? NULL : parent;
eb5d44eb 906}
907
ffe543af 908void dict_allow_dupes(dict_t *dict)
eb5d44eb 909{
ffe543af 910 dict->dupes = 1;
eb5d44eb 911}
912
913#undef dict_count
914#undef dict_isempty
915#undef dict_isfull
916#undef dnode_get
917#undef dnode_put
918#undef dnode_getkey
919
ffe543af 920dictcount_t dict_count(dict_t *dict)
eb5d44eb 921{
ffe543af 922 return dict->nodecount;
eb5d44eb 923}
924
ffe543af 925int dict_isempty(dict_t *dict)
eb5d44eb 926{
ffe543af 927 return dict->nodecount == 0;
eb5d44eb 928}
929
ffe543af 930int dict_isfull(dict_t *dict)
eb5d44eb 931{
ffe543af 932 return dict->nodecount == dict->maxcount;
eb5d44eb 933}
934
ffe543af 935int dict_contains(dict_t *dict, dnode_t *node)
eb5d44eb 936{
ffe543af 937 return verify_dict_has_node(dict_nil(dict), dict_root(dict), node);
eb5d44eb 938}
939
ffe543af 940static dnode_t *dnode_alloc(void *context)
eb5d44eb 941{
3f045a08 942 return XCALLOC(MTYPE_ISIS_DICT_NODE, sizeof(dnode_t));
eb5d44eb 943}
944
ffe543af 945static void dnode_free(dnode_t *node, void *context)
eb5d44eb 946{
3f045a08 947 XFREE(MTYPE_ISIS_DICT_NODE, node);
eb5d44eb 948}
949
ffe543af 950dnode_t *dnode_create(void *data)
eb5d44eb 951{
3f045a08 952 dnode_t *new = XCALLOC(MTYPE_ISIS_DICT_NODE, sizeof(dnode_t));
ffe543af 953 if (new) {
954 new->data = data;
955 new->parent = NULL;
956 new->left = NULL;
957 new->right = NULL;
eb5d44eb 958 }
ffe543af 959 return new;
eb5d44eb 960}
961
ffe543af 962dnode_t *dnode_init(dnode_t *dnode, void *data)
eb5d44eb 963{
ffe543af 964 dnode->data = data;
965 dnode->parent = NULL;
966 dnode->left = NULL;
967 dnode->right = NULL;
968 return dnode;
eb5d44eb 969}
970
ffe543af 971void dnode_destroy(dnode_t *dnode)
eb5d44eb 972{
ffe543af 973 assert (!dnode_is_in_a_dict(dnode));
3f045a08 974 XFREE(MTYPE_ISIS_DICT_NODE, dnode);
eb5d44eb 975}
976
ffe543af 977void *dnode_get(dnode_t *dnode)
eb5d44eb 978{
ffe543af 979 return dnode->data;
eb5d44eb 980}
981
ffe543af 982const void *dnode_getkey(dnode_t *dnode)
eb5d44eb 983{
ffe543af 984 return dnode->key;
eb5d44eb 985}
986
ffe543af 987void dnode_put(dnode_t *dnode, void *data)
eb5d44eb 988{
ffe543af 989 dnode->data = data;
eb5d44eb 990}
991
ffe543af 992int dnode_is_in_a_dict(dnode_t *dnode)
eb5d44eb 993{
ffe543af 994 return (dnode->parent && dnode->left && dnode->right);
eb5d44eb 995}
996
ffe543af 997void dict_process(dict_t *dict, void *context, dnode_process_t function)
eb5d44eb 998{
ffe543af 999 dnode_t *node = dict_first(dict), *next;
1000
1001 while (node != NULL) {
1002 /* check for callback function deleting */
1003 /* the next node from under us */
1004 assert (dict_contains(dict, node));
1005 next = dict_next(dict, node);
1006 function(dict, node, context);
1007 node = next;
eb5d44eb 1008 }
1009}
1010
ffe543af 1011static void load_begin_internal(dict_load_t *load, dict_t *dict)
eb5d44eb 1012{
ffe543af 1013 load->dictptr = dict;
1014 load->nilnode.left = &load->nilnode;
1015 load->nilnode.right = &load->nilnode;
eb5d44eb 1016}
1017
ffe543af 1018void dict_load_begin(dict_load_t *load, dict_t *dict)
eb5d44eb 1019{
ffe543af 1020 assert (dict_isempty(dict));
1021 load_begin_internal(load, dict);
eb5d44eb 1022}
1023
ffe543af 1024void dict_load_next(dict_load_t *load, dnode_t *newnode, const void *key)
eb5d44eb 1025{
ffe543af 1026 dict_t *dict = load->dictptr;
1027 dnode_t *nil = &load->nilnode;
1028
1029 assert (!dnode_is_in_a_dict(newnode));
1030 assert (dict->nodecount < dict->maxcount);
1031
1032 #ifndef NDEBUG
1033 if (dict->nodecount > 0) {
1034 if (dict->dupes)
1035 assert (dict->compare(nil->left->key, key) <= 0);
1036 else
1037 assert (dict->compare(nil->left->key, key) < 0);
eb5d44eb 1038 }
ffe543af 1039 #endif
eb5d44eb 1040
ffe543af 1041 newnode->key = key;
1042 nil->right->left = newnode;
1043 nil->right = newnode;
1044 newnode->left = nil;
1045 dict->nodecount++;
eb5d44eb 1046}
1047
ffe543af 1048void dict_load_end(dict_load_t *load)
eb5d44eb 1049{
ffe543af 1050 dict_t *dict = load->dictptr;
1051 dnode_t *tree[DICT_DEPTH_MAX] = { 0 };
1052 dnode_t *curr, *dictnil = dict_nil(dict), *loadnil = &load->nilnode, *next;
1053 dnode_t *complete = 0;
1054 dictcount_t fullcount = DICTCOUNT_T_MAX, nodecount = dict->nodecount;
1055 dictcount_t botrowcount;
1056 unsigned baselevel = 0, level = 0, i;
1057
1058 assert (dnode_red == 0 && dnode_black == 1);
1059
1060 while (fullcount >= nodecount && fullcount)
1061 fullcount >>= 1;
1062
1063 botrowcount = nodecount - fullcount;
1064
1065 for (curr = loadnil->left; curr != loadnil; curr = next) {
1066 next = curr->left;
1067
1068 if (complete == NULL && botrowcount-- == 0) {
1069 assert (baselevel == 0);
1070 assert (level == 0);
1071 baselevel = level = 1;
1072 complete = tree[0];
1073
1074 if (complete != 0) {
1075 tree[0] = 0;
1076 complete->right = dictnil;
1077 while (tree[level] != 0) {
1078 tree[level]->right = complete;
1079 complete->parent = tree[level];
1080 complete = tree[level];
1081 tree[level++] = 0;
eb5d44eb 1082 }
1083 }
1084 }
1085
ffe543af 1086 if (complete == NULL) {
1087 curr->left = dictnil;
1088 curr->right = dictnil;
1089 curr->color = level % 2;
1090 complete = curr;
1091
1092 assert (level == baselevel);
1093 while (tree[level] != 0) {
1094 tree[level]->right = complete;
1095 complete->parent = tree[level];
1096 complete = tree[level];
1097 tree[level++] = 0;
eb5d44eb 1098 }
ffe543af 1099 } else {
1100 curr->left = complete;
1101 curr->color = (level + 1) % 2;
1102 complete->parent = curr;
1103 tree[level] = curr;
1104 complete = 0;
1105 level = baselevel;
eb5d44eb 1106 }
1107 }
1108
ffe543af 1109 if (complete == NULL)
1110 complete = dictnil;
eb5d44eb 1111
ffe543af 1112 for (i = 0; i < DICT_DEPTH_MAX; i++) {
1113 if (tree[i] != 0) {
1114 tree[i]->right = complete;
1115 complete->parent = tree[i];
1116 complete = tree[i];
eb5d44eb 1117 }
1118 }
1119
ffe543af 1120 dictnil->color = dnode_black;
1121 dictnil->right = dictnil;
1122 complete->parent = dictnil;
1123 complete->color = dnode_black;
1124 dict_root(dict) = complete;
eb5d44eb 1125
ffe543af 1126 assert (dict_verify(dict));
eb5d44eb 1127}
1128
ffe543af 1129void dict_merge(dict_t *dest, dict_t *source)
eb5d44eb 1130{
ffe543af 1131 dict_load_t load;
1132 dnode_t *leftnode = dict_first(dest), *rightnode = dict_first(source);
eb5d44eb 1133
ffe543af 1134 assert (dict_similar(dest, source));
eb5d44eb 1135
ffe543af 1136 if (source == dest)
1137 return;
eb5d44eb 1138
ffe543af 1139 dest->nodecount = 0;
1140 load_begin_internal(&load, dest);
eb5d44eb 1141
ffe543af 1142 for (;;) {
1143 if (leftnode != NULL && rightnode != NULL) {
1144 if (dest->compare(leftnode->key, rightnode->key) < 0)
1145 goto copyleft;
1146 else
1147 goto copyright;
1148 } else if (leftnode != NULL) {
eb5d44eb 1149 goto copyleft;
ffe543af 1150 } else if (rightnode != NULL) {
eb5d44eb 1151 goto copyright;
ffe543af 1152 } else {
1153 assert (leftnode == NULL && rightnode == NULL);
1154 break;
eb5d44eb 1155 }
ffe543af 1156
1157 copyleft:
f390d2c7 1158 {
ffe543af 1159 dnode_t *next = dict_next(dest, leftnode);
1160 #ifndef NDEBUG
1161 leftnode->left = NULL; /* suppress assertion in dict_load_next */
1162 #endif
1163 dict_load_next(&load, leftnode, leftnode->key);
1164 leftnode = next;
1165 continue;
f390d2c7 1166 }
ffe543af 1167
1168 copyright:
eb5d44eb 1169 {
ffe543af 1170 dnode_t *next = dict_next(source, rightnode);
1171 #ifndef NDEBUG
1172 rightnode->left = NULL;
1173 #endif
1174 dict_load_next(&load, rightnode, rightnode->key);
1175 rightnode = next;
1176 continue;
eb5d44eb 1177 }
1178 }
1179
ffe543af 1180 dict_clear(source);
1181 dict_load_end(&load);
eb5d44eb 1182}
1183
1184#ifdef KAZLIB_TEST_MAIN
1185
1186#include <stdio.h>
1187#include <string.h>
1188#include <ctype.h>
1189#include <stdarg.h>
1190
1191typedef char input_t[256];
1192
ffe543af 1193static int tokenize(char *string, ...)
eb5d44eb 1194{
ffe543af 1195 char **tokptr;
1196 va_list arglist;
1197 int tokcount = 0;
1198
1199 va_start(arglist, string);
1200 tokptr = va_arg(arglist, char **);
1201 while (tokptr) {
1202 while (*string && isspace((unsigned char) *string))
1203 string++;
1204 if (!*string)
1205 break;
1206 *tokptr = string;
1207 while (*string && !isspace((unsigned char) *string))
1208 string++;
1209 tokptr = va_arg(arglist, char **);
1210 tokcount++;
1211 if (!*string)
1212 break;
1213 *string++ = 0;
eb5d44eb 1214 }
ffe543af 1215 va_end(arglist);
eb5d44eb 1216
ffe543af 1217 return tokcount;
eb5d44eb 1218}
1219
ffe543af 1220static int comparef(const void *key1, const void *key2)
eb5d44eb 1221{
ffe543af 1222 return strcmp(key1, key2);
eb5d44eb 1223}
1224
ffe543af 1225static char *dupstring(char *str)
eb5d44eb 1226{
ffe543af 1227 int sz = strlen(str) + 1;
3f045a08 1228 char *new = XCALLOC(MTYPE_ISIS_TMP, sz);
ffe543af 1229 if (new)
1230 memcpy(new, str, sz);
1231 return new;
eb5d44eb 1232}
1233
ffe543af 1234static dnode_t *new_node(void *c)
eb5d44eb 1235{
ffe543af 1236 static dnode_t few[5];
1237 static int count;
eb5d44eb 1238
ffe543af 1239 if (count < 5)
1240 return few + count++;
eb5d44eb 1241
ffe543af 1242 return NULL;
eb5d44eb 1243}
1244
ffe543af 1245static void del_node(dnode_t *n, void *c)
eb5d44eb 1246{
1247}
1248
1249static int prompt = 0;
1250
ffe543af 1251static void construct(dict_t *d)
eb5d44eb 1252{
ffe543af 1253 input_t in;
1254 int done = 0;
1255 dict_load_t dl;
1256 dnode_t *dn;
1257 char *tok1, *tok2, *val;
1258 const char *key;
1259 char *help =
1260 "p turn prompt on\n"
1261 "q finish construction\n"
1262 "a <key> <val> add new entry\n";
1263
1264 if (!dict_isempty(d))
1265 puts("warning: dictionary not empty!");
1266
1267 dict_load_begin(&dl, d);
1268
1269 while (!done) {
1270 if (prompt)
1271 putchar('>');
1272 fflush(stdout);
1273
1274 if (!fgets(in, sizeof(input_t), stdin))
1275 break;
1276
1277 switch (in[0]) {
1278 case '?':
1279 puts(help);
1280 break;
1281 case 'p':
1282 prompt = 1;
1283 break;
1284 case 'q':
1285 done = 1;
1286 break;
1287 case 'a':
1288 if (tokenize(in+1, &tok1, &tok2, (char **) 0) != 2) {
1289 puts("what?");
1290 break;
1291 }
1292 key = dupstring(tok1);
1293 val = dupstring(tok2);
1294 dn = dnode_create(val);
1295
1296 if (!key || !val || !dn) {
1297 puts("out of memory");
1298 free((void *) key);
1299 free(val);
1300 if (dn)
1301 dnode_destroy(dn);
1302 }
eb5d44eb 1303
ffe543af 1304 dict_load_next(&dl, dn, key);
1305 break;
1306 default:
1307 putchar('?');
1308 putchar('\n');
1309 break;
eb5d44eb 1310 }
1311 }
1312
ffe543af 1313 dict_load_end(&dl);
eb5d44eb 1314}
1315
ffe543af 1316int main(void)
eb5d44eb 1317{
ffe543af 1318 input_t in;
1319 dict_t darray[10];
1320 dict_t *d = &darray[0];
1321 dnode_t *dn;
1322 int i;
1323 char *tok1, *tok2, *val;
1324 const char *key;
1325
1326 char *help =
1327 "a <key> <val> add value to dictionary\n"
1328 "d <key> delete value from dictionary\n"
1329 "l <key> lookup value in dictionary\n"
1330 "( <key> lookup lower bound\n"
1331 ") <key> lookup upper bound\n"
1332 "# <num> switch to alternate dictionary (0-9)\n"
1333 "j <num> <num> merge two dictionaries\n"
1334 "f free the whole dictionary\n"
1335 "k allow duplicate keys\n"
1336 "c show number of entries\n"
1337 "t dump whole dictionary in sort order\n"
1338 "m make dictionary out of sorted items\n"
1339 "p turn prompt on\n"
1340 "s switch to non-functioning allocator\n"
1341 "q quit";
1342
3f045a08 1343 for (i = 0; i < 10; i++)
ffe543af 1344 dict_init(&darray[i], DICTCOUNT_T_MAX, comparef);
1345
1346 for (;;) {
1347 if (prompt)
1348 putchar('>');
1349 fflush(stdout);
1350
1351 if (!fgets(in, sizeof(input_t), stdin))
1352 break;
1353
1354 switch(in[0]) {
1355 case '?':
1356 puts(help);
1357 break;
1358 case 'a':
1359 if (tokenize(in+1, &tok1, &tok2, (char **) 0) != 2) {
1360 puts("what?");
1361 break;
1362 }
1363 key = dupstring(tok1);
1364 val = dupstring(tok2);
eb5d44eb 1365
ffe543af 1366 if (!key || !val) {
1367 puts("out of memory");
1368 free((void *) key);
1369 free(val);
1370 }
1371
1372 if (!dict_alloc_insert(d, key, val)) {
1373 puts("dict_alloc_insert failed");
1374 free((void *) key);
1375 free(val);
1376 break;
1377 }
1378 break;
1379 case 'd':
1380 if (tokenize(in+1, &tok1, (char **) 0) != 1) {
1381 puts("what?");
1382 break;
1383 }
1384 dn = dict_lookup(d, tok1);
1385 if (!dn) {
1386 puts("dict_lookup failed");
1387 break;
1388 }
1389 val = dnode_get(dn);
1390 key = dnode_getkey(dn);
1391 dict_delete_free(d, dn);
1392
1393 free(val);
1394 free((void *) key);
1395 break;
1396 case 'f':
1397 dict_free(d);
1398 break;
eb5d44eb 1399 case 'l':
1400 case '(':
1401 case ')':
ffe543af 1402 if (tokenize(in+1, &tok1, (char **) 0) != 1) {
1403 puts("what?");
1404 break;
eb5d44eb 1405 }
ffe543af 1406 dn = 0;
1407 switch (in[0]) {
1408 case 'l':
1409 dn = dict_lookup(d, tok1);
1410 break;
1411 case '(':
1412 dn = dict_lower_bound(d, tok1);
1413 break;
1414 case ')':
1415 dn = dict_upper_bound(d, tok1);
1416 break;
eb5d44eb 1417 }
ffe543af 1418 if (!dn) {
1419 puts("lookup failed");
1420 break;
1421 }
1422 val = dnode_get(dn);
1423 puts(val);
1424 break;
1425 case 'm':
1426 construct(d);
1427 break;
1428 case 'k':
1429 dict_allow_dupes(d);
1430 break;
1431 case 'c':
1432 printf("%lu\n", (unsigned long) dict_count(d));
1433 break;
1434 case 't':
1435 for (dn = dict_first(d); dn; dn = dict_next(d, dn)) {
1436 printf("%s\t%s\n", (char *) dnode_getkey(dn),
1437 (char *) dnode_get(dn));
1438 }
1439 break;
1440 case 'q':
1441 exit(0);
1442 break;
1443 case '\0':
1444 break;
1445 case 'p':
1446 prompt = 1;
1447 break;
1448 case 's':
1449 dict_set_allocator(d, new_node, del_node, NULL);
1450 break;
1451 case '#':
1452 if (tokenize(in+1, &tok1, (char **) 0) != 1) {
1453 puts("what?");
1454 break;
1455 } else {
1456 int dictnum = atoi(tok1);
1457 if (dictnum < 0 || dictnum > 9) {
1458 puts("invalid number");
1459 break;
1460 }
1461 d = &darray[dictnum];
1462 }
1463 break;
1464 case 'j':
1465 if (tokenize(in+1, &tok1, &tok2, (char **) 0) != 2) {
1466 puts("what?");
1467 break;
1468 } else {
1469 int dict1 = atoi(tok1), dict2 = atoi(tok2);
1470 if (dict1 < 0 || dict1 > 9 || dict2 < 0 || dict2 > 9) {
1471 puts("invalid number");
1472 break;
1473 }
1474 dict_merge(&darray[dict1], &darray[dict2]);
1475 }
1476 break;
1477 default:
1478 putchar('?');
1479 putchar('\n');
1480 break;
eb5d44eb 1481 }
1482 }
1483
ffe543af 1484 return 0;
eb5d44eb 1485}
1486
1487#endif