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