Back to index

openldap  2.4.31
memory.c
Go to the documentation of this file.
00001 /* $OpenLDAP$ */
00002 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
00003  *
00004  * Copyright 1998-2012 The OpenLDAP Foundation.
00005  * All rights reserved.
00006  *
00007  * Redistribution and use in source and binary forms, with or without
00008  * modification, are permitted only as authorized by the OpenLDAP
00009  * Public License.
00010  *
00011  * A copy of this license is available in the file LICENSE in the
00012  * top-level directory of the distribution or, alternatively, at
00013  * <http://www.OpenLDAP.org/license.html>.
00014  */
00015 
00016 #include "portable.h"
00017 
00018 #include <ac/stdlib.h>
00019 #include <ac/string.h>
00020 
00021 #include "lber-int.h"
00022 
00023 #ifdef LDAP_MEMORY_TRACE
00024 #include <stdio.h>
00025 #endif
00026 
00027 #ifdef LDAP_MEMORY_DEBUG
00028 /*
00029  * LDAP_MEMORY_DEBUG should only be enabled for the purposes of
00030  * debugging memory management within OpenLDAP libraries and slapd.
00031  *
00032  * It should only be enabled by an experienced developer as it causes
00033  * the inclusion of numerous assert()'s, many of which may be triggered
00034  * by a prefectly valid program.  If LDAP_MEMORY_DEBUG & 2 is true,
00035  * that includes asserts known to break both slapd and current clients.
00036  *
00037  * The code behind this macro is subject to change as needed to
00038  * support this testing.
00039  */
00040 
00041 struct ber_mem_hdr {
00042        ber_int_t     bm_top;       /* Pattern to detect buf overrun from prev buffer */
00043        ber_int_t     bm_length; /* Length of user allocated area */
00044 #ifdef LDAP_MEMORY_TRACE
00045        ber_int_t     bm_sequence; /* Allocation sequence number */
00046 #endif
00047        union bmu_align_u {  /* Force alignment, pattern to detect back clobber */
00048               ber_len_t     bmu_len_t;
00049               ber_tag_t     bmu_tag_t;
00050               ber_int_t     bmu_int_t;
00051 
00052               size_t bmu_size_t;
00053               void * bmu_voidp;
00054               double bmu_double;
00055               long   bmu_long;
00056               long   (*bmu_funcp)( double );
00057               unsigned char bmu_char[4];
00058        } ber_align;
00059 #define bm_junk      ber_align.bmu_len_t
00060 #define bm_data      ber_align.bmu_char[1]
00061 #define bm_char      ber_align.bmu_char
00062 };
00063 
00064 /* Pattern at top of allocated space */
00065 #define LBER_MEM_JUNK ((ber_int_t) 0xdeaddada)
00066 
00067 static const struct ber_mem_hdr ber_int_mem_hdr = { LBER_MEM_JUNK };
00068 
00069 /* Note sequence and ber_int_meminuse are counters, but are not
00070  * thread safe.  If you want to use these values for multithreaded applications,
00071  * you must put mutexes around them, otherwise they will have incorrect values.
00072  * When debugging, if you sort the debug output, the sequence number will 
00073  * put allocations/frees together.  It is then a simple matter to write a script
00074  * to find any allocations that don't have a buffer free function.
00075  */
00076 long ber_int_meminuse = 0;
00077 #ifdef LDAP_MEMORY_TRACE
00078 static ber_int_t sequence = 0;
00079 #endif
00080 
00081 /* Pattern placed just before user data */
00082 static unsigned char toppattern[4] = { 0xde, 0xad, 0xba, 0xde };
00083 /* Pattern placed just after user data */
00084 static unsigned char endpattern[4] = { 0xd1, 0xed, 0xde, 0xca };
00085 
00086 #define mbu_len sizeof(ber_int_mem_hdr.ber_align)
00087 
00088 /* Test if pattern placed just before user data is good */
00089 #define testdatatop(val) ( \
00090        *(val->bm_char+mbu_len-4)==toppattern[0] && \
00091        *(val->bm_char+mbu_len-3)==toppattern[1] && \
00092        *(val->bm_char+mbu_len-2)==toppattern[2] && \
00093        *(val->bm_char+mbu_len-1)==toppattern[3] )
00094 
00095 /* Place pattern just before user data */
00096 #define setdatatop(val)     *(val->bm_char+mbu_len-4)=toppattern[0]; \
00097        *(val->bm_char+mbu_len-3)=toppattern[1]; \
00098        *(val->bm_char+mbu_len-2)=toppattern[2]; \
00099        *(val->bm_char+mbu_len-1)=toppattern[3];
00100 
00101 /* Test if pattern placed just after user data is good */
00102 #define testend(val) (      *((unsigned char *)val+0)==endpattern[0] && \
00103        *((unsigned char *)val+1)==endpattern[1] && \
00104        *((unsigned char *)val+2)==endpattern[2] && \
00105        *((unsigned char *)val+3)==endpattern[3] )
00106 
00107 /* Place pattern just after user data */
00108 #define setend(val)         *((unsigned char *)val+0)=endpattern[0]; \
00109        *((unsigned char *)val+1)=endpattern[1]; \
00110        *((unsigned char *)val+2)=endpattern[2]; \
00111        *((unsigned char *)val+3)=endpattern[3];
00112 
00113 #define BER_MEM_BADADDR     ((void *) &ber_int_mem_hdr.bm_data)
00114 #define BER_MEM_VALID(p)    do { \
00115               assert( (p) != BER_MEM_BADADDR );  \
00116               assert( (p) != (void *) &ber_int_mem_hdr );      \
00117        } while(0)
00118 
00119 #else
00120 #define BER_MEM_VALID(p)    /* no-op */
00121 #endif
00122 
00123 BerMemoryFunctions *ber_int_memory_fns = NULL;
00124 
00125 void
00126 ber_memfree_x( void *p, void *ctx )
00127 {
00128        if( p == NULL ) {
00129               return;
00130        }
00131 
00132        BER_MEM_VALID( p );
00133 
00134        if( ber_int_memory_fns == NULL || ctx == NULL ) {
00135 #ifdef LDAP_MEMORY_DEBUG
00136               struct ber_mem_hdr *mh = (struct ber_mem_hdr *)
00137                      ((char *)p - sizeof(struct ber_mem_hdr));
00138               assert( mh->bm_top == LBER_MEM_JUNK);
00139               assert( testdatatop( mh));
00140               assert( testend( (char *)&mh[1] + mh->bm_length) );
00141               ber_int_meminuse -= mh->bm_length;
00142 
00143 #ifdef LDAP_MEMORY_TRACE
00144               fprintf(stderr, "0x%08lx 0x%08lx -f- %ld ber_memfree %ld\n",
00145                      (long)mh->bm_sequence, (long)mh, (long)mh->bm_length,
00146                      ber_int_meminuse);
00147 #endif
00148               /* Fill the free space with poison */
00149               memset( mh, 0xff, mh->bm_length + sizeof(struct ber_mem_hdr) + sizeof(ber_int_t));
00150               free( mh );
00151 #else
00152               free( p );
00153 #endif
00154               return;
00155        }
00156 
00157        assert( ber_int_memory_fns->bmf_free != 0 );
00158 
00159        (*ber_int_memory_fns->bmf_free)( p, ctx );
00160 }
00161 
00162 void
00163 ber_memfree( void *p )
00164 {
00165        ber_memfree_x(p, NULL);
00166 }
00167 
00168 void
00169 ber_memvfree_x( void **vec, void *ctx )
00170 {
00171        int    i;
00172 
00173        if( vec == NULL ) {
00174               return;
00175        }
00176 
00177        BER_MEM_VALID( vec );
00178 
00179        for ( i = 0; vec[i] != NULL; i++ ) {
00180               ber_memfree_x( vec[i], ctx );
00181        }
00182 
00183        ber_memfree_x( vec, ctx );
00184 }
00185 
00186 void
00187 ber_memvfree( void **vec )
00188 {
00189        ber_memvfree_x( vec, NULL );
00190 }
00191 
00192 void *
00193 ber_memalloc_x( ber_len_t s, void *ctx )
00194 {
00195        void *new;
00196 
00197        if( s == 0 ) {
00198               LDAP_MEMORY_DEBUG_ASSERT( s != 0 );
00199               return NULL;
00200        }
00201 
00202        if( ber_int_memory_fns == NULL || ctx == NULL ) {
00203 #ifdef LDAP_MEMORY_DEBUG
00204               new = malloc(s + sizeof(struct ber_mem_hdr) + sizeof( ber_int_t));
00205               if( new )
00206               {
00207               struct ber_mem_hdr *mh = new;
00208               mh->bm_top = LBER_MEM_JUNK;
00209               mh->bm_length = s;
00210               setdatatop( mh);
00211               setend( (char *)&mh[1] + mh->bm_length );
00212 
00213               ber_int_meminuse += mh->bm_length; /* Count mem inuse */
00214 
00215 #ifdef LDAP_MEMORY_TRACE
00216               mh->bm_sequence = sequence++;
00217               fprintf(stderr, "0x%08lx 0x%08lx -a- %ld ber_memalloc %ld\n",
00218                      (long)mh->bm_sequence, (long)mh, (long)mh->bm_length,
00219                      ber_int_meminuse);
00220 #endif
00221               /* poison new memory */
00222               memset( (char *)&mh[1], 0xff, s);
00223 
00224               BER_MEM_VALID( &mh[1] );
00225               new = &mh[1];
00226               }
00227 #else
00228               new = malloc( s );
00229 #endif
00230        } else {
00231               new = (*ber_int_memory_fns->bmf_malloc)( s, ctx );
00232        }
00233 
00234        if( new == NULL ) {
00235               ber_errno = LBER_ERROR_MEMORY;
00236        }
00237 
00238        return new;
00239 }
00240 
00241 void *
00242 ber_memalloc( ber_len_t s )
00243 {
00244        return ber_memalloc_x( s, NULL );
00245 }
00246 
00247 void *
00248 ber_memcalloc_x( ber_len_t n, ber_len_t s, void *ctx )
00249 {
00250        void *new;
00251 
00252        if( n == 0 || s == 0 ) {
00253               LDAP_MEMORY_DEBUG_ASSERT( n != 0 && s != 0);
00254               return NULL;
00255        }
00256 
00257        if( ber_int_memory_fns == NULL || ctx == NULL ) {
00258 #ifdef LDAP_MEMORY_DEBUG
00259               new = n < (-sizeof(struct ber_mem_hdr) - sizeof(ber_int_t)) / s
00260                      ? calloc(1, n*s + sizeof(struct ber_mem_hdr) + sizeof(ber_int_t))
00261                      : NULL;
00262               if( new )
00263               {
00264               struct ber_mem_hdr *mh = new;
00265 
00266               mh->bm_top = LBER_MEM_JUNK;
00267               mh->bm_length = n*s;
00268               setdatatop( mh);
00269               setend( (char *)&mh[1] + mh->bm_length );
00270 
00271               ber_int_meminuse += mh->bm_length;
00272 
00273 #ifdef LDAP_MEMORY_TRACE
00274               mh->bm_sequence = sequence++;
00275               fprintf(stderr, "0x%08lx 0x%08lx -a- %ld ber_memcalloc %ld\n",
00276                      (long)mh->bm_sequence, (long)mh, (long)mh->bm_length,
00277                      ber_int_meminuse);
00278 #endif
00279               BER_MEM_VALID( &mh[1] );
00280               new = &mh[1];
00281               }
00282 #else
00283               new = calloc( n, s );
00284 #endif
00285 
00286        } else {
00287               new = (*ber_int_memory_fns->bmf_calloc)( n, s, ctx );
00288        }
00289 
00290        if( new == NULL ) {
00291               ber_errno = LBER_ERROR_MEMORY;
00292        }
00293 
00294        return new;
00295 }
00296 
00297 void *
00298 ber_memcalloc( ber_len_t n, ber_len_t s )
00299 {
00300        return ber_memcalloc_x( n, s, NULL );
00301 }
00302 
00303 void *
00304 ber_memrealloc_x( void* p, ber_len_t s, void *ctx )
00305 {
00306        void *new = NULL;
00307 
00308        /* realloc(NULL,s) -> malloc(s) */
00309        if( p == NULL ) {
00310               return ber_memalloc_x( s, ctx );
00311        }
00312        
00313        /* realloc(p,0) -> free(p) */
00314        if( s == 0 ) {
00315               ber_memfree_x( p, ctx );
00316               return NULL;
00317        }
00318 
00319        BER_MEM_VALID( p );
00320 
00321        if( ber_int_memory_fns == NULL || ctx == NULL ) {
00322 #ifdef LDAP_MEMORY_DEBUG
00323               ber_int_t oldlen;
00324               struct ber_mem_hdr *mh = (struct ber_mem_hdr *)
00325                      ((char *)p - sizeof(struct ber_mem_hdr));
00326               assert( mh->bm_top == LBER_MEM_JUNK);
00327               assert( testdatatop( mh));
00328               assert( testend( (char *)&mh[1] + mh->bm_length) );
00329               oldlen = mh->bm_length;
00330 
00331               p = realloc( mh, s + sizeof(struct ber_mem_hdr) + sizeof(ber_int_t) );
00332               if( p == NULL ) {
00333                      ber_errno = LBER_ERROR_MEMORY;
00334                      return NULL;
00335               }
00336 
00337                      mh = p;
00338               mh->bm_length = s;
00339               setend( (char *)&mh[1] + mh->bm_length );
00340               if( s > oldlen ) {
00341                      /* poison any new memory */
00342                      memset( (char *)&mh[1] + oldlen, 0xff, s - oldlen);
00343               }
00344 
00345               assert( mh->bm_top == LBER_MEM_JUNK);
00346               assert( testdatatop( mh));
00347 
00348               ber_int_meminuse += s - oldlen;
00349 #ifdef LDAP_MEMORY_TRACE
00350               fprintf(stderr, "0x%08lx 0x%08lx -a- %ld ber_memrealloc %ld\n",
00351                      (long)mh->bm_sequence, (long)mh, (long)mh->bm_length,
00352                      ber_int_meminuse);
00353 #endif
00354                      BER_MEM_VALID( &mh[1] );
00355               return &mh[1];
00356 #else
00357               new = realloc( p, s );
00358 #endif
00359        } else {
00360               new = (*ber_int_memory_fns->bmf_realloc)( p, s, ctx );
00361        }
00362 
00363        if( new == NULL ) {
00364               ber_errno = LBER_ERROR_MEMORY;
00365        }
00366 
00367        return new;
00368 }
00369 
00370 void *
00371 ber_memrealloc( void* p, ber_len_t s )
00372 {
00373        return ber_memrealloc_x( p, s, NULL );
00374 }
00375 
00376 void
00377 ber_bvfree_x( struct berval *bv, void *ctx )
00378 {
00379        if( bv == NULL ) {
00380               return;
00381        }
00382 
00383        BER_MEM_VALID( bv );
00384 
00385        if ( bv->bv_val != NULL ) {
00386               ber_memfree_x( bv->bv_val, ctx );
00387        }
00388 
00389        ber_memfree_x( (char *) bv, ctx );
00390 }
00391 
00392 void
00393 ber_bvfree( struct berval *bv )
00394 {
00395        ber_bvfree_x( bv, NULL );
00396 }
00397 
00398 void
00399 ber_bvecfree_x( struct berval **bv, void *ctx )
00400 {
00401        int    i;
00402 
00403        if( bv == NULL ) {
00404               return;
00405        }
00406 
00407        BER_MEM_VALID( bv );
00408 
00409        /* count elements */
00410        for ( i = 0; bv[i] != NULL; i++ ) ;
00411 
00412        /* free in reverse order */
00413        for ( i--; i >= 0; i-- ) {
00414               ber_bvfree_x( bv[i], ctx );
00415        }
00416 
00417        ber_memfree_x( (char *) bv, ctx );
00418 }
00419 
00420 void
00421 ber_bvecfree( struct berval **bv )
00422 {
00423        ber_bvecfree_x( bv, NULL );
00424 }
00425 
00426 int
00427 ber_bvecadd_x( struct berval ***bvec, struct berval *bv, void *ctx )
00428 {
00429        ber_len_t i;
00430        struct berval **new;
00431 
00432        if( *bvec == NULL ) {
00433               if( bv == NULL ) {
00434                      /* nothing to add */
00435                      return 0;
00436               }
00437 
00438               *bvec = ber_memalloc_x( 2 * sizeof(struct berval *), ctx );
00439 
00440               if( *bvec == NULL ) {
00441                      return -1;
00442               }
00443 
00444               (*bvec)[0] = bv;
00445               (*bvec)[1] = NULL;
00446 
00447               return 1;
00448        }
00449 
00450        BER_MEM_VALID( bvec );
00451 
00452        /* count entries */
00453        for ( i = 0; (*bvec)[i] != NULL; i++ ) {
00454               /* EMPTY */;
00455        }
00456 
00457        if( bv == NULL ) {
00458               return i;
00459        }
00460 
00461        new = ber_memrealloc_x( *bvec, (i+2) * sizeof(struct berval *), ctx);
00462 
00463        if( new == NULL ) {
00464               return -1;
00465        }
00466 
00467        *bvec = new;
00468 
00469        (*bvec)[i++] = bv;
00470        (*bvec)[i] = NULL;
00471 
00472        return i;
00473 }
00474 
00475 int
00476 ber_bvecadd( struct berval ***bvec, struct berval *bv )
00477 {
00478        return ber_bvecadd_x( bvec, bv, NULL );
00479 }
00480 
00481 struct berval *
00482 ber_dupbv_x(
00483        struct berval *dst, struct berval *src, void *ctx )
00484 {
00485        struct berval *new;
00486 
00487        if( src == NULL ) {
00488               ber_errno = LBER_ERROR_PARAM;
00489               return NULL;
00490        }
00491 
00492        if ( dst ) {
00493               new = dst;
00494        } else {
00495               if(( new = ber_memalloc_x( sizeof(struct berval), ctx )) == NULL ) {
00496                      return NULL;
00497               }
00498        }
00499 
00500        if ( src->bv_val == NULL ) {
00501               new->bv_val = NULL;
00502               new->bv_len = 0;
00503               return new;
00504        }
00505 
00506        if(( new->bv_val = ber_memalloc_x( src->bv_len + 1, ctx )) == NULL ) {
00507               if ( !dst )
00508                      ber_memfree_x( new, ctx );
00509               return NULL;
00510        }
00511 
00512        AC_MEMCPY( new->bv_val, src->bv_val, src->bv_len );
00513        new->bv_val[src->bv_len] = '\0';
00514        new->bv_len = src->bv_len;
00515 
00516        return new;
00517 }
00518 
00519 struct berval *
00520 ber_dupbv(
00521        struct berval *dst, struct berval *src )
00522 {
00523        return ber_dupbv_x( dst, src, NULL );
00524 }
00525 
00526 struct berval *
00527 ber_bvdup(
00528        struct berval *src )
00529 {
00530        return ber_dupbv_x( NULL, src, NULL );
00531 }
00532 
00533 struct berval *
00534 ber_str2bv_x(
00535        LDAP_CONST char *s, ber_len_t len, int dup, struct berval *bv,
00536        void *ctx)
00537 {
00538        struct berval *new;
00539 
00540        if( s == NULL ) {
00541               ber_errno = LBER_ERROR_PARAM;
00542               return NULL;
00543        }
00544 
00545        if( bv ) {
00546               new = bv;
00547        } else {
00548               if(( new = ber_memalloc_x( sizeof(struct berval), ctx )) == NULL ) {
00549                      return NULL;
00550               }
00551        }
00552 
00553        new->bv_len = len ? len : strlen( s );
00554        if ( dup ) {
00555               if ( (new->bv_val = ber_memalloc_x( new->bv_len+1, ctx )) == NULL ) {
00556                      if ( !bv )
00557                             ber_memfree_x( new, ctx );
00558                      return NULL;
00559               }
00560 
00561               AC_MEMCPY( new->bv_val, s, new->bv_len );
00562               new->bv_val[new->bv_len] = '\0';
00563        } else {
00564               new->bv_val = (char *) s;
00565        }
00566 
00567        return( new );
00568 }
00569 
00570 struct berval *
00571 ber_str2bv(
00572        LDAP_CONST char *s, ber_len_t len, int dup, struct berval *bv)
00573 {
00574        return ber_str2bv_x( s, len, dup, bv, NULL );
00575 }
00576 
00577 struct berval *
00578 ber_mem2bv_x(
00579        LDAP_CONST char *s, ber_len_t len, int dup, struct berval *bv,
00580        void *ctx)
00581 {
00582        struct berval *new;
00583 
00584        if( s == NULL ) {
00585               ber_errno = LBER_ERROR_PARAM;
00586               return NULL;
00587        }
00588 
00589        if( bv ) {
00590               new = bv;
00591        } else {
00592               if(( new = ber_memalloc_x( sizeof(struct berval), ctx )) == NULL ) {
00593                      return NULL;
00594               }
00595        }
00596 
00597        new->bv_len = len;
00598        if ( dup ) {
00599               if ( (new->bv_val = ber_memalloc_x( new->bv_len+1, ctx )) == NULL ) {
00600                      if ( !bv ) {
00601                             ber_memfree_x( new, ctx );
00602                      }
00603                      return NULL;
00604               }
00605 
00606               AC_MEMCPY( new->bv_val, s, new->bv_len );
00607               new->bv_val[new->bv_len] = '\0';
00608        } else {
00609               new->bv_val = (char *) s;
00610        }
00611 
00612        return( new );
00613 }
00614 
00615 struct berval *
00616 ber_mem2bv(
00617        LDAP_CONST char *s, ber_len_t len, int dup, struct berval *bv)
00618 {
00619        return ber_mem2bv_x( s, len, dup, bv, NULL );
00620 }
00621 
00622 char *
00623 ber_strdup_x( LDAP_CONST char *s, void *ctx )
00624 {
00625        char    *p;
00626        size_t len;
00627        
00628 #ifdef LDAP_MEMORY_DEBUG
00629        assert(s != NULL);                 /* bv damn better point to something */
00630 #endif
00631 
00632        if( s == NULL ) {
00633               ber_errno = LBER_ERROR_PARAM;
00634               return NULL;
00635        }
00636 
00637        len = strlen( s ) + 1;
00638        if ( (p = ber_memalloc_x( len, ctx )) != NULL ) {
00639               AC_MEMCPY( p, s, len );
00640        }
00641 
00642        return p;
00643 }
00644 
00645 char *
00646 ber_strdup( LDAP_CONST char *s )
00647 {
00648        return ber_strdup_x( s, NULL );
00649 }
00650 
00651 ber_len_t
00652 ber_strnlen( LDAP_CONST char *s, ber_len_t len )
00653 {
00654        ber_len_t l;
00655 
00656        for ( l = 0; l < len && s[l] != '\0'; l++ ) ;
00657 
00658        return l;
00659 }
00660 
00661 char *
00662 ber_strndup_x( LDAP_CONST char *s, ber_len_t l, void *ctx )
00663 {
00664        char    *p;
00665        size_t len;
00666        
00667 #ifdef LDAP_MEMORY_DEBUG
00668        assert(s != NULL);                 /* bv damn better point to something */
00669 #endif
00670 
00671        if( s == NULL ) {
00672               ber_errno = LBER_ERROR_PARAM;
00673               return NULL;
00674        }
00675 
00676        len = ber_strnlen( s, l );
00677        if ( (p = ber_memalloc_x( len + 1, ctx )) != NULL ) {
00678               AC_MEMCPY( p, s, len );
00679               p[len] = '\0';
00680        }
00681 
00682        return p;
00683 }
00684 
00685 char *
00686 ber_strndup( LDAP_CONST char *s, ber_len_t l )
00687 {
00688        return ber_strndup_x( s, l, NULL );
00689 }
00690 
00691 /*
00692  * dst is resized as required by src and the value of src is copied into dst
00693  * dst->bv_val must be NULL (and dst->bv_len must be 0), or it must be
00694  * alloc'ed with the context ctx
00695  */
00696 struct berval *
00697 ber_bvreplace_x( struct berval *dst, LDAP_CONST struct berval *src, void *ctx )
00698 {
00699        assert( dst != NULL );
00700        assert( !BER_BVISNULL( src ) );
00701 
00702        if ( BER_BVISNULL( dst ) || dst->bv_len < src->bv_len ) {
00703               dst->bv_val = ber_memrealloc_x( dst->bv_val, src->bv_len + 1, ctx );
00704        }
00705 
00706        AC_MEMCPY( dst->bv_val, src->bv_val, src->bv_len + 1 );
00707        dst->bv_len = src->bv_len;
00708 
00709        return dst;
00710 }
00711 
00712 struct berval *
00713 ber_bvreplace( struct berval *dst, LDAP_CONST struct berval *src )
00714 {
00715        return ber_bvreplace_x( dst, src, NULL );
00716 }
00717 
00718 void
00719 ber_bvarray_free_x( BerVarray a, void *ctx )
00720 {
00721        int i;
00722 
00723        if (a) {
00724               BER_MEM_VALID( a );
00725 
00726               /* count elements */
00727               for (i=0; a[i].bv_val; i++) ;
00728               
00729               /* free in reverse order */
00730               for (i--; i>=0; i--) {
00731                      ber_memfree_x(a[i].bv_val, ctx);
00732               }
00733 
00734               ber_memfree_x(a, ctx);
00735        }
00736 }
00737 
00738 void
00739 ber_bvarray_free( BerVarray a )
00740 {
00741        ber_bvarray_free_x(a, NULL);
00742 }
00743 
00744 int
00745 ber_bvarray_dup_x( BerVarray *dst, BerVarray src, void *ctx )
00746 {
00747        int i, j;
00748        BerVarray new;
00749 
00750        if ( !src ) {
00751               *dst = NULL;
00752               return 0;
00753        }
00754 
00755        for (i=0; !BER_BVISNULL( &src[i] ); i++) ;
00756        new = ber_memalloc_x(( i+1 ) * sizeof(BerValue), ctx );
00757        if ( !new )
00758               return -1;
00759        for (j=0; j<i; j++) {
00760               ber_dupbv_x( &new[j], &src[j], ctx );
00761               if ( BER_BVISNULL( &new[j] )) {
00762                      ber_bvarray_free_x( new, ctx );
00763                      return -1;
00764               }
00765        }
00766        BER_BVZERO( &new[j] );
00767        *dst = new;
00768        return 0;
00769 }
00770 
00771 int
00772 ber_bvarray_add_x( BerVarray *a, BerValue *bv, void *ctx )
00773 {
00774        int    n;
00775 
00776        if ( *a == NULL ) {
00777               if (bv == NULL) {
00778                      return 0;
00779               }
00780               n = 0;
00781 
00782               *a = (BerValue *) ber_memalloc_x( 2 * sizeof(BerValue), ctx );
00783               if ( *a == NULL ) {
00784                      return -1;
00785               }
00786 
00787        } else {
00788               BerVarray atmp;
00789               BER_MEM_VALID( a );
00790 
00791               for ( n = 0; *a != NULL && (*a)[n].bv_val != NULL; n++ ) {
00792                      ;      /* just count them */
00793               }
00794 
00795               if (bv == NULL) {
00796                      return n;
00797               }
00798 
00799               atmp = (BerValue *) ber_memrealloc_x( (char *) *a,
00800                   (n + 2) * sizeof(BerValue), ctx );
00801 
00802               if( atmp == NULL ) {
00803                      return -1;
00804               }
00805 
00806               *a = atmp;
00807        }
00808 
00809        (*a)[n++] = *bv;
00810        (*a)[n].bv_val = NULL;
00811        (*a)[n].bv_len = 0;
00812 
00813        return n;
00814 }
00815 
00816 int
00817 ber_bvarray_add( BerVarray *a, BerValue *bv )
00818 {
00819        return ber_bvarray_add_x( a, bv, NULL );
00820 }