~ttx/openldap/lucid-gssapi-495418

« back to all changes in this revision

Viewing changes to libraries/liblutil/avl.c

  • Committer: Bazaar Package Importer
  • Author(s): Mathias Gug
  • Date: 2008-07-10 14:45:49 UTC
  • Revision ID: james.westby@ubuntu.com-20080710144549-wck73med0e72gfyo
Tags: upstream-2.4.10
ImportĀ upstreamĀ versionĀ 2.4.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* avl.c - routines to implement an avl tree */
 
2
/* $OpenLDAP: pkg/ldap/libraries/liblutil/avl.c,v 1.9.2.3 2008/02/11 23:26:42 kurt Exp $ */
 
3
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
 
4
 *
 
5
 * Copyright 1998-2008 The OpenLDAP Foundation.
 
6
 * All rights reserved.
 
7
 *
 
8
 * Redistribution and use in source and binary forms, with or without
 
9
 * modification, are permitted only as authorized by the OpenLDAP
 
10
 * Public License.
 
11
 *
 
12
 * A copy of this license is available in the file LICENSE in the
 
13
 * top-level directory of the distribution or, alternatively, at
 
14
 * <http://www.OpenLDAP.org/license.html>.
 
15
 */
 
16
/* Portions Copyright (c) 1993 Regents of the University of Michigan.
 
17
 * All rights reserved.
 
18
 *
 
19
 * Redistribution and use in source and binary forms are permitted
 
20
 * provided that this notice is preserved and that due credit is given
 
21
 * to the University of Michigan at Ann Arbor. The name of the University
 
22
 * may not be used to endorse or promote products derived from this
 
23
 * software without specific prior written permission. This software
 
24
 * is provided ``as is'' without express or implied warranty.
 
25
 */
 
26
/* ACKNOWLEDGEMENTS:
 
27
 * This work was originally developed by the University of Michigan
 
28
 * (as part of U-MICH LDAP).  Additional significant contributors
 
29
 * include:
 
30
 *   Howard Y. Chu
 
31
 *   Hallvard B. Furuseth
 
32
 *   Kurt D. Zeilenga
 
33
 */
 
34
 
 
35
#include "portable.h"
 
36
 
 
37
#include <stdio.h>
 
38
#include <ac/stdlib.h>
 
39
 
 
40
#ifdef CSRIMALLOC
 
41
#define ber_memalloc malloc
 
42
#define ber_memrealloc realloc
 
43
#define ber_memfree free
 
44
#else
 
45
#include "lber.h"
 
46
#endif
 
47
 
 
48
#define AVL_INTERNAL
 
49
#include "avl.h"
 
50
 
 
51
static const int avl_bfs[] = {LH, RH};
 
52
 
 
53
/*
 
54
 * avl_insert -- insert a node containing data data into the avl tree
 
55
 * with root root.  fcmp is a function to call to compare the data portion
 
56
 * of two nodes.  it should take two arguments and return <, >, or == 0,
 
57
 * depending on whether its first argument is <, >, or == its second
 
58
 * argument (like strcmp, e.g.).  fdup is a function to call when a duplicate
 
59
 * node is inserted.  it should return 0, or -1 and its return value
 
60
 * will be the return value from avl_insert in the case of a duplicate node.
 
61
 * the function will be called with the original node's data as its first
 
62
 * argument and with the incoming duplicate node's data as its second
 
63
 * argument.  this could be used, for example, to keep a count with each
 
64
 * node.
 
65
 *
 
66
 * NOTE: this routine may malloc memory
 
67
 */
 
68
int
 
69
avl_insert( Avlnode ** root, void *data, AVL_CMP fcmp, AVL_DUP fdup )
 
