| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461 |
- /** BEGIN COPYRIGHT BLOCK
- * This Program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License as published by the Free Software
- * Foundation; version 2 of the License.
- *
- * This Program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * In addition, as a special exception, Red Hat, Inc. gives You the additional
- * right to link the code of this Program with code not covered under the GNU
- * General Public License ("Non-GPL Code") and to distribute linked combinations
- * including the two, subject to the limitations in this paragraph. Non-GPL Code
- * permitted under this exception must only link to the code of this Program
- * through those well defined interfaces identified in the file named EXCEPTION
- * found in the source code files (the "Approved Interfaces"). The files of
- * Non-GPL Code may instantiate templates or use macros or inline functions from
- * the Approved Interfaces without causing the resulting work to be covered by
- * the GNU General Public License. Only Red Hat, Inc. may make changes or
- * additions to the list of Approved Interfaces. You must obey the GNU General
- * Public License in all respects for all of the Program code and other code used
- * in conjunction with the Program except the Non-GPL Code covered by this
- * exception. If you modify this file, you may extend this exception to your
- * version of the file, but you are not obligated to do so. If you do not wish to
- * provide this exception without modification, you must delete this exception
- * statement from your version and license this file solely under the GPL without
- * exception.
- *
- *
- * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
- * Copyright (C) 2005 Red Hat, Inc.
- * All rights reserved.
- * END COPYRIGHT BLOCK **/
- #ifdef HAVE_CONFIG_H
- # include <config.h>
- #endif
- /* valueset.c - routines for dealing with value sets */
- #include "slap.h"
- #include "slapi-private.h"
- /* <=========================== Berval Array ==========================> */
- /*
- * vals - The existing values.
- * addval - The value to add.
- * nvals - The number of existing values.
- * maxvals - The number of elements in the existing values array.
- */
- void
- bervalarray_add_berval_fast(
- struct berval ***vals,
- const struct berval *addval,
- int nvals,
- int *maxvals
- )
- {
- int need = nvals + 2;
- if(need>*maxvals)
- {
- if (*maxvals==0)
- {
- *maxvals = 2;
- }
- while ( *maxvals < need )
- {
- *maxvals *= 2;
- }
- if(*vals==NULL)
- {
- *vals = (struct berval **) slapi_ch_malloc( *maxvals * sizeof(struct berval *));
- }
- else
- {
- *vals = (struct berval **) slapi_ch_realloc( (char *) *vals, *maxvals * sizeof(struct berval *));
- }
- }
- (*vals)[nvals] = ber_bvdup( (struct berval *)addval );
- (*vals)[nvals+1] = NULL;
- }
-
- /* <=========================== Value Array ==========================> */
- /*
- * vals - The existing values.
- * addval - The value to add.
- * nvals - The number of existing values.
- * maxvals - The number of elements in the existing values array.
- */
- void
- valuearray_add_value_fast(Slapi_Value ***vals,
- Slapi_Value *addval,
- int nvals,
- int *maxvals,
- int exact, /* Don't create an array bigger than needed */
- int passin) /* The values are being passed in */
- {
- Slapi_Value *oneval[2];
- oneval[0]= addval;
- oneval[1]= NULL;
- valuearray_add_valuearray_fast(vals,oneval,nvals,1,maxvals,exact,passin);
- }
- void
- valuearray_add_valuearray_fast(Slapi_Value ***vals,
- Slapi_Value **addvals,
- int nvals,
- int naddvals,
- int *maxvals,
- int exact, /* Don't create an array bigger than needed */
- int passin) /* The values are being passed in */
- {
- int i, j;
- int allocate= 0;
- int need = nvals + naddvals + 1;
- if(exact)
- {
- /* Create an array exactly the right size. */
- if(need>*maxvals)
- {
- allocate= need;
- }
- }
- else
- {
- if (*maxvals==0) /* empty; create with 4 by default */
- {
- allocate= 4;
- }
- else if (need > *maxvals)
- {
- /* Exponentially expand the array */
- allocate= *maxvals;
- while ( allocate < need )
- {
- allocate *= 2;
- }
- }
- }
- if(allocate>0)
- {
- if(*vals==NULL)
- {
- *vals = (Slapi_Value **) slapi_ch_malloc( allocate * sizeof(Slapi_Value *));
- }
- else
- {
- *vals = (Slapi_Value **) slapi_ch_realloc( (char *) *vals, allocate * sizeof(Slapi_Value *));
- }
- *maxvals= allocate;
- }
- for ( i = 0, j = 0; i < naddvals; i++)
- {
- if ( addvals[i]!=NULL )
- {
- if(passin)
- {
- /* We consume the values */
- (*vals)[nvals + j] = addvals[i];
- }
- else
- {
- /* We copy the values */
- (*vals)[nvals + j] = slapi_value_dup(addvals[i]);
- }
- j++;
- }
- }
- (*vals)[nvals + j] = NULL;
- }
- void
- valuearray_add_value(Slapi_Value ***vals, const Slapi_Value *addval)
- {
- Slapi_Value *oneval[2];
- oneval[0]= (Slapi_Value*)addval;
- oneval[1]= NULL;
- valuearray_add_valuearray(vals,oneval,0);
- }
- void
- valuearray_add_valuearray(Slapi_Value ***vals, Slapi_Value **addvals, PRUint32 flags)
- {
- int valslen;
- int addvalslen;
- int maxvals;
- if(vals == NULL){
- return;
- }
- addvalslen= valuearray_count(addvals);
- if(*vals == NULL)
- {
- valslen= 0;
- maxvals= 0;
- }
- else
- {
- valslen= valuearray_count(*vals);
- maxvals= valslen+1;
- }
- valuearray_add_valuearray_fast(vals,addvals,valslen,addvalslen,&maxvals,1/*Exact*/,flags & SLAPI_VALUE_FLAG_PASSIN);
- }
- int
- valuearray_count( Slapi_Value **va)
- {
- int i=0;
- if(va!=NULL)
- {
- while(NULL != va[i]) i++;
- }
- return(i);
- }
- int
- valuearray_isempty( Slapi_Value **va)
- {
- return va==NULL || va[0]==NULL;
- }
- /*
- * JCM SLOW FUNCTION
- *
- * WARNING: Use only if you absolutley need to...
- * This function mostly exists to map from the old slapi berval
- * based interface to the new Slapi_Value based interfaces.
- */
- int
- valuearray_init_bervalarray(struct berval **bvals, Slapi_Value ***cvals)
- {
- int n;
- for(n=0; bvals != NULL && bvals[n] != NULL; n++);
- if(n==0)
- {
- *cvals = NULL;
- }
- else
- {
- int i;
- *cvals = (Slapi_Value **) slapi_ch_malloc((n + 1) * sizeof(Slapi_Value *));
- for(i=0;i<n;i++)
- {
- (*cvals)[i] = slapi_value_new_berval(bvals[i]);
- }
- (*cvals)[i] = NULL;
- }
- return n;
- }
- /*
- * JCM SLOW FUNCTION
- *
- * WARNING: Use only if you absolutley need to...
- * This function mostly exists to map from the old slapi berval
- * based interface to the new Slapi_Value based interfaces.
- */
- int
- valuearray_init_bervalarray_with_flags(struct berval **bvals, Slapi_Value ***cvals, unsigned long flags)
- {
- int n;
- for(n=0; bvals != NULL && bvals[n] != NULL; n++);
- if(n==0)
- {
- *cvals = NULL;
- }
- else
- {
- int i;
- *cvals = (Slapi_Value **) slapi_ch_malloc((n + 1) * sizeof(Slapi_Value *));
- for(i=0;i<n;i++)
- {
- (*cvals)[i] = slapi_value_new_berval(bvals[i]);
- slapi_value_set_flags((*cvals)[i], flags);
- }
- (*cvals)[i] = NULL;
- }
- return n;
- }
- /*
- * JCM SLOW FUNCTION
- *
- * Use only if you absolutley need to...
- * This function mostly exists to map from the old slapi berval
- * based interface to the new Slapi_Value based interfaces.
- */
- int
- valuearray_get_bervalarray(Slapi_Value **cvals,struct berval ***bvals)
- {
- int i,n;
- n= valuearray_count(cvals);
- if (0 == n)
- {
- *bvals = NULL;
- }
- else
- {
- *bvals = (struct berval **)slapi_ch_malloc((n + 1) * sizeof(struct berval *));
- for(i=0;i<n;i++)
- {
- (*bvals)[i] = ber_bvdup((struct berval *)slapi_value_get_berval(cvals[i]));
- }
- (*bvals)[i] = NULL;
- }
- return(0);
- }
- void
- valuearray_free_ext(Slapi_Value ***va, int idx)
- {
- if(va!=NULL && *va!=NULL)
- {
- for(; (*va)[idx]!=NULL; idx++)
- {
- slapi_value_free(&(*va)[idx]);
- }
- slapi_ch_free((void **)va);
- *va = NULL;
- }
- }
- void
- valuearray_free(Slapi_Value ***va)
- {
- valuearray_free_ext(va, 0);
- }
- int
- valuearray_next_value( Slapi_Value **va, int index, Slapi_Value **v)
- {
- int r= -1;
- if(va!=NULL && va[0]!=NULL)
- {
- r= index+1;
- *v= va[r];
- if(*v==NULL)
- {
- r= -1;
- }
- }
- else
- {
- *v= NULL;
- }
- return r;
- }
- int
- valuearray_first_value( Slapi_Value **va, Slapi_Value **v )
- {
- return valuearray_next_value( va, -1, v);
- }
- /*
- * Find the value and return an index number to it.
- */
- int
- valuearray_find(const Slapi_Attr *a, Slapi_Value **va, const Slapi_Value *v)
- {
- int i= 0;
- int found= -1;
- while(found==-1 && va!=NULL && va[i]!=NULL)
- {
- if(slapi_value_compare( a, v, va[i])==0)
- {
- found= i;
- }
- else
- {
- i++;
- }
- }
- return found;
- }
- /*
- * Shunt up the array to cover the value to remove.
- */
- void
- valuearray_remove_value_atindex(Slapi_Value **va, int index)
- {
- if(va!=NULL && va[0]!=NULL)
- {
- int k;
- for ( k = index + 1; va[k] != NULL; k++ )
- {
- va[k - 1] = va[k];
- }
- va[k - 1] = NULL;
- }
- }
- /*
- * Find the value in the array,
- * shunt up the array to cover it,
- * return a ptr to the value.
- * The caller is responsible for freeing the value.
- */
- Slapi_Value *
- valuearray_remove_value(const Slapi_Attr *a, Slapi_Value **va, const Slapi_Value *v)
- {
- Slapi_Value *r= NULL;
- int i= 0;
- i= valuearray_find(a, va, v);
- if(i!=-1)
- {
- r= va[i];
- valuearray_remove_value_atindex(va,i);
- }
- return r;
- }
- /*
- * Remove any values older than the CSN.
- */
- int
- valuearray_purge(Slapi_Value ***va, const CSN *csn)
- {
- int numValues=0;
- int i=0;
- int nextValue=0;
- PR_ASSERT(va!=NULL && *va!=NULL);
- /* Loop over all the values freeing the old ones. */
- for(i=0; (*va)[i]; i++)
- {
- csnset_purge(&((*va)[i]->v_csnset),csn);
- if ((*va)[i]->v_csnset == NULL)
- {
- slapi_value_free(&(*va)[i]);
- (*va)[i] = NULL;
- }
- }
- /* Now compact the value list. */
- numValues=i;
- nextValue = 0;
- i = 0;
- for(i=0;i<numValues;i++)
- {
- while((nextValue < numValues) && (NULL == (*va)[nextValue]))
- {
- nextValue++;
- }
- if(nextValue < numValues)
- {
- (*va)[i] = (*va)[nextValue];
- nextValue++;
- }
- else
- {
- break;
- }
- }
- (*va)[i] = NULL;
- /* All the values were deleted, we can discard the whole array. */
- if(NULL == (*va)[0])
- {
- slapi_ch_free((void**)va);
- *va= NULL;
- }
- return(0);
- }
- size_t
- valuearray_size(Slapi_Value **va)
- {
- size_t s= 0;
- if(va!=NULL && va[0]!=NULL)
- {
- int i;
- for (i = 0; va[i]; i++)
- {
- s += value_size(va[i]);
- }
- s += (i + 1) * sizeof(Slapi_Value*);
- }
- return s;
- }
- void
- valuearray_update_csn(Slapi_Value **va, CSNType t, const CSN *csn)
- {
- int i;
- for (i = 0; va!=NULL && va[i]; i++)
- {
- value_update_csn(va[i],t,csn);
- }
- }
- /*
- * Shunt up the values to cover the empty slots.
- *
- * "compressed" means "contains no NULL's"
- *
- * Invariant for the outer loop:
- * va[0..i] is compressed &&
- * va[n..numvalues] contains just NULL's
- *
- * Invariant for the inner loop:
- * i<j<=k<=n && va[j..k] has been shifted left by (j-i) places &&
- * va[k..n] remains to be shifted left by (j-i) places
- *
- */
- void
- valuearray_compress(Slapi_Value **va,int numvalues)
- {
- int i = 0;
- int n= numvalues;
- while(i<n)
- {
- if ( va[i] != NULL ) {
- i++;
- } else {
- int k,j;
- j = i + 1;
- /* Find the length of the next run of NULL's */
- while( j<n && va[j] == NULL) { j++; }
- /* va[i..j] is all NULL && j<= n */
- for ( k = j; k<n; k++ )
- {
- va[k - (j-i)] = va[k];
- va[k] = NULL;
- }
- /* va[i..n] has been shifted down by j-i places */
- n = n - (j-i);
- /*
- * If va[i] in now non null, then bump i,
- * if not then we are done anyway (j==n) so can bump it.
- */
- i++;
- }
- }
- }
- /* <=========================== Value Array Fast ==========================> */
- void
- valuearrayfast_init(struct valuearrayfast *vaf,Slapi_Value **va)
- {
- vaf->num= valuearray_count(va);
- vaf->max= vaf->num;
- vaf->va= va;
- }
- void
- valuearrayfast_done(struct valuearrayfast *vaf)
- {
- if(vaf->va!=NULL)
- {
- int i;
- for(i=0; i<vaf->num; i++)
- {
- slapi_value_free(&vaf->va[i]);
- }
- slapi_ch_free((void **)&vaf->va);
- vaf->num= 0;
- vaf->max= 0;
- }
- }
- void
- valuearrayfast_add_value(struct valuearrayfast *vaf,const Slapi_Value *v)
- {
- valuearray_add_value_fast(&vaf->va,(Slapi_Value *)v,vaf->num,&vaf->max,0/*Exact*/,0/*!PassIn*/);
- vaf->num++;
- }
- void
- valuearrayfast_add_value_passin(struct valuearrayfast *vaf,Slapi_Value *v)
- {
- valuearray_add_value_fast(&vaf->va,v,vaf->num,&vaf->max,0/*Exact*/,1/*PassIn*/);
- vaf->num++;
- }
- void
- valuearrayfast_add_valuearrayfast(struct valuearrayfast *vaf,const struct valuearrayfast *vaf_add)
- {
- valuearray_add_valuearray_fast(&vaf->va,vaf_add->va,vaf->num,vaf_add->num,&vaf->max,0/*Exact*/,0/*!PassIn*/);
- vaf->num+= vaf_add->num;
- }
- /* <=========================== ValueArrayIndexTree =======================> */
- static int valuetree_dupvalue_disallow( caddr_t d1, caddr_t d2 );
- static int valuetree_node_cmp( caddr_t d1, caddr_t d2 );
- static int valuetree_node_free( caddr_t data );
- /*
- * structure used within AVL value trees.
- */
- typedef struct valuetree_node
- {
- int index; /* index into the value array */
- Slapi_Value *sval; /* the actual value */
- } valuetree_node;
- /*
- * Create or update an AVL tree of values that can be used to speed up value
- * lookups. We store the index keys for the values in the AVL tree so
- * we can use a trivial comparison function.
- *
- * Returns:
- * LDAP_SUCCESS on success,
- * LDAP_TYPE_OR_VALUE_EXISTS if the value already exists,
- * LDAP_OPERATIONS_ERROR for some unexpected failure.
- *
- * Sets *valuetreep to the root of the AVL tree that was created. If a
- * non-zero value is returned, the tree is freed if free_on_error is non-zero
- * and *valuetreep is set to NULL.
- */
- int
- valuetree_add_valuearray( const Slapi_Attr *sattr, Slapi_Value **va, Avlnode **valuetreep, int *duplicate_index )
- {
- int rc= LDAP_SUCCESS;
- PR_ASSERT(sattr!=NULL);
- PR_ASSERT(valuetreep!=NULL);
- if ( duplicate_index ) {
- *duplicate_index = -1;
- }
- if ( !valuearray_isempty(va) )
- {
- Slapi_Value **keyvals;
- /* Convert the value array into key values */
- if ( slapi_attr_values2keys_sv( sattr, (Slapi_Value**)va, &keyvals, LDAP_FILTER_EQUALITY ) != 0 ) /* jcm cast */
- {
- LDAPDebug( LDAP_DEBUG_ANY,"slapi_attr_values2keys_sv for attribute %s failed\n", sattr->a_type, 0, 0 );
- rc= LDAP_OPERATIONS_ERROR;
- }
- else
- {
- int i;
- valuetree_node *vaip;
- for ( i = 0; rc==LDAP_SUCCESS && va[i] != NULL; ++i )
- {
- if ( keyvals[i] == NULL )
- {
- LDAPDebug( LDAP_DEBUG_ANY,"slapi_attr_values2keys_sv for attribute %s did not return enough key values\n", sattr->a_type, 0, 0 );
- rc= LDAP_OPERATIONS_ERROR;
- }
- else
- {
- vaip = (valuetree_node *)slapi_ch_malloc( sizeof( valuetree_node ));
- vaip->index = i;
- vaip->sval = keyvals[i];
- if (( rc = avl_insert( valuetreep, vaip, valuetree_node_cmp, valuetree_dupvalue_disallow )) != 0 )
- {
- slapi_ch_free( (void **)&vaip );
- /* Value must already be in there */
- rc= LDAP_TYPE_OR_VALUE_EXISTS;
- if ( duplicate_index ) {
- *duplicate_index = i;
- }
- }
- else
- {
- keyvals[i]= NULL;
- }
- }
- }
- /* start freeing at index i - the rest of them have already
- been moved into valuetreep
- the loop iteration will always do the +1, so we have
- to remove it if so */
- i = (i > 0) ? i-1 : 0;
- valuearray_free_ext( &keyvals, i );
- }
- }
- if(rc!=0)
- {
- valuetree_free( valuetreep );
- }
- return rc;
- }
- int
- valuetree_add_value( const Slapi_Attr *sattr, const Slapi_Value *v, Avlnode **valuetreep)
- {
- Slapi_Value *va[2];
- va[0]= (Slapi_Value*)v;
- va[1]= NULL;
- return valuetree_add_valuearray( sattr, va, valuetreep, NULL);
- }
- /*
- *
- * Find value "v" using AVL tree "valuetree"
- *
- * returns LDAP_SUCCESS if "v" was found, LDAP_NO_SUCH_ATTRIBUTE
- * if "v" was not found and LDAP_OPERATIONS_ERROR if some unexpected error occurs.
- */
- static int
- valuetree_find( const struct slapi_attr *a, const Slapi_Value *v, Avlnode *valuetree, int *index)
- {
- const Slapi_Value *oneval[2];
- Slapi_Value **keyvals;
- valuetree_node *vaip, tmpvain;
- PR_ASSERT(a!=NULL);
- PR_ASSERT(a->a_plugin!=NULL);
- PR_ASSERT(v!=NULL);
- PR_ASSERT(valuetree!=NULL);
- PR_ASSERT(index!=NULL);
- if ( a == NULL || v == NULL || valuetree == NULL )
- {
- return( LDAP_OPERATIONS_ERROR );
- }
-
- keyvals = NULL;
- oneval[0] = v;
- oneval[1] = NULL;
- if ( slapi_attr_values2keys_sv( a, (Slapi_Value**)oneval, &keyvals, LDAP_FILTER_EQUALITY ) != 0 /* jcm cast */
- || keyvals == NULL
- || keyvals[0] == NULL )
- {
- LDAPDebug( LDAP_DEBUG_ANY, "valuetree_find_and_replace: "
- "slapi_attr_values2keys_sv failed for type %s\n",
- a->a_type, 0, 0 );
- return( LDAP_OPERATIONS_ERROR );
- }
- tmpvain.index = 0;
- tmpvain.sval = keyvals[0];
- vaip = (valuetree_node *)avl_find( valuetree, &tmpvain, valuetree_node_cmp );
- if ( keyvals != NULL )
- {
- valuearray_free( &keyvals );
- }
- if (vaip == NULL)
- {
- return( LDAP_NO_SUCH_ATTRIBUTE );
- }
- else
- {
- *index= vaip->index;
- }
- return( LDAP_SUCCESS );
- }
- static int
- valuetree_dupvalue_disallow( caddr_t d1, caddr_t d2 )
- {
- return( 1 );
- }
- void
- valuetree_free( Avlnode **valuetreep )
- {
- if ( valuetreep != NULL && *valuetreep != NULL )
- {
- avl_free( *valuetreep, valuetree_node_free );
- *valuetreep = NULL;
- }
- }
- static int
- valuetree_node_free( caddr_t data )
- {
- if ( data!=NULL )
- {
- valuetree_node *vaip = (valuetree_node *)data;
- slapi_value_free(&vaip->sval);
- slapi_ch_free( (void **)&data );
- }
- return( 0 );
- }
- static int
- valuetree_node_cmp( caddr_t d1, caddr_t d2 )
- {
- const struct berval *bv1, *bv2;
- int rc;
- bv1 = slapi_value_get_berval(((valuetree_node *)d1)->sval);
- bv2 = slapi_value_get_berval(((valuetree_node *)d2)->sval);
- if ( bv1->bv_len < bv2->bv_len ) {
- rc = -1;
- } else if ( bv1->bv_len > bv2->bv_len ) {
- rc = 1;
- } else {
- rc = memcmp( bv1->bv_val, bv2->bv_val, bv1->bv_len );
- }
- return( rc );
- }
- /* <=========================== Value Set =======================> */
- /*
- * JCM: All of these valueset functions are just forwarded to the
- * JCM: valuearray functions... waste of time. Inline them!
- */
- Slapi_ValueSet *
- slapi_valueset_new()
- {
- Slapi_ValueSet *vs = (Slapi_ValueSet *)slapi_ch_calloc(1,sizeof(Slapi_ValueSet));
- if(vs)
- slapi_valueset_init(vs);
- return vs;
- }
- void
- slapi_valueset_init(Slapi_ValueSet *vs)
- {
- if(vs!=NULL)
- {
- vs->va= NULL;
- }
- }
- void
- slapi_valueset_done(Slapi_ValueSet *vs)
- {
- if(vs!=NULL)
- {
- if(vs->va!=NULL)
- {
- valuearray_free(&vs->va);
- vs->va= NULL;
- }
- }
- }
- void
- slapi_valueset_free(Slapi_ValueSet *vs)
- {
- if(vs!=NULL)
- {
- slapi_valueset_done(vs);
- slapi_ch_free((void **)&vs);
- }
- }
- void
- slapi_valueset_set_from_smod(Slapi_ValueSet *vs, Slapi_Mod *smod)
- {
- Slapi_Value **va= NULL;
- valuearray_init_bervalarray(slapi_mod_get_ldapmod_byref(smod)->mod_bvalues, &va);
- valueset_set_valuearray_passin(vs, va);
- }
- void
- valueset_set_valuearray_byval(Slapi_ValueSet *vs, Slapi_Value **addvals)
- {
- slapi_valueset_init(vs);
- valueset_add_valuearray(vs,addvals);
- }
- void
- valueset_set_valuearray_passin(Slapi_ValueSet *vs, Slapi_Value **addvals)
- {
- slapi_valueset_init(vs);
- vs->va= addvals;
- }
- void
- slapi_valueset_set_valueset(Slapi_ValueSet *vs1, const Slapi_ValueSet *vs2)
- {
- slapi_valueset_init(vs1);
- valueset_add_valueset(vs1,vs2);
- }
- int
- slapi_valueset_first_value( Slapi_ValueSet *vs, Slapi_Value **v )
- {
- return valuearray_first_value(vs->va,v);
- }
- int
- slapi_valueset_next_value( Slapi_ValueSet *vs, int index, Slapi_Value **v)
- {
- return valuearray_next_value(vs->va,index,v);
- }
- int
- slapi_valueset_count( const Slapi_ValueSet *vs)
- {
- int r=0;
- if (NULL != vs)
- {
- if(!valuearray_isempty(vs->va))
- {
- r= valuearray_count(vs->va);
- }
- }
- return r;
- }
- int
- valueset_isempty( const Slapi_ValueSet *vs)
- {
- return valuearray_isempty(vs->va);
- }
- Slapi_Value *
- slapi_valueset_find(const Slapi_Attr *a, const Slapi_ValueSet *vs, const Slapi_Value *v)
- {
- Slapi_Value *r= NULL;
- if(!valuearray_isempty(vs->va))
- {
- int i= valuearray_find(a,vs->va,v);
- if(i!=-1)
- {
- r= vs->va[i];
- }
- }
- return r;
- }
- /*
- * The value is found in the set, removed and returned.
- * The caller is responsible for freeing the value.
- */
- Slapi_Value *
- valueset_remove_value(const Slapi_Attr *a, Slapi_ValueSet *vs, const Slapi_Value *v)
- {
- Slapi_Value *r= NULL;
- if(!valuearray_isempty(vs->va))
- {
- r= valuearray_remove_value(a, vs->va, v);
- }
- return r;
- }
- /*
- * Remove any values older than the CSN.
- */
- int
- valueset_purge(Slapi_ValueSet *vs, const CSN *csn)
- {
- int r= 0;
- if(!valuearray_isempty(vs->va))
- {
- r= valuearray_purge(&vs->va, csn);
- }
- return r;
- }
- Slapi_Value **
- valueset_get_valuearray(const Slapi_ValueSet *vs)
- {
- return (Slapi_Value**)vs->va;
- }
- size_t
- valueset_size(const Slapi_ValueSet *vs)
- {
- size_t s= 0;
- if(!valuearray_isempty(vs->va))
- {
- s= valuearray_size(vs->va);
- }
- return s;
- }
- /*
- * The value array is passed in by value.
- */
- void
- valueset_add_valuearray(Slapi_ValueSet *vs, Slapi_Value **addvals)
- {
- if(!valuearray_isempty(addvals))
- {
- valuearray_add_valuearray(&vs->va, addvals, 0);
- }
- }
- void
- valueset_add_valuearray_ext(Slapi_ValueSet *vs, Slapi_Value **addvals, PRUint32 flags)
- {
- if(!valuearray_isempty(addvals))
- {
- valuearray_add_valuearray(&vs->va, addvals, flags);
- }
- }
- /*
- * The value is passed in by value.
- */
- void
- slapi_valueset_add_value(Slapi_ValueSet *vs, const Slapi_Value *addval)
- {
- valuearray_add_value(&vs->va,addval);
- }
- void
- slapi_valueset_add_value_ext(Slapi_ValueSet *vs, Slapi_Value *addval, unsigned long flags)
- {
- Slapi_Value *oneval[2];
- oneval[0]= (Slapi_Value*)addval;
- oneval[1]= NULL;
- valuearray_add_valuearray(&vs->va, oneval, flags);
- }
- /*
- * The string is passed in by value.
- */
- void
- valueset_add_string(Slapi_ValueSet *vs, const char *s, CSNType t, const CSN *csn)
- {
- Slapi_Value v;
- value_init(&v,NULL,t,csn);
- slapi_value_set_string(&v,s);
- valuearray_add_value(&vs->va,&v);
- value_done(&v);
- }
- /*
- * The value set is passed in by value.
- */
- void
- valueset_add_valueset(Slapi_ValueSet *vs1, const Slapi_ValueSet *vs2)
- {
- if (vs1 && vs2)
- valueset_add_valuearray(vs1, vs2->va);
- }
- void
- valueset_remove_string(const Slapi_Attr *a, Slapi_ValueSet *vs, const char *s)
- {
- Slapi_Value v;
- Slapi_Value *removed;
- value_init(&v,NULL,CSN_TYPE_NONE,NULL);
- slapi_value_set_string(&v,s);
- removed = valuearray_remove_value(a, vs->va, &v);
- if(removed) {
- slapi_value_free(&removed);
- }
- value_done(&v);
- }
- void
- valueset_update_csn(Slapi_ValueSet *vs, CSNType t, const CSN *csn)
- {
- if(!valuearray_isempty(vs->va))
- {
- valuearray_update_csn(vs->va,t,csn);
- }
- }
- /*
- * Remove an array of values from a value set.
- * The removed values are passed back in an array.
- *
- * Flags
- * SLAPI_VALUE_FLAG_PRESERVECSNSET - csnset in the value set is duplicated and
- * preserved in the matched element of the
- * array of values.
- * SLAPI_VALUE_FLAG_IGNOREERROR - ignore an error: Couldn't find the value to
- * be deleted.
- * SLAPI_VALUE_FLAG_USENEWVALUE - replace the value between the value set and
- * the matched element of the array of values
- * (used by entry_add_present_values_wsi).
- *
- * Returns
- * LDAP_SUCCESS - OK.
- * LDAP_NO_SUCH_ATTRIBUTE - A value to be deleted was not in the value set.
- * LDAP_OPERATIONS_ERROR - Something very bad happened.
- */
- int
- valueset_remove_valuearray(Slapi_ValueSet *vs, const Slapi_Attr *a, Slapi_Value **valuestodelete, int flags, Slapi_Value ***va_out)
- {
- int rc= LDAP_SUCCESS;
- if(!valuearray_isempty(vs->va))
- {
- int numberofvaluestodelete= valuearray_count(valuestodelete);
- struct valuearrayfast vaf_out;
- if ( va_out )
- {
- valuearrayfast_init(&vaf_out,*va_out);
- }
- /*
- * If there are more then one values, build an AVL tree to check
- * the duplicated values.
- */
- if ( numberofvaluestodelete > 1 )
- {
- /*
- * Several values to delete: first build an AVL tree that
- * holds all of the existing values and use that to find
- * the values we want to delete.
- */
- Avlnode *vtree = NULL;
- int numberofexistingvalues= slapi_valueset_count(vs);
- rc= valuetree_add_valuearray( a, vs->va, &vtree, NULL );
- if ( rc!=LDAP_SUCCESS )
- {
- /*
- * failed while constructing AVL tree of existing
- * values... something bad happened.
- */
- rc= LDAP_OPERATIONS_ERROR;
- }
- else
- {
- int i;
- /*
- * find and mark all the values that are to be deleted
- */
- for ( i = 0; rc == LDAP_SUCCESS && valuestodelete[i] != NULL; ++i )
- {
- int index= 0;
- rc = valuetree_find( a, valuestodelete[i], vtree, &index );
- if(rc==LDAP_SUCCESS)
- {
- if(vs->va[index]!=NULL)
- {
- /* Move the value to be removed to the out array */
- if ( va_out )
- {
- if (vs->va[index]->v_csnset &&
- (flags & (SLAPI_VALUE_FLAG_PRESERVECSNSET|
- SLAPI_VALUE_FLAG_USENEWVALUE)))
- {
- valuestodelete[i]->v_csnset = csnset_dup (vs->va[index]->v_csnset);
- }
- if (flags & SLAPI_VALUE_FLAG_USENEWVALUE)
- {
- valuearrayfast_add_value_passin(&vaf_out,valuestodelete[i]);
- valuestodelete[i] = vs->va[index];
- vs->va[index] = NULL;
- }
- else
- {
- valuearrayfast_add_value_passin(&vaf_out,vs->va[index]);
- vs->va[index] = NULL;
- }
- }
- else
- {
- if (flags & SLAPI_VALUE_FLAG_PRESERVECSNSET)
- {
- valuestodelete[i]->v_csnset = vs->va[index]->v_csnset;
- vs->va[index]->v_csnset = NULL;
- }
- slapi_value_free ( & vs->va[index] );
- }
- }
- else
- {
- /* We already deleted this value... */
- if((flags & SLAPI_VALUE_FLAG_IGNOREERROR) == 0)
- {
- /* ...that's an error. */
- rc= LDAP_NO_SUCH_ATTRIBUTE;
- }
- }
- }
- else
- {
- /* Couldn't find the value to be deleted */
- if(rc==LDAP_NO_SUCH_ATTRIBUTE && (flags & SLAPI_VALUE_FLAG_IGNOREERROR ))
- {
- rc= LDAP_SUCCESS;
- }
- }
- }
- valuetree_free( &vtree );
- if ( rc != LDAP_SUCCESS )
- {
- LDAPDebug( LDAP_DEBUG_ANY,"could not find value %d for attr %s (%s)\n", i-1, a->a_type, ldap_err2string( rc ));
- }
- else
- {
- /* Shunt up all the remaining values to cover the deleted ones. */
- valuearray_compress(vs->va,numberofexistingvalues);
- }
- }
- }
- else
- {
- /* We delete one or no value, so we use brute force. */
- int i;
- for ( i = 0; rc==LDAP_SUCCESS && valuestodelete[i] != NULL; ++i )
- {
- Slapi_Value *found= valueset_remove_value(a, vs, valuestodelete[i]);
- if(found!=NULL)
- {
- if ( va_out )
- {
- if (found->v_csnset &&
- (flags & (SLAPI_VALUE_FLAG_PRESERVECSNSET|
- SLAPI_VALUE_FLAG_USENEWVALUE)))
- {
- valuestodelete[i]->v_csnset = csnset_dup (found->v_csnset);
- }
- if (flags & SLAPI_VALUE_FLAG_USENEWVALUE)
- {
- valuearrayfast_add_value_passin(&vaf_out,valuestodelete[i]);
- valuestodelete[i] = found;
- }
- else
- {
- valuearrayfast_add_value_passin(&vaf_out,found);
- }
- }
- else
- {
- if (flags & SLAPI_VALUE_FLAG_PRESERVECSNSET)
- {
- valuestodelete[i]->v_csnset = found->v_csnset;
- found->v_csnset = NULL;
- }
- slapi_value_free ( & found );
- }
- }
- else
- {
- if((flags & SLAPI_VALUE_FLAG_IGNOREERROR) == 0)
- {
- LDAPDebug( LDAP_DEBUG_ARGS,"could not find value %d for attr %s\n", i-1, a->a_type, 0 );
- rc= LDAP_NO_SUCH_ATTRIBUTE;
- }
- }
- }
- }
- if ( va_out )
- {
- *va_out= vaf_out.va;
- if(rc!=LDAP_SUCCESS)
- {
- valuearray_free(va_out);
- }
- }
- }
- return rc;
- }
- /*
- * Check if the set of values in the valueset and the valuearray intersect.
- *
- * Returns
- * LDAP_SUCCESS - No intersection.
- * LDAP_NO_SUCH_ATTRIBUTE - There is an intersection.
- * LDAP_OPERATIONS_ERROR - There are duplicate values in the value set already.
- */
- int
- valueset_intersectswith_valuearray(Slapi_ValueSet *vs, const Slapi_Attr *a, Slapi_Value **values, int *duplicate_index )
- {
- int rc= LDAP_SUCCESS;
- if ( duplicate_index ) {
- *duplicate_index = -1;
- }
- if(valuearray_isempty(vs->va))
- {
- /* No intersection */
- }
- else
- {
- int numberofvalues= valuearray_count(values);
- /*
- * determine whether we should use an AVL tree of values or not
- */
- if (numberofvalues==0)
- {
- /* No intersection */
- }
- else if ( numberofvalues > 1 )
- {
- /*
- * Several values to add: use an AVL tree to detect duplicates.
- */
- Avlnode *vtree = NULL;
- rc= valuetree_add_valuearray( a, vs->va, &vtree, duplicate_index );
- if(rc==LDAP_OPERATIONS_ERROR)
- {
- /* There were already duplicate values in the value set */
- }
- else
- {
- rc= valuetree_add_valuearray( a, values, &vtree, duplicate_index );
- /*
- * Returns LDAP_OPERATIONS_ERROR if something very bad happens.
- * Or LDAP_TYPE_OR_VALUE_EXISTS if a value already exists.
- */
- }
- valuetree_free( &vtree );
- }
- else
- {
- /*
- * One value to add: don't bother constructing
- * an AVL tree, etc. since it probably isn't worth the time.
- *
- * JCM - This is actually quite slow because the comparison function is looked up many times.
- */
- int i;
- for ( i = 0; rc == LDAP_SUCCESS && values[i] != NULL; ++i )
- {
- if(valuearray_find(a, vs->va, values[i])!=-1)
- {
- rc = LDAP_TYPE_OR_VALUE_EXISTS;
- *duplicate_index = i;
- break;
- }
- }
- }
- }
- return rc;
- }
- Slapi_ValueSet *
- valueset_dup(const Slapi_ValueSet *dupee)
- {
- Slapi_ValueSet *duped= (Slapi_ValueSet *)slapi_ch_calloc(1,sizeof(Slapi_ValueSet));
- if (NULL!=duped)
- {
- valueset_add_valuearray( duped, dupee->va );
- }
- return duped;
- }
- /* quickly throw away any old contents of this valueset, and stick in the
- * new ones.
- *
- * return value: LDAP_SUCCESS - OK
- * : LDAP_OPERATIONS_ERROR - duplicated values given
- */
- int
- valueset_replace(Slapi_Attr *a, Slapi_ValueSet *vs, Slapi_Value **valstoreplace)
- {
- int rc = LDAP_SUCCESS;
- int numberofvalstoreplace= valuearray_count(valstoreplace);
- /* verify the given values are not duplicated.
- if replacing with one value, no need to check. just replace it.
- */
- if (numberofvalstoreplace > 1)
- {
- Avlnode *vtree = NULL;
- rc = valuetree_add_valuearray( a, valstoreplace, &vtree, NULL );
- valuetree_free(&vtree);
- if ( LDAP_SUCCESS != rc &&
- /* bz 247413: don't override LDAP_TYPE_OR_VALUE_EXISTS */
- LDAP_TYPE_OR_VALUE_EXISTS != rc )
- {
- /* There were already duplicate values in the value set */
- rc = LDAP_OPERATIONS_ERROR;
- }
- }
- if ( rc == LDAP_SUCCESS )
- {
- /* values look good - replace the values in the attribute */
- if(!valuearray_isempty(vs->va))
- {
- /* remove old values */
- slapi_valueset_done(vs);
- }
- /* we now own valstoreplace */
- vs->va = valstoreplace;
- }
- else
- {
- /* caller expects us to own valstoreplace - since we cannot
- use them, just delete them */
- valuearray_free(&valstoreplace);
- }
- return rc;
- }
- /*
- * Search the value set for each value to be update,
- * and update the value with the CSN provided.
- * Updated values are moved from the valuestoupdate
- * array to the valueupdated array.
- */
- void
- valueset_update_csn_for_valuearray(Slapi_ValueSet *vs, const Slapi_Attr *a, Slapi_Value **valuestoupdate, CSNType t, const CSN *csn, Slapi_Value ***valuesupdated)
- {
- if(!valuearray_isempty(valuestoupdate) &&
- !valuearray_isempty(vs->va))
- {
- /*
- * determine whether we should use an AVL tree of values or not
- */
- struct valuearrayfast vaf_valuesupdated;
- int numberofvaluestoupdate= valuearray_count(valuestoupdate);
- valuearrayfast_init(&vaf_valuesupdated,*valuesupdated);
- if (numberofvaluestoupdate > 1) /* multiple values to update */
- {
- int i;
- Avlnode *vtree = NULL;
- int rc= valuetree_add_valuearray( a, vs->va, &vtree, NULL );
- PR_ASSERT(rc==LDAP_SUCCESS);
- for (i=0;valuestoupdate[i]!=NULL;++i)
- {
- int index= 0;
- rc = valuetree_find( a, valuestoupdate[i], vtree, &index );
- if(rc==LDAP_SUCCESS)
- {
- value_update_csn(vs->va[index],t,csn);
- valuearrayfast_add_value_passin(&vaf_valuesupdated,valuestoupdate[i]);
- valuestoupdate[i] = NULL;
- }
- }
- valuetree_free(&vtree);
- }
- else
- {
- int i;
- for (i=0;valuestoupdate[i]!=NULL;++i)
- {
- int index= valuearray_find(a, vs->va, valuestoupdate[i]);
- if(index!=-1)
- {
- value_update_csn(vs->va[index],t,csn);
- valuearrayfast_add_value_passin(&vaf_valuesupdated,valuestoupdate[i]);
- valuestoupdate[i]= NULL;
- }
- }
- }
- valuearray_compress(valuestoupdate,numberofvaluestoupdate);
- *valuesupdated= vaf_valuesupdated.va;
- }
- }
- int
- valuearray_dn_normalize_value(Slapi_Value **vals)
- {
- int rc = 0;
- Slapi_Value **vp = NULL;
- for (vp = vals; vp && *vp; vp++) {
- rc |= value_dn_normalize_value(*vp);
- }
- return rc;
- }
|