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