blob: a78b82ac4f17acc569cc8405c15046b153c3ea49 [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.
jardineb5d44e2003-12-23 08:09:43 +000016 */
17
18#include <stdlib.h>
19#include <stddef.h>
Paul Jakma238497f2007-08-07 18:49:18 +000020#include "zebra.h"
ajscee3df12004-11-24 17:14:49 +000021#include "zassert.h"
jardineb5d44e2003-12-23 08:09:43 +000022#define DICT_IMPLEMENTATION
23#include "dict.h"
24
25#ifdef KAZLIB_RCSID
hassoffe543a2005-09-25 12:04:25 +000026static const char rcsid[] = "Id: dict.c,v 1.40.2.7 2000/11/13 01:36:44 kaz";
jardineb5d44e2003-12-23 08:09:43 +000027#endif
28
29/*
30 * These macros provide short convenient names for structure members,
31 * which are embellished with dict_ prefixes so that they are
32 * properly confined to the documented namespace. It's legal for a
33 * program which uses dict to define, for instance, a macro called ``parent''.
34 * Such a macro would interfere with the dnode_t struct definition.
35 * In general, highly portable and reusable C modules which expose their
36 * structures need to confine structure member names to well-defined spaces.
37 * The resulting identifiers aren't necessarily convenient to use, nor
38 * readable, in the implementation, however!
39 */
40
41#define left dict_left
42#define right dict_right
43#define parent dict_parent
44#define color dict_color
45#define key dict_key
46#define data dict_data
47
48#define nilnode dict_nilnode
49#define nodecount dict_nodecount
50#define maxcount dict_maxcount
51#define compare dict_compare
52#define allocnode dict_allocnode
53#define freenode dict_freenode
54#define context dict_context
55#define dupes dict_dupes
56
57#define dictptr dict_dictptr
58
59#define dict_root(D) ((D)->nilnode.left)
60#define dict_nil(D) (&(D)->nilnode)
61#define DICT_DEPTH_MAX 64
62
hassoffe543a2005-09-25 12:04:25 +000063static dnode_t *dnode_alloc(void *context);
64static void dnode_free(dnode_t *node, void *context);
jardineb5d44e2003-12-23 08:09:43 +000065
66/*
67 * Perform a ``left rotation'' adjustment on the tree. The given node P and
68 * its right child C are rearranged so that the P instead becomes the left
69 * child of C. The left subtree of C is inherited as the new right subtree
70 * for P. The ordering of the keys within the tree is thus preserved.
71 */
72
hassoffe543a2005-09-25 12:04:25 +000073static void rotate_left(dnode_t *upper)
jardineb5d44e2003-12-23 08:09:43 +000074{
hassoffe543a2005-09-25 12:04:25 +000075 dnode_t *lower, *lowleft, *upparent;
jardineb5d44e2003-12-23 08:09:43 +000076
hassoffe543a2005-09-25 12:04:25 +000077 lower = upper->right;
78 upper->right = lowleft = lower->left;
79 lowleft->parent = upper;
jardineb5d44e2003-12-23 08:09:43 +000080
hassoffe543a2005-09-25 12:04:25 +000081 lower->parent = upparent = upper->parent;
jardineb5d44e2003-12-23 08:09:43 +000082
hassoffe543a2005-09-25 12:04:25 +000083 /* don't need to check for root node here because root->parent is
84 the sentinel nil node, and root->parent->left points back to root */
jardineb5d44e2003-12-23 08:09:43 +000085
hassoffe543a2005-09-25 12:04:25 +000086 if (upper == upparent->left) {
87 upparent->left = lower;
88 } else {
89 assert (upper == upparent->right);
90 upparent->right = lower;
jardineb5d44e2003-12-23 08:09:43 +000091 }
92
hassoffe543a2005-09-25 12:04:25 +000093 lower->left = upper;
94 upper->parent = lower;
jardineb5d44e2003-12-23 08:09:43 +000095}
96
97/*
98 * This operation is the ``mirror'' image of rotate_left. It is
99 * the same procedure, but with left and right interchanged.
100 */
101
hassoffe543a2005-09-25 12:04:25 +0000102static void rotate_right(dnode_t *upper)
jardineb5d44e2003-12-23 08:09:43 +0000103{
hassoffe543a2005-09-25 12:04:25 +0000104 dnode_t *lower, *lowright, *upparent;
jardineb5d44e2003-12-23 08:09:43 +0000105
hassoffe543a2005-09-25 12:04:25 +0000106 lower = upper->left;
107 upper->left = lowright = lower->right;
108 lowright->parent = upper;
jardineb5d44e2003-12-23 08:09:43 +0000109
hassoffe543a2005-09-25 12:04:25 +0000110 lower->parent = upparent = upper->parent;
jardineb5d44e2003-12-23 08:09:43 +0000111
hassoffe543a2005-09-25 12:04:25 +0000112 if (upper == upparent->right) {
113 upparent->right = lower;
114 } else {
115 assert (upper == upparent->left);
116 upparent->left = lower;
jardineb5d44e2003-12-23 08:09:43 +0000117 }
118
hassoffe543a2005-09-25 12:04:25 +0000119 lower->right = upper;
120 upper->parent = lower;
jardineb5d44e2003-12-23 08:09:43 +0000121}
122
123/*
124 * Do a postorder traversal of the tree rooted at the specified
125 * node and free everything under it. Used by dict_free().
126 */
127
hassoffe543a2005-09-25 12:04:25 +0000128static void free_nodes(dict_t *dict, dnode_t *node, dnode_t *nil)
jardineb5d44e2003-12-23 08:09:43 +0000129{
hassoffe543a2005-09-25 12:04:25 +0000130 if (node == nil)
131 return;
132 free_nodes(dict, node->left, nil);
133 free_nodes(dict, node->right, nil);
134 dict->freenode(node, dict->context);
jardineb5d44e2003-12-23 08:09:43 +0000135}
136
137/*
138 * This procedure performs a verification that the given subtree is a binary
139 * search tree. It performs an inorder traversal of the tree using the
140 * dict_next() successor function, verifying that the key of each node is
141 * strictly lower than that of its successor, if duplicates are not allowed,
142 * or lower or equal if duplicates are allowed. This function is used for
143 * debugging purposes.
144 */
145
hassoffe543a2005-09-25 12:04:25 +0000146static int verify_bintree(dict_t *dict)
jardineb5d44e2003-12-23 08:09:43 +0000147{
hassoffe543a2005-09-25 12:04:25 +0000148 dnode_t *first, *next;
jardineb5d44e2003-12-23 08:09:43 +0000149
hassoffe543a2005-09-25 12:04:25 +0000150 first = dict_first(dict);
jardineb5d44e2003-12-23 08:09:43 +0000151
hassoffe543a2005-09-25 12:04:25 +0000152 if (dict->dupes) {
153 while (first && (next = dict_next(dict, first))) {
154 if (dict->compare(first->key, next->key) > 0)
155 return 0;
156 first = next;
157 }
158 } else {
159 while (first && (next = dict_next(dict, first))) {
160 if (dict->compare(first->key, next->key) >= 0)
161 return 0;
162 first = next;
jardineb5d44e2003-12-23 08:09:43 +0000163 }
164 }
hassoffe543a2005-09-25 12:04:25 +0000165 return 1;
jardineb5d44e2003-12-23 08:09:43 +0000166}
167
168
169/*
170 * This function recursively verifies that the given binary subtree satisfies
171 * three of the red black properties. It checks that every red node has only
172 * black children. It makes sure that each node is either red or black. And it
173 * checks that every path has the same count of black nodes from root to leaf.
174 * It returns the blackheight of the given subtree; this allows blackheights to
175 * be computed recursively and compared for left and right siblings for
176 * mismatches. It does not check for every nil node being black, because there
177 * is only one sentinel nil node. The return value of this function is the
178 * black height of the subtree rooted at the node ``root'', or zero if the
179 * subtree is not red-black.
180 */
181
hassoffe543a2005-09-25 12:04:25 +0000182static unsigned int verify_redblack(dnode_t *nil, dnode_t *root)
jardineb5d44e2003-12-23 08:09:43 +0000183{
hassoffe543a2005-09-25 12:04:25 +0000184 unsigned height_left, height_right;
jardineb5d44e2003-12-23 08:09:43 +0000185
hassoffe543a2005-09-25 12:04:25 +0000186 if (root != nil) {
187 height_left = verify_redblack(nil, root->left);
188 height_right = verify_redblack(nil, root->right);
189 if (height_left == 0 || height_right == 0)
jardineb5d44e2003-12-23 08:09:43 +0000190 return 0;
hassoffe543a2005-09-25 12:04:25 +0000191 if (height_left != height_right)
jardineb5d44e2003-12-23 08:09:43 +0000192 return 0;
hassoffe543a2005-09-25 12:04:25 +0000193 if (root->color == dnode_red) {
194 if (root->left->color != dnode_black)
195 return 0;
196 if (root->right->color != dnode_black)
197 return 0;
198 return height_left;
jardineb5d44e2003-12-23 08:09:43 +0000199 }
hassoffe543a2005-09-25 12:04:25 +0000200 if (root->color != dnode_black)
201 return 0;
202 return height_left + 1;
203 }
204 return 1;
jardineb5d44e2003-12-23 08:09:43 +0000205}
206
207/*
208 * Compute the actual count of nodes by traversing the tree and
209 * return it. This could be compared against the stored count to
210 * detect a mismatch.
211 */
212
hassoffe543a2005-09-25 12:04:25 +0000213static dictcount_t verify_node_count(dnode_t *nil, dnode_t *root)
jardineb5d44e2003-12-23 08:09:43 +0000214{
hassoffe543a2005-09-25 12:04:25 +0000215 if (root == nil)
216 return 0;
217 else
218 return 1 + verify_node_count(nil, root->left)
219 + verify_node_count(nil, root->right);
jardineb5d44e2003-12-23 08:09:43 +0000220}
221
222/*
223 * Verify that the tree contains the given node. This is done by
224 * traversing all of the nodes and comparing their pointers to the
225 * given pointer. Returns 1 if the node is found, otherwise
226 * returns zero. It is intended for debugging purposes.
227 */
228
hassoffe543a2005-09-25 12:04:25 +0000229static int verify_dict_has_node(dnode_t *nil, dnode_t *root, dnode_t *node)
jardineb5d44e2003-12-23 08:09:43 +0000230{
hassoffe543a2005-09-25 12:04:25 +0000231 if (root != nil) {
232 return root == node
233 || verify_dict_has_node(nil, root->left, node)
234 || verify_dict_has_node(nil, root->right, node);
jardineb5d44e2003-12-23 08:09:43 +0000235 }
hassoffe543a2005-09-25 12:04:25 +0000236 return 0;
jardineb5d44e2003-12-23 08:09:43 +0000237}
238
hassoffe543a2005-09-25 12:04:25 +0000239
jardineb5d44e2003-12-23 08:09:43 +0000240/*
241 * Dynamically allocate and initialize a dictionary object.
242 */
243
hassoffe543a2005-09-25 12:04:25 +0000244dict_t *dict_create(dictcount_t maxcount, dict_comp_t comp)
jardineb5d44e2003-12-23 08:09:43 +0000245{
hassoffe543a2005-09-25 12:04:25 +0000246 dict_t *new = malloc(sizeof *new);
jardineb5d44e2003-12-23 08:09:43 +0000247
hassoffe543a2005-09-25 12:04:25 +0000248 if (new) {
249 new->compare = comp;
250 new->allocnode = dnode_alloc;
251 new->freenode = dnode_free;
252 new->context = NULL;
253 new->nodecount = 0;
254 new->maxcount = maxcount;
255 new->nilnode.left = &new->nilnode;
256 new->nilnode.right = &new->nilnode;
257 new->nilnode.parent = &new->nilnode;
258 new->nilnode.color = dnode_black;
259 new->dupes = 0;
jardineb5d44e2003-12-23 08:09:43 +0000260 }
hassoffe543a2005-09-25 12:04:25 +0000261 return new;
jardineb5d44e2003-12-23 08:09:43 +0000262}
263
264/*
265 * Select a different set of node allocator routines.
266 */
267
hassoffe543a2005-09-25 12:04:25 +0000268void dict_set_allocator(dict_t *dict, dnode_alloc_t al,
269 dnode_free_t fr, void *context)
jardineb5d44e2003-12-23 08:09:43 +0000270{
hassoffe543a2005-09-25 12:04:25 +0000271 assert (dict_count(dict) == 0);
272 assert ((al == NULL && fr == NULL) || (al != NULL && fr != NULL));
jardineb5d44e2003-12-23 08:09:43 +0000273
hassoffe543a2005-09-25 12:04:25 +0000274 dict->allocnode = al ? al : dnode_alloc;
275 dict->freenode = fr ? fr : dnode_free;
276 dict->context = context;
jardineb5d44e2003-12-23 08:09:43 +0000277}
278
279/*
280 * Free a dynamically allocated dictionary object. Removing the nodes
281 * from the tree before deleting it is required.
282 */
283
hassoffe543a2005-09-25 12:04:25 +0000284void dict_destroy(dict_t *dict)
jardineb5d44e2003-12-23 08:09:43 +0000285{
hassoffe543a2005-09-25 12:04:25 +0000286 assert (dict_isempty(dict));
287 free(dict);
jardineb5d44e2003-12-23 08:09:43 +0000288}
289
290/*
291 * Free all the nodes in the dictionary by using the dictionary's
292 * installed free routine. The dictionary is emptied.
293 */
294
hassoffe543a2005-09-25 12:04:25 +0000295void dict_free_nodes(dict_t *dict)
jardineb5d44e2003-12-23 08:09:43 +0000296{
hassoffe543a2005-09-25 12:04:25 +0000297 dnode_t *nil = dict_nil(dict), *root = dict_root(dict);
298 free_nodes(dict, root, nil);
299 dict->nodecount = 0;
300 dict->nilnode.left = &dict->nilnode;
301 dict->nilnode.right = &dict->nilnode;
jardineb5d44e2003-12-23 08:09:43 +0000302}
303
304/*
305 * Obsolescent function, equivalent to dict_free_nodes
306 */
307
hassoffe543a2005-09-25 12:04:25 +0000308void dict_free(dict_t *dict)
jardineb5d44e2003-12-23 08:09:43 +0000309{
310#ifdef KAZLIB_OBSOLESCENT_DEBUG
hassoffe543a2005-09-25 12:04:25 +0000311 assert ("call to obsolescent function dict_free()" && 0);
jardineb5d44e2003-12-23 08:09:43 +0000312#endif
hassoffe543a2005-09-25 12:04:25 +0000313 dict_free_nodes(dict);
jardineb5d44e2003-12-23 08:09:43 +0000314}
315
316/*
317 * Initialize a user-supplied dictionary object.
318 */
319
hassoffe543a2005-09-25 12:04:25 +0000320dict_t *dict_init(dict_t *dict, dictcount_t maxcount, dict_comp_t comp)
jardineb5d44e2003-12-23 08:09:43 +0000321{
hassoffe543a2005-09-25 12:04:25 +0000322 dict->compare = comp;
323 dict->allocnode = dnode_alloc;
324 dict->freenode = dnode_free;
325 dict->context = NULL;
326 dict->nodecount = 0;
327 dict->maxcount = maxcount;
328 dict->nilnode.left = &dict->nilnode;
329 dict->nilnode.right = &dict->nilnode;
330 dict->nilnode.parent = &dict->nilnode;
331 dict->nilnode.color = dnode_black;
332 dict->dupes = 0;
333 return dict;
jardineb5d44e2003-12-23 08:09:43 +0000334}
335
336/*
337 * Initialize a dictionary in the likeness of another dictionary
338 */
339
hassoffe543a2005-09-25 12:04:25 +0000340void dict_init_like(dict_t *dict, const dict_t *template)
jardineb5d44e2003-12-23 08:09:43 +0000341{
hassoffe543a2005-09-25 12:04:25 +0000342 dict->compare = template->compare;
343 dict->allocnode = template->allocnode;
344 dict->freenode = template->freenode;
345 dict->context = template->context;
346 dict->nodecount = 0;
347 dict->maxcount = template->maxcount;
348 dict->nilnode.left = &dict->nilnode;
349 dict->nilnode.right = &dict->nilnode;
350 dict->nilnode.parent = &dict->nilnode;
351 dict->nilnode.color = dnode_black;
352 dict->dupes = template->dupes;
jardineb5d44e2003-12-23 08:09:43 +0000353
hassoffe543a2005-09-25 12:04:25 +0000354 assert (dict_similar(dict, template));
jardineb5d44e2003-12-23 08:09:43 +0000355}
356
357/*
358 * Remove all nodes from the dictionary (without freeing them in any way).
359 */
360
hassoffe543a2005-09-25 12:04:25 +0000361static void dict_clear(dict_t *dict)
jardineb5d44e2003-12-23 08:09:43 +0000362{
hassoffe543a2005-09-25 12:04:25 +0000363 dict->nodecount = 0;
364 dict->nilnode.left = &dict->nilnode;
365 dict->nilnode.right = &dict->nilnode;
366 dict->nilnode.parent = &dict->nilnode;
367 assert (dict->nilnode.color == dnode_black);
jardineb5d44e2003-12-23 08:09:43 +0000368}
369
hassoffe543a2005-09-25 12:04:25 +0000370
jardineb5d44e2003-12-23 08:09:43 +0000371/*
372 * Verify the integrity of the dictionary structure. This is provided for
373 * debugging purposes, and should be placed in assert statements. Just because
374 * this function succeeds doesn't mean that the tree is not corrupt. Certain
375 * corruptions in the tree may simply cause undefined behavior.
hassoffe543a2005-09-25 12:04:25 +0000376 */
jardineb5d44e2003-12-23 08:09:43 +0000377
hassoffe543a2005-09-25 12:04:25 +0000378int dict_verify(dict_t *dict)
jardineb5d44e2003-12-23 08:09:43 +0000379{
hassoffe543a2005-09-25 12:04:25 +0000380 dnode_t *nil = dict_nil(dict), *root = dict_root(dict);
jardineb5d44e2003-12-23 08:09:43 +0000381
hassoffe543a2005-09-25 12:04:25 +0000382 /* check that the sentinel node and root node are black */
383 if (root->color != dnode_black)
384 return 0;
385 if (nil->color != dnode_black)
386 return 0;
387 if (nil->right != nil)
388 return 0;
389 /* nil->left is the root node; check that its parent pointer is nil */
390 if (nil->left->parent != nil)
391 return 0;
392 /* perform a weak test that the tree is a binary search tree */
393 if (!verify_bintree(dict))
394 return 0;
395 /* verify that the tree is a red-black tree */
396 if (!verify_redblack(nil, root))
397 return 0;
398 if (verify_node_count(nil, root) != dict_count(dict))
399 return 0;
400 return 1;
jardineb5d44e2003-12-23 08:09:43 +0000401}
402
403/*
404 * Determine whether two dictionaries are similar: have the same comparison and
405 * allocator functions, and same status as to whether duplicates are allowed.
406 */
407
hassoffe543a2005-09-25 12:04:25 +0000408int dict_similar(const dict_t *left, const dict_t *right)
jardineb5d44e2003-12-23 08:09:43 +0000409{
hassoffe543a2005-09-25 12:04:25 +0000410 if (left->compare != right->compare)
411 return 0;
jardineb5d44e2003-12-23 08:09:43 +0000412
hassoffe543a2005-09-25 12:04:25 +0000413 if (left->allocnode != right->allocnode)
414 return 0;
jardineb5d44e2003-12-23 08:09:43 +0000415
hassoffe543a2005-09-25 12:04:25 +0000416 if (left->freenode != right->freenode)
417 return 0;
jardineb5d44e2003-12-23 08:09:43 +0000418
hassoffe543a2005-09-25 12:04:25 +0000419 if (left->context != right->context)
420 return 0;
jardineb5d44e2003-12-23 08:09:43 +0000421
hassoffe543a2005-09-25 12:04:25 +0000422 if (left->dupes != right->dupes)
423 return 0;
jardineb5d44e2003-12-23 08:09:43 +0000424
hassoffe543a2005-09-25 12:04:25 +0000425 return 1;
jardineb5d44e2003-12-23 08:09:43 +0000426}
427
428/*
429 * Locate a node in the dictionary having the given key.
430 * If the node is not found, a null a pointer is returned (rather than
431 * a pointer that dictionary's nil sentinel node), otherwise a pointer to the
432 * located node is returned.
433 */
434
hassoffe543a2005-09-25 12:04:25 +0000435dnode_t *dict_lookup(dict_t *dict, const void *key)
jardineb5d44e2003-12-23 08:09:43 +0000436{
hassoffe543a2005-09-25 12:04:25 +0000437 dnode_t *root = dict_root(dict);
438 dnode_t *nil = dict_nil(dict);
439 dnode_t *saved;
440 int result;
jardineb5d44e2003-12-23 08:09:43 +0000441
hassoffe543a2005-09-25 12:04:25 +0000442 /* simple binary search adapted for trees that contain duplicate keys */
jardineb5d44e2003-12-23 08:09:43 +0000443
hassoffe543a2005-09-25 12:04:25 +0000444 while (root != nil) {
445 result = dict->compare(key, root->key);
446 if (result < 0)
447 root = root->left;
448 else if (result > 0)
449 root = root->right;
450 else {
451 if (!dict->dupes) { /* no duplicates, return match */
452 return root;
453 } else { /* could be dupes, find leftmost one */
454 do {
455 saved = root;
456 root = root->left;
457 while (root != nil && dict->compare(key, root->key))
458 root = root->right;
459 } while (root != nil);
460 return saved;
jardineb5d44e2003-12-23 08:09:43 +0000461 }
462 }
463 }
464
hassoffe543a2005-09-25 12:04:25 +0000465 return NULL;
jardineb5d44e2003-12-23 08:09:43 +0000466}
467
468/*
469 * Look for the node corresponding to the lowest key that is equal to or
470 * greater than the given key. If there is no such node, return null.
471 */
472
hassoffe543a2005-09-25 12:04:25 +0000473dnode_t *dict_lower_bound(dict_t *dict, const void *key)
jardineb5d44e2003-12-23 08:09:43 +0000474{
hassoffe543a2005-09-25 12:04:25 +0000475 dnode_t *root = dict_root(dict);
476 dnode_t *nil = dict_nil(dict);
477 dnode_t *tentative = 0;
jardineb5d44e2003-12-23 08:09:43 +0000478
hassoffe543a2005-09-25 12:04:25 +0000479 while (root != nil) {
480 int result = dict->compare(key, root->key);
jardineb5d44e2003-12-23 08:09:43 +0000481
hassoffe543a2005-09-25 12:04:25 +0000482 if (result > 0) {
483 root = root->right;
484 } else if (result < 0) {
485 tentative = root;
486 root = root->left;
487 } else {
488 if (!dict->dupes) {
489 return root;
490 } else {
491 tentative = root;
492 root = root->left;
jardineb5d44e2003-12-23 08:09:43 +0000493 }
hassoffe543a2005-09-25 12:04:25 +0000494 }
jardineb5d44e2003-12-23 08:09:43 +0000495 }
hassoffe543a2005-09-25 12:04:25 +0000496
497 return tentative;
jardineb5d44e2003-12-23 08:09:43 +0000498}
499
500/*
501 * Look for the node corresponding to the greatest key that is equal to or
502 * lower than the given key. If there is no such node, return null.
503 */
504
hassoffe543a2005-09-25 12:04:25 +0000505dnode_t *dict_upper_bound(dict_t *dict, const void *key)
jardineb5d44e2003-12-23 08:09:43 +0000506{
hassoffe543a2005-09-25 12:04:25 +0000507 dnode_t *root = dict_root(dict);
508 dnode_t *nil = dict_nil(dict);
509 dnode_t *tentative = 0;
jardineb5d44e2003-12-23 08:09:43 +0000510
hassoffe543a2005-09-25 12:04:25 +0000511 while (root != nil) {
512 int result = dict->compare(key, root->key);
jardineb5d44e2003-12-23 08:09:43 +0000513
hassoffe543a2005-09-25 12:04:25 +0000514 if (result < 0) {
515 root = root->left;
516 } else if (result > 0) {
517 tentative = root;
518 root = root->right;
519 } else {
520 if (!dict->dupes) {
521 return root;
522 } else {
523 tentative = root;
524 root = root->right;
jardineb5d44e2003-12-23 08:09:43 +0000525 }
hassoffe543a2005-09-25 12:04:25 +0000526 }
jardineb5d44e2003-12-23 08:09:43 +0000527 }
hassoffe543a2005-09-25 12:04:25 +0000528
529 return tentative;
jardineb5d44e2003-12-23 08:09:43 +0000530}
531
532/*
533 * Insert a node into the dictionary. The node should have been
534 * initialized with a data field. All other fields are ignored.
535 * The behavior is undefined if the user attempts to insert into
536 * a dictionary that is already full (for which the dict_isfull()
537 * function returns true).
538 */
539
hassoffe543a2005-09-25 12:04:25 +0000540void dict_insert(dict_t *dict, dnode_t *node, const void *key)
jardineb5d44e2003-12-23 08:09:43 +0000541{
hassoffe543a2005-09-25 12:04:25 +0000542 dnode_t *where = dict_root(dict), *nil = dict_nil(dict);
543 dnode_t *parent = nil, *uncle, *grandpa;
544 int result = -1;
jardineb5d44e2003-12-23 08:09:43 +0000545
hassoffe543a2005-09-25 12:04:25 +0000546 node->key = key;
jardineb5d44e2003-12-23 08:09:43 +0000547
hassoffe543a2005-09-25 12:04:25 +0000548 assert (!dict_isfull(dict));
549 assert (!dict_contains(dict, node));
550 assert (!dnode_is_in_a_dict(node));
jardineb5d44e2003-12-23 08:09:43 +0000551
hassoffe543a2005-09-25 12:04:25 +0000552 /* basic binary tree insert */
jardineb5d44e2003-12-23 08:09:43 +0000553
hassoffe543a2005-09-25 12:04:25 +0000554 while (where != nil) {
555 parent = where;
556 result = dict->compare(key, where->key);
557 /* trap attempts at duplicate key insertion unless it's explicitly allowed */
558 assert (dict->dupes || result != 0);
559 if (result < 0)
560 where = where->left;
561 else
562 where = where->right;
jardineb5d44e2003-12-23 08:09:43 +0000563 }
564
hassoffe543a2005-09-25 12:04:25 +0000565 assert (where == nil);
jardineb5d44e2003-12-23 08:09:43 +0000566
hassoffe543a2005-09-25 12:04:25 +0000567 if (result < 0)
568 parent->left = node;
569 else
570 parent->right = node;
jardineb5d44e2003-12-23 08:09:43 +0000571
hassoffe543a2005-09-25 12:04:25 +0000572 node->parent = parent;
573 node->left = nil;
574 node->right = nil;
jardineb5d44e2003-12-23 08:09:43 +0000575
hassoffe543a2005-09-25 12:04:25 +0000576 dict->nodecount++;
jardineb5d44e2003-12-23 08:09:43 +0000577
hassoffe543a2005-09-25 12:04:25 +0000578 /* red black adjustments */
jardineb5d44e2003-12-23 08:09:43 +0000579
hassoffe543a2005-09-25 12:04:25 +0000580 node->color = dnode_red;
jardineb5d44e2003-12-23 08:09:43 +0000581
hassoffe543a2005-09-25 12:04:25 +0000582 while (parent->color == dnode_red) {
583 grandpa = parent->parent;
584 if (parent == grandpa->left) {
585 uncle = grandpa->right;
586 if (uncle->color == dnode_red) { /* red parent, red uncle */
587 parent->color = dnode_black;
588 uncle->color = dnode_black;
589 grandpa->color = dnode_red;
590 node = grandpa;
591 parent = grandpa->parent;
592 } else { /* red parent, black uncle */
593 if (node == parent->right) {
594 rotate_left(parent);
595 parent = node;
596 assert (grandpa == parent->parent);
597 /* rotation between parent and child preserves grandpa */
jardineb5d44e2003-12-23 08:09:43 +0000598 }
hassoffe543a2005-09-25 12:04:25 +0000599 parent->color = dnode_black;
600 grandpa->color = dnode_red;
601 rotate_right(grandpa);
602 break;
hassof390d2c2004-09-10 20:48:21 +0000603 }
hassoffe543a2005-09-25 12:04:25 +0000604 } else { /* symmetric cases: parent == parent->parent->right */
605 uncle = grandpa->left;
606 if (uncle->color == dnode_red) {
607 parent->color = dnode_black;
608 uncle->color = dnode_black;
609 grandpa->color = dnode_red;
610 node = grandpa;
611 parent = grandpa->parent;
612 } else {
613 if (node == parent->left) {
614 rotate_right(parent);
615 parent = node;
616 assert (grandpa == parent->parent);
hassof390d2c2004-09-10 20:48:21 +0000617 }
hassoffe543a2005-09-25 12:04:25 +0000618 parent->color = dnode_black;
619 grandpa->color = dnode_red;
620 rotate_left(grandpa);
621 break;
jardineb5d44e2003-12-23 08:09:43 +0000622 }
623 }
624 }
625
hassoffe543a2005-09-25 12:04:25 +0000626 dict_root(dict)->color = dnode_black;
jardineb5d44e2003-12-23 08:09:43 +0000627
hassoffe543a2005-09-25 12:04:25 +0000628 assert (dict_verify(dict));
jardineb5d44e2003-12-23 08:09:43 +0000629}
630
631/*
632 * Delete the given node from the dictionary. If the given node does not belong
633 * to the given dictionary, undefined behavior results. A pointer to the
634 * deleted node is returned.
635 */
636
hassoffe543a2005-09-25 12:04:25 +0000637dnode_t *dict_delete(dict_t *dict, dnode_t *delete)
jardineb5d44e2003-12-23 08:09:43 +0000638{
hassoffe543a2005-09-25 12:04:25 +0000639 dnode_t *nil = dict_nil(dict), *child, *delparent = delete->parent;
jardineb5d44e2003-12-23 08:09:43 +0000640
hassoffe543a2005-09-25 12:04:25 +0000641 /* basic deletion */
jardineb5d44e2003-12-23 08:09:43 +0000642
hassoffe543a2005-09-25 12:04:25 +0000643 assert (!dict_isempty(dict));
644 assert (dict_contains(dict, delete));
jardineb5d44e2003-12-23 08:09:43 +0000645
hassoffe543a2005-09-25 12:04:25 +0000646 /*
647 * If the node being deleted has two children, then we replace it with its
648 * successor (i.e. the leftmost node in the right subtree.) By doing this,
649 * we avoid the traditional algorithm under which the successor's key and
650 * value *only* move to the deleted node and the successor is spliced out
651 * from the tree. We cannot use this approach because the user may hold
652 * pointers to the successor, or nodes may be inextricably tied to some
653 * other structures by way of embedding, etc. So we must splice out the
654 * node we are given, not some other node, and must not move contents from
655 * one node to another behind the user's back.
656 */
jardineb5d44e2003-12-23 08:09:43 +0000657
hassoffe543a2005-09-25 12:04:25 +0000658 if (delete->left != nil && delete->right != nil) {
659 dnode_t *next = dict_next(dict, delete);
660 dnode_t *nextparent = next->parent;
661 dnode_color_t nextcolor = next->color;
jardineb5d44e2003-12-23 08:09:43 +0000662
hassoffe543a2005-09-25 12:04:25 +0000663 assert (next != nil);
664 assert (next->parent != nil);
665 assert (next->left == nil);
jardineb5d44e2003-12-23 08:09:43 +0000666
hassoffe543a2005-09-25 12:04:25 +0000667 /*
668 * First, splice out the successor from the tree completely, by
669 * moving up its right child into its place.
670 */
jardineb5d44e2003-12-23 08:09:43 +0000671
hassoffe543a2005-09-25 12:04:25 +0000672 child = next->right;
673 child->parent = nextparent;
jardineb5d44e2003-12-23 08:09:43 +0000674
hassoffe543a2005-09-25 12:04:25 +0000675 if (nextparent->left == next) {
676 nextparent->left = child;
677 } else {
678 assert (nextparent->right == next);
679 nextparent->right = child;
jardineb5d44e2003-12-23 08:09:43 +0000680 }
681
hassoffe543a2005-09-25 12:04:25 +0000682 /*
683 * Now that the successor has been extricated from the tree, install it
684 * in place of the node that we want deleted.
685 */
jardineb5d44e2003-12-23 08:09:43 +0000686
hassoffe543a2005-09-25 12:04:25 +0000687 next->parent = delparent;
688 next->left = delete->left;
689 next->right = delete->right;
690 next->left->parent = next;
691 next->right->parent = next;
692 next->color = delete->color;
693 delete->color = nextcolor;
jardineb5d44e2003-12-23 08:09:43 +0000694
hassoffe543a2005-09-25 12:04:25 +0000695 if (delparent->left == delete) {
696 delparent->left = next;
697 } else {
698 assert (delparent->right == delete);
699 delparent->right = next;
jardineb5d44e2003-12-23 08:09:43 +0000700 }
701
hassoffe543a2005-09-25 12:04:25 +0000702 } else {
703 assert (delete != nil);
704 assert (delete->left == nil || delete->right == nil);
jardineb5d44e2003-12-23 08:09:43 +0000705
hassoffe543a2005-09-25 12:04:25 +0000706 child = (delete->left != nil) ? delete->left : delete->right;
jardineb5d44e2003-12-23 08:09:43 +0000707
hassoffe543a2005-09-25 12:04:25 +0000708 child->parent = delparent = delete->parent;
jardineb5d44e2003-12-23 08:09:43 +0000709
hassoffe543a2005-09-25 12:04:25 +0000710 if (delete == delparent->left) {
711 delparent->left = child;
712 } else {
713 assert (delete == delparent->right);
714 delparent->right = child;
jardineb5d44e2003-12-23 08:09:43 +0000715 }
716 }
717
hassoffe543a2005-09-25 12:04:25 +0000718 delete->parent = NULL;
719 delete->right = NULL;
720 delete->left = NULL;
jardineb5d44e2003-12-23 08:09:43 +0000721
hassoffe543a2005-09-25 12:04:25 +0000722 dict->nodecount--;
jardineb5d44e2003-12-23 08:09:43 +0000723
hassoffe543a2005-09-25 12:04:25 +0000724 assert (verify_bintree(dict));
jardineb5d44e2003-12-23 08:09:43 +0000725
hassoffe543a2005-09-25 12:04:25 +0000726 /* red-black adjustments */
jardineb5d44e2003-12-23 08:09:43 +0000727
hassoffe543a2005-09-25 12:04:25 +0000728 if (delete->color == dnode_black) {
729 dnode_t *parent, *sister;
jardineb5d44e2003-12-23 08:09:43 +0000730
hassoffe543a2005-09-25 12:04:25 +0000731 dict_root(dict)->color = dnode_red;
jardineb5d44e2003-12-23 08:09:43 +0000732
hassoffe543a2005-09-25 12:04:25 +0000733 while (child->color == dnode_black) {
734 parent = child->parent;
735 if (child == parent->left) {
736 sister = parent->right;
737 assert (sister != nil);
738 if (sister->color == dnode_red) {
739 sister->color = dnode_black;
740 parent->color = dnode_red;
741 rotate_left(parent);
742 sister = parent->right;
743 assert (sister != nil);
jardineb5d44e2003-12-23 08:09:43 +0000744 }
hassoffe543a2005-09-25 12:04:25 +0000745 if (sister->left->color == dnode_black
746 && sister->right->color == dnode_black) {
747 sister->color = dnode_red;
748 child = parent;
749 } else {
750 if (sister->right->color == dnode_black) {
751 assert (sister->left->color == dnode_red);
752 sister->left->color = dnode_black;
753 sister->color = dnode_red;
754 rotate_right(sister);
755 sister = parent->right;
756 assert (sister != nil);
jardineb5d44e2003-12-23 08:09:43 +0000757 }
hassoffe543a2005-09-25 12:04:25 +0000758 sister->color = parent->color;
759 sister->right->color = dnode_black;
760 parent->color = dnode_black;
761 rotate_left(parent);
762 break;
jardineb5d44e2003-12-23 08:09:43 +0000763 }
hassoffe543a2005-09-25 12:04:25 +0000764 } else { /* symmetric case: child == child->parent->right */
765 assert (child == parent->right);
766 sister = parent->left;
767 assert (sister != nil);
768 if (sister->color == dnode_red) {
769 sister->color = dnode_black;
770 parent->color = dnode_red;
771 rotate_right(parent);
772 sister = parent->left;
773 assert (sister != nil);
jardineb5d44e2003-12-23 08:09:43 +0000774 }
hassoffe543a2005-09-25 12:04:25 +0000775 if (sister->right->color == dnode_black
776 && sister->left->color == dnode_black) {
777 sister->color = dnode_red;
778 child = parent;
779 } else {
780 if (sister->left->color == dnode_black) {
781 assert (sister->right->color == dnode_red);
782 sister->right->color = dnode_black;
783 sister->color = dnode_red;
784 rotate_left(sister);
785 sister = parent->left;
786 assert (sister != nil);
jardineb5d44e2003-12-23 08:09:43 +0000787 }
hassoffe543a2005-09-25 12:04:25 +0000788 sister->color = parent->color;
789 sister->left->color = dnode_black;
790 parent->color = dnode_black;
791 rotate_right(parent);
792 break;
jardineb5d44e2003-12-23 08:09:43 +0000793 }
794 }
795 }
796
hassoffe543a2005-09-25 12:04:25 +0000797 child->color = dnode_black;
798 dict_root(dict)->color = dnode_black;
jardineb5d44e2003-12-23 08:09:43 +0000799 }
800
hassoffe543a2005-09-25 12:04:25 +0000801 assert (dict_verify(dict));
jardineb5d44e2003-12-23 08:09:43 +0000802
hassoffe543a2005-09-25 12:04:25 +0000803 return delete;
jardineb5d44e2003-12-23 08:09:43 +0000804}
805
806/*
807 * Allocate a node using the dictionary's allocator routine, give it
808 * the data item.
809 */
810
hassoffe543a2005-09-25 12:04:25 +0000811int dict_alloc_insert(dict_t *dict, const void *key, void *data)
jardineb5d44e2003-12-23 08:09:43 +0000812{
hassoffe543a2005-09-25 12:04:25 +0000813 dnode_t *node = dict->allocnode(dict->context);
jardineb5d44e2003-12-23 08:09:43 +0000814
hassoffe543a2005-09-25 12:04:25 +0000815 if (node) {
816 dnode_init(node, data);
817 dict_insert(dict, node, key);
818 return 1;
jardineb5d44e2003-12-23 08:09:43 +0000819 }
hassoffe543a2005-09-25 12:04:25 +0000820 return 0;
jardineb5d44e2003-12-23 08:09:43 +0000821}
822
hassoffe543a2005-09-25 12:04:25 +0000823void dict_delete_free(dict_t *dict, dnode_t *node)
jardineb5d44e2003-12-23 08:09:43 +0000824{
hassoffe543a2005-09-25 12:04:25 +0000825 dict_delete(dict, node);
826 dict->freenode(node, dict->context);
jardineb5d44e2003-12-23 08:09:43 +0000827}
828
829/*
830 * Return the node with the lowest (leftmost) key. If the dictionary is empty
831 * (that is, dict_isempty(dict) returns 1) a null pointer is returned.
832 */
833
hassoffe543a2005-09-25 12:04:25 +0000834dnode_t *dict_first(dict_t *dict)
jardineb5d44e2003-12-23 08:09:43 +0000835{
hassoffe543a2005-09-25 12:04:25 +0000836 dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *left;
jardineb5d44e2003-12-23 08:09:43 +0000837
hassoffe543a2005-09-25 12:04:25 +0000838 if (root != nil)
839 while ((left = root->left) != nil)
840 root = left;
jardineb5d44e2003-12-23 08:09:43 +0000841
hassoffe543a2005-09-25 12:04:25 +0000842 return (root == nil) ? NULL : root;
jardineb5d44e2003-12-23 08:09:43 +0000843}
844
845/*
846 * Return the node with the highest (rightmost) key. If the dictionary is empty
847 * (that is, dict_isempty(dict) returns 1) a null pointer is returned.
848 */
849
hassoffe543a2005-09-25 12:04:25 +0000850dnode_t *dict_last(dict_t *dict)
jardineb5d44e2003-12-23 08:09:43 +0000851{
hassoffe543a2005-09-25 12:04:25 +0000852 dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *right;
jardineb5d44e2003-12-23 08:09:43 +0000853
hassoffe543a2005-09-25 12:04:25 +0000854 if (root != nil)
855 while ((right = root->right) != nil)
856 root = right;
jardineb5d44e2003-12-23 08:09:43 +0000857
hassoffe543a2005-09-25 12:04:25 +0000858 return (root == nil) ? NULL : root;
jardineb5d44e2003-12-23 08:09:43 +0000859}
860
861/*
862 * Return the given node's successor node---the node which has the
863 * next key in the the left to right ordering. If the node has
864 * no successor, a null pointer is returned rather than a pointer to
865 * the nil node.
866 */
867
hassoffe543a2005-09-25 12:04:25 +0000868dnode_t *dict_next(dict_t *dict, dnode_t *curr)
jardineb5d44e2003-12-23 08:09:43 +0000869{
hassoffe543a2005-09-25 12:04:25 +0000870 dnode_t *nil = dict_nil(dict), *parent, *left;
jardineb5d44e2003-12-23 08:09:43 +0000871
hassoffe543a2005-09-25 12:04:25 +0000872 if (curr->right != nil) {
873 curr = curr->right;
874 while ((left = curr->left) != nil)
875 curr = left;
876 return curr;
jardineb5d44e2003-12-23 08:09:43 +0000877 }
878
hassoffe543a2005-09-25 12:04:25 +0000879 parent = curr->parent;
jardineb5d44e2003-12-23 08:09:43 +0000880
hassoffe543a2005-09-25 12:04:25 +0000881 while (parent != nil && curr == parent->right) {
882 curr = parent;
883 parent = curr->parent;
jardineb5d44e2003-12-23 08:09:43 +0000884 }
885
hassoffe543a2005-09-25 12:04:25 +0000886 return (parent == nil) ? NULL : parent;
jardineb5d44e2003-12-23 08:09:43 +0000887}
888
889/*
890 * Return the given node's predecessor, in the key order.
891 * The nil sentinel node is returned if there is no predecessor.
892 */
893
hassoffe543a2005-09-25 12:04:25 +0000894dnode_t *dict_prev(dict_t *dict, dnode_t *curr)
jardineb5d44e2003-12-23 08:09:43 +0000895{
hassoffe543a2005-09-25 12:04:25 +0000896 dnode_t *nil = dict_nil(dict), *parent, *right;
jardineb5d44e2003-12-23 08:09:43 +0000897
hassoffe543a2005-09-25 12:04:25 +0000898 if (curr->left != nil) {
899 curr = curr->left;
900 while ((right = curr->right) != nil)
901 curr = right;
902 return curr;
jardineb5d44e2003-12-23 08:09:43 +0000903 }
904
hassoffe543a2005-09-25 12:04:25 +0000905 parent = curr->parent;
jardineb5d44e2003-12-23 08:09:43 +0000906
hassoffe543a2005-09-25 12:04:25 +0000907 while (parent != nil && curr == parent->left) {
908 curr = parent;
909 parent = curr->parent;
jardineb5d44e2003-12-23 08:09:43 +0000910 }
911
hassoffe543a2005-09-25 12:04:25 +0000912 return (parent == nil) ? NULL : parent;
jardineb5d44e2003-12-23 08:09:43 +0000913}
914
hassoffe543a2005-09-25 12:04:25 +0000915void dict_allow_dupes(dict_t *dict)
jardineb5d44e2003-12-23 08:09:43 +0000916{
hassoffe543a2005-09-25 12:04:25 +0000917 dict->dupes = 1;
jardineb5d44e2003-12-23 08:09:43 +0000918}
919
920#undef dict_count
921#undef dict_isempty
922#undef dict_isfull
923#undef dnode_get
924#undef dnode_put
925#undef dnode_getkey
926
hassoffe543a2005-09-25 12:04:25 +0000927dictcount_t dict_count(dict_t *dict)
jardineb5d44e2003-12-23 08:09:43 +0000928{
hassoffe543a2005-09-25 12:04:25 +0000929 return dict->nodecount;
jardineb5d44e2003-12-23 08:09:43 +0000930}
931
hassoffe543a2005-09-25 12:04:25 +0000932int dict_isempty(dict_t *dict)
jardineb5d44e2003-12-23 08:09:43 +0000933{
hassoffe543a2005-09-25 12:04:25 +0000934 return dict->nodecount == 0;
jardineb5d44e2003-12-23 08:09:43 +0000935}
936
hassoffe543a2005-09-25 12:04:25 +0000937int dict_isfull(dict_t *dict)
jardineb5d44e2003-12-23 08:09:43 +0000938{
hassoffe543a2005-09-25 12:04:25 +0000939 return dict->nodecount == dict->maxcount;
jardineb5d44e2003-12-23 08:09:43 +0000940}
941
hassoffe543a2005-09-25 12:04:25 +0000942int dict_contains(dict_t *dict, dnode_t *node)
jardineb5d44e2003-12-23 08:09:43 +0000943{
hassoffe543a2005-09-25 12:04:25 +0000944 return verify_dict_has_node(dict_nil(dict), dict_root(dict), node);
jardineb5d44e2003-12-23 08:09:43 +0000945}
946
hassoffe543a2005-09-25 12:04:25 +0000947static dnode_t *dnode_alloc(void *context)
jardineb5d44e2003-12-23 08:09:43 +0000948{
hassoffe543a2005-09-25 12:04:25 +0000949 return malloc(sizeof *dnode_alloc(NULL));
jardineb5d44e2003-12-23 08:09:43 +0000950}
951
hassoffe543a2005-09-25 12:04:25 +0000952static void dnode_free(dnode_t *node, void *context)
jardineb5d44e2003-12-23 08:09:43 +0000953{
hassoffe543a2005-09-25 12:04:25 +0000954 free(node);
jardineb5d44e2003-12-23 08:09:43 +0000955}
956
hassoffe543a2005-09-25 12:04:25 +0000957dnode_t *dnode_create(void *data)
jardineb5d44e2003-12-23 08:09:43 +0000958{
hassoffe543a2005-09-25 12:04:25 +0000959 dnode_t *new = malloc(sizeof *new);
960 if (new) {
961 new->data = data;
962 new->parent = NULL;
963 new->left = NULL;
964 new->right = NULL;
jardineb5d44e2003-12-23 08:09:43 +0000965 }
hassoffe543a2005-09-25 12:04:25 +0000966 return new;
jardineb5d44e2003-12-23 08:09:43 +0000967}
968
hassoffe543a2005-09-25 12:04:25 +0000969dnode_t *dnode_init(dnode_t *dnode, void *data)
jardineb5d44e2003-12-23 08:09:43 +0000970{
hassoffe543a2005-09-25 12:04:25 +0000971 dnode->data = data;
972 dnode->parent = NULL;
973 dnode->left = NULL;
974 dnode->right = NULL;
975 return dnode;
jardineb5d44e2003-12-23 08:09:43 +0000976}
977
hassoffe543a2005-09-25 12:04:25 +0000978void dnode_destroy(dnode_t *dnode)
jardineb5d44e2003-12-23 08:09:43 +0000979{
hassoffe543a2005-09-25 12:04:25 +0000980 assert (!dnode_is_in_a_dict(dnode));
981 free(dnode);
jardineb5d44e2003-12-23 08:09:43 +0000982}
983
hassoffe543a2005-09-25 12:04:25 +0000984void *dnode_get(dnode_t *dnode)
jardineb5d44e2003-12-23 08:09:43 +0000985{
hassoffe543a2005-09-25 12:04:25 +0000986 return dnode->data;
jardineb5d44e2003-12-23 08:09:43 +0000987}
988
hassoffe543a2005-09-25 12:04:25 +0000989const void *dnode_getkey(dnode_t *dnode)
jardineb5d44e2003-12-23 08:09:43 +0000990{
hassoffe543a2005-09-25 12:04:25 +0000991 return dnode->key;
jardineb5d44e2003-12-23 08:09:43 +0000992}
993
hassoffe543a2005-09-25 12:04:25 +0000994void dnode_put(dnode_t *dnode, void *data)
jardineb5d44e2003-12-23 08:09:43 +0000995{
hassoffe543a2005-09-25 12:04:25 +0000996 dnode->data = data;
jardineb5d44e2003-12-23 08:09:43 +0000997}
998
hassoffe543a2005-09-25 12:04:25 +0000999int dnode_is_in_a_dict(dnode_t *dnode)
jardineb5d44e2003-12-23 08:09:43 +00001000{
hassoffe543a2005-09-25 12:04:25 +00001001 return (dnode->parent && dnode->left && dnode->right);
jardineb5d44e2003-12-23 08:09:43 +00001002}
1003
hassoffe543a2005-09-25 12:04:25 +00001004void dict_process(dict_t *dict, void *context, dnode_process_t function)
jardineb5d44e2003-12-23 08:09:43 +00001005{
hassoffe543a2005-09-25 12:04:25 +00001006 dnode_t *node = dict_first(dict), *next;
jardineb5d44e2003-12-23 08:09:43 +00001007
hassoffe543a2005-09-25 12:04:25 +00001008 while (node != NULL) {
1009 /* check for callback function deleting */
1010 /* the next node from under us */
1011 assert (dict_contains(dict, node));
1012 next = dict_next(dict, node);
1013 function(dict, node, context);
1014 node = next;
jardineb5d44e2003-12-23 08:09:43 +00001015 }
1016}
1017
hassoffe543a2005-09-25 12:04:25 +00001018static void load_begin_internal(dict_load_t *load, dict_t *dict)
jardineb5d44e2003-12-23 08:09:43 +00001019{
hassoffe543a2005-09-25 12:04:25 +00001020 load->dictptr = dict;
1021 load->nilnode.left = &load->nilnode;
1022 load->nilnode.right = &load->nilnode;
jardineb5d44e2003-12-23 08:09:43 +00001023}
1024
hassoffe543a2005-09-25 12:04:25 +00001025void dict_load_begin(dict_load_t *load, dict_t *dict)
jardineb5d44e2003-12-23 08:09:43 +00001026{
hassoffe543a2005-09-25 12:04:25 +00001027 assert (dict_isempty(dict));
1028 load_begin_internal(load, dict);
jardineb5d44e2003-12-23 08:09:43 +00001029}
1030
hassoffe543a2005-09-25 12:04:25 +00001031void dict_load_next(dict_load_t *load, dnode_t *newnode, const void *key)
jardineb5d44e2003-12-23 08:09:43 +00001032{
hassoffe543a2005-09-25 12:04:25 +00001033 dict_t *dict = load->dictptr;
1034 dnode_t *nil = &load->nilnode;
1035
1036 assert (!dnode_is_in_a_dict(newnode));
1037 assert (dict->nodecount < dict->maxcount);
jardineb5d44e2003-12-23 08:09:43 +00001038
hassoffe543a2005-09-25 12:04:25 +00001039 #ifndef NDEBUG
1040 if (dict->nodecount > 0) {
1041 if (dict->dupes)
1042 assert (dict->compare(nil->left->key, key) <= 0);
1043 else
1044 assert (dict->compare(nil->left->key, key) < 0);
jardineb5d44e2003-12-23 08:09:43 +00001045 }
hassoffe543a2005-09-25 12:04:25 +00001046 #endif
jardineb5d44e2003-12-23 08:09:43 +00001047
hassoffe543a2005-09-25 12:04:25 +00001048 newnode->key = key;
1049 nil->right->left = newnode;
1050 nil->right = newnode;
1051 newnode->left = nil;
1052 dict->nodecount++;
jardineb5d44e2003-12-23 08:09:43 +00001053}
1054
hassoffe543a2005-09-25 12:04:25 +00001055void dict_load_end(dict_load_t *load)
jardineb5d44e2003-12-23 08:09:43 +00001056{
hassoffe543a2005-09-25 12:04:25 +00001057 dict_t *dict = load->dictptr;
1058 dnode_t *tree[DICT_DEPTH_MAX] = { 0 };
1059 dnode_t *curr, *dictnil = dict_nil(dict), *loadnil = &load->nilnode, *next;
1060 dnode_t *complete = 0;
1061 dictcount_t fullcount = DICTCOUNT_T_MAX, nodecount = dict->nodecount;
1062 dictcount_t botrowcount;
1063 unsigned baselevel = 0, level = 0, i;
jardineb5d44e2003-12-23 08:09:43 +00001064
hassoffe543a2005-09-25 12:04:25 +00001065 assert (dnode_red == 0 && dnode_black == 1);
jardineb5d44e2003-12-23 08:09:43 +00001066
hassoffe543a2005-09-25 12:04:25 +00001067 while (fullcount >= nodecount && fullcount)
1068 fullcount >>= 1;
jardineb5d44e2003-12-23 08:09:43 +00001069
hassoffe543a2005-09-25 12:04:25 +00001070 botrowcount = nodecount - fullcount;
jardineb5d44e2003-12-23 08:09:43 +00001071
hassoffe543a2005-09-25 12:04:25 +00001072 for (curr = loadnil->left; curr != loadnil; curr = next) {
1073 next = curr->left;
jardineb5d44e2003-12-23 08:09:43 +00001074
hassoffe543a2005-09-25 12:04:25 +00001075 if (complete == NULL && botrowcount-- == 0) {
1076 assert (baselevel == 0);
1077 assert (level == 0);
1078 baselevel = level = 1;
1079 complete = tree[0];
jardineb5d44e2003-12-23 08:09:43 +00001080
hassoffe543a2005-09-25 12:04:25 +00001081 if (complete != 0) {
1082 tree[0] = 0;
1083 complete->right = dictnil;
1084 while (tree[level] != 0) {
1085 tree[level]->right = complete;
1086 complete->parent = tree[level];
1087 complete = tree[level];
1088 tree[level++] = 0;
jardineb5d44e2003-12-23 08:09:43 +00001089 }
1090 }
1091 }
1092
hassoffe543a2005-09-25 12:04:25 +00001093 if (complete == NULL) {
1094 curr->left = dictnil;
1095 curr->right = dictnil;
1096 curr->color = level % 2;
1097 complete = curr;
jardineb5d44e2003-12-23 08:09:43 +00001098
hassoffe543a2005-09-25 12:04:25 +00001099 assert (level == baselevel);
1100 while (tree[level] != 0) {
1101 tree[level]->right = complete;
1102 complete->parent = tree[level];
1103 complete = tree[level];
1104 tree[level++] = 0;
jardineb5d44e2003-12-23 08:09:43 +00001105 }
hassoffe543a2005-09-25 12:04:25 +00001106 } else {
1107 curr->left = complete;
1108 curr->color = (level + 1) % 2;
1109 complete->parent = curr;
1110 tree[level] = curr;
1111 complete = 0;
1112 level = baselevel;
jardineb5d44e2003-12-23 08:09:43 +00001113 }
1114 }
1115
hassoffe543a2005-09-25 12:04:25 +00001116 if (complete == NULL)
1117 complete = dictnil;
jardineb5d44e2003-12-23 08:09:43 +00001118
hassoffe543a2005-09-25 12:04:25 +00001119 for (i = 0; i < DICT_DEPTH_MAX; i++) {
1120 if (tree[i] != 0) {
1121 tree[i]->right = complete;
1122 complete->parent = tree[i];
1123 complete = tree[i];
jardineb5d44e2003-12-23 08:09:43 +00001124 }
1125 }
1126
hassoffe543a2005-09-25 12:04:25 +00001127 dictnil->color = dnode_black;
1128 dictnil->right = dictnil;
1129 complete->parent = dictnil;
1130 complete->color = dnode_black;
1131 dict_root(dict) = complete;
jardineb5d44e2003-12-23 08:09:43 +00001132
hassoffe543a2005-09-25 12:04:25 +00001133 assert (dict_verify(dict));
jardineb5d44e2003-12-23 08:09:43 +00001134}
1135
hassoffe543a2005-09-25 12:04:25 +00001136void dict_merge(dict_t *dest, dict_t *source)
jardineb5d44e2003-12-23 08:09:43 +00001137{
hassoffe543a2005-09-25 12:04:25 +00001138 dict_load_t load;
1139 dnode_t *leftnode = dict_first(dest), *rightnode = dict_first(source);
jardineb5d44e2003-12-23 08:09:43 +00001140
hassoffe543a2005-09-25 12:04:25 +00001141 assert (dict_similar(dest, source));
jardineb5d44e2003-12-23 08:09:43 +00001142
hassoffe543a2005-09-25 12:04:25 +00001143 if (source == dest)
1144 return;
jardineb5d44e2003-12-23 08:09:43 +00001145
hassoffe543a2005-09-25 12:04:25 +00001146 dest->nodecount = 0;
1147 load_begin_internal(&load, dest);
jardineb5d44e2003-12-23 08:09:43 +00001148
hassoffe543a2005-09-25 12:04:25 +00001149 for (;;) {
1150 if (leftnode != NULL && rightnode != NULL) {
1151 if (dest->compare(leftnode->key, rightnode->key) < 0)
1152 goto copyleft;
1153 else
1154 goto copyright;
1155 } else if (leftnode != NULL) {
jardineb5d44e2003-12-23 08:09:43 +00001156 goto copyleft;
hassoffe543a2005-09-25 12:04:25 +00001157 } else if (rightnode != NULL) {
jardineb5d44e2003-12-23 08:09:43 +00001158 goto copyright;
hassoffe543a2005-09-25 12:04:25 +00001159 } else {
1160 assert (leftnode == NULL && rightnode == NULL);
1161 break;
jardineb5d44e2003-12-23 08:09:43 +00001162 }
1163
1164 copyleft:
hassoffe543a2005-09-25 12:04:25 +00001165 {
1166 dnode_t *next = dict_next(dest, leftnode);
1167 #ifndef NDEBUG
1168 leftnode->left = NULL; /* suppress assertion in dict_load_next */
1169 #endif
1170 dict_load_next(&load, leftnode, leftnode->key);
1171 leftnode = next;
1172 continue;
1173 }
1174
jardineb5d44e2003-12-23 08:09:43 +00001175 copyright:
hassoffe543a2005-09-25 12:04:25 +00001176 {
1177 dnode_t *next = dict_next(source, rightnode);
1178 #ifndef NDEBUG
1179 rightnode->left = NULL;
1180 #endif
1181 dict_load_next(&load, rightnode, rightnode->key);
1182 rightnode = next;
1183 continue;
1184 }
jardineb5d44e2003-12-23 08:09:43 +00001185 }
1186
hassoffe543a2005-09-25 12:04:25 +00001187 dict_clear(source);
1188 dict_load_end(&load);
jardineb5d44e2003-12-23 08:09:43 +00001189}
1190
1191#ifdef KAZLIB_TEST_MAIN
1192
1193#include <stdio.h>
1194#include <string.h>
1195#include <ctype.h>
1196#include <stdarg.h>
1197
1198typedef char input_t[256];
1199
hassoffe543a2005-09-25 12:04:25 +00001200static int tokenize(char *string, ...)
jardineb5d44e2003-12-23 08:09:43 +00001201{
hassoffe543a2005-09-25 12:04:25 +00001202 char **tokptr;
1203 va_list arglist;
1204 int tokcount = 0;
jardineb5d44e2003-12-23 08:09:43 +00001205
hassoffe543a2005-09-25 12:04:25 +00001206 va_start(arglist, string);
1207 tokptr = va_arg(arglist, char **);
1208 while (tokptr) {
1209 while (*string && isspace((unsigned char) *string))
1210 string++;
1211 if (!*string)
1212 break;
1213 *tokptr = string;
1214 while (*string && !isspace((unsigned char) *string))
1215 string++;
1216 tokptr = va_arg(arglist, char **);
1217 tokcount++;
1218 if (!*string)
1219 break;
1220 *string++ = 0;
jardineb5d44e2003-12-23 08:09:43 +00001221 }
hassoffe543a2005-09-25 12:04:25 +00001222 va_end(arglist);
jardineb5d44e2003-12-23 08:09:43 +00001223
hassoffe543a2005-09-25 12:04:25 +00001224 return tokcount;
jardineb5d44e2003-12-23 08:09:43 +00001225}
1226
hassoffe543a2005-09-25 12:04:25 +00001227static int comparef(const void *key1, const void *key2)
jardineb5d44e2003-12-23 08:09:43 +00001228{
hassoffe543a2005-09-25 12:04:25 +00001229 return strcmp(key1, key2);
jardineb5d44e2003-12-23 08:09:43 +00001230}
1231
hassoffe543a2005-09-25 12:04:25 +00001232static char *dupstring(char *str)
jardineb5d44e2003-12-23 08:09:43 +00001233{
hassoffe543a2005-09-25 12:04:25 +00001234 int sz = strlen(str) + 1;
1235 char *new = malloc(sz);
1236 if (new)
1237 memcpy(new, str, sz);
1238 return new;
jardineb5d44e2003-12-23 08:09:43 +00001239}
1240
hassoffe543a2005-09-25 12:04:25 +00001241static dnode_t *new_node(void *c)
jardineb5d44e2003-12-23 08:09:43 +00001242{
hassoffe543a2005-09-25 12:04:25 +00001243 static dnode_t few[5];
1244 static int count;
jardineb5d44e2003-12-23 08:09:43 +00001245
hassoffe543a2005-09-25 12:04:25 +00001246 if (count < 5)
1247 return few + count++;
jardineb5d44e2003-12-23 08:09:43 +00001248
hassoffe543a2005-09-25 12:04:25 +00001249 return NULL;
jardineb5d44e2003-12-23 08:09:43 +00001250}
1251
hassoffe543a2005-09-25 12:04:25 +00001252static void del_node(dnode_t *n, void *c)
jardineb5d44e2003-12-23 08:09:43 +00001253{
1254}
1255
1256static int prompt = 0;
1257
hassoffe543a2005-09-25 12:04:25 +00001258static void construct(dict_t *d)
jardineb5d44e2003-12-23 08:09:43 +00001259{
hassoffe543a2005-09-25 12:04:25 +00001260 input_t in;
1261 int done = 0;
1262 dict_load_t dl;
1263 dnode_t *dn;
1264 char *tok1, *tok2, *val;
1265 const char *key;
1266 char *help =
1267 "p turn prompt on\n"
1268 "q finish construction\n"
1269 "a <key> <val> add new entry\n";
jardineb5d44e2003-12-23 08:09:43 +00001270
hassoffe543a2005-09-25 12:04:25 +00001271 if (!dict_isempty(d))
1272 puts("warning: dictionary not empty!");
jardineb5d44e2003-12-23 08:09:43 +00001273
hassoffe543a2005-09-25 12:04:25 +00001274 dict_load_begin(&dl, d);
jardineb5d44e2003-12-23 08:09:43 +00001275
hassoffe543a2005-09-25 12:04:25 +00001276 while (!done) {
1277 if (prompt)
1278 putchar('>');
1279 fflush(stdout);
jardineb5d44e2003-12-23 08:09:43 +00001280
hassoffe543a2005-09-25 12:04:25 +00001281 if (!fgets(in, sizeof(input_t), stdin))
1282 break;
jardineb5d44e2003-12-23 08:09:43 +00001283
hassoffe543a2005-09-25 12:04:25 +00001284 switch (in[0]) {
1285 case '?':
1286 puts(help);
1287 break;
1288 case 'p':
1289 prompt = 1;
1290 break;
1291 case 'q':
1292 done = 1;
1293 break;
1294 case 'a':
1295 if (tokenize(in+1, &tok1, &tok2, (char **) 0) != 2) {
1296 puts("what?");
1297 break;
1298 }
1299 key = dupstring(tok1);
1300 val = dupstring(tok2);
1301 dn = dnode_create(val);
jardineb5d44e2003-12-23 08:09:43 +00001302
hassoffe543a2005-09-25 12:04:25 +00001303 if (!key || !val || !dn) {
1304 puts("out of memory");
1305 free((void *) key);
1306 free(val);
1307 if (dn)
1308 dnode_destroy(dn);
1309 }
jardineb5d44e2003-12-23 08:09:43 +00001310
hassoffe543a2005-09-25 12:04:25 +00001311 dict_load_next(&dl, dn, key);
1312 break;
1313 default:
1314 putchar('?');
1315 putchar('\n');
1316 break;
jardineb5d44e2003-12-23 08:09:43 +00001317 }
1318 }
1319
hassoffe543a2005-09-25 12:04:25 +00001320 dict_load_end(&dl);
jardineb5d44e2003-12-23 08:09:43 +00001321}
1322
hassoffe543a2005-09-25 12:04:25 +00001323int main(void)
jardineb5d44e2003-12-23 08:09:43 +00001324{
hassoffe543a2005-09-25 12:04:25 +00001325 input_t in;
1326 dict_t darray[10];
1327 dict_t *d = &darray[0];
1328 dnode_t *dn;
1329 int i;
1330 char *tok1, *tok2, *val;
1331 const char *key;
jardineb5d44e2003-12-23 08:09:43 +00001332
hassoffe543a2005-09-25 12:04:25 +00001333 char *help =
1334 "a <key> <val> add value to dictionary\n"
1335 "d <key> delete value from dictionary\n"
1336 "l <key> lookup value in dictionary\n"
1337 "( <key> lookup lower bound\n"
1338 ") <key> lookup upper bound\n"
1339 "# <num> switch to alternate dictionary (0-9)\n"
1340 "j <num> <num> merge two dictionaries\n"
1341 "f free the whole dictionary\n"
1342 "k allow duplicate keys\n"
1343 "c show number of entries\n"
1344 "t dump whole dictionary in sort order\n"
1345 "m make dictionary out of sorted items\n"
1346 "p turn prompt on\n"
1347 "s switch to non-functioning allocator\n"
1348 "q quit";
jardineb5d44e2003-12-23 08:09:43 +00001349
hassoffe543a2005-09-25 12:04:25 +00001350 for (i = 0; i < sizeof darray / sizeof *darray; i++)
1351 dict_init(&darray[i], DICTCOUNT_T_MAX, comparef);
jardineb5d44e2003-12-23 08:09:43 +00001352
hassoffe543a2005-09-25 12:04:25 +00001353 for (;;) {
1354 if (prompt)
1355 putchar('>');
1356 fflush(stdout);
jardineb5d44e2003-12-23 08:09:43 +00001357
hassoffe543a2005-09-25 12:04:25 +00001358 if (!fgets(in, sizeof(input_t), stdin))
1359 break;
jardineb5d44e2003-12-23 08:09:43 +00001360
hassoffe543a2005-09-25 12:04:25 +00001361 switch(in[0]) {
1362 case '?':
1363 puts(help);
1364 break;
1365 case 'a':
1366 if (tokenize(in+1, &tok1, &tok2, (char **) 0) != 2) {
1367 puts("what?");
1368 break;
1369 }
1370 key = dupstring(tok1);
1371 val = dupstring(tok2);
jardineb5d44e2003-12-23 08:09:43 +00001372
hassoffe543a2005-09-25 12:04:25 +00001373 if (!key || !val) {
1374 puts("out of memory");
1375 free((void *) key);
1376 free(val);
1377 }
jardineb5d44e2003-12-23 08:09:43 +00001378
hassoffe543a2005-09-25 12:04:25 +00001379 if (!dict_alloc_insert(d, key, val)) {
1380 puts("dict_alloc_insert failed");
1381 free((void *) key);
1382 free(val);
1383 break;
1384 }
1385 break;
1386 case 'd':
1387 if (tokenize(in+1, &tok1, (char **) 0) != 1) {
1388 puts("what?");
1389 break;
1390 }
1391 dn = dict_lookup(d, tok1);
1392 if (!dn) {
1393 puts("dict_lookup failed");
1394 break;
1395 }
1396 val = dnode_get(dn);
1397 key = dnode_getkey(dn);
1398 dict_delete_free(d, dn);
jardineb5d44e2003-12-23 08:09:43 +00001399
hassoffe543a2005-09-25 12:04:25 +00001400 free(val);
1401 free((void *) key);
1402 break;
1403 case 'f':
1404 dict_free(d);
1405 break;
jardineb5d44e2003-12-23 08:09:43 +00001406 case 'l':
1407 case '(':
1408 case ')':
hassoffe543a2005-09-25 12:04:25 +00001409 if (tokenize(in+1, &tok1, (char **) 0) != 1) {
1410 puts("what?");
1411 break;
jardineb5d44e2003-12-23 08:09:43 +00001412 }
hassoffe543a2005-09-25 12:04:25 +00001413 dn = 0;
1414 switch (in[0]) {
1415 case 'l':
1416 dn = dict_lookup(d, tok1);
1417 break;
1418 case '(':
1419 dn = dict_lower_bound(d, tok1);
1420 break;
1421 case ')':
1422 dn = dict_upper_bound(d, tok1);
1423 break;
jardineb5d44e2003-12-23 08:09:43 +00001424 }
hassoffe543a2005-09-25 12:04:25 +00001425 if (!dn) {
1426 puts("lookup failed");
1427 break;
1428 }
1429 val = dnode_get(dn);
1430 puts(val);
1431 break;
1432 case 'm':
1433 construct(d);
1434 break;
1435 case 'k':
1436 dict_allow_dupes(d);
1437 break;
1438 case 'c':
1439 printf("%lu\n", (unsigned long) dict_count(d));
1440 break;
1441 case 't':
1442 for (dn = dict_first(d); dn; dn = dict_next(d, dn)) {
1443 printf("%s\t%s\n", (char *) dnode_getkey(dn),
1444 (char *) dnode_get(dn));
1445 }
1446 break;
1447 case 'q':
1448 exit(0);
1449 break;
1450 case '\0':
1451 break;
1452 case 'p':
1453 prompt = 1;
1454 break;
1455 case 's':
1456 dict_set_allocator(d, new_node, del_node, NULL);
1457 break;
1458 case '#':
1459 if (tokenize(in+1, &tok1, (char **) 0) != 1) {
1460 puts("what?");
1461 break;
1462 } else {
1463 int dictnum = atoi(tok1);
1464 if (dictnum < 0 || dictnum > 9) {
1465 puts("invalid number");
1466 break;
1467 }
1468 d = &darray[dictnum];
1469 }
1470 break;
1471 case 'j':
1472 if (tokenize(in+1, &tok1, &tok2, (char **) 0) != 2) {
1473 puts("what?");
1474 break;
1475 } else {
1476 int dict1 = atoi(tok1), dict2 = atoi(tok2);
1477 if (dict1 < 0 || dict1 > 9 || dict2 < 0 || dict2 > 9) {
1478 puts("invalid number");
1479 break;
1480 }
1481 dict_merge(&darray[dict1], &darray[dict2]);
1482 }
1483 break;
1484 default:
1485 putchar('?');
1486 putchar('\n');
1487 break;
jardineb5d44e2003-12-23 08:09:43 +00001488 }
1489 }
1490
hassoffe543a2005-09-25 12:04:25 +00001491 return 0;
jardineb5d44e2003-12-23 08:09:43 +00001492}
1493
1494#endif