70
{
 
71
    Avlnode *t, *p, *s, *q, *r;
 
72
    int a, cmp, ncmp;
 
73
 
 
74
        if ( *root == NULL ) {
 
75
                if (( r = (Avlnode *) ber_memalloc( sizeof( Avlnode ))) == NULL ) {
 
76
                        return( -1 );
 
77
                }
 
78
                r->avl_link[0] = r->avl_link[1] = NULL;
 
79
                r->avl_data = data;
 
80
                r->avl_bf = EH;
 
81
                *root = r;
 
82
 
 
83
                return( 0 );
 
84
        }
 
85
 
 
86
    t = NULL;
 
87
    s = p = *root;
 
88
 
 
89
        /* find insertion point */
 
90
    while (1) {
 
91
                cmp = fcmp( data, p->avl_data );
 
92
                if ( cmp == 0 )
 
93
                        return (*fdup)( p->avl_data, data );
 
94
 
 
95
                cmp = (cmp > 0);
 
96
                q = p->avl_link[cmp];
 
97
                if (q == NULL) {
 
98
                        /* insert */
 
99
                        if (( q = (Avlnode *) ber_memalloc( sizeof( Avlnode ))) == NULL ) {
 
100
                                return( -1 );
 
101
                        }
 
102
                        q->avl_link[0] = q->avl_link[1] = NULL;
 
103
                        q->avl_data = data;
 
104
                        q->avl_bf = EH;
 
105
 
 
106
                        p->avl_link[cmp] = q;
 
107
                        break;
 
108
                } else if ( q->avl_bf ) {
 
109
                        t = p;
 
110
                        s = q;
 
111
                }
 
112
                p = q;
 
113
    }
 
114
 
 
115
    /* adjust balance factors */
 
116
    cmp = fcmp( data, s->avl_data ) > 0;
 
117
        r = p = s->avl_link[cmp];
 
118
        a = avl_bfs[cmp];
 
119
 
 
120
        while ( p != q ) {
 
121
                cmp = fcmp( data, p->avl_data ) > 0;
 
122
                p->avl_bf = avl_bfs[cmp];
 
123
                p = p->avl_link[cmp];
 
124
        }
 
125
 
 
126
        /* checks and balances */
 
127
 
 
128
        if ( s->avl_bf == EH ) {
 
129
                s->avl_bf = a;
 
130
                return 0;
 
131
        } else if ( s->avl_bf == -a ) {
 
132
                s->avl_bf = EH;
 
133
                return 0;
 
134
    } else if ( s->avl_bf == a ) {
 
135
                cmp = (a > 0);
 
136
                ncmp = !cmp;
 
137
                if ( r->avl_bf == a ) {
 
138
                        /* single rotation */
 
139
                        p = r;
 
140
                        s->avl_link[cmp] = r->avl_link[ncmp];
 
141
                        r->avl_link[ncmp] = s;
 
142
                        s->avl_bf = 0;
 
143
                        r->avl_bf = 0;
 
144
                } else if ( r->avl_bf == -a ) {
 
145
                        /* double rotation */
 
146
                        p = r->avl_link[ncmp];
 
147
                        r->avl_link[ncmp] = p->avl_link[cmp];
 
148
                        p->avl_link[cmp] = r;
 
149
                        s->avl_link[cmp] = p->avl_link[ncmp];
 
150
                        p->avl_link[ncmp] = s;
 
151
 
 
152
                        if ( p->avl_bf == a ) {
 
153
                                s->avl_bf = -a;
 
154
                                r->avl_bf = 0;
 
155
                        } else if ( p->avl_bf == -a ) {
 
156
                                s->avl_bf = 0;
 
157
                                r->avl_bf = a;
 
158
                        } else {
 
159
                                s->avl_bf = 0;
 
160
                                r->avl_bf = 0;
 
161
                        }
 
162
                        p->avl_bf = 0;
 
163
                }
 
164
                /* Update parent */
 
165
                if ( t == NULL )
 
166
                        *root = p;
 
167
                else if ( s == t->avl_right )
 
168
                        t->avl_right = p;
 
169
                else
 
170
                        t->avl_left = p;
 
171
    }
 
172
 
 
173
  return 0;
 
174
}
 
