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