blob: a333d3eff7229b0b5780de1fe1a11e022ad3b4e6 [file] [log] [blame]
jardineb5d44e2003-12-23 08:09:43 +00001/*
2 * Dictionary Abstract Data Type
3 * Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net>
4 *
5 * Free Software License:
6 *
7 * All rights are reserved by the author, with the following exceptions:
8 * Permission is granted to freely reproduce and distribute this software,
9 * possibly in exchange for a fee, provided that this copyright notice appears
10 * intact. Permission is also granted to adapt this software to produce
11 * derivative works, as long as the modified versions carry this copyright
12 * notice and additional notices stating that the work has been modified.
13 * This source code may be translated into executable form and incorporated
14 * into proprietary software; there is no requirement for such software to
15 * contain a copyright notice related to this source.
16 *
hassoffe543a2005-09-25 12:04:25 +000017 * $Id: dict.c,v 1.4 2005/09/25 12:04:25 hasso Exp $
jardineb5d44e2003-12-23 08:09:43 +000018 * $Name: $
19 */
20
21#include <stdlib.h>
22#include <stddef.h>
ajscee3df12004-11-24 17:14:49 +000023#include "zassert.h"
jardineb5d44e2003-12-23 08:09:43 +000024#define DICT_IMPLEMENTATION
25#include "dict.h"
26
27#ifdef KAZLIB_RCSID
hassoffe543a2005-09-25 12:04:25 +000028static const char rcsid[] = "Id: dict.c,v 1.40.2.7 2000/11/13 01:36:44 kaz";
jardineb5d44e2003-12-23 08:09:43 +000029#endif
30
31/*
32 * These macros provide short convenient names for structure members,
33 * which are embellished with dict_ prefixes so that they are
34 * properly confined to the documented namespace. It's legal for a
35 * program which uses dict to define, for instance, a macro called ``parent''.
36 * Such a macro would interfere with the dnode_t struct definition.
37 * In general, highly portable and reusable C modules which expose their
38 * structures need to confine structure member names to well-defined spaces.
39 * The resulting identifiers aren't necessarily convenient to use, nor
40 * readable, in the implementation, however!
41 */
42
43#define left dict_left
44#define right dict_right
45#define parent dict_parent
46#define color dict_color
47#define key dict_key
48#define data dict_data
49
50#define nilnode dict_nilnode
51#define nodecount dict_nodecount
52#define maxcount dict_maxcount
53#define compare dict_compare
54#define allocnode dict_allocnode
55#define freenode dict_freenode
56#define context dict_context
57#define dupes dict_dupes
58
59#define dictptr dict_dictptr
60
61#define dict_root(D) ((D)->nilnode.left)
62#define dict_nil(D) (&(D)->nilnode)
63#define DICT_DEPTH_MAX 64
64
hassoffe543a2005-09-25 12:04:25 +000065static dnode_t *dnode_alloc(void *context);
66static void dnode_free(dnode_t *node, void *context);
jardineb5d44e2003-12-23 08:09:43 +000067
68/*
69 * Perform a ``left rotation'' adjustment on the tree. The given node P and
70 * its right child C are rearranged so that the P instead becomes the left
71 * child of C. The left subtree of C is inherited as the new right subtree
72 * for P. The ordering of the keys within the tree is thus preserved.
73 */
74
hassoffe543a2005-09-25 12:04:25 +000075static void rotate_left(dnode_t *upper)
jardineb5d44e2003-12-23 08:09:43 +000076{
hassoffe543a2005-09-25 12:04:25 +000077 dnode_t *lower, *lowleft, *upparent;
jardineb5d44e2003-12-23 08:09:43 +000078
hassoffe543a2005-09-25 12:04:25 +000079 lower = upper->right;
80 upper->right = lowleft = lower->left;
81 lowleft->parent = upper;
jardineb5d44e2003-12-23 08:09:43 +000082
hassoffe543a2005-09-25 12:04:25 +000083 lower->parent = upparent = upper->parent;
jardineb5d44e2003-12-23 08:09:43 +000084
hassoffe543a2005-09-25 12:04:25 +000085 /* don't need to check for root node here because root->parent is
86 the sentinel nil node, and root->parent->left points back to root */
jardineb5d44e2003-12-23 08:09:43 +000087
hassoffe543a2005-09-25 12:04:25 +000088 if (upper == upparent->left) {
89 upparent->left = lower;
90 } else {
91 assert (upper == upparent->right);
92 upparent->right = lower;
jardineb5d44e2003-12-23 08:09:43 +000093 }
94
hassoffe543a2005-09-25 12:04:25 +000095 lower->left = upper;
96 upper->parent = lower;
jardineb5d44e2003-12-23 08:09:43 +000097}
98
99/*
100 * This operation is the ``mirror'' image of rotate_left. It is
101 * the same procedure, but with left and right interchanged.
102 */
103
hassoffe543a2005-09-25 12:04:25 +0000104static void rotate_right(dnode_t *upper)
jardineb5d44e2003-12-23 08:09:43 +0000105{
hassoffe543a2005-09-25 12:04:25 +0000106 dnode_t *lower, *lowright, *upparent;
jardineb5d44e2003-12-23 08:09:43 +0000107
hassoffe543a2005-09-25 12:04:25 +0000108 lower = upper->left;
109 upper->left = lowright = lower->right;
110 lowright->parent = upper;
jardineb5d44e2003-12-23 08:09:43 +0000111
hassoffe543a2005-09-25 12:04:25 +0000112 lower->parent = upparent = upper->parent;
jardineb5d44e2003-12-23 08:09:43 +0000113
hassoffe543a2005-09-25 12:04:25 +0000114 if (upper == upparent->right) {
115 upparent->right = lower;
116 } else {
117 assert (upper == upparent->left);
118 upparent->left = lower;
jardineb5d44e2003-12-23 08:09:43 +0000119 }
120
hassoffe543a2005-09-25 12:04:25 +0000121 lower->right = upper;
122 upper->parent = lower;
jardineb5d44e2003-12-23 08:09:43 +0000123}
124
125/*
126 * Do a postorder traversal of the tree rooted at the specified
127 * node and free everything under it. Used by dict_free().
128 */
129
hassoffe543a2005-09-25 12:04:25 +0000130static void free_nodes(dict_t *dict, dnode_t *node, dnode_t *nil)
jardineb5d44e2003-12-23 08:09:43 +0000131{
hassoffe543a2005-09-25 12:04:25 +0000132 if (node == nil)
133 return;
134 free_nodes(dict, node->left, nil);
135 free_nodes(dict, node->right, nil);
136 dict->freenode(node, dict->context);
jardineb5d44e2003-12-23 08:09:43 +0000137}
138
139/*
140 * This procedure performs a verification that the given subtree is a binary
141 * search tree. It performs an inorder traversal of the tree using the
142 * dict_next() successor function, verifying that the key of each node is
143 * strictly lower than that of its successor, if duplicates are not allowed,
144 * or lower or equal if duplicates are allowed. This function is used for
145 * debugging purposes.
146 */
147
hassoffe543a2005-09-25 12:04:25 +0000148static int verify_bintree(dict_t *dict)
jardineb5d44e2003-12-23 08:09:43 +0000149{
hassoffe543a2005-09-25 12:04:25 +0000150 dnode_t *first, *next;
jardineb5d44e2003-12-23 08:09:43 +0000151
hassoffe543a2005-09-25 12:04:25 +0000152 first = dict_first(dict);
jardineb5d44e2003-12-23 08:09:43 +0000153
hassoffe543a2005-09-25 12:04:25 +0000154 if (dict->dupes) {
155 while (first && (next = dict_next(dict, first))) {
156 if (dict->compare(first->key, next->key) > 0)
157 return 0;
158 first = next;
159 }
160 } else {
161 while (first && (next = dict_next(dict, first))) {
162 if (dict->compare(first->key, next->key) >= 0)
163 return 0;
164 first = next;
jardineb5d44e2003-12-23 08:09:43 +0000165 }
166 }
hassoffe543a2005-09-25 12:04:25 +0000167 return 1;
jardineb5d44e2003-12-23 08:09:43 +0000168}
169
170
171/*
172 * This function recursively verifies that the given binary subtree satisfies
173 * three of the red black properties. It checks that every red node has only
174 * black children. It makes sure that each node is either red or black. And it
175 * checks that every path has the same count of black nodes from root to leaf.
176 * It returns the blackheight of the given subtree; this allows blackheights to
177 * be computed recursively and compared for left and right siblings for
178 * mismatches. It does not check for every nil node being black, because there
179 * is only one sentinel nil node. The return value of this function is the
180 * black height of the subtree rooted at the node ``root'', or zero if the
181 * subtree is not red-black.
182 */
183
hassoffe543a2005-09-25 12:04:25 +0000184static unsigned int verify_redblack(dnode_t *nil, dnode_t *root)
jardineb5d44e2003-12-23 08:09:43 +0000185{
hassoffe543a2005-09-25 12:04:25 +0000186 unsigned height_left, height_right;
jardineb5d44e2003-12-23 08:09:43 +0000187
hassoffe543a2005-09-25 12:04:25 +0000188 if (root != nil) {
189 height_left = verify_redblack(nil, root->left);
190 height_right = verify_redblack(nil, root->right);
191 if (height_left == 0 || height_right == 0)
jardineb5d44e2003-12-23 08:09:43 +0000192 return 0;
hassoffe543a2005-09-25 12:04:25 +0000193 if (height_left != height_right)
jardineb5d44e2003-12-23 08:09:43 +0000194 return 0;
hassoffe543a2005-09-25 12:04:25 +0000195 if (root->color == dnode_red) {
196 if (root->left->color != dnode_black)
197 return 0;
198 if (root->right->color != dnode_black)
199 return 0;
200 return height_left;
jardineb5d44e2003-12-23 08:09:43 +0000201 }
hassoffe543a2005-09-25 12:04:25 +0000202 if (root->color != dnode_black)
203 return 0;
204 return height_left + 1;
205 }
206 return 1;
jardineb5d44e2003-12-23 08:09:43 +0000207}
208
209/*
210 * Compute the actual count of nodes by traversing the tree and
211 * return it. This could be compared against the stored count to
212 * detect a mismatch.
213 */
214
hassoffe543a2005-09-25 12:04:25 +0000215static dictcount_t verify_node_count(dnode_t *nil, dnode_t *root)
jardineb5d44e2003-12-23 08:09:43 +0000216{
hassoffe543a2005-09-25 12:04:25 +0000217 if (root == nil)
218 return 0;
219 else
220 return 1 + verify_node_count(nil, root->left)
221 + verify_node_count(nil, root->right);
jardineb5d44e2003-12-23 08:09:43 +0000222}
223
224/*
225 * Verify that the tree contains the given node. This is done by
226 * traversing all of the nodes and comparing their pointers to the
227 * given pointer. Returns 1 if the node is found, otherwise
228 * returns zero. It is intended for debugging purposes.
229 */
230
hassoffe543a2005-09-25 12:04:25 +0000231static int verify_dict_has_node(dnode_t *nil, dnode_t *root, dnode_t *node)
jardineb5d44e2003-12-23 08:09:43 +0000232{
hassoffe543a2005-09-25 12:04:25 +0000233 if (root != nil) {
234 return root == node
235 || verify_dict_has_node(nil, root->left, node)
236 || verify_dict_has_node(nil, root->right, node);
jardineb5d44e2003-12-23 08:09:43 +0000237 }
hassoffe543a2005-09-25 12:04:25 +0000238 return 0;
jardineb5d44e2003-12-23 08:09:43 +0000239}
240
hassoffe543a2005-09-25 12:04:25 +0000241
jardineb5d44e2003-12-23 08:09:43 +0000242/*
243 * Dynamically allocate and initialize a dictionary object.
244 */
245
hassoffe543a2005-09-25 12:04:25 +0000246dict_t *dict_create(dictcount_t maxcount, dict_comp_t comp)
jardineb5d44e2003-12-23 08:09:43 +0000247{
hassoffe543a2005-09-25 12:04:25 +0000248 dict_t *new = malloc(sizeof *new);
jardineb5d44e2003-12-23 08:09:43 +0000249
hassoffe543a2005-09-25 12:04:25 +0000250 if (new) {
251 new->compare = comp;
252 new->allocnode = dnode_alloc;
253 new->freenode = dnode_free;
254 new->context = NULL;
255 new->nodecount = 0;
256 new->maxcount = maxcount;
257 new->nilnode.left = &new->nilnode;
258 new->nilnode.right = &new->nilnode;
259 new->nilnode.parent = &new->nilnode;
260 new->nilnode.color = dnode_black;
261 new->dupes = 0;
jardineb5d44e2003-12-23 08:09:43 +0000262 }
hassoffe543a2005-09-25 12:04:25 +0000263 return new;
jardineb5d44e2003-12-23 08:09:43 +0000264}
265
266/*
267 * Select a different set of node allocator routines.
268 */
269
hassoffe543a2005-09-25 12:04:25 +0000270void dict_set_allocator(dict_t *dict, dnode_alloc_t al,
271 dnode_free_t fr, void *context)
jardineb5d44e2003-12-23 08:09:43 +0000272{
hassoffe543a2005-09-25 12:04:25 +0000273 assert (dict_count(dict) == 0);
274 assert ((al == NULL && fr == NULL) || (al != NULL && fr != NULL));
jardineb5d44e2003-12-23 08:09:43 +0000275
hassoffe543a2005-09-25 12:04:25 +0000276 dict->allocnode = al ? al : dnode_alloc;
277 dict->freenode = fr ? fr : dnode_free;
278 dict->context = context;
jardineb5d44e2003-12-23 08:09:43 +0000279}
280
281/*
282 * Free a dynamically allocated dictionary object. Removing the nodes
283 * from the tree before deleting it is required.
284 */
285
hassoffe543a2005-09-25 12:04:25 +0000286void dict_destroy(dict_t *dict)
jardineb5d44e2003-12-23 08:09:43 +0000287{
hassoffe543a2005-09-25 12:04:25 +0000288 assert (dict_isempty(dict));
289 free(dict);
jardineb5d44e2003-12-23 08:09:43 +0000290}
291
292/*
293 * Free all the nodes in the dictionary by using the dictionary's
294 * installed free routine. The dictionary is emptied.
295 */
296
hassoffe543a2005-09-25 12:04:25 +0000297void dict_free_nodes(dict_t *dict)
jardineb5d44e2003-12-23 08:09:43 +0000298{
hassoffe543a2005-09-25 12:04:25 +0000299 dnode_t *nil = dict_nil(dict), *root = dict_root(dict);
300 free_nodes(dict, root, nil);
301 dict->nodecount = 0;
302 dict->nilnode.left = &dict->nilnode;
303 dict->nilnode.right = &dict->nilnode;
jardineb5d44e2003-12-23 08:09:43 +0000304}
305
306/*
307 * Obsolescent function, equivalent to dict_free_nodes
308 */
309
hassoffe543a2005-09-25 12:04:25 +0000310void dict_free(dict_t *dict)
jardineb5d44e2003-12-23 08:09:43 +0000311{
312#ifdef KAZLIB_OBSOLESCENT_DEBUG
hassoffe543a2005-09-25 12:04:25 +0000313 assert ("call to obsolescent function dict_free()" && 0);
jardineb5d44e2003-12-23 08:09:43 +0000314#endif
hassoffe543a2005-09-25 12:04:25 +0000315 dict_free_nodes(dict);
jardineb5d44e2003-12-23 08:09:43 +0000316}
317
318/*
319 * Initialize a user-supplied dictionary object.
320 */
321
hassoffe543a2005-09-25 12:04:25 +0000322dict_t *dict_init(dict_t *dict, dictcount_t maxcount, dict_comp_t comp)
jardineb5d44e2003-12-23 08:09:43 +0000323{
hassoffe543a2005-09-25 12:04:25 +0000324 dict->compare = comp;
325 dict->allocnode = dnode_alloc;
326 dict->freenode = dnode_free;
327 dict->context = NULL;
328 dict->nodecount = 0;
329 dict->maxcount = maxcount;
330 dict->nilnode.left = &dict->nilnode;
331 dict->nilnode.right = &dict->nilnode;
332 dict->nilnode.parent = &dict->nilnode;
333 dict->nilnode.color = dnode_black;
334 dict->dupes = 0;
335 return dict;
jardineb5d44e2003-12-23 08:09:43 +0000336}
337
338/*
339 * Initialize a dictionary in the likeness of another dictionary
340 */
341
hassoffe543a2005-09-25 12:04:25 +0000342void dict_init_like(dict_t *dict, const dict_t *template)
jardineb5d44e2003-12-23 08:09:43 +0000343{
hassoffe543a2005-09-25 12:04:25 +0000344 dict->compare = template->compare;
345 dict->allocnode = template->allocnode;
346 dict->freenode = template->freenode;
347 dict->context = template->context;
348 dict->nodecount = 0;
349 dict->maxcount = template->maxcount;
350 dict->nilnode.left = &dict->nilnode;
351 dict->nilnode.right = &dict->nilnode;
352 dict->nilnode.parent = &dict->nilnode;
353 dict->nilnode.color = dnode_black;
354 dict->dupes = template->dupes;
jardineb5d44e2003-12-23 08:09:43 +0000355
hassoffe543a2005-09-25 12:04:25 +0000356 assert (dict_similar(dict, template));
jardineb5d44e2003-12-23 08:09:43 +0000357}
358
359/*
360 * Remove all nodes from the dictionary (without freeing them in any way).
361 */
362
hassoffe543a2005-09-25 12:04:25 +0000363static void dict_clear(dict_t *dict)
jardineb5d44e2003-12-23 08:09:43 +0000364{
hassoffe543a2005-09-25 12:04:25 +0000365 dict->nodecount = 0;
366 dict->nilnode.left = &dict->nilnode;
367 dict->nilnode.right = &dict->nilnode;
368 dict->nilnode.parent = &dict->nilnode;
369 assert (dict->nilnode.color == dnode_black);
jardineb5d44e2003-12-23 08:09:43 +0000370}
371
hassoffe543a2005-09-25 12:04:25 +0000372
jardineb5d44e2003-12-23 08:09:43 +0000373/*
374 * Verify the integrity of the dictionary structure. This is provided for
375 * debugging purposes, and should be placed in assert statements. Just because
376 * this function succeeds doesn't mean that the tree is not corrupt. Certain
377 * corruptions in the tree may simply cause undefined behavior.
hassoffe543a2005-09-25 12:04:25 +0000378 */
jardineb5d44e2003-12-23 08:09:43 +0000379
hassoffe543a2005-09-25 12:04:25 +0000380int dict_verify(dict_t *dict)
jardineb5d44e2003-12-23 08:09:43 +0000381{
hassoffe543a2005-09-25 12:04:25 +0000382 dnode_t *nil = dict_nil(dict), *root = dict_root(dict);
jardineb5d44e2003-12-23 08:09:43 +0000383
hassoffe543a2005-09-25 12:04:25 +0000384 /* check that the sentinel node and root node are black */
385 if (root->color != dnode_black)
386 return 0;
387 if (nil->color != dnode_black)
388 return 0;
389 if (nil->right != nil)
390 return 0;
391 /* nil->left is the root node; check that its parent pointer is nil */
392 if (nil->left->parent != nil)
393 return 0;
394 /* perform a weak test that the tree is a binary search tree */
395 if (!verify_bintree(dict))
396 return 0;
397 /* verify that the tree is a red-black tree */
398 if (!verify_redblack(nil, root))
399 return 0;
400 if (verify_node_count(nil, root) != dict_count(dict))
401 return 0;
402 return 1;
jardineb5d44e2003-12-23 08:09:43 +0000403}
404
405/*
406 * Determine whether two dictionaries are similar: have the same comparison and
407 * allocator functions, and same status as to whether duplicates are allowed.
408 */
409
hassoffe543a2005-09-25 12:04:25 +0000410int dict_similar(const dict_t *left, const dict_t *right)
jardineb5d44e2003-12-23 08:09:43 +0000411{
hassoffe543a2005-09-25 12:04:25 +0000412 if (left->compare != right->compare)
413 return 0;
jardineb5d44e2003-12-23 08:09:43 +0000414
hassoffe543a2005-09-25 12:04:25 +0000415 if (left->allocnode != right->allocnode)
416 return 0;
jardineb5d44e2003-12-23 08:09:43 +0000417
hassoffe543a2005-09-25 12:04:25 +0000418 if (left->freenode != right->freenode)
419 return 0;
jardineb5d44e2003-12-23 08:09:43 +0000420
hassoffe543a2005-09-25 12:04:25 +0000421 if (left->context != right->context)
422 return 0;
jardineb5d44e2003-12-23 08:09:43 +0000423
hassoffe543a2005-09-25 12:04:25 +0000424 if (left->dupes != right->dupes)
425 return 0;
jardineb5d44e2003-12-23 08:09:43 +0000426
hassoffe543a2005-09-25 12:04:25 +0000427 return 1;
jardineb5d44e2003-12-23 08:09:43 +0000428}
429
430/*
431 * Locate a node in the dictionary having the given key.
432 * If the node is not found, a null a pointer is returned (rather than
433 * a pointer that dictionary's nil sentinel node), otherwise a pointer to the
434 * located node is returned.
435 */
436
hassoffe543a2005-09-25 12:04:25 +0000437dnode_t *dict_lookup(dict_t *dict, const void *key)
jardineb5d44e2003-12-23 08:09:43 +0000438{
hassoffe543a2005-09-25 12:04:25 +0000439 dnode_t *root = dict_root(dict);
440 dnode_t *nil = dict_nil(dict);
441 dnode_t *saved;
442 int result;
jardineb5d44e2003-12-23 08:09:43 +0000443
hassoffe543a2005-09-25 12:04:25 +0000444 /* simple binary search adapted for trees that contain duplicate keys */
jardineb5d44e2003-12-23 08:09:43 +0000445
hassoffe543a2005-09-25 12:04:25 +0000446 while (root != nil) {
447 result = dict->compare(key, root->key);
448 if (result < 0)
449 root = root->left;
450 else if (result > 0)
451 root = root->right;
452 else {
453 if (!dict->dupes) { /* no duplicates, return match */
454 return root;
455 } else { /* could be dupes, find leftmost one */
456 do {
457 saved = root;
458 root = root->left;
459 while (root != nil && dict->compare(key, root->key))
460 root = root->right;
461 } while (root != nil);
462 return saved;
jardineb5d44e2003-12-23 08:09:43 +0000463 }
464 }
465 }
466
hassoffe543a2005-09-25 12:04:25 +0000467 return NULL;
jardineb5d44e2003-12-23 08:09:43 +0000468}
469
470/*
471 * Look for the node corresponding to the lowest key that is equal to or
472 * greater than the given key. If there is no such node, return null.
473 */
474
hassoffe543a2005-09-25 12:04:25 +0000475dnode_t *dict_lower_bound(dict_t *dict, const void *key)
jardineb5d44e2003-12-23 08:09:43 +0000476{
hassoffe543a2005-09-25 12:04:25 +0000477 dnode_t *root = dict_root(dict);
478 dnode_t *nil = dict_nil(dict);
479 dnode_t *tentative = 0;
jardineb5d44e2003-12-23 08:09:43 +0000480
hassoffe543a2005-09-25 12:04:25 +0000481 while (root != nil) {
482 int result = dict->compare(key, root->key);
jardineb5d44e2003-12-23 08:09:43 +0000483
hassoffe543a2005-09-25 12:04:25 +0000484 if (result > 0) {
485 root = root->right;
486 } else if (result < 0) {
487 tentative = root;
488 root = root->left;
489 } else {
490 if (!dict->dupes) {
491 return root;
492 } else {
493 tentative = root;
494 root = root->left;
jardineb5d44e2003-12-23 08:09:43 +0000495 }
hassoffe543a2005-09-25 12:04:25 +0000496 }
jardineb5d44e2003-12-23 08:09:43 +0000497 }
hassoffe543a2005-09-25 12:04:25 +0000498
499 return tentative;
jardineb5d44e2003-12-23 08:09:43 +0000500}
501
502/*
503 * Look for the node corresponding to the greatest key that is equal to or
504 * lower than the given key. If there is no such node, return null.
505 */
506
hassoffe543a2005-09-25 12:04:25 +0000507dnode_t *dict_upper_bound(dict_t *dict, const void *key)
jardineb5d44e2003-12-23 08:09:43 +0000508{
hassoffe543a2005-09-25 12:04:25 +0000509 dnode_t *root = dict_root(dict);
510 dnode_t *nil = dict_nil(dict);
511 dnode_t *tentative = 0;
jardineb5d44e2003-12-23 08:09:43 +0000512
hassoffe543a2005-09-25 12:04:25 +0000513 while (root != nil) {
514 int result = dict->compare(key, root->key);
jardineb5d44e2003-12-23 08:09:43 +0000515
hassoffe543a2005-09-25 12:04:25 +0000516 if (result < 0) {
517 root = root->left;
518 } else if (result > 0) {
519 tentative = root;
520 root = root->right;
521 } else {
522 if (!dict->dupes) {
523 return root;
524 } else {
525 tentative = root;
526 root = root->right;
jardineb5d44e2003-12-23 08:09:43 +0000527 }
hassoffe543a2005-09-25 12:04:25 +0000528 }
jardineb5d44e2003-12-23 08:09:43 +0000529 }
hassoffe543a2005-09-25 12:04:25 +0000530
531 return tentative;
jardineb5d44e2003-12-23 08:09:43 +0000532}
533
534/*
535 * Insert a node into the dictionary. The node should have been
536 * initialized with a data field. All other fields are ignored.
537 * The behavior is undefined if the user attempts to insert into
538 * a dictionary that is already full (for which the dict_isfull()
539 * function returns true).
540 */
541
hassoffe543a2005-09-25 12:04:25 +0000542void dict_insert(dict_t *dict, dnode_t *node, const void *key)
jardineb5d44e2003-12-23 08:09:43 +0000543{
hassoffe543a2005-09-25 12:04:25 +0000544 dnode_t *where = dict_root(dict), *nil = dict_nil(dict);
545 dnode_t *parent = nil, *uncle, *grandpa;
546 int result = -1;
jardineb5d44e2003-12-23 08:09:43 +0000547
hassoffe543a2005-09-25 12:04:25 +0000548 node->key = key;
jardineb5d44e2003-12-23 08:09:43 +0000549
hassoffe543a2005-09-25 12:04:25 +0000550 assert (!dict_isfull(dict));
551 assert (!dict_contains(dict, node));
552 assert (!dnode_is_in_a_dict(node));
jardineb5d44e2003-12-23 08:09:43 +0000553
hassoffe543a2005-09-25 12:04:25 +0000554 /* basic binary tree insert */
jardineb5d44e2003-12-23 08:09:43 +0000555
hassoffe543a2005-09-25 12:04:25 +0000556 while (where != nil) {
557 parent = where;
558 result = dict->compare(key, where->key);
559 /* trap attempts at duplicate key insertion unless it's explicitly allowed */
560 assert (dict->dupes || result != 0);
561 if (result < 0)
562 where = where->left;
563 else
564 where = where->right;
jardineb5d44e2003-12-23 08:09:43 +0000565 }
566
hassoffe543a2005-09-25 12:04:25 +0000567 assert (where == nil);
jardineb5d44e2003-12-23 08:09:43 +0000568
hassoffe543a2005-09-25 12:04:25 +0000569 if (result < 0)
570 parent->left = node;
571 else
572 parent->right = node;
jardineb5d44e2003-12-23 08:09:43 +0000573
hassoffe543a2005-09-25 12:04:25 +0000574 node->parent = parent;
575 node->left = nil;
576 node->right = nil;
jardineb5d44e2003-12-23 08:09:43 +0000577
hassoffe543a2005-09-25 12:04:25 +0000578 dict->nodecount++;
jardineb5d44e2003-12-23 08:09:43 +0000579
hassoffe543a2005-09-25 12:04:25 +0000580 /* red black adjustments */
jardineb5d44e2003-12-23 08:09:43 +0000581
hassoffe543a2005-09-25 12:04:25 +0000582 node->color = dnode_red;
jardineb5d44e2003-12-23 08:09:43 +0000583
hassoffe543a2005-09-25 12:04:25 +0000584 while (parent->color == dnode_red) {
585 grandpa = parent->parent;
586 if (parent == grandpa->left) {
587 uncle = grandpa->right;
588 if (uncle->color == dnode_red) { /* red parent, red uncle */
589 parent->color = dnode_black;
590 uncle->color = dnode_black;
591 grandpa->color = dnode_red;
592 node = grandpa;
593 parent = grandpa->parent;
594 } else { /* red parent, black uncle */
595 if (node == parent->right) {
596 rotate_left(parent);
597 parent = node;
598 assert (grandpa == parent->parent);
599 /* rotation between parent and child preserves grandpa */
jardineb5d44e2003-12-23 08:09:43 +0000600 }
hassoffe543a2005-09-25 12:04:25 +0000601 parent->color = dnode_black;
602 grandpa->color = dnode_red;
603 rotate_right(grandpa);
604 break;
hassof390d2c2004-09-10 20:48:21 +0000605 }
hassoffe543a2005-09-25 12:04:25 +0000606 } else { /* symmetric cases: parent == parent->parent->right */
607 uncle = grandpa->left;
608 if (uncle->color == dnode_red) {
609 parent->color = dnode_black;
610 uncle->color = dnode_black;
611 grandpa->color = dnode_red;
612 node = grandpa;
613 parent = grandpa->parent;
614 } else {
615 if (node == parent->left) {
616 rotate_right(parent);
617 parent = node;
618 assert (grandpa == parent->parent);
hassof390d2c2004-09-10 20:48:21 +0000619 }
hassoffe543a2005-09-25 12:04:25 +0000620 parent->color = dnode_black;
621 grandpa->color = dnode_red;
622 rotate_left(grandpa);
623 break;
jardineb5d44e2003-12-23 08:09:43 +0000624 }
625 }
626 }
627
hassoffe543a2005-09-25 12:04:25 +0000628 dict_root(dict)->color = dnode_black;
jardineb5d44e2003-12-23 08:09:43 +0000629
hassoffe543a2005-09-25 12:04:25 +0000630 assert (dict_verify(dict));
jardineb5d44e2003-12-23 08:09:43 +0000631}
632
633/*
634 * Delete the given node from the dictionary. If the given node does not belong
635 * to the given dictionary, undefined behavior results. A pointer to the
636 * deleted node is returned.
637 */
638
hassoffe543a2005-09-25 12:04:25 +0000639dnode_t *dict_delete(dict_t *dict, dnode_t *delete)
jardineb5d44e2003-12-23 08:09:43 +0000640{
hassoffe543a2005-09-25 12:04:25 +0000641 dnode_t *nil = dict_nil(dict), *child, *delparent = delete->parent;
jardineb5d44e2003-12-23 08:09:43 +0000642
hassoffe543a2005-09-25 12:04:25 +0000643 /* basic deletion */
jardineb5d44e2003-12-23 08:09:43 +0000644
hassoffe543a2005-09-25 12:04:25 +0000645 assert (!dict_isempty(dict));
646 assert (dict_contains(dict, delete));
jardineb5d44e2003-12-23 08:09:43 +0000647
hassoffe543a2005-09-25 12:04:25 +0000648 /*
649 * If the node being deleted has two children, then we replace it with its
650 * successor (i.e. the leftmost node in the right subtree.) By doing this,
651 * we avoid the traditional algorithm under which the successor's key and
652 * value *only* move to the deleted node and the successor is spliced out
653 * from the tree. We cannot use this approach because the user may hold
654 * pointers to the successor, or nodes may be inextricably tied to some
655 * other structures by way of embedding, etc. So we must splice out the
656 * node we are given, not some other node, and must not move contents from
657 * one node to another behind the user's back.
658 */
jardineb5d44e2003-12-23 08:09:43 +0000659
hassoffe543a2005-09-25 12:04:25 +0000660 if (delete->left != nil && delete->right != nil) {
661 dnode_t *next = dict_next(dict, delete);
662 dnode_t *nextparent = next->parent;
663 dnode_color_t nextcolor = next->color;
jardineb5d44e2003-12-23 08:09:43 +0000664
hassoffe543a2005-09-25 12:04:25 +0000665 assert (next != nil);
666 assert (next->parent != nil);
667 assert (next->left == nil);
jardineb5d44e2003-12-23 08:09:43 +0000668
hassoffe543a2005-09-25 12:04:25 +0000669 /*
670 * First, splice out the successor from the tree completely, by
671 * moving up its right child into its place.
672 */
jardineb5d44e2003-12-23 08:09:43 +0000673
hassoffe543a2005-09-25 12:04:25 +0000674 child = next->right;
675 child->parent = nextparent;
jardineb5d44e2003-12-23 08:09:43 +0000676
hassoffe543a2005-09-25 12:04:25 +0000677 if (nextparent->left == next) {
678 nextparent->left = child;
679 } else {
680 assert (nextparent->right == next);
681 nextparent->right = child;
jardineb5d44e2003-12-23 08:09:43 +0000682 }
683
hassoffe543a2005-09-25 12:04:25 +0000684 /*
685 * Now that the successor has been extricated from the tree, install it
686 * in place of the node that we want deleted.
687 */
jardineb5d44e2003-12-23 08:09:43 +0000688
hassoffe543a2005-09-25 12:04:25 +0000689 next->parent = delparent;
690 next->left = delete->left;
691 next->right = delete->right;
692 next->left->parent = next;
693 next->right->parent = next;
694 next->color = delete->color;
695 delete->color = nextcolor;
jardineb5d44e2003-12-23 08:09:43 +0000696
hassoffe543a2005-09-25 12:04:25 +0000697 if (delparent->left == delete) {
698 delparent->left = next;
699 } else {
700 assert (delparent->right == delete);
701 delparent->right = next;
jardineb5d44e2003-12-23 08:09:43 +0000702 }
703
hassoffe543a2005-09-25 12:04:25 +0000704 } else {
705 assert (delete != nil);
706 assert (delete->left == nil || delete->right == nil);
jardineb5d44e2003-12-23 08:09:43 +0000707
hassoffe543a2005-09-25 12:04:25 +0000708 child = (delete->left != nil) ? delete->left : delete->right;
jardineb5d44e2003-12-23 08:09:43 +0000709
hassoffe543a2005-09-25 12:04:25 +0000710 child->parent = delparent = delete->parent;
jardineb5d44e2003-12-23 08:09:43 +0000711
hassoffe543a2005-09-25 12:04:25 +0000712 if (delete == delparent->left) {
713 delparent->left = child;
714 } else {
715 assert (delete == delparent->right);
716 delparent->right = child;
jardineb5d44e2003-12-23 08:09:43 +0000717 }
718 }
719
hassoffe543a2005-09-25 12:04:25 +0000720 delete->parent = NULL;
721 delete->right = NULL;
722 delete->left = NULL;
jardineb5d44e2003-12-23 08:09:43 +0000723
hassoffe543a2005-09-25 12:04:25 +0000724 dict->nodecount--;
jardineb5d44e2003-12-23 08:09:43 +0000725
hassoffe543a2005-09-25 12:04:25 +0000726 assert (verify_bintree(dict));
jardineb5d44e2003-12-23 08:09:43 +0000727
hassoffe543a2005-09-25 12:04:25 +0000728 /* red-black adjustments */
jardineb5d44e2003-12-23 08:09:43 +0000729
hassoffe543a2005-09-25 12:04:25 +0000730 if (delete->color == dnode_black) {
731 dnode_t *parent, *sister;
jardineb5d44e2003-12-23 08:09:43 +0000732
hassoffe543a2005-09-25 12:04:25 +0000733 dict_root(dict)->color = dnode_red;
jardineb5d44e2003-12-23 08:09:43 +0000734
hassoffe543a2005-09-25 12:04:25 +0000735 while (child->color == dnode_black) {
736 parent = child->parent;
737 if (child == parent->left) {
738 sister = parent->right;
739 assert (sister != nil);
740 if (sister->color == dnode_red) {
741 sister->color = dnode_black;
742 parent->color = dnode_red;
743 rotate_left(parent);
744 sister = parent->right;
745 assert (sister != nil);
jardineb5d44e2003-12-23 08:09:43 +0000746 }
hassoffe543a2005-09-25 12:04:25 +0000747 if (sister->left->color == dnode_black
748 && sister->right->color == dnode_black) {
749 sister->color = dnode_red;
750 child = parent;
751 } else {
752 if (sister->right->color == dnode_black) {
753 assert (sister->left->color == dnode_red);
754 sister->left->color = dnode_black;
755 sister->color = dnode_red;
756 rotate_right(sister);
757 sister = parent->right;
758 assert (sister != nil);
jardineb5d44e2003-12-23 08:09:43 +0000759 }
hassoffe543a2005-09-25 12:04:25 +0000760 sister->color = parent->color;
761 sister->right->color = dnode_black;
762 parent->color = dnode_black;
763 rotate_left(parent);
764 break;
jardineb5d44e2003-12-23 08:09:43 +0000765 }
hassoffe543a2005-09-25 12:04:25 +0000766 } else { /* symmetric case: child == child->parent->right */
767 assert (child == parent->right);
768 sister = parent->left;
769 assert (sister != nil);
770 if (sister->color == dnode_red) {
771 sister->color = dnode_black;
772 parent->color = dnode_red;
773 rotate_right(parent);
774 sister = parent->left;
775 assert (sister != nil);
jardineb5d44e2003-12-23 08:09:43 +0000776 }
hassoffe543a2005-09-25 12:04:25 +0000777 if (sister->right->color == dnode_black
778 && sister->left->color == dnode_black) {
779 sister->color = dnode_red;
780 child = parent;
781 } else {
782 if (sister->left->color == dnode_black) {
783 assert (sister->right->color == dnode_red);
784 sister->right->color = dnode_black;
785 sister->color = dnode_red;
786 rotate_left(sister);
787 sister = parent->left;
788 assert (sister != nil);
jardineb5d44e2003-12-23 08:09:43 +0000789 }
hassoffe543a2005-09-25 12:04:25 +0000790 sister->color = parent->color;
791 sister->left->color = dnode_black;
792 parent->color = dnode_black;
793 rotate_right(parent);
794 break;
jardineb5d44e2003-12-23 08:09:43 +0000795 }
796 }
797 }
798
hassoffe543a2005-09-25 12:04:25 +0000799 child->color = dnode_black;
800 dict_root(dict)->color = dnode_black;
jardineb5d44e2003-12-23 08:09:43 +0000801 }
802
hassoffe543a2005-09-25 12:04:25 +0000803 assert (dict_verify(dict));
jardineb5d44e2003-12-23 08:09:43 +0000804
hassoffe543a2005-09-25 12:04:25 +0000805 return delete;
jardineb5d44e2003-12-23 08:09:43 +0000806}
807
808/*
809 * Allocate a node using the dictionary's allocator routine, give it
810 * the data item.
811 */
812
hassoffe543a2005-09-25 12:04:25 +0000813int dict_alloc_insert(dict_t *dict, const void *key, void *data)
jardineb5d44e2003-12-23 08:09:43 +0000814{
hassoffe543a2005-09-25 12:04:25 +0000815 dnode_t *node = dict->allocnode(dict->context);
jardineb5d44e2003-12-23 08:09:43 +0000816
hassoffe543a2005-09-25 12:04:25 +0000817 if (node) {
818 dnode_init(node, data);
819 dict_insert(dict, node, key);
820 return 1;
jardineb5d44e2003-12-23 08:09:43 +0000821 }
hassoffe543a2005-09-25 12:04:25 +0000822 return 0;
jardineb5d44e2003-12-23 08:09:43 +0000823}
824
hassoffe543a2005-09-25 12:04:25 +0000825void dict_delete_free(dict_t *dict, dnode_t *node)
jardineb5d44e2003-12-23 08:09:43 +0000826{
hassoffe543a2005-09-25 12:04:25 +0000827 dict_delete(dict, node);
828 dict->freenode(node, dict->context);
jardineb5d44e2003-12-23 08:09:43 +0000829}
830
831/*
832 * Return the node with the lowest (leftmost) key. If the dictionary is empty
833 * (that is, dict_isempty(dict) returns 1) a null pointer is returned.
834 */
835
hassoffe543a2005-09-25 12:04:25 +0000836dnode_t *dict_first(dict_t *dict)
jardineb5d44e2003-12-23 08:09:43 +0000837{
hassoffe543a2005-09-25 12:04:25 +0000838 dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *left;
jardineb5d44e2003-12-23 08:09:43 +0000839
hassoffe543a2005-09-25 12:04:25 +0000840 if (root != nil)
841 while ((left = root->left) != nil)
842 root = left;
jardineb5d44e2003-12-23 08:09:43 +0000843
hassoffe543a2005-09-25 12:04:25 +0000844 return (root == nil) ? NULL : root;
jardineb5d44e2003-12-23 08:09:43 +0000845}
846
847/*
848 * Return the node with the highest (rightmost) key. If the dictionary is empty
849 * (that is, dict_isempty(dict) returns 1) a null pointer is returned.
850 */
851
hassoffe543a2005-09-25 12:04:25 +0000852dnode_t *dict_last(dict_t *dict)
jardineb5d44e2003-12-23 08:09:43 +0000853{
hassoffe543a2005-09-25 12:04:25 +0000854 dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *right;
jardineb5d44e2003-12-23 08:09:43 +0000855
hassoffe543a2005-09-25 12:04:25 +0000856 if (root != nil)
857 while ((right = root->right) != nil)
858 root = right;
jardineb5d44e2003-12-23 08:09:43 +0000859
hassoffe543a2005-09-25 12:04:25 +0000860 return (root == nil) ? NULL : root;
jardineb5d44e2003-12-23 08:09:43 +0000861}
862
863/*
864 * Return the given node's successor node---the node which has the
865 * next key in the the left to right ordering. If the node has
866 * no successor, a null pointer is returned rather than a pointer to
867 * the nil node.
868 */
869
hassoffe543a2005-09-25 12:04:25 +0000870dnode_t *dict_next(dict_t *dict, dnode_t *curr)
jardineb5d44e2003-12-23 08:09:43 +0000871{
hassoffe543a2005-09-25 12:04:25 +0000872 dnode_t *nil = dict_nil(dict), *parent, *left;
jardineb5d44e2003-12-23 08:09:43 +0000873
hassoffe543a2005-09-25 12:04:25 +0000874 if (curr->right != nil) {
875 curr = curr->right;
876 while ((left = curr->left) != nil)
877 curr = left;
878 return curr;
jardineb5d44e2003-12-23 08:09:43 +0000879 }
880
hassoffe543a2005-09-25 12:04:25 +0000881 parent = curr->parent;
jardineb5d44e2003-12-23 08:09:43 +0000882
hassoffe543a2005-09-25 12:04:25 +0000883 while (parent != nil && curr == parent->right) {
884 curr = parent;
885 parent = curr->parent;
jardineb5d44e2003-12-23 08:09:43 +0000886 }
887
hassoffe543a2005-09-25 12:04:25 +0000888 return (parent == nil) ? NULL : parent;
jardineb5d44e2003-12-23 08:09:43 +0000889}
890
891/*
892 * Return the given node's predecessor, in the key order.
893 * The nil sentinel node is returned if there is no predecessor.
894 */
895
hassoffe543a2005-09-25 12:04:25 +0000896dnode_t *dict_prev(dict_t *dict, dnode_t *curr)
jardineb5d44e2003-12-23 08:09:43 +0000897{
hassoffe543a2005-09-25 12:04:25 +0000898 dnode_t *nil = dict_nil(dict), *parent, *right;
jardineb5d44e2003-12-23 08:09:43 +0000899
hassoffe543a2005-09-25 12:04:25 +0000900 if (curr->left != nil) {
901 curr = curr->left;
902 while ((right = curr->right) != nil)
903 curr = right;
904 return curr;
jardineb5d44e2003-12-23 08:09:43 +0000905 }
906
hassoffe543a2005-09-25 12:04:25 +0000907 parent = curr->parent;
jardineb5d44e2003-12-23 08:09:43 +0000908
hassoffe543a2005-09-25 12:04:25 +0000909 while (parent != nil && curr == parent->left) {
910 curr = parent;
911 parent = curr->parent;
jardineb5d44e2003-12-23 08:09:43 +0000912 }
913
hassoffe543a2005-09-25 12:04:25 +0000914 return (parent == nil) ? NULL : parent;
jardineb5d44e2003-12-23 08:09:43 +0000915}
916
hassoffe543a2005-09-25 12:04:25 +0000917void dict_allow_dupes(dict_t *dict)
jardineb5d44e2003-12-23 08:09:43 +0000918{
hassoffe543a2005-09-25 12:04:25 +0000919 dict->dupes = 1;
jardineb5d44e2003-12-23 08:09:43 +0000920}
921
922#undef dict_count
923#undef dict_isempty
924#undef dict_isfull
925#undef dnode_get
926#undef dnode_put
927#undef dnode_getkey
928
hassoffe543a2005-09-25 12:04:25 +0000929dictcount_t dict_count(dict_t *dict)
jardineb5d44e2003-12-23 08:09:43 +0000930{
hassoffe543a2005-09-25 12:04:25 +0000931 return dict->nodecount;
jardineb5d44e2003-12-23 08:09:43 +0000932}
933
hassoffe543a2005-09-25 12:04:25 +0000934int dict_isempty(dict_t *dict)
jardineb5d44e2003-12-23 08:09:43 +0000935{
hassoffe543a2005-09-25 12:04:25 +0000936 return dict->nodecount == 0;
jardineb5d44e2003-12-23 08:09:43 +0000937}
938
hassoffe543a2005-09-25 12:04:25 +0000939int dict_isfull(dict_t *dict)
jardineb5d44e2003-12-23 08:09:43 +0000940{
hassoffe543a2005-09-25 12:04:25 +0000941 return dict->nodecount == dict->maxcount;
jardineb5d44e2003-12-23 08:09:43 +0000942}
943
hassoffe543a2005-09-25 12:04:25 +0000944int dict_contains(dict_t *dict, dnode_t *node)
jardineb5d44e2003-12-23 08:09:43 +0000945{
hassoffe543a2005-09-25 12:04:25 +0000946 return verify_dict_has_node(dict_nil(dict), dict_root(dict), node);
jardineb5d44e2003-12-23 08:09:43 +0000947}
948
hassoffe543a2005-09-25 12:04:25 +0000949static dnode_t *dnode_alloc(void *context)
jardineb5d44e2003-12-23 08:09:43 +0000950{
hassoffe543a2005-09-25 12:04:25 +0000951 return malloc(sizeof *dnode_alloc(NULL));
jardineb5d44e2003-12-23 08:09:43 +0000952}
953
hassoffe543a2005-09-25 12:04:25 +0000954static void dnode_free(dnode_t *node, void *context)
jardineb5d44e2003-12-23 08:09:43 +0000955{
hassoffe543a2005-09-25 12:04:25 +0000956 free(node);
jardineb5d44e2003-12-23 08:09:43 +0000957}
958
hassoffe543a2005-09-25 12:04:25 +0000959dnode_t *dnode_create(void *data)
jardineb5d44e2003-12-23 08:09:43 +0000960{
hassoffe543a2005-09-25 12:04:25 +0000961 dnode_t *new = malloc(sizeof *new);
962 if (new) {
963 new->data = data;
964 new->parent = NULL;
965 new->left = NULL;
966 new->right = NULL;
jardineb5d44e2003-12-23 08:09:43 +0000967 }
hassoffe543a2005-09-25 12:04:25 +0000968 return new;
jardineb5d44e2003-12-23 08:09:43 +0000969}
970
hassoffe543a2005-09-25 12:04:25 +0000971dnode_t *dnode_init(dnode_t *dnode, void *data)
jardineb5d44e2003-12-23 08:09:43 +0000972{
hassoffe543a2005-09-25 12:04:25 +0000973 dnode->data = data;
974 dnode->parent = NULL;
975 dnode->left = NULL;
976 dnode->right = NULL;
977 return dnode;
jardineb5d44e2003-12-23 08:09:43 +0000978}
979
hassoffe543a2005-09-25 12:04:25 +0000980void dnode_destroy(dnode_t *dnode)
jardineb5d44e2003-12-23 08:09:43 +0000981{
hassoffe543a2005-09-25 12:04:25 +0000982 assert (!dnode_is_in_a_dict(dnode));
983 free(dnode);
jardineb5d44e2003-12-23 08:09:43 +0000984}
985
hassoffe543a2005-09-25 12:04:25 +0000986void *dnode_get(dnode_t *dnode)
jardineb5d44e2003-12-23 08:09:43 +0000987{
hassoffe543a2005-09-25 12:04:25 +0000988 return dnode->data;
jardineb5d44e2003-12-23 08:09:43 +0000989}
990
hassoffe543a2005-09-25 12:04:25 +0000991const void *dnode_getkey(dnode_t *dnode)
jardineb5d44e2003-12-23 08:09:43 +0000992{
hassoffe543a2005-09-25 12:04:25 +0000993 return dnode->key;
jardineb5d44e2003-12-23 08:09:43 +0000994}
995
hassoffe543a2005-09-25 12:04:25 +0000996void dnode_put(dnode_t *dnode, void *data)
jardineb5d44e2003-12-23 08:09:43 +0000997{
hassoffe543a2005-09-25 12:04:25 +0000998 dnode->data = data;
jardineb5d44e2003-12-23 08:09:43 +0000999}
1000
hassoffe543a2005-09-25 12:04:25 +00001001int dnode_is_in_a_dict(dnode_t *dnode)
jardineb5d44e2003-12-23 08:09:43 +00001002{
hassoffe543a2005-09-25 12:04:25 +00001003 return (dnode->parent && dnode->left && dnode->right);
jardineb5d44e2003-12-23 08:09:43 +00001004}
1005
hassoffe543a2005-09-25 12:04:25 +00001006void dict_process(dict_t *dict, void *context, dnode_process_t function)
jardineb5d44e2003-12-23 08:09:43 +00001007{
hassoffe543a2005-09-25 12:04:25 +00001008 dnode_t *node = dict_first(dict), *next;
jardineb5d44e2003-12-23 08:09:43 +00001009
hassoffe543a2005-09-25 12:04:25 +00001010 while (node != NULL) {
1011 /* check for callback function deleting */
1012 /* the next node from under us */
1013 assert (dict_contains(dict, node));
1014 next = dict_next(dict, node);
1015 function(dict, node, context);
1016 node = next;
jardineb5d44e2003-12-23 08:09:43 +00001017 }
1018}
1019
hassoffe543a2005-09-25 12:04:25 +00001020static void load_begin_internal(dict_load_t *load, dict_t *dict)
jardineb5d44e2003-12-23 08:09:43 +00001021{
hassoffe543a2005-09-25 12:04:25 +00001022 load->dictptr = dict;
1023 load->nilnode.left = &load->nilnode;
1024 load->nilnode.right = &load->nilnode;
jardineb5d44e2003-12-23 08:09:43 +00001025}
1026
hassoffe543a2005-09-25 12:04:25 +00001027void dict_load_begin(dict_load_t *load, dict_t *dict)
jardineb5d44e2003-12-23 08:09:43 +00001028{
hassoffe543a2005-09-25 12:04:25 +00001029 assert (dict_isempty(dict));
1030 load_begin_internal(load, dict);
jardineb5d44e2003-12-23 08:09:43 +00001031}
1032
hassoffe543a2005-09-25 12:04:25 +00001033void dict_load_next(dict_load_t *load, dnode_t *newnode, const void *key)
jardineb5d44e2003-12-23 08:09:43 +00001034{
hassoffe543a2005-09-25 12:04:25 +00001035 dict_t *dict = load->dictptr;
1036 dnode_t *nil = &load->nilnode;
1037
1038 assert (!dnode_is_in_a_dict(newnode));
1039 assert (dict->nodecount < dict->maxcount);
jardineb5d44e2003-12-23 08:09:43 +00001040
hassoffe543a2005-09-25 12:04:25 +00001041 #ifndef NDEBUG
1042 if (dict->nodecount > 0) {
1043 if (dict->dupes)
1044 assert (dict->compare(nil->left->key, key) <= 0);
1045 else
1046 assert (dict->compare(nil->left->key, key) < 0);
jardineb5d44e2003-12-23 08:09:43 +00001047 }
hassoffe543a2005-09-25 12:04:25 +00001048 #endif
jardineb5d44e2003-12-23 08:09:43 +00001049
hassoffe543a2005-09-25 12:04:25 +00001050 newnode->key = key;
1051 nil->right->left = newnode;
1052 nil->right = newnode;
1053 newnode->left = nil;
1054 dict->nodecount++;
jardineb5d44e2003-12-23 08:09:43 +00001055}
1056
hassoffe543a2005-09-25 12:04:25 +00001057void dict_load_end(dict_load_t *load)
jardineb5d44e2003-12-23 08:09:43 +00001058{
hassoffe543a2005-09-25 12:04:25 +00001059 dict_t *dict = load->dictptr;
1060 dnode_t *tree[DICT_DEPTH_MAX] = { 0 };
1061 dnode_t *curr, *dictnil = dict_nil(dict), *loadnil = &load->nilnode, *next;
1062 dnode_t *complete = 0;
1063 dictcount_t fullcount = DICTCOUNT_T_MAX, nodecount = dict->nodecount;
1064 dictcount_t botrowcount;
1065 unsigned baselevel = 0, level = 0, i;
jardineb5d44e2003-12-23 08:09:43 +00001066
hassoffe543a2005-09-25 12:04:25 +00001067 assert (dnode_red == 0 && dnode_black == 1);
jardineb5d44e2003-12-23 08:09:43 +00001068
hassoffe543a2005-09-25 12:04:25 +00001069 while (fullcount >= nodecount && fullcount)
1070 fullcount >>= 1;
jardineb5d44e2003-12-23 08:09:43 +00001071
hassoffe543a2005-09-25 12:04:25 +00001072 botrowcount = nodecount - fullcount;
jardineb5d44e2003-12-23 08:09:43 +00001073
hassoffe543a2005-09-25 12:04:25 +00001074 for (curr = loadnil->left; curr != loadnil; curr = next) {
1075 next = curr->left;
jardineb5d44e2003-12-23 08:09:43 +00001076
hassoffe543a2005-09-25 12:04:25 +00001077 if (complete == NULL && botrowcount-- == 0) {
1078 assert (baselevel == 0);
1079 assert (level == 0);
1080 baselevel = level = 1;
1081 complete = tree[0];
jardineb5d44e2003-12-23 08:09:43 +00001082
hassoffe543a2005-09-25 12:04:25 +00001083 if (complete != 0) {
1084 tree[0] = 0;
1085 complete->right = dictnil;
1086 while (tree[level] != 0) {
1087 tree[level]->right = complete;
1088 complete->parent = tree[level];
1089 complete = tree[level];
1090 tree[level++] = 0;
jardineb5d44e2003-12-23 08:09:43 +00001091 }
1092 }
1093 }
1094
hassoffe543a2005-09-25 12:04:25 +00001095 if (complete == NULL) {
1096 curr->left = dictnil;
1097 curr->right = dictnil;
1098 curr->color = level % 2;
1099 complete = curr;
jardineb5d44e2003-12-23 08:09:43 +00001100
hassoffe543a2005-09-25 12:04:25 +00001101 assert (level == baselevel);
1102 while (tree[level] != 0) {
1103 tree[level]->right = complete;
1104 complete->parent = tree[level];
1105 complete = tree[level];
1106 tree[level++] = 0;
jardineb5d44e2003-12-23 08:09:43 +00001107 }
hassoffe543a2005-09-25 12:04:25 +00001108 } else {
1109 curr->left = complete;
1110 curr->color = (level + 1) % 2;
1111 complete->parent = curr;
1112 tree[level] = curr;
1113 complete = 0;
1114 level = baselevel;
jardineb5d44e2003-12-23 08:09:43 +00001115 }
1116 }
1117
hassoffe543a2005-09-25 12:04:25 +00001118 if (complete == NULL)
1119 complete = dictnil;
jardineb5d44e2003-12-23 08:09:43 +00001120
hassoffe543a2005-09-25 12:04:25 +00001121 for (i = 0; i < DICT_DEPTH_MAX; i++) {
1122 if (tree[i] != 0) {
1123 tree[i]->right = complete;
1124 complete->parent = tree[i];
1125 complete = tree[i];
jardineb5d44e2003-12-23 08:09:43 +00001126 }
1127 }
1128
hassoffe543a2005-09-25 12:04:25 +00001129 dictnil->color = dnode_black;
1130 dictnil->right = dictnil;
1131 complete->parent = dictnil;
1132 complete->color = dnode_black;
1133 dict_root(dict) = complete;
jardineb5d44e2003-12-23 08:09:43 +00001134
hassoffe543a2005-09-25 12:04:25 +00001135 assert (dict_verify(dict));
jardineb5d44e2003-12-23 08:09:43 +00001136}
1137
hassoffe543a2005-09-25 12:04:25 +00001138void dict_merge(dict_t *dest, dict_t *source)
jardineb5d44e2003-12-23 08:09:43 +00001139{
hassoffe543a2005-09-25 12:04:25 +00001140 dict_load_t load;
1141 dnode_t *leftnode = dict_first(dest), *rightnode = dict_first(source);
jardineb5d44e2003-12-23 08:09:43 +00001142
hassoffe543a2005-09-25 12:04:25 +00001143 assert (dict_similar(dest, source));
jardineb5d44e2003-12-23 08:09:43 +00001144
hassoffe543a2005-09-25 12:04:25 +00001145 if (source == dest)
1146 return;
jardineb5d44e2003-12-23 08:09:43 +00001147
hassoffe543a2005-09-25 12:04:25 +00001148 dest->nodecount = 0;
1149 load_begin_internal(&load, dest);
jardineb5d44e2003-12-23 08:09:43 +00001150
hassoffe543a2005-09-25 12:04:25 +00001151 for (;;) {
1152 if (leftnode != NULL && rightnode != NULL) {
1153 if (dest->compare(leftnode->key, rightnode->key) < 0)
1154 goto copyleft;
1155 else
1156 goto copyright;
1157 } else if (leftnode != NULL) {
jardineb5d44e2003-12-23 08:09:43 +00001158 goto copyleft;
hassoffe543a2005-09-25 12:04:25 +00001159 } else if (rightnode != NULL) {
jardineb5d44e2003-12-23 08:09:43 +00001160 goto copyright;
hassoffe543a2005-09-25 12:04:25 +00001161 } else {
1162 assert (leftnode == NULL && rightnode == NULL);
1163 break;
jardineb5d44e2003-12-23 08:09:43 +00001164 }
1165
1166 copyleft:
hassoffe543a2005-09-25 12:04:25 +00001167 {
1168 dnode_t *next = dict_next(dest, leftnode);
1169 #ifndef NDEBUG
1170 leftnode->left = NULL; /* suppress assertion in dict_load_next */
1171 #endif
1172 dict_load_next(&load, leftnode, leftnode->key);
1173 leftnode = next;
1174 continue;
1175 }
1176
jardineb5d44e2003-12-23 08:09:43 +00001177 copyright:
hassoffe543a2005-09-25 12:04:25 +00001178 {
1179 dnode_t *next = dict_next(source, rightnode);
1180 #ifndef NDEBUG
1181 rightnode->left = NULL;
1182 #endif
1183 dict_load_next(&load, rightnode, rightnode->key);
1184 rightnode = next;
1185 continue;
1186 }
jardineb5d44e2003-12-23 08:09:43 +00001187 }
1188
hassoffe543a2005-09-25 12:04:25 +00001189 dict_clear(source);
1190 dict_load_end(&load);
jardineb5d44e2003-12-23 08:09:43 +00001191}
1192
1193#ifdef KAZLIB_TEST_MAIN
1194
1195#include <stdio.h>
1196#include <string.h>
1197#include <ctype.h>
1198#include <stdarg.h>
1199
1200typedef char input_t[256];
1201
hassoffe543a2005-09-25 12:04:25 +00001202static int tokenize(char *string, ...)
jardineb5d44e2003-12-23 08:09:43 +00001203{
hassoffe543a2005-09-25 12:04:25 +00001204 char **tokptr;
1205 va_list arglist;
1206 int tokcount = 0;
jardineb5d44e2003-12-23 08:09:43 +00001207
hassoffe543a2005-09-25 12:04:25 +00001208 va_start(arglist, string);
1209 tokptr = va_arg(arglist, char **);
1210 while (tokptr) {
1211 while (*string && isspace((unsigned char) *string))
1212 string++;
1213 if (!*string)
1214 break;
1215 *tokptr = string;
1216 while (*string && !isspace((unsigned char) *string))
1217 string++;
1218 tokptr = va_arg(arglist, char **);
1219 tokcount++;
1220 if (!*string)
1221 break;
1222 *string++ = 0;
jardineb5d44e2003-12-23 08:09:43 +00001223 }
hassoffe543a2005-09-25 12:04:25 +00001224 va_end(arglist);
jardineb5d44e2003-12-23 08:09:43 +00001225
hassoffe543a2005-09-25 12:04:25 +00001226 return tokcount;
jardineb5d44e2003-12-23 08:09:43 +00001227}
1228
hassoffe543a2005-09-25 12:04:25 +00001229static int comparef(const void *key1, const void *key2)
jardineb5d44e2003-12-23 08:09:43 +00001230{
hassoffe543a2005-09-25 12:04:25 +00001231 return strcmp(key1, key2);
jardineb5d44e2003-12-23 08:09:43 +00001232}
1233
hassoffe543a2005-09-25 12:04:25 +00001234static char *dupstring(char *str)
jardineb5d44e2003-12-23 08:09:43 +00001235{
hassoffe543a2005-09-25 12:04:25 +00001236 int sz = strlen(str) + 1;
1237 char *new = malloc(sz);
1238 if (new)
1239 memcpy(new, str, sz);
1240 return new;
jardineb5d44e2003-12-23 08:09:43 +00001241}
1242
hassoffe543a2005-09-25 12:04:25 +00001243static dnode_t *new_node(void *c)
jardineb5d44e2003-12-23 08:09:43 +00001244{
hassoffe543a2005-09-25 12:04:25 +00001245 static dnode_t few[5];
1246 static int count;
jardineb5d44e2003-12-23 08:09:43 +00001247
hassoffe543a2005-09-25 12:04:25 +00001248 if (count < 5)
1249 return few + count++;
jardineb5d44e2003-12-23 08:09:43 +00001250
hassoffe543a2005-09-25 12:04:25 +00001251 return NULL;
jardineb5d44e2003-12-23 08:09:43 +00001252}
1253
hassoffe543a2005-09-25 12:04:25 +00001254static void del_node(dnode_t *n, void *c)
jardineb5d44e2003-12-23 08:09:43 +00001255{
1256}
1257
1258static int prompt = 0;
1259
hassoffe543a2005-09-25 12:04:25 +00001260static void construct(dict_t *d)
jardineb5d44e2003-12-23 08:09:43 +00001261{
hassoffe543a2005-09-25 12:04:25 +00001262 input_t in;
1263 int done = 0;
1264 dict_load_t dl;
1265 dnode_t *dn;
1266 char *tok1, *tok2, *val;
1267 const char *key;
1268 char *help =
1269 "p turn prompt on\n"
1270 "q finish construction\n"
1271 "a <key> <val> add new entry\n";
jardineb5d44e2003-12-23 08:09:43 +00001272
hassoffe543a2005-09-25 12:04:25 +00001273 if (!dict_isempty(d))
1274 puts("warning: dictionary not empty!");
jardineb5d44e2003-12-23 08:09:43 +00001275
hassoffe543a2005-09-25 12:04:25 +00001276 dict_load_begin(&dl, d);
jardineb5d44e2003-12-23 08:09:43 +00001277
hassoffe543a2005-09-25 12:04:25 +00001278 while (!done) {
1279 if (prompt)
1280 putchar('>');
1281 fflush(stdout);
jardineb5d44e2003-12-23 08:09:43 +00001282
hassoffe543a2005-09-25 12:04:25 +00001283 if (!fgets(in, sizeof(input_t), stdin))
1284 break;
jardineb5d44e2003-12-23 08:09:43 +00001285
hassoffe543a2005-09-25 12:04:25 +00001286 switch (in[0]) {
1287 case '?':
1288 puts(help);
1289 break;
1290 case 'p':
1291 prompt = 1;
1292 break;
1293 case 'q':
1294 done = 1;
1295 break;
1296 case 'a':
1297 if (tokenize(in+1, &tok1, &tok2, (char **) 0) != 2) {
1298 puts("what?");
1299 break;
1300 }
1301 key = dupstring(tok1);
1302 val = dupstring(tok2);
1303 dn = dnode_create(val);
jardineb5d44e2003-12-23 08:09:43 +00001304
hassoffe543a2005-09-25 12:04:25 +00001305 if (!key || !val || !dn) {
1306 puts("out of memory");
1307 free((void *) key);
1308 free(val);
1309 if (dn)
1310 dnode_destroy(dn);
1311 }
jardineb5d44e2003-12-23 08:09:43 +00001312
hassoffe543a2005-09-25 12:04:25 +00001313 dict_load_next(&dl, dn, key);
1314 break;
1315 default:
1316 putchar('?');
1317 putchar('\n');
1318 break;
jardineb5d44e2003-12-23 08:09:43 +00001319 }
1320 }
1321
hassoffe543a2005-09-25 12:04:25 +00001322 dict_load_end(&dl);
jardineb5d44e2003-12-23 08:09:43 +00001323}
1324
hassoffe543a2005-09-25 12:04:25 +00001325int main(void)
jardineb5d44e2003-12-23 08:09:43 +00001326{
hassoffe543a2005-09-25 12:04:25 +00001327 input_t in;
1328 dict_t darray[10];
1329 dict_t *d = &darray[0];
1330 dnode_t *dn;
1331 int i;
1332 char *tok1, *tok2, *val;
1333 const char *key;
jardineb5d44e2003-12-23 08:09:43 +00001334
hassoffe543a2005-09-25 12:04:25 +00001335 char *help =
1336 "a <key> <val> add value to dictionary\n"
1337 "d <key> delete value from dictionary\n"
1338 "l <key> lookup value in dictionary\n"
1339 "( <key> lookup lower bound\n"
1340 ") <key> lookup upper bound\n"
1341 "# <num> switch to alternate dictionary (0-9)\n"
1342 "j <num> <num> merge two dictionaries\n"
1343 "f free the whole dictionary\n"
1344 "k allow duplicate keys\n"
1345 "c show number of entries\n"
1346 "t dump whole dictionary in sort order\n"
1347 "m make dictionary out of sorted items\n"
1348 "p turn prompt on\n"
1349 "s switch to non-functioning allocator\n"
1350 "q quit";
jardineb5d44e2003-12-23 08:09:43 +00001351
hassoffe543a2005-09-25 12:04:25 +00001352 for (i = 0; i < sizeof darray / sizeof *darray; i++)
1353 dict_init(&darray[i], DICTCOUNT_T_MAX, comparef);
jardineb5d44e2003-12-23 08:09:43 +00001354
hassoffe543a2005-09-25 12:04:25 +00001355 for (;;) {
1356 if (prompt)
1357 putchar('>');
1358 fflush(stdout);
jardineb5d44e2003-12-23 08:09:43 +00001359
hassoffe543a2005-09-25 12:04:25 +00001360 if (!fgets(in, sizeof(input_t), stdin))
1361 break;
jardineb5d44e2003-12-23 08:09:43 +00001362
hassoffe543a2005-09-25 12:04:25 +00001363 switch(in[0]) {
1364 case '?':
1365 puts(help);
1366 break;
1367 case 'a':
1368 if (tokenize(in+1, &tok1, &tok2, (char **) 0) != 2) {
1369 puts("what?");
1370 break;
1371 }
1372 key = dupstring(tok1);
1373 val = dupstring(tok2);
jardineb5d44e2003-12-23 08:09:43 +00001374
hassoffe543a2005-09-25 12:04:25 +00001375 if (!key || !val) {
1376 puts("out of memory");
1377 free((void *) key);
1378 free(val);
1379 }
jardineb5d44e2003-12-23 08:09:43 +00001380
hassoffe543a2005-09-25 12:04:25 +00001381 if (!dict_alloc_insert(d, key, val)) {
1382 puts("dict_alloc_insert failed");
1383 free((void *) key);
1384 free(val);
1385 break;
1386 }
1387 break;
1388 case 'd':
1389 if (tokenize(in+1, &tok1, (char **) 0) != 1) {
1390 puts("what?");
1391 break;
1392 }
1393 dn = dict_lookup(d, tok1);
1394 if (!dn) {
1395 puts("dict_lookup failed");
1396 break;
1397 }
1398 val = dnode_get(dn);
1399 key = dnode_getkey(dn);
1400 dict_delete_free(d, dn);
jardineb5d44e2003-12-23 08:09:43 +00001401
hassoffe543a2005-09-25 12:04:25 +00001402 free(val);
1403 free((void *) key);
1404 break;
1405 case 'f':
1406 dict_free(d);
1407 break;
jardineb5d44e2003-12-23 08:09:43 +00001408 case 'l':
1409 case '(':
1410 case ')':
hassoffe543a2005-09-25 12:04:25 +00001411 if (tokenize(in+1, &tok1, (char **) 0) != 1) {
1412 puts("what?");
1413 break;
jardineb5d44e2003-12-23 08:09:43 +00001414 }
hassoffe543a2005-09-25 12:04:25 +00001415 dn = 0;
1416 switch (in[0]) {
1417 case 'l':
1418 dn = dict_lookup(d, tok1);
1419 break;
1420 case '(':
1421 dn = dict_lower_bound(d, tok1);
1422 break;
1423 case ')':
1424 dn = dict_upper_bound(d, tok1);
1425 break;
jardineb5d44e2003-12-23 08:09:43 +00001426 }
hassoffe543a2005-09-25 12:04:25 +00001427 if (!dn) {
1428 puts("lookup failed");
1429 break;
1430 }
1431 val = dnode_get(dn);
1432 puts(val);
1433 break;
1434 case 'm':
1435 construct(d);
1436 break;
1437 case 'k':
1438 dict_allow_dupes(d);
1439 break;
1440 case 'c':
1441 printf("%lu\n", (unsigned long) dict_count(d));
1442 break;
1443 case 't':
1444 for (dn = dict_first(d); dn; dn = dict_next(d, dn)) {
1445 printf("%s\t%s\n", (char *) dnode_getkey(dn),
1446 (char *) dnode_get(dn));
1447 }
1448 break;
1449 case 'q':
1450 exit(0);
1451 break;
1452 case '\0':
1453 break;
1454 case 'p':
1455 prompt = 1;
1456 break;
1457 case 's':
1458 dict_set_allocator(d, new_node, del_node, NULL);
1459 break;
1460 case '#':
1461 if (tokenize(in+1, &tok1, (char **) 0) != 1) {
1462 puts("what?");
1463 break;
1464 } else {
1465 int dictnum = atoi(tok1);
1466 if (dictnum < 0 || dictnum > 9) {
1467 puts("invalid number");
1468 break;
1469 }
1470 d = &darray[dictnum];
1471 }
1472 break;
1473 case 'j':
1474 if (tokenize(in+1, &tok1, &tok2, (char **) 0) != 2) {
1475 puts("what?");
1476 break;
1477 } else {
1478 int dict1 = atoi(tok1), dict2 = atoi(tok2);
1479 if (dict1 < 0 || dict1 > 9 || dict2 < 0 || dict2 > 9) {
1480 puts("invalid number");
1481 break;
1482 }
1483 dict_merge(&darray[dict1], &darray[dict2]);
1484 }
1485 break;
1486 default:
1487 putchar('?');
1488 putchar('\n');
1489 break;
jardineb5d44e2003-12-23 08:09:43 +00001490 }
1491 }
1492
hassoffe543a2005-09-25 12:04:25 +00001493 return 0;
jardineb5d44e2003-12-23 08:09:43 +00001494}
1495
1496#endif