175
 
 
176
void*
 
177
avl_delete( Avlnode **root, void* data, AVL_CMP fcmp )
 
178
{
 
179
        Avlnode *p, *q, *r, *top;
 
180
        int side, side_bf, shorter, nside;
 
181
 
 
182
        /* parent stack */
 
183
        Avlnode *pptr[sizeof(void *)*8];
 
184
        unsigned char pdir[sizeof(void *)*8];
 
185
        int depth = 0;
 
186
 
 
187
        if ( *root == NULL )
 
188
                return NULL;
 
189
 
 
190
        p = *root;
 
191
 
 
192
        while (1) {
 
193
                side = fcmp( data, p->avl_data );
 
194
                if ( !side )
 
195
                        break;
 
196
                side = ( side > 0 );
 
197
                pdir[depth] = side;
 
198
                pptr[depth++] = p;
 
199
 
 
200
                p = p->avl_link[side];
 
201
                if ( p == NULL )
 
202
                        return p;
 
203
        }
 
204
        data = p->avl_data;
 
205
 
 
206
        /* If this node has two children, swap so we are deleting a node with
 
207
         * at most one child.
 
208
         */
 
209
        if ( p->avl_link[0] && p->avl_link[1] ) {
 
210
 
 
211
                /* find the immediate predecessor <q> */
 
212
                q = p->avl_link[0];
 
213
                side = depth;
 
214
                pdir[depth++] = 0;
 
215
                while (q->avl_link[1]) {
 
216
                        pdir[depth] = 1;
 
217
                        pptr[depth++] = q;
 
218
                        q = q->avl_link[1];
 
219
                }
 
220
                /* swap links */
 
221
                r = p->avl_link[0];
 
222
                p->avl_link[0] = q->avl_link[0];
 
223
                q->avl_link[0] = r;
 
224
 
 
225
                q->avl_link[1] = p->avl_link[1];
 
226
                p->avl_link[1] = NULL;
 
227
 
 
228
                q->avl_bf = p->avl_bf;
 
229
 
 
230
                /* fix stack positions: old parent of p points to q */
 
231
                pptr[side] = q;
 
232
                if ( side ) {
 
233
                        r = pptr[side-1];
 
234
                        r->avl_link[pdir[side-1]] = q;
 
235
                } else {
 
236
                        *root = q;
 
237
                }
 
238
                /* new parent of p points to p */
 
239
                if ( depth-side > 1 ) {
 
240
                        r = pptr[depth-1];
 
241
                        r->avl_link[1] = p;
 
242
                } else {
 
243
                        q->avl_link[0] = p;
 
244
                }
 
245
        }
 
246
 
 
247
        /* now <p> has at most one child, get it */
 
248
        q = p->avl_link[0] ? p->avl_link[0] : p->avl_link[1];
 
249
 
 
250
        ber_memfree( p );
 
251
 
 
252
        if ( !depth ) {
 
253
                *root = q;
 
254
                return data;
 
255
        }
 
256
 
 
257
        /* set the child into p's parent */
 
258
        depth--;
 
259
        p = pptr[depth];
 
260
        side = pdir[depth];
 
261
        p->avl_link[side] = q;
 
262
 
 
263
        top = NULL;
 
264
        shorter = 1;
 
265
  
 
266
        while ( shorter ) {
 
267
                p = pptr[depth];
 
268
                side = pdir[depth];
 
269
                nside = !side;
 
270
                side_bf = avl_bfs[side];
 
271
 
 
272
                /* case 1: height unchanged */
 
273
                if ( p->avl_bf == EH ) {
 
274
                        /* Tree is now heavier on opposite side */
 
275
                        p->avl_bf = avl_bfs[nside];
 
276
                        shorter = 0;
 
277
                  
 
278
                } else if ( p->avl_bf == side_bf ) {
 
279
                /* case 2: taller subtree shortened, height reduced */
 
280
                        p->avl_bf = EH;
 
281
                } else {
 
282
                /* case 3: shorter subtree shortened */
 
283
                        if ( depth )
 
284
                                top = pptr[depth-1]; /* p->parent; */
 
285
                        else
 
286
                                top = NULL;
 
287
                        /* set <q> to the taller of the two subtrees of <p> */
 
288
                        q = p->avl_link[nside];
 
289
                        if ( q->avl_bf == EH ) {
 
290
                                /* case 3a: height unchanged, single rotate */
 
291
                                p->avl_link[nside] = q->avl_link[side];
 
292
                                q->avl_link[side] = p;
 
293
                                shorter = 0;
 
294
                                q->avl_bf = side_bf;
 
295
                                p->avl_bf = (- side_bf);
 
296
 
 
297
                        } else if ( q->avl_bf == p->avl_bf ) {
 
298
                                /* case 3b: height reduced, single rotate */
 
299
                                p->avl_link[nside] = q->avl_link[side];
 
300
                                q->avl_link[side] = p;
 
301
                                shorter = 1;
 
302
                                q->avl_bf = EH;
 
303
                                p->avl_bf = EH;
 
304
 
 
305
                        } else {
 
306
                                /* case 3c: height reduced, balance factors opposite */
 
307
                                r = q->avl_link[side];
 
308
                                q->avl_link[side] = r->avl_link[nside];
 
309
                                r->avl_link[nside] = q;
 
310
 
 
311
                                p->avl_link[nside] = r->avl_link[side];
 
312
                                r->avl_link[side] = p;
 
313
 
 
314
                                if ( r->avl_bf == side_bf ) {
 
315
                                        q->avl_bf = (- side_bf);
 
316
                                        p->avl_bf = EH;
 
317
                                } else if ( r->avl_bf == (- side_bf)) {
 
318
                                        q->avl_bf = EH;
 
319
                                        p->avl_bf = side_bf;
 
320
                                } else {
 
321
                                        q->avl_bf = EH;
 
322
                                        p->avl_bf = EH;
 
323
                                }
 
324
                                r->avl_bf = EH;
 
325
                                q = r;
 
326
                        }
 
327
                        /* a rotation has caused <q> (or <r> in case 3c) to become
 
328
                         * the root.  let <p>'s former parent know this.
 
329
                         */
 
330
                        if ( top == NULL ) {
 
331
                                *root = q;
 
332
                        } else if (top->avl_link[0] == p) {
 
333
                                top->avl_link[0] = q;
 
334
                        } else {
 
335
                                top->avl_link[1] = q;
 
336
                        }
 
337
                        /* end case 3 */
 
338
                        p = q;
 
339
                }
 
340
                if ( !depth )
 
341
                        break;
 
342
                depth--;
 
343
        } /* end while(shorter) */
 
344
 
 
345
        return data;
 
346
}
 
