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