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