347
 
 
348
static int
 
349
avl_inapply( Avlnode *root, AVL_APPLY fn, void* arg, int stopflag )
 
350
{
 
351
        if ( root == 0 )
 
352
                return( AVL_NOMORE );
 
353
 
 
354
        if ( root->avl_left != 0 )
 
355
                if ( avl_inapply( root->avl_left, fn, arg, stopflag ) 
 
356
                    == stopflag )
 
357
                        return( stopflag );
 
358
 
 
359
        if ( (*fn)( root->avl_data, arg ) == stopflag )
 
360
                return( stopflag );
 
361
 
 
362
        if ( root->avl_right == 0 )
 
363
                return( AVL_NOMORE );
 
364
        else
 
365
                return( avl_inapply( root->avl_right, fn, arg, stopflag ) );
 
366
}
 
367
 
 
368
static int
 
369
avl_postapply( Avlnode *root, AVL_APPLY fn, void* arg, int stopflag )
 
370
{
 
371
        if ( root == 0 )
 
372
                return( AVL_NOMORE );
 
373
 
 
374
        if ( root->avl_left != 0 )
 
375
                if ( avl_postapply( root->avl_left, fn, arg, stopflag ) 
 
376
                    == stopflag )
 
377
                        return( stopflag );
 
378
 
 
379
        if ( root->avl_right != 0 )
 
380
                if ( avl_postapply( root->avl_right, fn, arg, stopflag ) 
 
381
                    == stopflag )
 
382
                        return( stopflag );
 
383
 
 
384
        return( (*fn)( root->avl_data, arg ) );
 
385
}
 
