GRASS 8 Programmer's Manual 8.6.0dev(2026)-1d1e47ad9d
Loading...
Searching...
No Matches
tavl.c
Go to the documentation of this file.
1/* Produced by texiweb from libavl.w. */
2
3/* libavl - library for manipulation of binary trees.
4 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004 Free Software
5 Foundation, Inc.
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 3 of the License, or (at your option) any later version.
11
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public
18 License along with this library; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 02110-1301 USA.
21 */
22
23/* Nov 2016, Markus Metz
24 * from libavl-2.0.3
25 * added safety checks and speed optimizations
26 */
27
28#include <assert.h>
29#include <stdio.h>
30#include <stdlib.h>
31#include "tavl.h"
32
33/* Creates and returns a new table
34 with comparison function |compare| using parameter |param|
35 and memory allocator |allocator|.
36 Returns |NULL| if memory allocation failed. */
37struct tavl_table *tavl_create(tavl_comparison_func *compare, void *param,
39{
40 struct tavl_table *tree;
41
43
44 if (allocator == NULL)
46
47 tree = allocator->libavl_malloc(allocator, sizeof *tree);
48 if (tree == NULL)
49 return NULL;
50
51 tree->tavl_root = NULL;
52 tree->tavl_compare = compare;
53 tree->tavl_param = param;
54 tree->tavl_alloc = allocator;
55 tree->tavl_count = 0;
56
57 return tree;
58}
59
60/* Search |tree| for an item matching |item|, and return it if found.
61 Otherwise return |NULL|. */
62void *tavl_find(const struct tavl_table *tree, const void *item)
63{
64 const struct tavl_node *p;
65
66 assert(tree != NULL && item != NULL);
67
68 p = tree->tavl_root;
69 while (p != NULL) {
70 int cmp, dir;
71
72 cmp = tree->tavl_compare(item, p->tavl_data, tree->tavl_param);
73 if (cmp == 0)
74 return p->tavl_data;
75
76 dir = cmp > 0;
77 if (p->tavl_tag[dir] == TAVL_CHILD)
78 p = p->tavl_link[dir];
79 else
80 p = NULL;
81 }
82
83 return NULL;
84}
85
86/* Inserts |item| into |tree| and returns a pointer to |item|'s address.
87 If a duplicate item is found in the tree,
88 returns a pointer to the duplicate without inserting |item|.
89 Returns |NULL| in case of memory allocation failure. */
90void **tavl_probe(struct tavl_table *tree, void *item)
91{
92 struct tavl_node *y,
93 *z; /* Top node to update balance factor, and parent. */
94 struct tavl_node *p, *q; /* Iterator, and parent. */
95 struct tavl_node *n; /* Newly inserted node. */
96 struct tavl_node *w; /* New root of rebalanced subtree. */
97 int dir; /* Direction to descend. */
98
99 unsigned char da[TAVL_MAX_HEIGHT]; /* Cached comparison results. */
100 int k = 0; /* Number of cached results. */
101
102 assert(tree != NULL && item != NULL);
103
104 z = (struct tavl_node *)&tree->tavl_root;
105 y = tree->tavl_root;
106 dir = 0;
107 q = z, p = y;
108 while (p != NULL) {
109 int cmp = tree->tavl_compare(item, p->tavl_data, tree->tavl_param);
110 if (cmp == 0)
111 return &p->tavl_data;
112
113 if (p->tavl_balance != 0)
114 z = q, y = p, k = 0;
115 da[k++] = dir = cmp > 0;
116
117 if (p->tavl_tag[dir] == TAVL_THREAD)
118 break;
119 q = p, p = p->tavl_link[dir];
120 }
121
122 n = tree->tavl_alloc->libavl_malloc(tree->tavl_alloc, sizeof *n);
123 if (n == NULL)
124 return NULL;
125
126 tree->tavl_count++;
127 n->tavl_data = item;
128 n->tavl_tag[0] = n->tavl_tag[1] = TAVL_THREAD;
129 n->tavl_balance = 0;
130 if (y == NULL) {
131 n->tavl_link[0] = n->tavl_link[1] = NULL;
132 tree->tavl_root = n;
133
134 return &n->tavl_data;
135 }
136 n->tavl_link[dir] = p->tavl_link[dir];
137 n->tavl_link[!dir] = p;
138 p->tavl_tag[dir] = TAVL_CHILD;
139 p->tavl_link[dir] = n;
140
141 p = y, k = 0;
142 while (p != n) {
143 if (da[k] == 0)
144 p->tavl_balance--;
145 else
146 p->tavl_balance++;
147 p = p->tavl_link[da[k]], k++;
148 }
149
150 if (y->tavl_balance == -2) {
151 struct tavl_node *x = y->tavl_link[0];
152
153 if (x->tavl_balance == -1) {
154 w = x;
155 if (x->tavl_tag[1] == TAVL_THREAD) {
156 x->tavl_tag[1] = TAVL_CHILD;
157 y->tavl_tag[0] = TAVL_THREAD;
158 y->tavl_link[0] = x;
159 }
160 else
161 y->tavl_link[0] = x->tavl_link[1];
162 x->tavl_link[1] = y;
163 x->tavl_balance = y->tavl_balance = 0;
164 }
165 else {
166 assert(x->tavl_balance == +1);
167 w = x->tavl_link[1];
168 x->tavl_link[1] = w->tavl_link[0];
169 w->tavl_link[0] = x;
170 y->tavl_link[0] = w->tavl_link[1];
171 w->tavl_link[1] = y;
172 if (w->tavl_balance == -1)
173 x->tavl_balance = 0, y->tavl_balance = +1;
174 else if (w->tavl_balance == 0)
175 x->tavl_balance = y->tavl_balance = 0;
176 else /* |w->tavl_balance == +1| */
177 x->tavl_balance = -1, y->tavl_balance = 0;
178 w->tavl_balance = 0;
179 if (w->tavl_tag[0] == TAVL_THREAD) {
180 x->tavl_tag[1] = TAVL_THREAD;
181 x->tavl_link[1] = w;
182 w->tavl_tag[0] = TAVL_CHILD;
183 }
184 if (w->tavl_tag[1] == TAVL_THREAD) {
185 y->tavl_tag[0] = TAVL_THREAD;
186 y->tavl_link[0] = w;
187 w->tavl_tag[1] = TAVL_CHILD;
188 }
189 }
190 }
191 else if (y->tavl_balance == +2) {
192 struct tavl_node *x = y->tavl_link[1];
193
194 if (x->tavl_balance == +1) {
195 w = x;
196 if (x->tavl_tag[0] == TAVL_THREAD) {
197 x->tavl_tag[0] = TAVL_CHILD;
198 y->tavl_tag[1] = TAVL_THREAD;
199 y->tavl_link[1] = x;
200 }
201 else
202 y->tavl_link[1] = x->tavl_link[0];
203 x->tavl_link[0] = y;
204 x->tavl_balance = y->tavl_balance = 0;
205 }
206 else {
207 assert(x->tavl_balance == -1);
208 w = x->tavl_link[0];
209 x->tavl_link[0] = w->tavl_link[1];
210 w->tavl_link[1] = x;
211 y->tavl_link[1] = w->tavl_link[0];
212 w->tavl_link[0] = y;
213 if (w->tavl_balance == +1)
214 x->tavl_balance = 0, y->tavl_balance = -1;
215 else if (w->tavl_balance == 0)
216 x->tavl_balance = y->tavl_balance = 0;
217 else /* |w->tavl_balance == -1| */
218 x->tavl_balance = +1, y->tavl_balance = 0;
219 w->tavl_balance = 0;
220 if (w->tavl_tag[0] == TAVL_THREAD) {
221 y->tavl_tag[1] = TAVL_THREAD;
222 y->tavl_link[1] = w;
223 w->tavl_tag[0] = TAVL_CHILD;
224 }
225 if (w->tavl_tag[1] == TAVL_THREAD) {
226 x->tavl_tag[0] = TAVL_THREAD;
227 x->tavl_link[0] = w;
228 w->tavl_tag[1] = TAVL_CHILD;
229 }
230 }
231 }
232 else
233 return &n->tavl_data;
234 z->tavl_link[y != z->tavl_link[0]] = w;
235
236 return &n->tavl_data;
237}
238
239/* Inserts |item| into |table|.
240 Returns |NULL| if |item| was successfully inserted
241 or if a memory allocation error occurred.
242 Otherwise, returns the duplicate item. */
243void *tavl_insert(struct tavl_table *table, void *item)
244{
245 void **p = tavl_probe(table, item);
246
247 return p == NULL || *p == item ? NULL : *p;
248}
249
250/* Inserts |item| into |table|, replacing any duplicate item.
251 Returns |NULL| if |item| was inserted without replacing a duplicate,
252 or if a memory allocation error occurred.
253 Otherwise, returns the item that was replaced. */
254void *tavl_replace(struct tavl_table *table, void *item)
255{
256 void **p = tavl_probe(table, item);
257
258 if (p == NULL || *p == item)
259 return NULL;
260 else {
261 void *r = *p;
262
263 *p = item;
264
265 return r;
266 }
267}
268
269/* Returns the parent of |node| within |tree|,
270 or a pointer to |tavl_root| if |s| is the root of the tree. */
271static struct tavl_node *find_parent(struct tavl_table *tree,
272 struct tavl_node *node)
273{
274 if (node != tree->tavl_root) {
275 struct tavl_node *x, *y;
276
277 for (x = y = node;; x = x->tavl_link[0], y = y->tavl_link[1])
278 if (y->tavl_tag[1] == TAVL_THREAD) {
279 struct tavl_node *p = y->tavl_link[1];
280
281 if (p == NULL || p->tavl_link[0] != node) {
282 while (x->tavl_tag[0] == TAVL_CHILD)
283 x = x->tavl_link[0];
284 p = x->tavl_link[0];
285 }
286 return p;
287 }
288 else if (x->tavl_tag[0] == TAVL_THREAD) {
289 struct tavl_node *p = x->tavl_link[0];
290
291 if (p == NULL || p->tavl_link[1] != node) {
292 while (y->tavl_tag[1] == TAVL_CHILD)
293 y = y->tavl_link[1];
294 p = y->tavl_link[1];
295 }
296 return p;
297 }
298 }
299 else
300 return (struct tavl_node *)&tree->tavl_root;
301}
302
303/* Deletes from |tree| and returns an item matching |item|.
304 Returns a null pointer if no matching item found. */
305void *tavl_delete(struct tavl_table *tree, const void *item)
306{
307 struct tavl_node *p; /* Traverses tree to find node to delete. */
308 struct tavl_node *q; /* Parent of |p|. */
309 int dir; /* Index into |q->tavl_link[]| to get |p|. */
310 int cmp; /* Result of comparison between |item| and |p|. */
311
312 assert(tree != NULL && item != NULL);
313
314 q = (struct tavl_node *)&tree->tavl_root;
315 p = tree->tavl_root;
316 dir = 0;
317 while (p != NULL) {
318 cmp = tree->tavl_compare(item, p->tavl_data, tree->tavl_param);
319
320 if (cmp == 0)
321 break;
322
323 dir = cmp > 0;
324
325 q = p;
326 if (p->tavl_tag[dir] == TAVL_CHILD)
327 p = p->tavl_link[dir];
328 else
329 p = NULL;
330 }
331 if (p == NULL)
332 return NULL;
333
334 item = p->tavl_data;
335
336 if (p->tavl_tag[1] == TAVL_THREAD) {
337 if (p->tavl_tag[0] == TAVL_CHILD) {
338 struct tavl_node *t = p->tavl_link[0];
339
340 while (t->tavl_tag[1] == TAVL_CHILD)
341 t = t->tavl_link[1];
342 t->tavl_link[1] = p->tavl_link[1];
343 q->tavl_link[dir] = p->tavl_link[0];
344 }
345 else {
346 q->tavl_link[dir] = p->tavl_link[dir];
347 if (q != (struct tavl_node *)&tree->tavl_root)
348 q->tavl_tag[dir] = TAVL_THREAD;
349 }
350 }
351 else {
352 struct tavl_node *r = p->tavl_link[1];
353
354 if (r->tavl_tag[0] == TAVL_THREAD) {
355 r->tavl_link[0] = p->tavl_link[0];
356 r->tavl_tag[0] = p->tavl_tag[0];
357 if (r->tavl_tag[0] == TAVL_CHILD) {
358 struct tavl_node *t = r->tavl_link[0];
359
360 while (t->tavl_tag[1] == TAVL_CHILD)
361 t = t->tavl_link[1];
362 t->tavl_link[1] = r;
363 }
364 q->tavl_link[dir] = r;
365 r->tavl_balance = p->tavl_balance;
366 q = r;
367 dir = 1;
368 }
369 else {
370 struct tavl_node *s;
371
372 while (r != NULL) {
373 s = r->tavl_link[0];
374 if (s->tavl_tag[0] == TAVL_THREAD)
375 break;
376
377 r = s;
378 }
379
380 if (s->tavl_tag[1] == TAVL_CHILD)
381 r->tavl_link[0] = s->tavl_link[1];
382 else {
383 r->tavl_link[0] = s;
384 r->tavl_tag[0] = TAVL_THREAD;
385 }
386
387 s->tavl_link[0] = p->tavl_link[0];
388 if (p->tavl_tag[0] == TAVL_CHILD) {
389 struct tavl_node *t = p->tavl_link[0];
390
391 while (t->tavl_tag[1] == TAVL_CHILD)
392 t = t->tavl_link[1];
393 t->tavl_link[1] = s;
394
395 s->tavl_tag[0] = TAVL_CHILD;
396 }
397
398 s->tavl_link[1] = p->tavl_link[1];
399 s->tavl_tag[1] = TAVL_CHILD;
400
401 q->tavl_link[dir] = s;
403 q = r;
404 dir = 0;
405 }
406 }
407
408 tree->tavl_alloc->libavl_free(tree->tavl_alloc, p);
409
410 while (q != (struct tavl_node *)&tree->tavl_root) {
411 struct tavl_node *y = q;
412
413 q = find_parent(tree, y);
414
415 if (dir == 0) {
416 dir = q->tavl_link[0] != y;
417 y->tavl_balance++;
418 if (y->tavl_balance == +1)
419 break;
420 else if (y->tavl_balance == +2) {
421 struct tavl_node *x = y->tavl_link[1];
422
423 assert(x != NULL);
424 if (x->tavl_balance == -1) {
425 struct tavl_node *w;
426
427 assert(x->tavl_balance == -1);
428 w = x->tavl_link[0];
429 x->tavl_link[0] = w->tavl_link[1];
430 w->tavl_link[1] = x;
431 y->tavl_link[1] = w->tavl_link[0];
432 w->tavl_link[0] = y;
433 if (w->tavl_balance == +1)
434 x->tavl_balance = 0, y->tavl_balance = -1;
435 else if (w->tavl_balance == 0)
436 x->tavl_balance = y->tavl_balance = 0;
437 else /* |w->tavl_balance == -1| */
438 x->tavl_balance = +1, y->tavl_balance = 0;
439 w->tavl_balance = 0;
440 if (w->tavl_tag[0] == TAVL_THREAD) {
441 y->tavl_tag[1] = TAVL_THREAD;
442 y->tavl_link[1] = w;
443 w->tavl_tag[0] = TAVL_CHILD;
444 }
445 if (w->tavl_tag[1] == TAVL_THREAD) {
446 x->tavl_tag[0] = TAVL_THREAD;
447 x->tavl_link[0] = w;
448 w->tavl_tag[1] = TAVL_CHILD;
449 }
450 q->tavl_link[dir] = w;
451 }
452 else {
453 q->tavl_link[dir] = x;
454
455 if (x->tavl_balance == 0) {
456 y->tavl_link[1] = x->tavl_link[0];
457 x->tavl_link[0] = y;
458 x->tavl_balance = -1;
459 y->tavl_balance = +1;
460 break;
461 }
462 else { /* |x->tavl_balance == +1| */
463
464 if (x->tavl_tag[0] == TAVL_CHILD)
465 y->tavl_link[1] = x->tavl_link[0];
466 else {
467 y->tavl_tag[1] = TAVL_THREAD;
468 x->tavl_tag[0] = TAVL_CHILD;
469 }
470 x->tavl_link[0] = y;
471 y->tavl_balance = x->tavl_balance = 0;
472 }
473 }
474 }
475 }
476 else {
477 dir = q->tavl_link[0] != y;
478 y->tavl_balance--;
479 if (y->tavl_balance == -1)
480 break;
481 else if (y->tavl_balance == -2) {
482 struct tavl_node *x = y->tavl_link[0];
483
484 assert(x != NULL);
485 if (x->tavl_balance == +1) {
486 struct tavl_node *w;
487
488 assert(x->tavl_balance == +1);
489 w = x->tavl_link[1];
490 x->tavl_link[1] = w->tavl_link[0];
491 w->tavl_link[0] = x;
492 y->tavl_link[0] = w->tavl_link[1];
493 w->tavl_link[1] = y;
494 if (w->tavl_balance == -1)
495 x->tavl_balance = 0, y->tavl_balance = +1;
496 else if (w->tavl_balance == 0)
497 x->tavl_balance = y->tavl_balance = 0;
498 else /* |w->tavl_balance == +1| */
499 x->tavl_balance = -1, y->tavl_balance = 0;
500 w->tavl_balance = 0;
501 if (w->tavl_tag[0] == TAVL_THREAD) {
502 x->tavl_tag[1] = TAVL_THREAD;
503 x->tavl_link[1] = w;
504 w->tavl_tag[0] = TAVL_CHILD;
505 }
506 if (w->tavl_tag[1] == TAVL_THREAD) {
507 y->tavl_tag[0] = TAVL_THREAD;
508 y->tavl_link[0] = w;
509 w->tavl_tag[1] = TAVL_CHILD;
510 }
511 q->tavl_link[dir] = w;
512 }
513 else {
514 q->tavl_link[dir] = x;
515
516 if (x->tavl_balance == 0) {
517 y->tavl_link[0] = x->tavl_link[1];
518 x->tavl_link[1] = y;
519 x->tavl_balance = +1;
520 y->tavl_balance = -1;
521 break;
522 }
523 else { /* |x->tavl_balance == -1| */
524
525 if (x->tavl_tag[1] == TAVL_CHILD)
526 y->tavl_link[0] = x->tavl_link[1];
527 else {
528 y->tavl_tag[0] = TAVL_THREAD;
529 x->tavl_tag[1] = TAVL_CHILD;
530 }
531 x->tavl_link[1] = y;
532 y->tavl_balance = x->tavl_balance = 0;
533 }
534 }
535 }
536 }
537 }
538
539 tree->tavl_count--;
540
541 return (void *)item;
542}
543
544/* Initializes |trav| for use with |tree|
545 and selects the null node. */
546void tavl_t_init(struct tavl_traverser *trav, struct tavl_table *tree)
547{
548 trav->tavl_table = tree;
549 trav->tavl_node = NULL;
550}
551
552/* Initializes |trav| for |tree|.
553 Returns data item in |tree| with the least value,
554 or |NULL| if |tree| is empty. */
555void *tavl_t_first(struct tavl_traverser *trav, struct tavl_table *tree)
556{
557 assert(tree != NULL && trav != NULL);
558
559 trav->tavl_table = tree;
560 trav->tavl_node = tree->tavl_root;
561 if (trav->tavl_node != NULL) {
562 while (trav->tavl_node->tavl_tag[0] == TAVL_CHILD)
563 trav->tavl_node = trav->tavl_node->tavl_link[0];
564 return trav->tavl_node->tavl_data;
565 }
566 else
567 return NULL;
568}
569
570/* Initializes |trav| for |tree|.
571 Returns data item in |tree| with the greatest value,
572 or |NULL| if |tree| is empty. */
573void *tavl_t_last(struct tavl_traverser *trav, struct tavl_table *tree)
574{
575 assert(tree != NULL && trav != NULL);
576
577 trav->tavl_table = tree;
578 trav->tavl_node = tree->tavl_root;
579 if (trav->tavl_node != NULL) {
580 while (trav->tavl_node->tavl_tag[1] == TAVL_CHILD)
581 trav->tavl_node = trav->tavl_node->tavl_link[1];
582 return trav->tavl_node->tavl_data;
583 }
584 else
585 return NULL;
586}
587
588/* Searches for |item| in |tree|.
589 If found, initializes |trav| to the item found and returns the item
590 as well.
591 If there is no matching item, initializes |trav| to the null item
592 and returns |NULL|. */
593void *tavl_t_find(struct tavl_traverser *trav, struct tavl_table *tree,
594 void *item)
595{
596 struct tavl_node *p;
597
598 assert(trav != NULL && tree != NULL && item != NULL);
599
600 trav->tavl_table = tree;
601 trav->tavl_node = NULL;
602
603 p = tree->tavl_root;
604 while (p != NULL) {
605 int cmp, dir;
606
607 cmp = tree->tavl_compare(item, p->tavl_data, tree->tavl_param);
608 if (cmp == 0) {
609 trav->tavl_node = p;
610
611 return p->tavl_data;
612 }
613
614 dir = cmp > 0;
615 if (p->tavl_tag[dir] == TAVL_CHILD)
616 p = p->tavl_link[dir];
617 else
618 p = NULL;
619 }
620
621 trav->tavl_node = NULL;
622
623 return NULL;
624}
625
626/* Attempts to insert |item| into |tree|.
627 If |item| is inserted successfully, it is returned and |trav| is
628 initialized to its location.
629 If a duplicate is found, it is returned and |trav| is initialized to
630 its location. No replacement of the item occurs.
631 If a memory allocation failure occurs, |NULL| is returned and |trav|
632 is initialized to the null item. */
633void *tavl_t_insert(struct tavl_traverser *trav, struct tavl_table *tree,
634 void *item)
635{
636 void **p;
637
638 assert(trav != NULL && tree != NULL && item != NULL);
639
640 p = tavl_probe(tree, item);
641 if (p != NULL) {
642 trav->tavl_table = tree;
643 trav->tavl_node =
644 ((struct tavl_node *)((char *)p -
645 offsetof(struct tavl_node, tavl_data)));
646 return *p;
647 }
648 else {
649 tavl_t_init(trav, tree);
650
651 return NULL;
652 }
653}
654
655/* Initializes |trav| to have the same current node as |src|. */
656void *tavl_t_copy(struct tavl_traverser *trav, const struct tavl_traverser *src)
657{
658 assert(trav != NULL && src != NULL);
659
660 trav->tavl_table = src->tavl_table;
661 trav->tavl_node = src->tavl_node;
662
663 return trav->tavl_node != NULL ? trav->tavl_node->tavl_data : NULL;
664}
665
666/* Returns the next data item in inorder
667 within the tree being traversed with |trav|,
668 or if there are no more data items returns |NULL|. */
670{
671 assert(trav != NULL);
672
673 if (trav->tavl_node == NULL)
674 return tavl_t_first(trav, trav->tavl_table);
675 else if (trav->tavl_node->tavl_tag[1] == TAVL_THREAD) {
676 trav->tavl_node = trav->tavl_node->tavl_link[1];
677 return trav->tavl_node != NULL ? trav->tavl_node->tavl_data : NULL;
678 }
679 else {
680 trav->tavl_node = trav->tavl_node->tavl_link[1];
681 while (trav->tavl_node->tavl_tag[0] == TAVL_CHILD)
682 trav->tavl_node = trav->tavl_node->tavl_link[0];
683 return trav->tavl_node->tavl_data;
684 }
685}
686
687/* Returns the previous data item in inorder
688 within the tree being traversed with |trav|,
689 or if there are no more data items returns |NULL|. */
691{
692 assert(trav != NULL);
693
694 if (trav->tavl_node == NULL)
695 return tavl_t_last(trav, trav->tavl_table);
696 else if (trav->tavl_node->tavl_tag[0] == TAVL_THREAD) {
697 trav->tavl_node = trav->tavl_node->tavl_link[0];
698 return trav->tavl_node != NULL ? trav->tavl_node->tavl_data : NULL;
699 }
700 else {
701 trav->tavl_node = trav->tavl_node->tavl_link[0];
702 while (trav->tavl_node->tavl_tag[1] == TAVL_CHILD)
703 trav->tavl_node = trav->tavl_node->tavl_link[1];
704 return trav->tavl_node->tavl_data;
705 }
706}
707
708/* Returns |trav|'s current item. */
710{
711 assert(trav != NULL);
712
713 return trav->tavl_node != NULL ? trav->tavl_node->tavl_data : NULL;
714}
715
716/* Replaces the current item in |trav| by |new| and returns the item replaced.
717 |trav| must not have the null item selected.
718 The new item must not upset the ordering of the tree. */
719void *tavl_t_replace(struct tavl_traverser *trav, void *new)
720{
721 void *old;
722
723 assert(trav != NULL && trav->tavl_node != NULL && new != NULL);
724 old = trav->tavl_node->tavl_data;
725 trav->tavl_node->tavl_data = new;
726
727 return old;
728}
729
730/* Creates a new node as a child of |dst| on side |dir|.
731 Copies data and |tavl_balance| from |src| into the new node,
732 applying |copy()|, if non-null.
733 Returns nonzero only if fully successful.
734 Regardless of success, integrity of the tree structure is assured,
735 though failure may leave a null pointer in a |tavl_data| member. */
736static int copy_node(struct tavl_table *tree, struct tavl_node *dst, int dir,
737 const struct tavl_node *src, tavl_copy_func *copy)
738{
739 struct tavl_node *new =
740 tree->tavl_alloc->libavl_malloc(tree->tavl_alloc, sizeof *new);
741 if (new == NULL)
742 return 0;
743
744 new->tavl_link[dir] = dst->tavl_link[dir];
745 new->tavl_tag[dir] = TAVL_THREAD;
746 new->tavl_link[!dir] = dst;
747 new->tavl_tag[!dir] = TAVL_THREAD;
748 dst->tavl_link[dir] = new;
749 dst->tavl_tag[dir] = TAVL_CHILD;
750
751 new->tavl_balance = src->tavl_balance;
752 if (copy == NULL)
753 new->tavl_data = src->tavl_data;
754 else {
755 new->tavl_data = copy(src->tavl_data, tree->tavl_param);
756 if (new->tavl_data == NULL)
757 return 0;
758 }
759
760 return 1;
761}
762
763/* Destroys |new| with |tavl_destroy (new, destroy)|,
764 first initializing the right link in |new| that has
765 not yet been initialized. */
766static void copy_error_recovery(struct tavl_node *p, struct tavl_table *new,
768{
769 new->tavl_root = p;
770 if (p != NULL) {
771 while (p->tavl_tag[1] == TAVL_CHILD)
772 p = p->tavl_link[1];
773 p->tavl_link[1] = NULL;
774 }
775 tavl_destroy(new, destroy);
776}
777
778/* Copies |org| to a newly created tree, which is returned.
779 If |copy != NULL|, each data item in |org| is first passed to |copy|,
780 and the return values are inserted into the tree,
781 with |NULL| return values taken as indications of failure.
782 On failure, destroys the partially created new tree,
783 applying |destroy|, if non-null, to each item in the new tree so far,
784 and returns |NULL|.
785 If |allocator != NULL|, it is used for allocation in the new tree.
786 Otherwise, the same allocator used for |org| is used. */
790{
791 struct tavl_table *new;
792
793 const struct tavl_node *p;
794 struct tavl_node *q;
795 struct tavl_node rp, rq;
796
797 assert(org != NULL);
798 new = tavl_create(org->tavl_compare, org->tavl_param,
799 allocator != NULL ? allocator : org->tavl_alloc);
800 if (new == NULL)
801 return NULL;
802
803 new->tavl_count = org->tavl_count;
804 if (new->tavl_count == 0)
805 return new;
806
807 p = &rp;
808 rp.tavl_link[0] = org->tavl_root;
809 rp.tavl_tag[0] = TAVL_CHILD;
810
811 q = &rq;
812 rq.tavl_link[0] = NULL;
813 rq.tavl_tag[0] = TAVL_THREAD;
814
815 while (p != NULL) {
816 if (p->tavl_tag[0] == TAVL_CHILD) {
817 if (!copy_node(new, q, 0, p->tavl_link[0], copy)) {
818 copy_error_recovery(rq.tavl_link[0], new, destroy);
819 return NULL;
820 }
821
822 p = p->tavl_link[0];
823 q = q->tavl_link[0];
824 }
825 else {
826 while (p->tavl_tag[1] == TAVL_THREAD) {
827 p = p->tavl_link[1];
828 if (p == NULL) {
829 q->tavl_link[1] = NULL;
830 new->tavl_root = rq.tavl_link[0];
831 return new;
832 }
833
834 q = q->tavl_link[1];
835 }
836
837 p = p->tavl_link[1];
838 q = q->tavl_link[1];
839 }
840
841 if (p->tavl_tag[1] == TAVL_CHILD)
842 if (!copy_node(new, q, 1, p->tavl_link[1], copy)) {
843 copy_error_recovery(rq.tavl_link[0], new, destroy);
844 return NULL;
845 }
846 }
847
848 return new;
849}
850
851/* Frees storage allocated for |tree|.
852 If |destroy != NULL|, applies it to each data item in inorder. */
854{
855 struct tavl_node *p; /* Current node. */
856 struct tavl_node *n; /* Next node. */
857
858 p = tree->tavl_root;
859 if (p != NULL) {
860 while (p->tavl_tag[0] == TAVL_CHILD)
861 p = p->tavl_link[0];
862 }
863
864 while (p != NULL) {
865 n = p->tavl_link[1];
866 if (p->tavl_tag[1] == TAVL_CHILD)
867 while (n->tavl_tag[0] == TAVL_CHILD)
868 n = n->tavl_link[0];
869
870 if (destroy != NULL && p->tavl_data != NULL)
871 destroy(p->tavl_data, tree->tavl_param);
872 tree->tavl_alloc->libavl_free(tree->tavl_alloc, p);
873
874 p = n;
875 }
876
877 tree->tavl_alloc->libavl_free(tree->tavl_alloc, tree);
878}
879
880/* Allocates |size| bytes of space using |malloc()|.
881 Returns a null pointer if allocation fails. */
882void *tavl_malloc(struct libavl_allocator *allocator, size_t size)
883{
884 assert(allocator != NULL && size > 0);
885 return malloc(size);
886}
887
888/* Frees |block|. */
889void tavl_free(struct libavl_allocator *allocator, void *block)
890{
891 assert(allocator != NULL && block != NULL);
892 free(block);
893}
894
895/* Default memory allocator that uses |malloc()| and |free()|. */
897
898#undef NDEBUG
899#include <assert.h>
900
901/* Asserts that |tavl_insert()| succeeds at inserting |item| into |table|. */
902void(tavl_assert_insert)(struct tavl_table *table, void *item)
903{
904 void **p = tavl_probe(table, item);
905
906 assert(p != NULL && *p == item);
907}
908
909/* Asserts that |tavl_delete()| really removes |item| from |table|,
910 and returns the removed item. */
911void *(tavl_assert_delete)(struct tavl_table * table, void *item)
912{
913 void *p = tavl_delete(table, item);
914
915 assert(p != NULL);
916
917 return p;
918}
#define NULL
Definition ccmath.h:32
int compare(const void *a, const void *b)
Definition dgraph.c:168
#define assert(condition)
Definition lz4.c:291
double t
Definition r_raster.c:39
double r
Definition r_raster.c:39
void * malloc(unsigned)
void free(void *)
struct tavl_node * tavl_link[2]
Definition tavl.h:70
unsigned char tavl_tag[2]
Definition tavl.h:72
void * tavl_data
Definition tavl.h:71
signed char tavl_balance
Definition tavl.h:73
tavl_comparison_func * tavl_compare
Definition tavl.h:56
void * tavl_param
Definition tavl.h:57
struct libavl_allocator * tavl_alloc
Definition tavl.h:58
struct tavl_node * tavl_root
Definition tavl.h:55
size_t tavl_count
Definition tavl.h:59
struct tavl_node * tavl_node
Definition tavl.h:79
struct tavl_table * tavl_table
Definition tavl.h:78
void tavl_t_init(struct tavl_traverser *trav, struct tavl_table *tree)
Definition tavl.c:546
void * tavl_malloc(struct libavl_allocator *allocator, size_t size)
Definition tavl.c:882
void * tavl_t_last(struct tavl_traverser *trav, struct tavl_table *tree)
Definition tavl.c:573
void * tavl_t_cur(struct tavl_traverser *trav)
Definition tavl.c:709
struct tavl_table * tavl_create(tavl_comparison_func *compare, void *param, struct libavl_allocator *allocator)
Definition tavl.c:37
void *() tavl_assert_delete(struct tavl_table *table, void *item)
Definition tavl.c:911
struct libavl_allocator tavl_allocator_default
Definition tavl.c:896
void * tavl_insert(struct tavl_table *table, void *item)
Definition tavl.c:243
struct tavl_table * tavl_copy(const struct tavl_table *org, tavl_copy_func *copy, tavl_item_func *destroy, struct libavl_allocator *allocator)
Definition tavl.c:787
void * tavl_t_replace(struct tavl_traverser *trav, void *new)
Definition tavl.c:719
void ** tavl_probe(struct tavl_table *tree, void *item)
Definition tavl.c:90
void tavl_free(struct libavl_allocator *allocator, void *block)
Definition tavl.c:889
void * tavl_find(const struct tavl_table *tree, const void *item)
Definition tavl.c:62
void * tavl_t_prev(struct tavl_traverser *trav)
Definition tavl.c:690
void * tavl_t_copy(struct tavl_traverser *trav, const struct tavl_traverser *src)
Definition tavl.c:656
void * tavl_t_find(struct tavl_traverser *trav, struct tavl_table *tree, void *item)
Definition tavl.c:593
void * tavl_replace(struct tavl_table *table, void *item)
Definition tavl.c:254
void * tavl_delete(struct tavl_table *tree, const void *item)
Definition tavl.c:305
void * tavl_t_insert(struct tavl_traverser *trav, struct tavl_table *tree, void *item)
Definition tavl.c:633
void() tavl_assert_insert(struct tavl_table *table, void *item)
Definition tavl.c:902
void * tavl_t_next(struct tavl_traverser *trav)
Definition tavl.c:669
void tavl_destroy(struct tavl_table *tree, tavl_item_func *destroy)
Definition tavl.c:853
void * tavl_t_first(struct tavl_traverser *trav, struct tavl_table *tree)
Definition tavl.c:555
void tavl_item_func(void *tavl_item, void *tavl_param)
Definition tavl.h:31
#define TAVL_MAX_HEIGHT
Definition tavl.h:50
void * tavl_copy_func(void *tavl_item, void *tavl_param)
Definition tavl.h:32
@ TAVL_CHILD
Definition tavl.h:64
@ TAVL_THREAD
Definition tavl.h:65
int tavl_comparison_func(const void *tavl_a, const void *tavl_b, void *tavl_param)
Definition tavl.h:29
#define x