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