386
 
 
387
static int
 
388
avl_preapply( Avlnode *root, AVL_APPLY fn, void* arg, int stopflag )
 
389
{
 
390
        if ( root == 0 )
 
391
                return( AVL_NOMORE );
 
392
 
 
393
        if ( (*fn)( root->avl_data, arg ) == stopflag )
 
394
                return( stopflag );
 
395
 
 
396
        if ( root->avl_left != 0 )
 
397
                if ( avl_preapply( root->avl_left, fn, arg, stopflag ) 
 
398
                    == stopflag )
 
399
                        return( stopflag );
 
400
 
 
401
        if ( root->avl_right == 0 )
 
402
                return( AVL_NOMORE );
 
403
        else
 
404
                return( avl_preapply( root->avl_right, fn, arg, stopflag ) );
 
405
}
 
406
 
 
407
/*
 
408
 * avl_apply -- avl tree root is traversed, function fn is called with
 
409
 * arguments arg and the data portion of each node.  if fn returns stopflag,
 
410
 * the traversal is cut short, otherwise it continues.  Do not use -6 as
 
411
 * a stopflag, as this is what is used to indicate the traversal ran out
 
412
 * of nodes.
 
413
 */
 
414
 
 
415
int
 
416
avl_apply( Avlnode *root, AVL_APPLY fn, void* arg, int stopflag, int type )
 
417
{
 
418
        switch ( type ) {
 
419
        case AVL_INORDER:
 
420
                return( avl_inapply( root, fn, arg, stopflag ) );
 
421
        case AVL_PREORDER:
 
422
                return( avl_preapply( root, fn, arg, stopflag ) );
 
423
        case AVL_POSTORDER:
 
424
                return( avl_postapply( root, fn, arg, stopflag ) );
 
425
        default:
 
426
                fprintf( stderr, "Invalid traversal type %d\n", type );
 
427
                return( -1 );
 
428
        }
 
429
 
 
430
        /* NOTREACHED */
 
431
}
 
432
 
 
433
/*
 
434
 * avl_prefixapply - traverse avl tree root, applying function fprefix
 
435
 * to any nodes that match.  fcmp is called with data as its first arg
 
436
 * and the current node's data as its second arg.  it should return
 
437
 * 0 if they match, < 0 if data is less, and > 0 if data is greater.
 
438
 * the idea is to efficiently find all nodes that are prefixes of
 
439
 * some key...  Like avl_apply, this routine also takes a stopflag
 
440
 * and will return prematurely if fmatch returns this value.  Otherwise,
 
441
 * AVL_NOMORE is returned.
 
442
 */
 
443
 
 
444
int
 
445
avl_prefixapply(
 
446
    Avlnode     *root,
 
447
    void*       data,
 
448
    AVL_CMP             fmatch,
 
449
    void*       marg,
 
450
    AVL_CMP             fcmp,
 
451
    void*       carg,
 
452
    int         stopflag
 
453
)
 
