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