blob: 6c3e1e7fddd70c1c3ca2cc11831253c5a83ddf7b [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 *
Paul Jakma238497f2007-08-07 18:49:18 +000017 * $Id$
18 * $Name$
jardineb5d44e2003-12-23 08:09:43 +000019 */
20
21#include <stdlib.h>
22#include <stddef.h>
Paul Jakma238497f2007-08-07 18:49:18 +000023#include "zebra.h"
ajscee3df12004-11-24 17:14:49 +000024#include "zassert.h"
jardineb5d44e2003-12-23 08:09:43 +000025#define DICT_IMPLEMENTATION
26#include "dict.h"
27
28#ifdef KAZLIB_RCSID
hassoffe543a2005-09-25 12:04:25 +000029static const char rcsid[] = "Id: dict.c,v 1.40.2.7 2000/11/13 01:36:44 kaz";
jardineb5d44e2003-12-23 08:09:43 +000030#endif
31
32/*
33 * These macros provide short convenient names for structure members,
34 * which are embellished with dict_ prefixes so that they are
35 * properly confined to the documented namespace. It's legal for a
36 * program which uses dict to define, for instance, a macro called ``parent''.
37 * Such a macro would interfere with the dnode_t struct definition.
38 * In general, highly portable and reusable C modules which expose their
39 * structures need to confine structure member names to well-defined spaces.
40 * The resulting identifiers aren't necessarily convenient to use, nor
41 * readable, in the implementation, however!
42 */
43
44#define left dict_left
45#define right dict_right
46#define parent dict_parent
47#define color dict_color
48#define key dict_key
49#define data dict_data
50
51#define nilnode dict_nilnode
52#define nodecount dict_nodecount
53#define maxcount dict_maxcount
54#define compare dict_compare
55#define allocnode dict_allocnode
56#define freenode dict_freenode
57#define context dict_context
58#define dupes dict_dupes
59
60#define dictptr dict_dictptr
61
62#define dict_root(D) ((D)->nilnode.left)
63#define dict_nil(D) (&(D)->nilnode)
64#define DICT_DEPTH_MAX 64
65
hassoffe543a2005-09-25 12:04:25 +000066static dnode_t *dnode_alloc(void *context);
67static void dnode_free(dnode_t *node, void *context);
jardineb5d44e2003-12-23 08:09:43 +000068
69/*
70 * Perform a ``left rotation'' adjustment on the tree. The given node P and
71 * its right child C are rearranged so that the P instead becomes the left
72 * child of C. The left subtree of C is inherited as the new right subtree
73 * for P. The ordering of the keys within the tree is thus preserved.
74 */
75
hassoffe543a2005-09-25 12:04:25 +000076static void rotate_left(dnode_t *upper)
jardineb5d44e2003-12-23 08:09:43 +000077{
hassoffe543a2005-09-25 12:04:25 +000078 dnode_t *lower, *lowleft, *upparent;
jardineb5d44e2003-12-23 08:09:43 +000079
hassoffe543a2005-09-25 12:04:25 +000080 lower = upper->right;
81 upper->right = lowleft = lower->left;
82 lowleft->parent = upper;
jardineb5d44e2003-12-23 08:09:43 +000083
hassoffe543a2005-09-25 12:04:25 +000084 lower->parent = upparent = upper->parent;
jardineb5d44e2003-12-23 08:09:43 +000085
hassoffe543a2005-09-25 12:04:25 +000086 /* don't need to check for root node here because root->parent is
87 the sentinel nil node, and root->parent->left points back to root */
jardineb5d44e2003-12-23 08:09:43 +000088
hassoffe543a2005-09-25 12:04:25 +000089 if (upper == upparent->left) {
90 upparent->left = lower;
91 } else {
92 assert (upper == upparent->right);
93 upparent->right = lower;
jardineb5d44e2003-12-23 08:09:43 +000094 }
95
hassoffe543a2005-09-25 12:04:25 +000096 lower->left = upper;
97 upper->parent = lower;
jardineb5d44e2003-12-23 08:09:43 +000098}
99
100/*
101 * This operation is the ``mirror'' image of rotate_left. It is
102 * the same procedure, but with left and right interchanged.
103 */
104
hassoffe543a2005-09-25 12:04:25 +0000105static void rotate_right(dnode_t *upper)
jardineb5d44e2003-12-23 08:09:43 +0000106{
hassoffe543a2005-09-25 12:04:25 +0000107 dnode_t *lower, *lowright, *upparent;
jardineb5d44e2003-12-23 08:09:43 +0000108
hassoffe543a2005-09-25 12:04:25 +0000109 lower = upper->left;
110 upper->left = lowright = lower->right;
111 lowright->parent = upper;
jardineb5d44e2003-12-23 08:09:43 +0000112
hassoffe543a2005-09-25 12:04:25 +0000113 lower->parent = upparent = upper->parent;
jardineb5d44e2003-12-23 08:09:43 +0000114
hassoffe543a2005-09-25 12:04:25 +0000115 if (upper == upparent->right) {
116 upparent->right = lower;
117 } else {
118 assert (upper == upparent->left);
119 upparent->left = lower;
jardineb5d44e2003-12-23 08:09:43 +0000120 }
121
hassoffe543a2005-09-25 12:04:25 +0000122 lower->right = upper;
123 upper->parent = lower;
jardineb5d44e2003-12-23 08:09:43 +0000124}
125
126/*
127 * Do a postorder traversal of the tree rooted at the specified
128 * node and free everything under it. Used by dict_free().
129 */
130
hassoffe543a2005-09-25 12:04:25 +0000131static void free_nodes(dict_t *dict, dnode_t *node, dnode_t *nil)
jardineb5d44e2003-12-23 08:09:43 +0000132{
hassoffe543a2005-09-25 12:04:25 +0000133 if (node == nil)
134 return;
135 free_nodes(dict, node->left, nil);
136 free_nodes(dict, node->right, nil);
137 dict->freenode(node, dict->context);
jardineb5d44e2003-12-23 08:09:43 +0000138}
139
140/*
141 * This procedure performs a verification that the given subtree is a binary
142 * search tree. It performs an inorder traversal of the tree using the
143 * dict_next() successor function, verifying that the key of each node is
144 * strictly lower than that of its successor, if duplicates are not allowed,
145 * or lower or equal if duplicates are allowed. This function is used for
146 * debugging purposes.
147 */
148
hassoffe543a2005-09-25 12:04:25 +0000149static int verify_bintree(dict_t *dict)
jardineb5d44e2003-12-23 08:09:43 +0000150{
hassoffe543a2005-09-25 12:04:25 +0000151 dnode_t *first, *next;
jardineb5d44e2003-12-23 08:09:43 +0000152
hassoffe543a2005-09-25 12:04:25 +0000153 first = dict_first(dict);
jardineb5d44e2003-12-23 08:09:43 +0000154
hassoffe543a2005-09-25 12:04:25 +0000155 if (dict->dupes) {
156 while (first && (next = dict_next(dict, first))) {
157 if (dict->compare(first->key, next->key) > 0)
158 return 0;
159 first = next;
160 }
161 } else {
162 while (first && (next = dict_next(dict, first))) {
163 if (dict->compare(first->key, next->key) >= 0)
164 return 0;
165 first = next;
jardineb5d44e2003-12-23 08:09:43 +0000166 }
167 }
hassoffe543a2005-09-25 12:04:25 +0000168 return 1;
jardineb5d44e2003-12-23 08:09:43 +0000169}
170
171
172/*
173 * This function recursively verifies that the given binary subtree satisfies
174 * three of the red black properties. It checks that every red node has only
175 * black children. It makes sure that each node is either red or black. And it
176 * checks that every path has the same count of black nodes from root to leaf.
177 * It returns the blackheight of the given subtree; this allows blackheights to
178 * be computed recursively and compared for left and right siblings for
179 * mismatches. It does not check for every nil node being black, because there
180 * is only one sentinel nil node. The return value of this function is the
181 * black height of the subtree rooted at the node ``root'', or zero if the
182 * subtree is not red-black.
183 */
184
hassoffe543a2005-09-25 12:04:25 +0000185static unsigned int verify_redblack(dnode_t *nil, dnode_t *root)
jardineb5d44e2003-12-23 08:09:43 +0000186{
hassoffe543a2005-09-25 12:04:25 +0000187 unsigned height_left, height_right;
jardineb5d44e2003-12-23 08:09:43 +0000188
hassoffe543a2005-09-25 12:04:25 +0000189 if (root != nil) {
190 height_left = verify_redblack(nil, root->left);
191 height_right = verify_redblack(nil, root->right);
192 if (height_left == 0 || height_right == 0)
jardineb5d44e2003-12-23 08:09:43 +0000193 return 0;
hassoffe543a2005-09-25 12:04:25 +0000194 if (height_left != height_right)
jardineb5d44e2003-12-23 08:09:43 +0000195 return 0;
hassoffe543a2005-09-25 12:04:25 +0000196 if (root->color == dnode_red) {
197 if (root->left->color != dnode_black)
198 return 0;
199 if (root->right->color != dnode_black)
200 return 0;
201 return height_left;
jardineb5d44e2003-12-23 08:09:43 +0000202 }
hassoffe543a2005-09-25 12:04:25 +0000203 if (root->color != dnode_black)
204 return 0;
205 return height_left + 1;
206 }
207 return 1;
jardineb5d44e2003-12-23 08:09:43 +0000208}
209
210/*
211 * Compute the actual count of nodes by traversing the tree and
212 * return it. This could be compared against the stored count to
213 * detect a mismatch.
214 */
215
hassoffe543a2005-09-25 12:04:25 +0000216static dictcount_t verify_node_count(dnode_t *nil, dnode_t *root)
jardineb5d44e2003-12-23 08:09:43 +0000217{
hassoffe543a2005-09-25 12:04:25 +0000218 if (root == nil)
219 return 0;
220 else
221 return 1 + verify_node_count(nil, root->left)
222 + verify_node_count(nil, root->right);
jardineb5d44e2003-12-23 08:09:43 +0000223}
224
225/*
226 * Verify that the tree contains the given node. This is done by
227 * traversing all of the nodes and comparing their pointers to the
228 * given pointer. Returns 1 if the node is found, otherwise
229 * returns zero. It is intended for debugging purposes.
230 */
231
hassoffe543a2005-09-25 12:04:25 +0000232static int verify_dict_has_node(dnode_t *nil, dnode_t *root, dnode_t *node)
jardineb5d44e2003-12-23 08:09:43 +0000233{
hassoffe543a2005-09-25 12:04:25 +0000234 if (root != nil) {
235 return root == node
236 || verify_dict_has_node(nil, root->left, node)
237 || verify_dict_has_node(nil, root->right, node);
jardineb5d44e2003-12-23 08:09:43 +0000238 }
hassoffe543a2005-09-25 12:04:25 +0000239 return 0;
jardineb5d44e2003-12-23 08:09:43 +0000240}
241
hassoffe543a2005-09-25 12:04:25 +0000242
jardineb5d44e2003-12-23 08:09:43 +0000243/*
244 * Dynamically allocate and initialize a dictionary object.
245 */
246
hassoffe543a2005-09-25 12:04:25 +0000247dict_t *dict_create(dictcount_t maxcount, dict_comp_t comp)
jardineb5d44e2003-12-23 08:09:43 +0000248{
hassoffe543a2005-09-25 12:04:25 +0000249 dict_t *new = malloc(sizeof *new);
jardineb5d44e2003-12-23 08:09:43 +0000250
hassoffe543a2005-09-25 12:04:25 +0000251 if (new) {
252 new->compare = comp;
253 new->allocnode = dnode_alloc;
254 new->freenode = dnode_free;
255 new->context = NULL;
256 new->nodecount = 0;
257 new->maxcount = maxcount;
258 new->nilnode.left = &new->nilnode;
259 new->nilnode.right = &new->nilnode;
260 new->nilnode.parent = &new->nilnode;
261 new->nilnode.color = dnode_black;
262 new->dupes = 0;
jardineb5d44e2003-12-23 08:09:43 +0000263 }
hassoffe543a2005-09-25 12:04:25 +0000264 return new;
jardineb5d44e2003-12-23 08:09:43 +0000265}
266
267/*
268 * Select a different set of node allocator routines.
269 */
270
hassoffe543a2005-09-25 12:04:25 +0000271void dict_set_allocator(dict_t *dict, dnode_alloc_t al,
272 dnode_free_t fr, void *context)
jardineb5d44e2003-12-23 08:09:43 +0000273{
hassoffe543a2005-09-25 12:04:25 +0000274 assert (dict_count(dict) == 0);
275 assert ((al == NULL && fr == NULL) || (al != NULL && fr != NULL));
jardineb5d44e2003-12-23 08:09:43 +0000276
hassoffe543a2005-09-25 12:04:25 +0000277 dict->allocnode = al ? al : dnode_alloc;
278 dict->freenode = fr ? fr : dnode_free;
279 dict->context = context;
jardineb5d44e2003-12-23 08:09:43 +0000280}
281
282/*
283 * Free a dynamically allocated dictionary object. Removing the nodes
284 * from the tree before deleting it is required.
285 */
286
hassoffe543a2005-09-25 12:04:25 +0000287void dict_destroy(dict_t *dict)
jardineb5d44e2003-12-23 08:09:43 +0000288{
hassoffe543a2005-09-25 12:04:25 +0000289 assert (dict_isempty(dict));
290 free(dict);
jardineb5d44e2003-12-23 08:09:43 +0000291}
292
293/*
294 * Free all the nodes in the dictionary by using the dictionary's
295 * installed free routine. The dictionary is emptied.
296 */
297
hassoffe543a2005-09-25 12:04:25 +0000298void dict_free_nodes(dict_t *dict)
jardineb5d44e2003-12-23 08:09:43 +0000299{
hassoffe543a2005-09-25 12:04:25 +0000300 dnode_t *nil = dict_nil(dict), *root = dict_root(dict);
301 free_nodes(dict, root, nil);
302 dict->nodecount = 0;
303 dict->nilnode.left = &dict->nilnode;
304 dict->nilnode.right = &dict->nilnode;
jardineb5d44e2003-12-23 08:09:43 +0000305}
306
307/*
308 * Obsolescent function, equivalent to dict_free_nodes
309 */
310
hassoffe543a2005-09-25 12:04:25 +0000311void dict_free(dict_t *dict)
jardineb5d44e2003-12-23 08:09:43 +0000312{
313#ifdef KAZLIB_OBSOLESCENT_DEBUG
hassoffe543a2005-09-25 12:04:25 +0000314 assert ("call to obsolescent function dict_free()" && 0);
jardineb5d44e2003-12-23 08:09:43 +0000315#endif
hassoffe543a2005-09-25 12:04:25 +0000316 dict_free_nodes(dict);
jardineb5d44e2003-12-23 08:09:43 +0000317}
318
319/*
320 * Initialize a user-supplied dictionary object.
321 */
322
hassoffe543a2005-09-25 12:04:25 +0000323dict_t *dict_init(dict_t *dict, dictcount_t maxcount, dict_comp_t comp)
jardineb5d44e2003-12-23 08:09:43 +0000324{
hassoffe543a2005-09-25 12:04:25 +0000325 dict->compare = comp;
326 dict->allocnode = dnode_alloc;
327 dict->freenode = dnode_free;
328 dict->context = NULL;
329 dict->nodecount = 0;
330 dict->maxcount = maxcount;
331 dict->nilnode.left = &dict->nilnode;
332 dict->nilnode.right = &dict->nilnode;
333 dict->nilnode.parent = &dict->nilnode;
334 dict->nilnode.color = dnode_black;
335 dict->dupes = 0;
336 return dict;
jardineb5d44e2003-12-23 08:09:43 +0000337}
338
339/*
340 * Initialize a dictionary in the likeness of another dictionary
341 */
342
hassoffe543a2005-09-25 12:04:25 +0000343void dict_init_like(dict_t *dict, const dict_t *template)
jardineb5d44e2003-12-23 08:09:43 +0000344{
hassoffe543a2005-09-25 12:04:25 +0000345 dict->compare = template->compare;
346 dict->allocnode = template->allocnode;
347 dict->freenode = template->freenode;
348 dict->context = template->context;
349 dict->nodecount = 0;
350 dict->maxcount = template->maxcount;
351 dict->nilnode.left = &dict->nilnode;
352 dict->nilnode.right = &dict->nilnode;
353 dict->nilnode.parent = &dict->nilnode;
354 dict->nilnode.color = dnode_black;
355 dict->dupes = template->dupes;
jardineb5d44e2003-12-23 08:09:43 +0000356
hassoffe543a2005-09-25 12:04:25 +0000357 assert (dict_similar(dict, template));
jardineb5d44e2003-12-23 08:09:43 +0000358}
359
360/*
361 * Remove all nodes from the dictionary (without freeing them in any way).
362 */
363
hassoffe543a2005-09-25 12:04:25 +0000364static void dict_clear(dict_t *dict)
jardineb5d44e2003-12-23 08:09:43 +0000365{
hassoffe543a2005-09-25 12:04:25 +0000366 dict->nodecount = 0;
367 dict->nilnode.left = &dict->nilnode;
368 dict->nilnode.right = &dict->nilnode;
369 dict->nilnode.parent = &dict->nilnode;
370 assert (dict->nilnode.color == dnode_black);
jardineb5d44e2003-12-23 08:09:43 +0000371}
372
hassoffe543a2005-09-25 12:04:25 +0000373
jardineb5d44e2003-12-23 08:09:43 +0000374/*
375 * Verify the integrity of the dictionary structure. This is provided for
376 * debugging purposes, and should be placed in assert statements. Just because
377 * this function succeeds doesn't mean that the tree is not corrupt. Certain
378 * corruptions in the tree may simply cause undefined behavior.
hassoffe543a2005-09-25 12:04:25 +0000379 */
jardineb5d44e2003-12-23 08:09:43 +0000380
hassoffe543a2005-09-25 12:04:25 +0000381int dict_verify(dict_t *dict)
jardineb5d44e2003-12-23 08:09:43 +0000382{
hassoffe543a2005-09-25 12:04:25 +0000383 dnode_t *nil = dict_nil(dict), *root = dict_root(dict);
jardineb5d44e2003-12-23 08:09:43 +0000384
hassoffe543a2005-09-25 12:04:25 +0000385 /* check that the sentinel node and root node are black */
386 if (root->color != dnode_black)
387 return 0;
388 if (nil->color != dnode_black)
389 return 0;
390 if (nil->right != nil)
391 return 0;
392 /* nil->left is the root node; check that its parent pointer is nil */
393 if (nil->left->parent != nil)
394 return 0;
395 /* perform a weak test that the tree is a binary search tree */
396 if (!verify_bintree(dict))
397 return 0;
398 /* verify that the tree is a red-black tree */
399 if (!verify_redblack(nil, root))
400 return 0;
401 if (verify_node_count(nil, root) != dict_count(dict))
402 return 0;
403 return 1;
jardineb5d44e2003-12-23 08:09:43 +0000404}
405
406/*
407 * Determine whether two dictionaries are similar: have the same comparison and
408 * allocator functions, and same status as to whether duplicates are allowed.
409 */
410
hassoffe543a2005-09-25 12:04:25 +0000411int dict_similar(const dict_t *left, const dict_t *right)
jardineb5d44e2003-12-23 08:09:43 +0000412{
hassoffe543a2005-09-25 12:04:25 +0000413 if (left->compare != right->compare)
414 return 0;
jardineb5d44e2003-12-23 08:09:43 +0000415
hassoffe543a2005-09-25 12:04:25 +0000416 if (left->allocnode != right->allocnode)
417 return 0;
jardineb5d44e2003-12-23 08:09:43 +0000418
hassoffe543a2005-09-25 12:04:25 +0000419 if (left->freenode != right->freenode)
420 return 0;
jardineb5d44e2003-12-23 08:09:43 +0000421
hassoffe543a2005-09-25 12:04:25 +0000422 if (left->context != right->context)
423 return 0;
jardineb5d44e2003-12-23 08:09:43 +0000424
hassoffe543a2005-09-25 12:04:25 +0000425 if (left->dupes != right->dupes)
426 return 0;
jardineb5d44e2003-12-23 08:09:43 +0000427
hassoffe543a2005-09-25 12:04:25 +0000428 return 1;
jardineb5d44e2003-12-23 08:09:43 +0000429}
430
431/*
432 * Locate a node in the dictionary having the given key.
433 * If the node is not found, a null a pointer is returned (rather than
434 * a pointer that dictionary's nil sentinel node), otherwise a pointer to the
435 * located node is returned.
436 */
437
hassoffe543a2005-09-25 12:04:25 +0000438dnode_t *dict_lookup(dict_t *dict, const void *key)
jardineb5d44e2003-12-23 08:09:43 +0000439{
hassoffe543a2005-09-25 12:04:25 +0000440 dnode_t *root = dict_root(dict);
441 dnode_t *nil = dict_nil(dict);
442 dnode_t *saved;
443 int result;
jardineb5d44e2003-12-23 08:09:43 +0000444
hassoffe543a2005-09-25 12:04:25 +0000445 /* simple binary search adapted for trees that contain duplicate keys */
jardineb5d44e2003-12-23 08:09:43 +0000446
hassoffe543a2005-09-25 12:04:25 +0000447 while (root != nil) {
448 result = dict->compare(key, root->key);
449 if (result < 0)
450 root = root->left;
451 else if (result > 0)
452 root = root->right;
453 else {
454 if (!dict->dupes) { /* no duplicates, return match */
455 return root;
456 } else { /* could be dupes, find leftmost one */
457 do {
458 saved = root;
459 root = root->left;
460 while (root != nil && dict->compare(key, root->key))
461 root = root->right;
462 } while (root != nil);
463 return saved;
jardineb5d44e2003-12-23 08:09:43 +0000464 }
465 }
466 }
467
hassoffe543a2005-09-25 12:04:25 +0000468 return NULL;
jardineb5d44e2003-12-23 08:09:43 +0000469}
470
471/*
472 * Look for the node corresponding to the lowest key that is equal to or
473 * greater than the given key. If there is no such node, return null.
474 */
475
hassoffe543a2005-09-25 12:04:25 +0000476dnode_t *dict_lower_bound(dict_t *dict, const void *key)
jardineb5d44e2003-12-23 08:09:43 +0000477{
hassoffe543a2005-09-25 12:04:25 +0000478 dnode_t *root = dict_root(dict);
479 dnode_t *nil = dict_nil(dict);
480 dnode_t *tentative = 0;
jardineb5d44e2003-12-23 08:09:43 +0000481
hassoffe543a2005-09-25 12:04:25 +0000482 while (root != nil) {
483 int result = dict->compare(key, root->key);
jardineb5d44e2003-12-23 08:09:43 +0000484
hassoffe543a2005-09-25 12:04:25 +0000485 if (result > 0) {
486 root = root->right;
487 } else if (result < 0) {
488 tentative = root;
489 root = root->left;
490 } else {
491 if (!dict->dupes) {
492 return root;
493 } else {
494 tentative = root;
495 root = root->left;
jardineb5d44e2003-12-23 08:09:43 +0000496 }
hassoffe543a2005-09-25 12:04:25 +0000497 }
jardineb5d44e2003-12-23 08:09:43 +0000498 }
hassoffe543a2005-09-25 12:04:25 +0000499
500 return tentative;
jardineb5d44e2003-12-23 08:09:43 +0000501}
502
503/*
504 * Look for the node corresponding to the greatest key that is equal to or
505 * lower than the given key. If there is no such node, return null.
506 */
507
hassoffe543a2005-09-25 12:04:25 +0000508dnode_t *dict_upper_bound(dict_t *dict, const void *key)
jardineb5d44e2003-12-23 08:09:43 +0000509{
hassoffe543a2005-09-25 12:04:25 +0000510 dnode_t *root = dict_root(dict);
511 dnode_t *nil = dict_nil(dict);
512 dnode_t *tentative = 0;
jardineb5d44e2003-12-23 08:09:43 +0000513
hassoffe543a2005-09-25 12:04:25 +0000514 while (root != nil) {
515 int result = dict->compare(key, root->key);
jardineb5d44e2003-12-23 08:09:43 +0000516
hassoffe543a2005-09-25 12:04:25 +0000517 if (result < 0) {
518 root = root->left;
519 } else if (result > 0) {
520 tentative = root;
521 root = root->right;
522 } else {
523 if (!dict->dupes) {
524 return root;
525 } else {
526 tentative = root;
527 root = root->right;
jardineb5d44e2003-12-23 08:09:43 +0000528 }
hassoffe543a2005-09-25 12:04:25 +0000529 }
jardineb5d44e2003-12-23 08:09:43 +0000530 }
hassoffe543a2005-09-25 12:04:25 +0000531
532 return tentative;
jardineb5d44e2003-12-23 08:09:43 +0000533}
534
535/*
536 * Insert a node into the dictionary. The node should have been
537 * initialized with a data field. All other fields are ignored.
538 * The behavior is undefined if the user attempts to insert into
539 * a dictionary that is already full (for which the dict_isfull()
540 * function returns true).
541 */
542
hassoffe543a2005-09-25 12:04:25 +0000543void dict_insert(dict_t *dict, dnode_t *node, const void *key)
jardineb5d44e2003-12-23 08:09:43 +0000544{
hassoffe543a2005-09-25 12:04:25 +0000545 dnode_t *where = dict_root(dict), *nil = dict_nil(dict);
546 dnode_t *parent = nil, *uncle, *grandpa;
547 int result = -1;
jardineb5d44e2003-12-23 08:09:43 +0000548
hassoffe543a2005-09-25 12:04:25 +0000549 node->key = key;
jardineb5d44e2003-12-23 08:09:43 +0000550
hassoffe543a2005-09-25 12:04:25 +0000551 assert (!dict_isfull(dict));
552 assert (!dict_contains(dict, node));
553 assert (!dnode_is_in_a_dict(node));
jardineb5d44e2003-12-23 08:09:43 +0000554
hassoffe543a2005-09-25 12:04:25 +0000555 /* basic binary tree insert */
jardineb5d44e2003-12-23 08:09:43 +0000556
hassoffe543a2005-09-25 12:04:25 +0000557 while (where != nil) {
558 parent = where;
559 result = dict->compare(key, where->key);
560 /* trap attempts at duplicate key insertion unless it's explicitly allowed */
561 assert (dict->dupes || result != 0);
562 if (result < 0)
563 where = where->left;
564 else
565 where = where->right;
jardineb5d44e2003-12-23 08:09:43 +0000566 }
567
hassoffe543a2005-09-25 12:04:25 +0000568 assert (where == nil);
jardineb5d44e2003-12-23 08:09:43 +0000569
hassoffe543a2005-09-25 12:04:25 +0000570 if (result < 0)
571 parent->left = node;
572 else
573 parent->right = node;
jardineb5d44e2003-12-23 08:09:43 +0000574
hassoffe543a2005-09-25 12:04:25 +0000575 node->parent = parent;
576 node->left = nil;
577 node->right = nil;
jardineb5d44e2003-12-23 08:09:43 +0000578
hassoffe543a2005-09-25 12:04:25 +0000579 dict->nodecount++;
jardineb5d44e2003-12-23 08:09:43 +0000580
hassoffe543a2005-09-25 12:04:25 +0000581 /* red black adjustments */
jardineb5d44e2003-12-23 08:09:43 +0000582
hassoffe543a2005-09-25 12:04:25 +0000583 node->color = dnode_red;
jardineb5d44e2003-12-23 08:09:43 +0000584
hassoffe543a2005-09-25 12:04:25 +0000585 while (parent->color == dnode_red) {
586 grandpa = parent->parent;
587 if (parent == grandpa->left) {
588 uncle = grandpa->right;
589 if (uncle->color == dnode_red) { /* red parent, red uncle */
590 parent->color = dnode_black;
591 uncle->color = dnode_black;
592 grandpa->color = dnode_red;
593 node = grandpa;
594 parent = grandpa->parent;
595 } else { /* red parent, black uncle */
596 if (node == parent->right) {
597 rotate_left(parent);
598 parent = node;
599 assert (grandpa == parent->parent);
600 /* rotation between parent and child preserves grandpa */
jardineb5d44e2003-12-23 08:09:43 +0000601 }
hassoffe543a2005-09-25 12:04:25 +0000602 parent->color = dnode_black;
603 grandpa->color = dnode_red;
604 rotate_right(grandpa);
605 break;
hassof390d2c2004-09-10 20:48:21 +0000606 }
hassoffe543a2005-09-25 12:04:25 +0000607 } else { /* symmetric cases: parent == parent->parent->right */
608 uncle = grandpa->left;
609 if (uncle->color == dnode_red) {
610 parent->color = dnode_black;
611 uncle->color = dnode_black;
612 grandpa->color = dnode_red;
613 node = grandpa;
614 parent = grandpa->parent;
615 } else {
616 if (node == parent->left) {
617 rotate_right(parent);
618 parent = node;
619 assert (grandpa == parent->parent);
hassof390d2c2004-09-10 20:48:21 +0000620 }
hassoffe543a2005-09-25 12:04:25 +0000621 parent->color = dnode_black;
622 grandpa->color = dnode_red;
623 rotate_left(grandpa);
624 break;
jardineb5d44e2003-12-23 08:09:43 +0000625 }
626 }
627 }
628
hassoffe543a2005-09-25 12:04:25 +0000629 dict_root(dict)->color = dnode_black;
jardineb5d44e2003-12-23 08:09:43 +0000630
hassoffe543a2005-09-25 12:04:25 +0000631 assert (dict_verify(dict));
jardineb5d44e2003-12-23 08:09:43 +0000632}
633
634/*
635 * Delete the given node from the dictionary. If the given node does not belong
636 * to the given dictionary, undefined behavior results. A pointer to the
637 * deleted node is returned.
638 */
639
hassoffe543a2005-09-25 12:04:25 +0000640dnode_t *dict_delete(dict_t *dict, dnode_t *delete)
jardineb5d44e2003-12-23 08:09:43 +0000641{
hassoffe543a2005-09-25 12:04:25 +0000642 dnode_t *nil = dict_nil(dict), *child, *delparent = delete->parent;
jardineb5d44e2003-12-23 08:09:43 +0000643
hassoffe543a2005-09-25 12:04:25 +0000644 /* basic deletion */
jardineb5d44e2003-12-23 08:09:43 +0000645
hassoffe543a2005-09-25 12:04:25 +0000646 assert (!dict_isempty(dict));
647 assert (dict_contains(dict, delete));
jardineb5d44e2003-12-23 08:09:43 +0000648
hassoffe543a2005-09-25 12:04:25 +0000649 /*
650 * If the node being deleted has two children, then we replace it with its
651 * successor (i.e. the leftmost node in the right subtree.) By doing this,
652 * we avoid the traditional algorithm under which the successor's key and
653 * value *only* move to the deleted node and the successor is spliced out
654 * from the tree. We cannot use this approach because the user may hold
655 * pointers to the successor, or nodes may be inextricably tied to some
656 * other structures by way of embedding, etc. So we must splice out the
657 * node we are given, not some other node, and must not move contents from
658 * one node to another behind the user's back.
659 */
jardineb5d44e2003-12-23 08:09:43 +0000660
hassoffe543a2005-09-25 12:04:25 +0000661 if (delete->left != nil && delete->right != nil) {
662 dnode_t *next = dict_next(dict, delete);
663 dnode_t *nextparent = next->parent;
664 dnode_color_t nextcolor = next->color;
jardineb5d44e2003-12-23 08:09:43 +0000665
hassoffe543a2005-09-25 12:04:25 +0000666 assert (next != nil);
667 assert (next->parent != nil);
668 assert (next->left == nil);
jardineb5d44e2003-12-23 08:09:43 +0000669
hassoffe543a2005-09-25 12:04:25 +0000670 /*
671 * First, splice out the successor from the tree completely, by
672 * moving up its right child into its place.
673 */
jardineb5d44e2003-12-23 08:09:43 +0000674
hassoffe543a2005-09-25 12:04:25 +0000675 child = next->right;
676 child->parent = nextparent;
jardineb5d44e2003-12-23 08:09:43 +0000677
hassoffe543a2005-09-25 12:04:25 +0000678 if (nextparent->left == next) {
679 nextparent->left = child;
680 } else {
681 assert (nextparent->right == next);
682 nextparent->right = child;
jardineb5d44e2003-12-23 08:09:43 +0000683 }
684
hassoffe543a2005-09-25 12:04:25 +0000685 /*
686 * Now that the successor has been extricated from the tree, install it
687 * in place of the node that we want deleted.
688 */
jardineb5d44e2003-12-23 08:09:43 +0000689
hassoffe543a2005-09-25 12:04:25 +0000690 next->parent = delparent;
691 next->left = delete->left;
692 next->right = delete->right;
693 next->left->parent = next;
694 next->right->parent = next;
695 next->color = delete->color;
696 delete->color = nextcolor;
jardineb5d44e2003-12-23 08:09:43 +0000697
hassoffe543a2005-09-25 12:04:25 +0000698 if (delparent->left == delete) {
699 delparent->left = next;
700 } else {
701 assert (delparent->right == delete);
702 delparent->right = next;
jardineb5d44e2003-12-23 08:09:43 +0000703 }
704
hassoffe543a2005-09-25 12:04:25 +0000705 } else {
706 assert (delete != nil);
707 assert (delete->left == nil || delete->right == nil);
jardineb5d44e2003-12-23 08:09:43 +0000708
hassoffe543a2005-09-25 12:04:25 +0000709 child = (delete->left != nil) ? delete->left : delete->right;
jardineb5d44e2003-12-23 08:09:43 +0000710
hassoffe543a2005-09-25 12:04:25 +0000711 child->parent = delparent = delete->parent;
jardineb5d44e2003-12-23 08:09:43 +0000712
hassoffe543a2005-09-25 12:04:25 +0000713 if (delete == delparent->left) {
714 delparent->left = child;
715 } else {
716 assert (delete == delparent->right);
717 delparent->right = child;
jardineb5d44e2003-12-23 08:09:43 +0000718 }
719 }
720
hassoffe543a2005-09-25 12:04:25 +0000721 delete->parent = NULL;
722 delete->right = NULL;
723 delete->left = NULL;
jardineb5d44e2003-12-23 08:09:43 +0000724
hassoffe543a2005-09-25 12:04:25 +0000725 dict->nodecount--;
jardineb5d44e2003-12-23 08:09:43 +0000726
hassoffe543a2005-09-25 12:04:25 +0000727 assert (verify_bintree(dict));
jardineb5d44e2003-12-23 08:09:43 +0000728
hassoffe543a2005-09-25 12:04:25 +0000729 /* red-black adjustments */
jardineb5d44e2003-12-23 08:09:43 +0000730
hassoffe543a2005-09-25 12:04:25 +0000731 if (delete->color == dnode_black) {
732 dnode_t *parent, *sister;
jardineb5d44e2003-12-23 08:09:43 +0000733
hassoffe543a2005-09-25 12:04:25 +0000734 dict_root(dict)->color = dnode_red;
jardineb5d44e2003-12-23 08:09:43 +0000735
hassoffe543a2005-09-25 12:04:25 +0000736 while (child->color == dnode_black) {
737 parent = child->parent;
738 if (child == parent->left) {
739 sister = parent->right;
740 assert (sister != nil);
741 if (sister->color == dnode_red) {
742 sister->color = dnode_black;
743 parent->color = dnode_red;
744 rotate_left(parent);
745 sister = parent->right;
746 assert (sister != nil);
jardineb5d44e2003-12-23 08:09:43 +0000747 }
hassoffe543a2005-09-25 12:04:25 +0000748 if (sister->left->color == dnode_black
749 && sister->right->color == dnode_black) {
750 sister->color = dnode_red;
751 child = parent;
752 } else {
753 if (sister->right->color == dnode_black) {
754 assert (sister->left->color == dnode_red);
755 sister->left->color = dnode_black;
756 sister->color = dnode_red;
757 rotate_right(sister);
758 sister = parent->right;
759 assert (sister != nil);
jardineb5d44e2003-12-23 08:09:43 +0000760 }
hassoffe543a2005-09-25 12:04:25 +0000761 sister->color = parent->color;
762 sister->right->color = dnode_black;
763 parent->color = dnode_black;
764 rotate_left(parent);
765 break;
jardineb5d44e2003-12-23 08:09:43 +0000766 }
hassoffe543a2005-09-25 12:04:25 +0000767 } else { /* symmetric case: child == child->parent->right */
768 assert (child == parent->right);
769 sister = parent->left;
770 assert (sister != nil);
771 if (sister->color == dnode_red) {
772 sister->color = dnode_black;
773 parent->color = dnode_red;
774 rotate_right(parent);
775 sister = parent->left;
776 assert (sister != nil);
jardineb5d44e2003-12-23 08:09:43 +0000777 }
hassoffe543a2005-09-25 12:04:25 +0000778 if (sister->right->color == dnode_black
779 && sister->left->color == dnode_black) {
780 sister->color = dnode_red;
781 child = parent;
782 } else {
783 if (sister->left->color == dnode_black) {
784 assert (sister->right->color == dnode_red);
785 sister->right->color = dnode_black;
786 sister->color = dnode_red;
787 rotate_left(sister);
788 sister = parent->left;
789 assert (sister != nil);
jardineb5d44e2003-12-23 08:09:43 +0000790 }
hassoffe543a2005-09-25 12:04:25 +0000791 sister->color = parent->color;
792 sister->left->color = dnode_black;
793 parent->color = dnode_black;
794 rotate_right(parent);
795 break;
jardineb5d44e2003-12-23 08:09:43 +0000796 }
797 }
798 }
799
hassoffe543a2005-09-25 12:04:25 +0000800 child->color = dnode_black;
801 dict_root(dict)->color = dnode_black;
jardineb5d44e2003-12-23 08:09:43 +0000802 }
803
hassoffe543a2005-09-25 12:04:25 +0000804 assert (dict_verify(dict));
jardineb5d44e2003-12-23 08:09:43 +0000805
hassoffe543a2005-09-25 12:04:25 +0000806 return delete;
jardineb5d44e2003-12-23 08:09:43 +0000807}
808
809/*
810 * Allocate a node using the dictionary's allocator routine, give it
811 * the data item.
812 */
813
hassoffe543a2005-09-25 12:04:25 +0000814int dict_alloc_insert(dict_t *dict, const void *key, void *data)
jardineb5d44e2003-12-23 08:09:43 +0000815{
hassoffe543a2005-09-25 12:04:25 +0000816 dnode_t *node = dict->allocnode(dict->context);
jardineb5d44e2003-12-23 08:09:43 +0000817
hassoffe543a2005-09-25 12:04:25 +0000818 if (node) {
819 dnode_init(node, data);
820 dict_insert(dict, node, key);
821 return 1;
jardineb5d44e2003-12-23 08:09:43 +0000822 }
hassoffe543a2005-09-25 12:04:25 +0000823 return 0;
jardineb5d44e2003-12-23 08:09:43 +0000824}
825
hassoffe543a2005-09-25 12:04:25 +0000826void dict_delete_free(dict_t *dict, dnode_t *node)
jardineb5d44e2003-12-23 08:09:43 +0000827{
hassoffe543a2005-09-25 12:04:25 +0000828 dict_delete(dict, node);
829 dict->freenode(node, dict->context);
jardineb5d44e2003-12-23 08:09:43 +0000830}
831
832/*
833 * Return the node with the lowest (leftmost) key. If the dictionary is empty
834 * (that is, dict_isempty(dict) returns 1) a null pointer is returned.
835 */
836
hassoffe543a2005-09-25 12:04:25 +0000837dnode_t *dict_first(dict_t *dict)
jardineb5d44e2003-12-23 08:09:43 +0000838{
hassoffe543a2005-09-25 12:04:25 +0000839 dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *left;
jardineb5d44e2003-12-23 08:09:43 +0000840
hassoffe543a2005-09-25 12:04:25 +0000841 if (root != nil)
842 while ((left = root->left) != nil)
843 root = left;
jardineb5d44e2003-12-23 08:09:43 +0000844
hassoffe543a2005-09-25 12:04:25 +0000845 return (root == nil) ? NULL : root;
jardineb5d44e2003-12-23 08:09:43 +0000846}
847
848/*
849 * Return the node with the highest (rightmost) key. If the dictionary is empty
850 * (that is, dict_isempty(dict) returns 1) a null pointer is returned.
851 */
852
hassoffe543a2005-09-25 12:04:25 +0000853dnode_t *dict_last(dict_t *dict)
jardineb5d44e2003-12-23 08:09:43 +0000854{
hassoffe543a2005-09-25 12:04:25 +0000855 dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *right;
jardineb5d44e2003-12-23 08:09:43 +0000856
hassoffe543a2005-09-25 12:04:25 +0000857 if (root != nil)
858 while ((right = root->right) != nil)
859 root = right;
jardineb5d44e2003-12-23 08:09:43 +0000860
hassoffe543a2005-09-25 12:04:25 +0000861 return (root == nil) ? NULL : root;
jardineb5d44e2003-12-23 08:09:43 +0000862}
863
864/*
865 * Return the given node's successor node---the node which has the
866 * next key in the the left to right ordering. If the node has
867 * no successor, a null pointer is returned rather than a pointer to
868 * the nil node.
869 */
870
hassoffe543a2005-09-25 12:04:25 +0000871dnode_t *dict_next(dict_t *dict, dnode_t *curr)
jardineb5d44e2003-12-23 08:09:43 +0000872{
hassoffe543a2005-09-25 12:04:25 +0000873 dnode_t *nil = dict_nil(dict), *parent, *left;
jardineb5d44e2003-12-23 08:09:43 +0000874
hassoffe543a2005-09-25 12:04:25 +0000875 if (curr->right != nil) {
876 curr = curr->right;
877 while ((left = curr->left) != nil)
878 curr = left;
879 return curr;
jardineb5d44e2003-12-23 08:09:43 +0000880 }
881
hassoffe543a2005-09-25 12:04:25 +0000882 parent = curr->parent;
jardineb5d44e2003-12-23 08:09:43 +0000883
hassoffe543a2005-09-25 12:04:25 +0000884 while (parent != nil && curr == parent->right) {
885 curr = parent;
886 parent = curr->parent;
jardineb5d44e2003-12-23 08:09:43 +0000887 }
888
hassoffe543a2005-09-25 12:04:25 +0000889 return (parent == nil) ? NULL : parent;
jardineb5d44e2003-12-23 08:09:43 +0000890}
891
892/*
893 * Return the given node's predecessor, in the key order.
894 * The nil sentinel node is returned if there is no predecessor.
895 */
896
hassoffe543a2005-09-25 12:04:25 +0000897dnode_t *dict_prev(dict_t *dict, dnode_t *curr)
jardineb5d44e2003-12-23 08:09:43 +0000898{
hassoffe543a2005-09-25 12:04:25 +0000899 dnode_t *nil = dict_nil(dict), *parent, *right;
jardineb5d44e2003-12-23 08:09:43 +0000900
hassoffe543a2005-09-25 12:04:25 +0000901 if (curr->left != nil) {
902 curr = curr->left;
903 while ((right = curr->right) != nil)
904 curr = right;
905 return curr;
jardineb5d44e2003-12-23 08:09:43 +0000906 }
907
hassoffe543a2005-09-25 12:04:25 +0000908 parent = curr->parent;
jardineb5d44e2003-12-23 08:09:43 +0000909
hassoffe543a2005-09-25 12:04:25 +0000910 while (parent != nil && curr == parent->left) {
911 curr = parent;
912 parent = curr->parent;
jardineb5d44e2003-12-23 08:09:43 +0000913 }
914
hassoffe543a2005-09-25 12:04:25 +0000915 return (parent == nil) ? NULL : parent;
jardineb5d44e2003-12-23 08:09:43 +0000916}
917
hassoffe543a2005-09-25 12:04:25 +0000918void dict_allow_dupes(dict_t *dict)
jardineb5d44e2003-12-23 08:09:43 +0000919{
hassoffe543a2005-09-25 12:04:25 +0000920 dict->dupes = 1;
jardineb5d44e2003-12-23 08:09:43 +0000921}
922
923#undef dict_count
924#undef dict_isempty
925#undef dict_isfull
926#undef dnode_get
927#undef dnode_put
928#undef dnode_getkey
929
hassoffe543a2005-09-25 12:04:25 +0000930dictcount_t dict_count(dict_t *dict)
jardineb5d44e2003-12-23 08:09:43 +0000931{
hassoffe543a2005-09-25 12:04:25 +0000932 return dict->nodecount;
jardineb5d44e2003-12-23 08:09:43 +0000933}
934
hassoffe543a2005-09-25 12:04:25 +0000935int dict_isempty(dict_t *dict)
jardineb5d44e2003-12-23 08:09:43 +0000936{
hassoffe543a2005-09-25 12:04:25 +0000937 return dict->nodecount == 0;
jardineb5d44e2003-12-23 08:09:43 +0000938}
939
hassoffe543a2005-09-25 12:04:25 +0000940int dict_isfull(dict_t *dict)
jardineb5d44e2003-12-23 08:09:43 +0000941{
hassoffe543a2005-09-25 12:04:25 +0000942 return dict->nodecount == dict->maxcount;
jardineb5d44e2003-12-23 08:09:43 +0000943}
944
hassoffe543a2005-09-25 12:04:25 +0000945int dict_contains(dict_t *dict, dnode_t *node)
jardineb5d44e2003-12-23 08:09:43 +0000946{
hassoffe543a2005-09-25 12:04:25 +0000947 return verify_dict_has_node(dict_nil(dict), dict_root(dict), node);
jardineb5d44e2003-12-23 08:09:43 +0000948}
949
hassoffe543a2005-09-25 12:04:25 +0000950static dnode_t *dnode_alloc(void *context)
jardineb5d44e2003-12-23 08:09:43 +0000951{
hassoffe543a2005-09-25 12:04:25 +0000952 return malloc(sizeof *dnode_alloc(NULL));
jardineb5d44e2003-12-23 08:09:43 +0000953}
954
hassoffe543a2005-09-25 12:04:25 +0000955static void dnode_free(dnode_t *node, void *context)
jardineb5d44e2003-12-23 08:09:43 +0000956{
hassoffe543a2005-09-25 12:04:25 +0000957 free(node);
jardineb5d44e2003-12-23 08:09:43 +0000958}
959
hassoffe543a2005-09-25 12:04:25 +0000960dnode_t *dnode_create(void *data)
jardineb5d44e2003-12-23 08:09:43 +0000961{
hassoffe543a2005-09-25 12:04:25 +0000962 dnode_t *new = malloc(sizeof *new);
963 if (new) {
964 new->data = data;
965 new->parent = NULL;
966 new->left = NULL;
967 new->right = NULL;
jardineb5d44e2003-12-23 08:09:43 +0000968 }
hassoffe543a2005-09-25 12:04:25 +0000969 return new;
jardineb5d44e2003-12-23 08:09:43 +0000970}
971
hassoffe543a2005-09-25 12:04:25 +0000972dnode_t *dnode_init(dnode_t *dnode, void *data)
jardineb5d44e2003-12-23 08:09:43 +0000973{
hassoffe543a2005-09-25 12:04:25 +0000974 dnode->data = data;
975 dnode->parent = NULL;
976 dnode->left = NULL;
977 dnode->right = NULL;
978 return dnode;
jardineb5d44e2003-12-23 08:09:43 +0000979}
980
hassoffe543a2005-09-25 12:04:25 +0000981void dnode_destroy(dnode_t *dnode)
jardineb5d44e2003-12-23 08:09:43 +0000982{
hassoffe543a2005-09-25 12:04:25 +0000983 assert (!dnode_is_in_a_dict(dnode));
984 free(dnode);
jardineb5d44e2003-12-23 08:09:43 +0000985}
986
hassoffe543a2005-09-25 12:04:25 +0000987void *dnode_get(dnode_t *dnode)
jardineb5d44e2003-12-23 08:09:43 +0000988{
hassoffe543a2005-09-25 12:04:25 +0000989 return dnode->data;
jardineb5d44e2003-12-23 08:09:43 +0000990}
991
hassoffe543a2005-09-25 12:04:25 +0000992const void *dnode_getkey(dnode_t *dnode)
jardineb5d44e2003-12-23 08:09:43 +0000993{
hassoffe543a2005-09-25 12:04:25 +0000994 return dnode->key;
jardineb5d44e2003-12-23 08:09:43 +0000995}
996
hassoffe543a2005-09-25 12:04:25 +0000997void dnode_put(dnode_t *dnode, void *data)
jardineb5d44e2003-12-23 08:09:43 +0000998{
hassoffe543a2005-09-25 12:04:25 +0000999 dnode->data = data;
jardineb5d44e2003-12-23 08:09:43 +00001000}
1001
hassoffe543a2005-09-25 12:04:25 +00001002int dnode_is_in_a_dict(dnode_t *dnode)
jardineb5d44e2003-12-23 08:09:43 +00001003{
hassoffe543a2005-09-25 12:04:25 +00001004 return (dnode->parent && dnode->left && dnode->right);
jardineb5d44e2003-12-23 08:09:43 +00001005}
1006
hassoffe543a2005-09-25 12:04:25 +00001007void dict_process(dict_t *dict, void *context, dnode_process_t function)
jardineb5d44e2003-12-23 08:09:43 +00001008{
hassoffe543a2005-09-25 12:04:25 +00001009 dnode_t *node = dict_first(dict), *next;
jardineb5d44e2003-12-23 08:09:43 +00001010
hassoffe543a2005-09-25 12:04:25 +00001011 while (node != NULL) {
1012 /* check for callback function deleting */
1013 /* the next node from under us */
1014 assert (dict_contains(dict, node));
1015 next = dict_next(dict, node);
1016 function(dict, node, context);
1017 node = next;
jardineb5d44e2003-12-23 08:09:43 +00001018 }
1019}
1020
hassoffe543a2005-09-25 12:04:25 +00001021static void load_begin_internal(dict_load_t *load, dict_t *dict)
jardineb5d44e2003-12-23 08:09:43 +00001022{
hassoffe543a2005-09-25 12:04:25 +00001023 load->dictptr = dict;
1024 load->nilnode.left = &load->nilnode;
1025 load->nilnode.right = &load->nilnode;
jardineb5d44e2003-12-23 08:09:43 +00001026}
1027
hassoffe543a2005-09-25 12:04:25 +00001028void dict_load_begin(dict_load_t *load, dict_t *dict)
jardineb5d44e2003-12-23 08:09:43 +00001029{
hassoffe543a2005-09-25 12:04:25 +00001030 assert (dict_isempty(dict));
1031 load_begin_internal(load, dict);
jardineb5d44e2003-12-23 08:09:43 +00001032}
1033
hassoffe543a2005-09-25 12:04:25 +00001034void dict_load_next(dict_load_t *load, dnode_t *newnode, const void *key)
jardineb5d44e2003-12-23 08:09:43 +00001035{
hassoffe543a2005-09-25 12:04:25 +00001036 dict_t *dict = load->dictptr;
1037 dnode_t *nil = &load->nilnode;
1038
1039 assert (!dnode_is_in_a_dict(newnode));
1040 assert (dict->nodecount < dict->maxcount);
jardineb5d44e2003-12-23 08:09:43 +00001041
hassoffe543a2005-09-25 12:04:25 +00001042 #ifndef NDEBUG
1043 if (dict->nodecount > 0) {
1044 if (dict->dupes)
1045 assert (dict->compare(nil->left->key, key) <= 0);
1046 else
1047 assert (dict->compare(nil->left->key, key) < 0);
jardineb5d44e2003-12-23 08:09:43 +00001048 }
hassoffe543a2005-09-25 12:04:25 +00001049 #endif
jardineb5d44e2003-12-23 08:09:43 +00001050
hassoffe543a2005-09-25 12:04:25 +00001051 newnode->key = key;
1052 nil->right->left = newnode;
1053 nil->right = newnode;
1054 newnode->left = nil;
1055 dict->nodecount++;
jardineb5d44e2003-12-23 08:09:43 +00001056}
1057
hassoffe543a2005-09-25 12:04:25 +00001058void dict_load_end(dict_load_t *load)
jardineb5d44e2003-12-23 08:09:43 +00001059{
hassoffe543a2005-09-25 12:04:25 +00001060 dict_t *dict = load->dictptr;
1061 dnode_t *tree[DICT_DEPTH_MAX] = { 0 };
1062 dnode_t *curr, *dictnil = dict_nil(dict), *loadnil = &load->nilnode, *next;
1063 dnode_t *complete = 0;
1064 dictcount_t fullcount = DICTCOUNT_T_MAX, nodecount = dict->nodecount;
1065 dictcount_t botrowcount;
1066 unsigned baselevel = 0, level = 0, i;
jardineb5d44e2003-12-23 08:09:43 +00001067
hassoffe543a2005-09-25 12:04:25 +00001068 assert (dnode_red == 0 && dnode_black == 1);
jardineb5d44e2003-12-23 08:09:43 +00001069
hassoffe543a2005-09-25 12:04:25 +00001070 while (fullcount >= nodecount && fullcount)
1071 fullcount >>= 1;
jardineb5d44e2003-12-23 08:09:43 +00001072
hassoffe543a2005-09-25 12:04:25 +00001073 botrowcount = nodecount - fullcount;
jardineb5d44e2003-12-23 08:09:43 +00001074
hassoffe543a2005-09-25 12:04:25 +00001075 for (curr = loadnil->left; curr != loadnil; curr = next) {
1076 next = curr->left;
jardineb5d44e2003-12-23 08:09:43 +00001077
hassoffe543a2005-09-25 12:04:25 +00001078 if (complete == NULL && botrowcount-- == 0) {
1079 assert (baselevel == 0);
1080 assert (level == 0);
1081 baselevel = level = 1;
1082 complete = tree[0];
jardineb5d44e2003-12-23 08:09:43 +00001083
hassoffe543a2005-09-25 12:04:25 +00001084 if (complete != 0) {
1085 tree[0] = 0;
1086 complete->right = dictnil;
1087 while (tree[level] != 0) {
1088 tree[level]->right = complete;
1089 complete->parent = tree[level];
1090 complete = tree[level];
1091 tree[level++] = 0;
jardineb5d44e2003-12-23 08:09:43 +00001092 }
1093 }
1094 }
1095
hassoffe543a2005-09-25 12:04:25 +00001096 if (complete == NULL) {
1097 curr->left = dictnil;
1098 curr->right = dictnil;
1099 curr->color = level % 2;
1100 complete = curr;
jardineb5d44e2003-12-23 08:09:43 +00001101
hassoffe543a2005-09-25 12:04:25 +00001102 assert (level == baselevel);
1103 while (tree[level] != 0) {
1104 tree[level]->right = complete;
1105 complete->parent = tree[level];
1106 complete = tree[level];
1107 tree[level++] = 0;
jardineb5d44e2003-12-23 08:09:43 +00001108 }
hassoffe543a2005-09-25 12:04:25 +00001109 } else {
1110 curr->left = complete;
1111 curr->color = (level + 1) % 2;
1112 complete->parent = curr;
1113 tree[level] = curr;
1114 complete = 0;
1115 level = baselevel;
jardineb5d44e2003-12-23 08:09:43 +00001116 }
1117 }
1118
hassoffe543a2005-09-25 12:04:25 +00001119 if (complete == NULL)
1120 complete = dictnil;
jardineb5d44e2003-12-23 08:09:43 +00001121
hassoffe543a2005-09-25 12:04:25 +00001122 for (i = 0; i < DICT_DEPTH_MAX; i++) {
1123 if (tree[i] != 0) {
1124 tree[i]->right = complete;
1125 complete->parent = tree[i];
1126 complete = tree[i];
jardineb5d44e2003-12-23 08:09:43 +00001127 }
1128 }
1129
hassoffe543a2005-09-25 12:04:25 +00001130 dictnil->color = dnode_black;
1131 dictnil->right = dictnil;
1132 complete->parent = dictnil;
1133 complete->color = dnode_black;
1134 dict_root(dict) = complete;
jardineb5d44e2003-12-23 08:09:43 +00001135
hassoffe543a2005-09-25 12:04:25 +00001136 assert (dict_verify(dict));
jardineb5d44e2003-12-23 08:09:43 +00001137}
1138
hassoffe543a2005-09-25 12:04:25 +00001139void dict_merge(dict_t *dest, dict_t *source)
jardineb5d44e2003-12-23 08:09:43 +00001140{
hassoffe543a2005-09-25 12:04:25 +00001141 dict_load_t load;
1142 dnode_t *leftnode = dict_first(dest), *rightnode = dict_first(source);
jardineb5d44e2003-12-23 08:09:43 +00001143
hassoffe543a2005-09-25 12:04:25 +00001144 assert (dict_similar(dest, source));
jardineb5d44e2003-12-23 08:09:43 +00001145
hassoffe543a2005-09-25 12:04:25 +00001146 if (source == dest)
1147 return;
jardineb5d44e2003-12-23 08:09:43 +00001148
hassoffe543a2005-09-25 12:04:25 +00001149 dest->nodecount = 0;
1150 load_begin_internal(&load, dest);
jardineb5d44e2003-12-23 08:09:43 +00001151
hassoffe543a2005-09-25 12:04:25 +00001152 for (;;) {
1153 if (leftnode != NULL && rightnode != NULL) {
1154 if (dest->compare(leftnode->key, rightnode->key) < 0)
1155 goto copyleft;
1156 else
1157 goto copyright;
1158 } else if (leftnode != NULL) {
jardineb5d44e2003-12-23 08:09:43 +00001159 goto copyleft;
hassoffe543a2005-09-25 12:04:25 +00001160 } else if (rightnode != NULL) {
jardineb5d44e2003-12-23 08:09:43 +00001161 goto copyright;
hassoffe543a2005-09-25 12:04:25 +00001162 } else {
1163 assert (leftnode == NULL && rightnode == NULL);
1164 break;
jardineb5d44e2003-12-23 08:09:43 +00001165 }
1166
1167 copyleft:
hassoffe543a2005-09-25 12:04:25 +00001168 {
1169 dnode_t *next = dict_next(dest, leftnode);
1170 #ifndef NDEBUG
1171 leftnode->left = NULL; /* suppress assertion in dict_load_next */
1172 #endif
1173 dict_load_next(&load, leftnode, leftnode->key);
1174 leftnode = next;
1175 continue;
1176 }
1177
jardineb5d44e2003-12-23 08:09:43 +00001178 copyright:
hassoffe543a2005-09-25 12:04:25 +00001179 {
1180 dnode_t *next = dict_next(source, rightnode);
1181 #ifndef NDEBUG
1182 rightnode->left = NULL;
1183 #endif
1184 dict_load_next(&load, rightnode, rightnode->key);
1185 rightnode = next;
1186 continue;
1187 }
jardineb5d44e2003-12-23 08:09:43 +00001188 }
1189
hassoffe543a2005-09-25 12:04:25 +00001190 dict_clear(source);
1191 dict_load_end(&load);
jardineb5d44e2003-12-23 08:09:43 +00001192}
1193
1194#ifdef KAZLIB_TEST_MAIN
1195
1196#include <stdio.h>
1197#include <string.h>
1198#include <ctype.h>
1199#include <stdarg.h>
1200
1201typedef char input_t[256];
1202
hassoffe543a2005-09-25 12:04:25 +00001203static int tokenize(char *string, ...)
jardineb5d44e2003-12-23 08:09:43 +00001204{
hassoffe543a2005-09-25 12:04:25 +00001205 char **tokptr;
1206 va_list arglist;
1207 int tokcount = 0;
jardineb5d44e2003-12-23 08:09:43 +00001208
hassoffe543a2005-09-25 12:04:25 +00001209 va_start(arglist, string);
1210 tokptr = va_arg(arglist, char **);
1211 while (tokptr) {
1212 while (*string && isspace((unsigned char) *string))
1213 string++;
1214 if (!*string)
1215 break;
1216 *tokptr = string;
1217 while (*string && !isspace((unsigned char) *string))
1218 string++;
1219 tokptr = va_arg(arglist, char **);
1220 tokcount++;
1221 if (!*string)
1222 break;
1223 *string++ = 0;
jardineb5d44e2003-12-23 08:09:43 +00001224 }
hassoffe543a2005-09-25 12:04:25 +00001225 va_end(arglist);
jardineb5d44e2003-12-23 08:09:43 +00001226
hassoffe543a2005-09-25 12:04:25 +00001227 return tokcount;
jardineb5d44e2003-12-23 08:09:43 +00001228}
1229
hassoffe543a2005-09-25 12:04:25 +00001230static int comparef(const void *key1, const void *key2)
jardineb5d44e2003-12-23 08:09:43 +00001231{
hassoffe543a2005-09-25 12:04:25 +00001232 return strcmp(key1, key2);
jardineb5d44e2003-12-23 08:09:43 +00001233}
1234
hassoffe543a2005-09-25 12:04:25 +00001235static char *dupstring(char *str)
jardineb5d44e2003-12-23 08:09:43 +00001236{
hassoffe543a2005-09-25 12:04:25 +00001237 int sz = strlen(str) + 1;
1238 char *new = malloc(sz);
1239 if (new)
1240 memcpy(new, str, sz);
1241 return new;
jardineb5d44e2003-12-23 08:09:43 +00001242}
1243
hassoffe543a2005-09-25 12:04:25 +00001244static dnode_t *new_node(void *c)
jardineb5d44e2003-12-23 08:09:43 +00001245{
hassoffe543a2005-09-25 12:04:25 +00001246 static dnode_t few[5];
1247 static int count;
jardineb5d44e2003-12-23 08:09:43 +00001248
hassoffe543a2005-09-25 12:04:25 +00001249 if (count < 5)
1250 return few + count++;
jardineb5d44e2003-12-23 08:09:43 +00001251
hassoffe543a2005-09-25 12:04:25 +00001252 return NULL;
jardineb5d44e2003-12-23 08:09:43 +00001253}
1254
hassoffe543a2005-09-25 12:04:25 +00001255static void del_node(dnode_t *n, void *c)
jardineb5d44e2003-12-23 08:09:43 +00001256{
1257}
1258
1259static int prompt = 0;
1260
hassoffe543a2005-09-25 12:04:25 +00001261static void construct(dict_t *d)
jardineb5d44e2003-12-23 08:09:43 +00001262{
hassoffe543a2005-09-25 12:04:25 +00001263 input_t in;
1264 int done = 0;
1265 dict_load_t dl;
1266 dnode_t *dn;
1267 char *tok1, *tok2, *val;
1268 const char *key;
1269 char *help =
1270 "p turn prompt on\n"
1271 "q finish construction\n"
1272 "a <key> <val> add new entry\n";
jardineb5d44e2003-12-23 08:09:43 +00001273
hassoffe543a2005-09-25 12:04:25 +00001274 if (!dict_isempty(d))
1275 puts("warning: dictionary not empty!");
jardineb5d44e2003-12-23 08:09:43 +00001276
hassoffe543a2005-09-25 12:04:25 +00001277 dict_load_begin(&dl, d);
jardineb5d44e2003-12-23 08:09:43 +00001278
hassoffe543a2005-09-25 12:04:25 +00001279 while (!done) {
1280 if (prompt)
1281 putchar('>');
1282 fflush(stdout);
jardineb5d44e2003-12-23 08:09:43 +00001283
hassoffe543a2005-09-25 12:04:25 +00001284 if (!fgets(in, sizeof(input_t), stdin))
1285 break;
jardineb5d44e2003-12-23 08:09:43 +00001286
hassoffe543a2005-09-25 12:04:25 +00001287 switch (in[0]) {
1288 case '?':
1289 puts(help);
1290 break;
1291 case 'p':
1292 prompt = 1;
1293 break;
1294 case 'q':
1295 done = 1;
1296 break;
1297 case 'a':
1298 if (tokenize(in+1, &tok1, &tok2, (char **) 0) != 2) {
1299 puts("what?");
1300 break;
1301 }
1302 key = dupstring(tok1);
1303 val = dupstring(tok2);
1304 dn = dnode_create(val);
jardineb5d44e2003-12-23 08:09:43 +00001305
hassoffe543a2005-09-25 12:04:25 +00001306 if (!key || !val || !dn) {
1307 puts("out of memory");
1308 free((void *) key);
1309 free(val);
1310 if (dn)
1311 dnode_destroy(dn);
1312 }
jardineb5d44e2003-12-23 08:09:43 +00001313
hassoffe543a2005-09-25 12:04:25 +00001314 dict_load_next(&dl, dn, key);
1315 break;
1316 default:
1317 putchar('?');
1318 putchar('\n');
1319 break;
jardineb5d44e2003-12-23 08:09:43 +00001320 }
1321 }
1322
hassoffe543a2005-09-25 12:04:25 +00001323 dict_load_end(&dl);
jardineb5d44e2003-12-23 08:09:43 +00001324}
1325
hassoffe543a2005-09-25 12:04:25 +00001326int main(void)
jardineb5d44e2003-12-23 08:09:43 +00001327{
hassoffe543a2005-09-25 12:04:25 +00001328 input_t in;
1329 dict_t darray[10];
1330 dict_t *d = &darray[0];
1331 dnode_t *dn;
1332 int i;
1333 char *tok1, *tok2, *val;
1334 const char *key;
jardineb5d44e2003-12-23 08:09:43 +00001335
hassoffe543a2005-09-25 12:04:25 +00001336 char *help =
1337 "a <key> <val> add value to dictionary\n"
1338 "d <key> delete value from dictionary\n"
1339 "l <key> lookup value in dictionary\n"
1340 "( <key> lookup lower bound\n"
1341 ") <key> lookup upper bound\n"
1342 "# <num> switch to alternate dictionary (0-9)\n"
1343 "j <num> <num> merge two dictionaries\n"
1344 "f free the whole dictionary\n"
1345 "k allow duplicate keys\n"
1346 "c show number of entries\n"
1347 "t dump whole dictionary in sort order\n"
1348 "m make dictionary out of sorted items\n"
1349 "p turn prompt on\n"
1350 "s switch to non-functioning allocator\n"
1351 "q quit";
jardineb5d44e2003-12-23 08:09:43 +00001352
hassoffe543a2005-09-25 12:04:25 +00001353 for (i = 0; i < sizeof darray / sizeof *darray; i++)
1354 dict_init(&darray[i], DICTCOUNT_T_MAX, comparef);
jardineb5d44e2003-12-23 08:09:43 +00001355
hassoffe543a2005-09-25 12:04:25 +00001356 for (;;) {
1357 if (prompt)
1358 putchar('>');
1359 fflush(stdout);
jardineb5d44e2003-12-23 08:09:43 +00001360
hassoffe543a2005-09-25 12:04:25 +00001361 if (!fgets(in, sizeof(input_t), stdin))
1362 break;
jardineb5d44e2003-12-23 08:09:43 +00001363
hassoffe543a2005-09-25 12:04:25 +00001364 switch(in[0]) {
1365 case '?':
1366 puts(help);
1367 break;
1368 case 'a':
1369 if (tokenize(in+1, &tok1, &tok2, (char **) 0) != 2) {
1370 puts("what?");
1371 break;
1372 }
1373 key = dupstring(tok1);
1374 val = dupstring(tok2);
jardineb5d44e2003-12-23 08:09:43 +00001375
hassoffe543a2005-09-25 12:04:25 +00001376 if (!key || !val) {
1377 puts("out of memory");
1378 free((void *) key);
1379 free(val);
1380 }
jardineb5d44e2003-12-23 08:09:43 +00001381
hassoffe543a2005-09-25 12:04:25 +00001382 if (!dict_alloc_insert(d, key, val)) {
1383 puts("dict_alloc_insert failed");
1384 free((void *) key);
1385 free(val);
1386 break;
1387 }
1388 break;
1389 case 'd':
1390 if (tokenize(in+1, &tok1, (char **) 0) != 1) {
1391 puts("what?");
1392 break;
1393 }
1394 dn = dict_lookup(d, tok1);
1395 if (!dn) {
1396 puts("dict_lookup failed");
1397 break;
1398 }
1399 val = dnode_get(dn);
1400 key = dnode_getkey(dn);
1401 dict_delete_free(d, dn);
jardineb5d44e2003-12-23 08:09:43 +00001402
hassoffe543a2005-09-25 12:04:25 +00001403 free(val);
1404 free((void *) key);
1405 break;
1406 case 'f':
1407 dict_free(d);
1408 break;
jardineb5d44e2003-12-23 08:09:43 +00001409 case 'l':
1410 case '(':
1411 case ')':
hassoffe543a2005-09-25 12:04:25 +00001412 if (tokenize(in+1, &tok1, (char **) 0) != 1) {
1413 puts("what?");
1414 break;
jardineb5d44e2003-12-23 08:09:43 +00001415 }
hassoffe543a2005-09-25 12:04:25 +00001416 dn = 0;
1417 switch (in[0]) {
1418 case 'l':
1419 dn = dict_lookup(d, tok1);
1420 break;
1421 case '(':
1422 dn = dict_lower_bound(d, tok1);
1423 break;
1424 case ')':
1425 dn = dict_upper_bound(d, tok1);
1426 break;
jardineb5d44e2003-12-23 08:09:43 +00001427 }
hassoffe543a2005-09-25 12:04:25 +00001428 if (!dn) {
1429 puts("lookup failed");
1430 break;
1431 }
1432 val = dnode_get(dn);
1433 puts(val);
1434 break;
1435 case 'm':
1436 construct(d);
1437 break;
1438 case 'k':
1439 dict_allow_dupes(d);
1440 break;
1441 case 'c':
1442 printf("%lu\n", (unsigned long) dict_count(d));
1443 break;
1444 case 't':
1445 for (dn = dict_first(d); dn; dn = dict_next(d, dn)) {
1446 printf("%s\t%s\n", (char *) dnode_getkey(dn),
1447 (char *) dnode_get(dn));
1448 }
1449 break;
1450 case 'q':
1451 exit(0);
1452 break;
1453 case '\0':
1454 break;
1455 case 'p':
1456 prompt = 1;
1457 break;
1458 case 's':
1459 dict_set_allocator(d, new_node, del_node, NULL);
1460 break;
1461 case '#':
1462 if (tokenize(in+1, &tok1, (char **) 0) != 1) {
1463 puts("what?");
1464 break;
1465 } else {
1466 int dictnum = atoi(tok1);
1467 if (dictnum < 0 || dictnum > 9) {
1468 puts("invalid number");
1469 break;
1470 }
1471 d = &darray[dictnum];
1472 }
1473 break;
1474 case 'j':
1475 if (tokenize(in+1, &tok1, &tok2, (char **) 0) != 2) {
1476 puts("what?");
1477 break;
1478 } else {
1479 int dict1 = atoi(tok1), dict2 = atoi(tok2);
1480 if (dict1 < 0 || dict1 > 9 || dict2 < 0 || dict2 > 9) {
1481 puts("invalid number");
1482 break;
1483 }
1484 dict_merge(&darray[dict1], &darray[dict2]);
1485 }
1486 break;
1487 default:
1488 putchar('?');
1489 putchar('\n');
1490 break;
jardineb5d44e2003-12-23 08:09:43 +00001491 }
1492 }
1493
hassoffe543a2005-09-25 12:04:25 +00001494 return 0;
jardineb5d44e2003-12-23 08:09:43 +00001495}
1496
1497#endif