454
{
 
455
        int     cmp;
 
456
 
 
457
        if ( root == 0 )
 
458
                return( AVL_NOMORE );
 
459
 
 
460
        cmp = (*fcmp)( data, root->avl_data /* , carg */);
 
461
        if ( cmp == 0 ) {
 
462
                if ( (*fmatch)( root->avl_data, marg ) == stopflag )
 
463
                        return( stopflag );
 
464
 
 
465
                if ( root->avl_left != 0 )
 
466
                        if ( avl_prefixapply( root->avl_left, data, fmatch,
 
467
                            marg, fcmp, carg, stopflag ) == stopflag )
 
468
                                return( stopflag );
 
469
 
 
470
                if ( root->avl_right != 0 )
 
471
                        return( avl_prefixapply( root->avl_right, data, fmatch,
 
472
                            marg, fcmp, carg, stopflag ) );
 
473
                else
 
474
                        return( AVL_NOMORE );
 
475
 
 
476
        } else if ( cmp < 0 ) {
 
477
                if ( root->avl_left != 0 )
 
478
                        return( avl_prefixapply( root->avl_left, data, fmatch,
 
479
                            marg, fcmp, carg, stopflag ) );
 
480
        } else {
 
481
                if ( root->avl_right != 0 )
 
482
                        return( avl_prefixapply( root->avl_right, data, fmatch,
 
483
                            marg, fcmp, carg, stopflag ) );
 
484
        }
 
485
 
 
486
        return( AVL_NOMORE );
 
487
}
 
488
 
 
489
/*
 
490
 * avl_free -- traverse avltree root, freeing the memory it is using.
 
491
 * the dfree() is called to free the data portion of each node.  The
 
492
 * number of items actually freed is returned.
 
493
 */
 
494
 
 
495
int
 
496
avl_free( Avlnode *root, AVL_FREE dfree )
 
497
{
 
498
        int     nleft, nright;
 
499
 
 
500
        if ( root == 0 )
 
501
                return( 0 );
 
502
 
 
503
        nleft = nright = 0;
 
504
        if ( root->avl_left != 0 )
 
505
                nleft = avl_free( root->avl_left, dfree );
 
506
 
 
507
        if ( root->avl_right != 0 )
 
508
                nright = avl_free( root->avl_right, dfree );
 
509
 
 
510
        if ( dfree )
 
511
                (*dfree)( root->avl_data );
 
512
        ber_memfree( root );
 
513
 
 
514
        return( nleft + nright + 1 );
 
515
}
 
516
 
 
517
/*
 
518
 * avl_find -- search avltree root for a node with data data.  the function
 
519
 * cmp is used to compare things.  it is called with data as its first arg 
 
520
 * and the current node data as its second.  it should return 0 if they match,
 
521
 * < 0 if arg1 is less than arg2 and > 0 if arg1 is greater than arg2.
 
522
 */
 
523
 
 
524
Avlnode *
 
525
avl_find2( Avlnode *root, const void *data, AVL_CMP fcmp )
 
526
{
 
527
        int     cmp;
 
528
 
 
529
        while ( root != 0 && (cmp = (*fcmp)( data, root->avl_data )) != 0 ) {
 
530
                cmp = cmp > 0;
 
531
                root = root->avl_link[cmp];
 
532
        }
 
533
        return root;
 
534
}
 
535
 
 
536
void*
 
537
avl_find( Avlnode *root, const void* data, AVL_CMP fcmp )
 
538
{
 
539
        int     cmp;
 
540
 
 
541
        while ( root != 0 && (cmp = (*fcmp)( data, root->avl_data )) != 0 ) {
 
542
                cmp = cmp > 0;
 
543
                root = root->avl_link[cmp];
 
544
        }
 
545
 
 
546
        return( root ? root->avl_data : 0 );
 
547
}
 
548
 
 
549
/*
 
550
 * avl_find_lin -- search avltree root linearly for a node with data data. 
 
551
 * the function cmp is used to compare things.  it is called with data as its
 
552
 * first arg and the current node data as its second.  it should return 0 if
 
553
 * they match, non-zero otherwise.
 
554
 */
 
555
 
 
556
void*
 
557
avl_find_lin( Avlnode *root, const void* data, AVL_CMP fcmp )
 
