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