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