558
{
 
559
        void*   res;
 
560
 
 
561
        if ( root == 0 )
 
562
                return( NULL );
 
563
 
 
564
        if ( (*fcmp)( data, root->avl_data ) == 0 )
 
565
                return( root->avl_data );
 
566
 
 
567
        if ( root->avl_left != 0 )
 
568
                if ( (res = avl_find_lin( root->avl_left, data, fcmp ))
 
569
                    != NULL )
 
570
                        return( res );
 
571
 
 
572
        if ( root->avl_right == 0 )
 
573
                return( NULL );
 
574
        else
 
575
                return( avl_find_lin( root->avl_right, data, fcmp ) );
 
576
}
 
577
 
 
578
/* NON-REENTRANT INTERFACE */
 
579
 
 
580
static void*    *avl_list;
 
581
static int      avl_maxlist;
 
582
static int      avl_nextlist;
 
583
 
 
584
#define AVL_GRABSIZE    100
 
585
 
 
586
/* ARGSUSED */
 
587
static int
 
588
avl_buildlist( void* data, void* arg )
 
589
{
 
590
        static int      slots;
 
591
 
 
592
        if ( avl_list == (void* *) 0 ) {
 
593
                avl_list = (void* *) ber_memalloc(AVL_GRABSIZE * sizeof(void*));
 
594
                slots = AVL_GRABSIZE;
 
595
                avl_maxlist = 0;
 
596
        } else if ( avl_maxlist == slots ) {
 
597
                slots += AVL_GRABSIZE;
 
598
                avl_list = (void* *) ber_memrealloc( (char *) avl_list,
 
599
                    (unsigned) slots * sizeof(void*));
 
600
        }
 
601
 
 
602
        avl_list[ avl_maxlist++ ] = data;
 
603
 
 
604
        return( 0 );
 
605
}
 
606
 
 
607
/*
 
608
 * avl_getfirst() and avl_getnext() are provided as alternate tree
 
609
 * traversal methods, to be used when a single function cannot be
 
610
 * provided to be called with every node in the tree.  avl_getfirst()
 
611
 * traverses the tree and builds a linear list of all the nodes,
 
612
 * returning the first node.  avl_getnext() returns the next thing
 
613
 * on the list built by avl_getfirst().  This means that avl_getfirst()
 
614
 * can take a while, and that the tree should not be messed with while
 
615
 * being traversed in this way, and that multiple traversals (even of
 
616
 * different trees) cannot be active at once.
 
617
 */
 
618
 
 
619
void*
 
620
avl_getfirst( Avlnode *root )
 
621
{
 
622
        if ( avl_list ) {
 
623
                ber_memfree( (char *) avl_list);
 
624
                avl_list = (void* *) 0;
 
625
        }
 
626
        avl_maxlist = 0;
 
627
        avl_nextlist = 0;
 
628
 
 
629
        if ( root == 0 )
 
630
                return( 0 );
 
631
 
 
632
        (void) avl_apply( root, avl_buildlist, (void*) 0, -1, AVL_INORDER );
 
633
 
 
634
        return( avl_list[ avl_nextlist++ ] );
 
635
}
 
636
 
 
637
void*
 
638
avl_getnext( void )
 
639
{
 
640
        if ( avl_list == 0 )
 
641
                return( 0 );
 
642
 
 
643
        if ( avl_nextlist == avl_maxlist ) {
 
644
                ber_memfree( (void*) avl_list);
 
645
                avl_list = (void* *) 0;
 
646
                return( 0 );
 
647
        }
 
648
 
 
649
        return( avl_list[ avl_nextlist++ ] );
 
650
}
 
651
 
 
652
/* end non-reentrant code */
 
653
 
 
654
 
 
655
int
 
656
avl_dup_error( void* left, void* right )
 
657
{
 
658
        return( -1 );
 
659
}
 
660
 
 
661
int
 
662
avl_dup_ok( void* left, void* right )
 
663
{
 
664
        return( 0 );
 
665
}