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