Annotation of embedaddon/quagga/isisd/dict.c, revision 1.1.1.1
1.1 misho 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
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>