valueset.c 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455
  1. /** BEGIN COPYRIGHT BLOCK
  2. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  3. * Copyright (C) 2005 Red Hat, Inc.
  4. * All rights reserved.
  5. *
  6. * License: GPL (version 3 or any later version).
  7. * See LICENSE for details.
  8. * END COPYRIGHT BLOCK **/
  9. #ifdef HAVE_CONFIG_H
  10. # include <config.h>
  11. #endif
  12. /* valueset.c - routines for dealing with value sets */
  13. #include "slap.h"
  14. #include "slapi-private.h"
  15. /* <=========================== Berval Array ==========================> */
  16. /*
  17. * vals - The existing values.
  18. * addval - The value to add.
  19. * nvals - The number of existing values.
  20. * maxvals - The number of elements in the existing values array.
  21. */
  22. void
  23. bervalarray_add_berval_fast(
  24. struct berval ***vals,
  25. const struct berval *addval,
  26. int nvals,
  27. int *maxvals
  28. )
  29. {
  30. int need = nvals + 2;
  31. if(need>*maxvals)
  32. {
  33. if (*maxvals==0)
  34. {
  35. *maxvals = 2;
  36. }
  37. while ( *maxvals < need )
  38. {
  39. *maxvals *= 2;
  40. }
  41. if(*vals==NULL)
  42. {
  43. *vals = (struct berval **) slapi_ch_malloc( *maxvals * sizeof(struct berval *));
  44. }
  45. else
  46. {
  47. *vals = (struct berval **) slapi_ch_realloc( (char *) *vals, *maxvals * sizeof(struct berval *));
  48. }
  49. }
  50. (*vals)[nvals] = ber_bvdup( (struct berval *)addval );
  51. (*vals)[nvals+1] = NULL;
  52. }
  53. /* <=========================== Value Array ==========================> */
  54. /*
  55. * vals - The existing values.
  56. * addval - The value to add.
  57. * nvals - The number of existing values.
  58. * maxvals - The number of elements in the existing values array.
  59. */
  60. void
  61. valuearray_add_value_fast(Slapi_Value ***vals,
  62. Slapi_Value *addval,
  63. int nvals,
  64. int *maxvals,
  65. int exact, /* Don't create an array bigger than needed */
  66. int passin) /* The values are being passed in */
  67. {
  68. Slapi_Value *oneval[2];
  69. oneval[0]= addval;
  70. oneval[1]= NULL;
  71. valuearray_add_valuearray_fast(vals,oneval,nvals,1,maxvals,exact,passin);
  72. }
  73. void
  74. valuearray_add_valuearray_fast(Slapi_Value ***vals,
  75. Slapi_Value **addvals,
  76. int nvals,
  77. int naddvals,
  78. int *maxvals,
  79. int exact, /* Don't create an array bigger than needed */
  80. int passin) /* The values are being passed in */
  81. {
  82. int i, j;
  83. int allocate= 0;
  84. int need = nvals + naddvals + 1;
  85. if(exact)
  86. {
  87. /* Create an array exactly the right size. */
  88. if(need>*maxvals)
  89. {
  90. allocate= need;
  91. }
  92. }
  93. else
  94. {
  95. if (*maxvals==0) /* empty; create with 4 by default */
  96. {
  97. allocate= 4;
  98. }
  99. else if (need > *maxvals)
  100. {
  101. /* Exponentially expand the array */
  102. allocate= *maxvals;
  103. while ( allocate < need )
  104. {
  105. allocate *= 2;
  106. }
  107. }
  108. }
  109. if(allocate>0)
  110. {
  111. if(*vals==NULL)
  112. {
  113. *vals = (Slapi_Value **) slapi_ch_malloc( allocate * sizeof(Slapi_Value *));
  114. }
  115. else
  116. {
  117. *vals = (Slapi_Value **) slapi_ch_realloc( (char *) *vals, allocate * sizeof(Slapi_Value *));
  118. }
  119. *maxvals= allocate;
  120. }
  121. for ( i = 0, j = 0; i < naddvals; i++)
  122. {
  123. if ( addvals[i]!=NULL )
  124. {
  125. if(passin)
  126. {
  127. /* We consume the values */
  128. (*vals)[nvals + j] = addvals[i];
  129. }
  130. else
  131. {
  132. /* We copy the values */
  133. (*vals)[nvals + j] = slapi_value_dup(addvals[i]);
  134. }
  135. j++;
  136. }
  137. }
  138. (*vals)[nvals + j] = NULL;
  139. }
  140. void
  141. valuearray_add_value(Slapi_Value ***vals, const Slapi_Value *addval)
  142. {
  143. Slapi_Value *oneval[2];
  144. oneval[0]= (Slapi_Value*)addval;
  145. oneval[1]= NULL;
  146. valuearray_add_valuearray(vals,oneval,0);
  147. }
  148. void
  149. valuearray_add_valuearray(Slapi_Value ***vals, Slapi_Value **addvals, PRUint32 flags)
  150. {
  151. int valslen;
  152. int addvalslen;
  153. int maxvals;
  154. if(vals == NULL){
  155. return;
  156. }
  157. addvalslen= valuearray_count(addvals);
  158. if(*vals == NULL)
  159. {
  160. valslen= 0;
  161. maxvals= 0;
  162. }
  163. else
  164. {
  165. valslen= valuearray_count(*vals);
  166. maxvals= valslen+1;
  167. }
  168. valuearray_add_valuearray_fast(vals,addvals,valslen,addvalslen,&maxvals,1/*Exact*/,flags & SLAPI_VALUE_FLAG_PASSIN);
  169. }
  170. int
  171. valuearray_count( Slapi_Value **va)
  172. {
  173. int i=0;
  174. if(va!=NULL)
  175. {
  176. while(NULL != va[i]) i++;
  177. }
  178. return(i);
  179. }
  180. int
  181. valuearray_isempty( Slapi_Value **va)
  182. {
  183. return va==NULL || va[0]==NULL;
  184. }
  185. /*
  186. * JCM SLOW FUNCTION
  187. *
  188. * WARNING: Use only if you absolutley need to...
  189. * This function mostly exists to map from the old slapi berval
  190. * based interface to the new Slapi_Value based interfaces.
  191. */
  192. int
  193. valuearray_init_bervalarray(struct berval **bvals, Slapi_Value ***cvals)
  194. {
  195. int n;
  196. for(n=0; bvals != NULL && bvals[n] != NULL; n++);
  197. if(n==0)
  198. {
  199. *cvals = NULL;
  200. }
  201. else
  202. {
  203. int i;
  204. *cvals = (Slapi_Value **) slapi_ch_malloc((n + 1) * sizeof(Slapi_Value *));
  205. for(i=0;i<n;i++)
  206. {
  207. (*cvals)[i] = slapi_value_new_berval(bvals[i]);
  208. }
  209. (*cvals)[i] = NULL;
  210. }
  211. return n;
  212. }
  213. /*
  214. * JCM SLOW FUNCTION
  215. *
  216. * WARNING: Use only if you absolutley need to...
  217. * This function mostly exists to map from the old slapi berval
  218. * based interface to the new Slapi_Value based interfaces.
  219. */
  220. int
  221. valuearray_init_bervalarray_with_flags(struct berval **bvals, Slapi_Value ***cvals, unsigned long flags)
  222. {
  223. int n;
  224. for(n=0; bvals != NULL && bvals[n] != NULL; n++);
  225. if(n==0)
  226. {
  227. *cvals = NULL;
  228. }
  229. else
  230. {
  231. int i;
  232. *cvals = (Slapi_Value **) slapi_ch_malloc((n + 1) * sizeof(Slapi_Value *));
  233. for(i=0;i<n;i++)
  234. {
  235. (*cvals)[i] = slapi_value_new_berval(bvals[i]);
  236. slapi_value_set_flags((*cvals)[i], flags);
  237. }
  238. (*cvals)[i] = NULL;
  239. }
  240. return n;
  241. }
  242. /*
  243. * JCM SLOW FUNCTION
  244. *
  245. * Use only if you absolutley need to...
  246. * This function mostly exists to map from the old slapi berval
  247. * based interface to the new Slapi_Value based interfaces.
  248. */
  249. int
  250. valuearray_get_bervalarray(Slapi_Value **cvals,struct berval ***bvals)
  251. {
  252. int i,n;
  253. n= valuearray_count(cvals);
  254. if (0 == n)
  255. {
  256. *bvals = NULL;
  257. }
  258. else
  259. {
  260. *bvals = (struct berval **)slapi_ch_malloc((n + 1) * sizeof(struct berval *));
  261. for(i=0;i<n;i++)
  262. {
  263. (*bvals)[i] = ber_bvdup((struct berval *)slapi_value_get_berval(cvals[i]));
  264. }
  265. (*bvals)[i] = NULL;
  266. }
  267. return(0);
  268. }
  269. void
  270. valuearray_free_ext(Slapi_Value ***va, int idx)
  271. {
  272. if(va!=NULL && *va!=NULL)
  273. {
  274. for(; (*va)[idx]!=NULL; idx++)
  275. {
  276. slapi_value_free(&(*va)[idx]);
  277. }
  278. slapi_ch_free((void **)va);
  279. *va = NULL;
  280. }
  281. }
  282. void
  283. valuearray_free(Slapi_Value ***va)
  284. {
  285. valuearray_free_ext(va, 0);
  286. }
  287. int
  288. valuearray_next_value( Slapi_Value **va, int index, Slapi_Value **v)
  289. {
  290. int r= -1;
  291. if(va!=NULL && va[0]!=NULL)
  292. {
  293. r= index+1;
  294. *v= va[r];
  295. if(*v==NULL)
  296. {
  297. r= -1;
  298. }
  299. }
  300. else
  301. {
  302. *v= NULL;
  303. }
  304. return r;
  305. }
  306. int
  307. valuearray_first_value( Slapi_Value **va, Slapi_Value **v )
  308. {
  309. return valuearray_next_value( va, -1, v);
  310. }
  311. /*
  312. * Find the value and return an index number to it.
  313. */
  314. int
  315. valuearray_find(const Slapi_Attr *a, Slapi_Value **va, const Slapi_Value *v)
  316. {
  317. int i= 0;
  318. int found= -1;
  319. while(found==-1 && va!=NULL && va[i]!=NULL)
  320. {
  321. if(slapi_value_compare( a, v, va[i])==0)
  322. {
  323. found= i;
  324. }
  325. else
  326. {
  327. i++;
  328. }
  329. }
  330. return found;
  331. }
  332. /*
  333. * Shunt up the array to cover the value to remove.
  334. */
  335. void
  336. valuearray_remove_value_atindex(Slapi_Value **va, int index)
  337. {
  338. if(va!=NULL && va[0]!=NULL)
  339. {
  340. int k;
  341. for ( k = index + 1; va[k] != NULL; k++ )
  342. {
  343. va[k - 1] = va[k];
  344. }
  345. va[k - 1] = NULL;
  346. }
  347. }
  348. /*
  349. * Subtract bvalues from value array
  350. * return value: subtracted count
  351. */
  352. int
  353. valuearray_subtract_bvalues(Slapi_Value **va, struct berval **bvals)
  354. {
  355. Slapi_Value **vap;
  356. struct berval **bvp;
  357. int rv = 0;
  358. if (NULL == va || NULL == *va || NULL == bvals || NULL == *bvals) {
  359. return rv; /* No op */
  360. }
  361. for (vap = va; vap && *vap; vap++) {
  362. for (bvp = bvals; bvp && *bvp; bvp++) {
  363. if (0 == slapi_berval_cmp(&(*vap)->bv, *bvp)) {
  364. Slapi_Value **vapp;
  365. slapi_value_free(vap);
  366. for (vapp = vap; vapp && *vapp; vapp++) {
  367. *vapp = *(vapp + 1);
  368. }
  369. vapp++;
  370. rv++;
  371. }
  372. }
  373. }
  374. return rv;
  375. }
  376. /*
  377. * Find the value in the array,
  378. * shunt up the array to cover it,
  379. * return a ptr to the value.
  380. * The caller is responsible for freeing the value.
  381. */
  382. Slapi_Value *
  383. valuearray_remove_value(const Slapi_Attr *a, Slapi_Value **va, const Slapi_Value *v)
  384. {
  385. Slapi_Value *r= NULL;
  386. int i= 0;
  387. i= valuearray_find(a, va, v);
  388. if(i!=-1)
  389. {
  390. r= va[i];
  391. valuearray_remove_value_atindex(va,i);
  392. }
  393. return r;
  394. }
  395. /*
  396. * Remove any values older than the CSN.
  397. */
  398. int
  399. valuearray_purge(Slapi_Value ***va, const CSN *csn)
  400. {
  401. int numValues=0;
  402. int i=0;
  403. int nextValue=0;
  404. PR_ASSERT(va!=NULL && *va!=NULL);
  405. /* Loop over all the values freeing the old ones. */
  406. for(i=0; (*va)[i]; i++)
  407. {
  408. csnset_purge(&((*va)[i]->v_csnset),csn);
  409. if ((*va)[i]->v_csnset == NULL)
  410. {
  411. slapi_value_free(&(*va)[i]);
  412. (*va)[i] = NULL;
  413. }
  414. }
  415. /* Now compact the value list. */
  416. numValues=i;
  417. nextValue = 0;
  418. i = 0;
  419. for(i=0;i<numValues;i++)
  420. {
  421. while((nextValue < numValues) && (NULL == (*va)[nextValue]))
  422. {
  423. nextValue++;
  424. }
  425. if(nextValue < numValues)
  426. {
  427. (*va)[i] = (*va)[nextValue];
  428. nextValue++;
  429. }
  430. else
  431. {
  432. break;
  433. }
  434. }
  435. (*va)[i] = NULL;
  436. /* All the values were deleted, we can discard the whole array. */
  437. if(NULL == (*va)[0])
  438. {
  439. slapi_ch_free((void**)va);
  440. *va= NULL;
  441. }
  442. /* return the number of remaining values */
  443. return(i);
  444. }
  445. size_t
  446. valuearray_size(Slapi_Value **va)
  447. {
  448. size_t s= 0;
  449. if(va!=NULL && va[0]!=NULL)
  450. {
  451. int i;
  452. for (i = 0; va[i]; i++)
  453. {
  454. s += value_size(va[i]);
  455. }
  456. s += (i + 1) * sizeof(Slapi_Value*);
  457. }
  458. return s;
  459. }
  460. void
  461. valuearray_update_csn(Slapi_Value **va, CSNType t, const CSN *csn)
  462. {
  463. int i;
  464. for (i = 0; va!=NULL && va[i]; i++)
  465. {
  466. value_update_csn(va[i],t,csn);
  467. }
  468. }
  469. /* <=========================== Value Array Fast ==========================> */
  470. void
  471. valuearrayfast_init(struct valuearrayfast *vaf,Slapi_Value **va)
  472. {
  473. vaf->num= valuearray_count(va);
  474. vaf->max= vaf->num;
  475. vaf->va= va;
  476. }
  477. void
  478. valuearrayfast_done(struct valuearrayfast *vaf)
  479. {
  480. if(vaf->va!=NULL)
  481. {
  482. int i;
  483. for(i=0; i<vaf->num; i++)
  484. {
  485. slapi_value_free(&vaf->va[i]);
  486. }
  487. slapi_ch_free((void **)&vaf->va);
  488. vaf->num= 0;
  489. vaf->max= 0;
  490. }
  491. }
  492. void
  493. valuearrayfast_add_value(struct valuearrayfast *vaf,const Slapi_Value *v)
  494. {
  495. valuearray_add_value_fast(&vaf->va,(Slapi_Value *)v,vaf->num,&vaf->max,0/*Exact*/,0/*!PassIn*/);
  496. vaf->num++;
  497. }
  498. void
  499. valuearrayfast_add_value_passin(struct valuearrayfast *vaf,Slapi_Value *v)
  500. {
  501. valuearray_add_value_fast(&vaf->va,v,vaf->num,&vaf->max,0/*Exact*/,1/*PassIn*/);
  502. vaf->num++;
  503. }
  504. /* <=========================== Value Set =======================> */
  505. #define VALUESET_ARRAY_SORT_THRESHOLD 10
  506. #define VALUESET_ARRAY_MINSIZE 2
  507. #define VALUESET_ARRAY_MAXINCREMENT 4096
  508. Slapi_ValueSet *
  509. slapi_valueset_new()
  510. {
  511. Slapi_ValueSet *vs = (Slapi_ValueSet *)slapi_ch_calloc(1,sizeof(Slapi_ValueSet));
  512. if(vs)
  513. slapi_valueset_init(vs);
  514. return vs;
  515. }
  516. void
  517. slapi_valueset_init(Slapi_ValueSet *vs)
  518. {
  519. if(vs!=NULL)
  520. {
  521. vs->va= NULL;
  522. vs->sorted = NULL;
  523. vs->num = 0;
  524. vs->max = 0;
  525. }
  526. }
  527. void
  528. slapi_valueset_done(Slapi_ValueSet *vs)
  529. {
  530. if(vs!=NULL)
  531. {
  532. PR_ASSERT((vs->sorted == NULL) || (vs->num == 0) || ((vs->sorted[0] >= 0) && (vs->sorted[0] < vs->num)));
  533. if(vs->va!=NULL)
  534. {
  535. valuearray_free(&vs->va);
  536. vs->va= NULL;
  537. }
  538. if (vs->sorted != NULL)
  539. {
  540. slapi_ch_free ((void **)&vs->sorted);
  541. vs->sorted = NULL;
  542. }
  543. vs->num = 0;
  544. vs->max = 0;
  545. }
  546. }
  547. void
  548. slapi_valueset_free(Slapi_ValueSet *vs)
  549. {
  550. if(vs!=NULL)
  551. {
  552. slapi_valueset_done(vs);
  553. slapi_ch_free((void **)&vs);
  554. }
  555. }
  556. void
  557. slapi_valueset_set_from_smod(Slapi_ValueSet *vs, Slapi_Mod *smod)
  558. {
  559. Slapi_Value **va= NULL;
  560. valuearray_init_bervalarray(slapi_mod_get_ldapmod_byref(smod)->mod_bvalues, &va);
  561. valueset_set_valuearray_passin(vs, va);
  562. PR_ASSERT((vs->sorted == NULL) || (vs->num == 0) || ((vs->sorted[0] >= 0) && (vs->sorted[0] < vs->num)));
  563. }
  564. void
  565. valueset_set_valuearray_byval(Slapi_ValueSet *vs, Slapi_Value **addvals)
  566. {
  567. int i, j=0;
  568. slapi_valueset_init(vs);
  569. vs->num = valuearray_count(addvals);
  570. vs->max = vs->num + 1;
  571. vs->va = (Slapi_Value **) slapi_ch_malloc( vs->max * sizeof(Slapi_Value *));
  572. for ( i = 0, j = 0; i < vs->num; i++)
  573. {
  574. if ( addvals[i]!=NULL )
  575. {
  576. /* We copy the values */
  577. vs->va[j] = slapi_value_dup(addvals[i]);
  578. j++;
  579. }
  580. }
  581. vs->va[j] = NULL;
  582. PR_ASSERT((vs->sorted == NULL) || (vs->num == 0) || ((vs->sorted[0] >= 0) && (vs->sorted[0] < vs->num)));
  583. }
  584. /* WARNING: you must call this function with a new vs - if it points to existing data, it
  585. * will leak - call slapi_valueset_done to free it first if necessary
  586. */
  587. void
  588. valueset_set_valuearray_passin(Slapi_ValueSet *vs, Slapi_Value **addvals)
  589. {
  590. slapi_valueset_init(vs);
  591. vs->va= addvals;
  592. vs->num = valuearray_count(addvals);
  593. vs->max = vs->num + 1;
  594. PR_ASSERT((vs->sorted == NULL) || (vs->num == 0) || ((vs->sorted[0] >= 0) && (vs->sorted[0] < vs->num)));
  595. }
  596. /* WARNING: you must call this function with a new vs1 - if it points to existing data, it
  597. * will leak - call slapi_valueset_done(vs1) to free it first if necessary
  598. */
  599. void
  600. slapi_valueset_set_valueset(Slapi_ValueSet *vs1, const Slapi_ValueSet *vs2)
  601. {
  602. slapi_valueset_init(vs1);
  603. valueset_set_valueset(vs1,vs2);
  604. }
  605. void
  606. slapi_valueset_join_attr_valueset(const Slapi_Attr *a, Slapi_ValueSet *vs1, const Slapi_ValueSet *vs2)
  607. {
  608. if (slapi_valueset_isempty(vs1))
  609. valueset_set_valueset(vs1,vs2);
  610. else
  611. slapi_valueset_add_attr_valuearray_ext (a, vs1, vs2->va, vs2->num, 0, NULL);
  612. }
  613. int
  614. slapi_valueset_first_value( Slapi_ValueSet *vs, Slapi_Value **v )
  615. {
  616. if (NULL == vs) {
  617. if (v) {
  618. *v = NULL;
  619. }
  620. return 0;
  621. }
  622. return valuearray_first_value(vs->va,v);
  623. }
  624. int
  625. slapi_valueset_next_value( Slapi_ValueSet *vs, int index, Slapi_Value **v)
  626. {
  627. if (NULL == vs) {
  628. if (v) {
  629. *v = NULL;
  630. }
  631. return index;
  632. }
  633. return valuearray_next_value(vs->va,index,v);
  634. }
  635. int
  636. slapi_valueset_count( const Slapi_ValueSet *vs)
  637. {
  638. if (NULL != vs)
  639. {
  640. return (vs->num);
  641. }
  642. return 0;
  643. }
  644. int
  645. slapi_valueset_isempty( const Slapi_ValueSet *vs)
  646. {
  647. if (NULL != vs)
  648. {
  649. return (vs->num == 0);
  650. }
  651. return 1;
  652. }
  653. int
  654. valueset_isempty( const Slapi_ValueSet *vs)
  655. {
  656. if (NULL == vs) {
  657. return 1; /* true */
  658. }
  659. return valuearray_isempty(vs->va);
  660. }
  661. Slapi_Value *
  662. slapi_valueset_find(const Slapi_Attr *a, const Slapi_ValueSet *vs, const Slapi_Value *v)
  663. {
  664. Slapi_Value *r= NULL;
  665. if(vs && (vs->num > 0))
  666. {
  667. if (vs->sorted) {
  668. r = valueset_find_sorted(a,vs,v,NULL);
  669. } else {
  670. int i= valuearray_find(a,vs->va,v);
  671. if(i!=-1) {
  672. r= vs->va[i];
  673. }
  674. }
  675. }
  676. return r;
  677. }
  678. /*
  679. * The value is found in the set, removed and returned.
  680. * The caller is responsible for freeing the value.
  681. *
  682. * The _sorted function also handles the cleanup of the sorted array
  683. */
  684. Slapi_Value *
  685. valueset_remove_value_sorted(const Slapi_Attr *a, Slapi_ValueSet *vs, const Slapi_Value *v)
  686. {
  687. Slapi_Value *r= NULL;
  688. int i, position = 0;
  689. r = valueset_find_sorted(a,vs,v,&position);
  690. if (r) {
  691. /* the value was found, remove from valuearray */
  692. int index = vs->sorted[position];
  693. memmove(&vs->sorted[position],&vs->sorted[position+1],(vs->num - position)*sizeof(int));
  694. memmove(&vs->va[index],&vs->va[index+1],(vs->num - index)*sizeof(Slapi_Value *));
  695. vs->num--;
  696. /* unfortunately the references in the sorted array
  697. * to values past the removed one are no longer correct
  698. * need to adjust */
  699. for (i=0; i < vs->num; i++) {
  700. if (vs->sorted[i] > index) vs->sorted[i]--;
  701. }
  702. PR_ASSERT((vs->sorted == NULL) || (vs->num == 0) || ((vs->sorted[0] >= 0) && (vs->sorted[0] < vs->num)));
  703. }
  704. return r;
  705. }
  706. Slapi_Value *
  707. valueset_remove_value(const Slapi_Attr *a, Slapi_ValueSet *vs, const Slapi_Value *v)
  708. {
  709. Slapi_Value *r = NULL;
  710. if (vs->sorted) {
  711. r = valueset_remove_value_sorted(a, vs, v);
  712. } else {
  713. if(!valuearray_isempty(vs->va))
  714. {
  715. r= valuearray_remove_value(a, vs->va, v);
  716. if (r)
  717. vs->num--;
  718. }
  719. }
  720. PR_ASSERT((vs->sorted == NULL) || (vs->num == 0) || ((vs->sorted[0] >= 0) && (vs->sorted[0] < vs->num)));
  721. return r;
  722. }
  723. /*
  724. * Remove any values older than the CSN.
  725. */
  726. int
  727. valueset_purge(Slapi_ValueSet *vs, const CSN *csn)
  728. {
  729. int r= 0;
  730. if(!valuearray_isempty(vs->va)) {
  731. /* valuearray_purge is not valueset and sorting aware,
  732. * maybe need to rewrite, at least keep the valueset
  733. * consistent
  734. */
  735. r= valuearray_purge(&vs->va, csn);
  736. vs->num = r;
  737. if (vs->va == NULL) {
  738. /* va was freed */
  739. vs->max = 0;
  740. }
  741. /* we can no longer rely on the sorting */
  742. if (vs->sorted != NULL)
  743. {
  744. slapi_ch_free ((void **)&vs->sorted);
  745. vs->sorted = NULL;
  746. }
  747. PR_ASSERT((vs->sorted == NULL) || (vs->num == 0) || ((vs->sorted[0] >= 0) && (vs->sorted[0] < vs->num)));
  748. }
  749. return 0;
  750. }
  751. Slapi_Value **
  752. valueset_get_valuearray(const Slapi_ValueSet *vs)
  753. {
  754. return (Slapi_Value**)vs->va;
  755. }
  756. size_t
  757. valueset_size(const Slapi_ValueSet *vs)
  758. {
  759. size_t s = 0;
  760. if (vs && !valuearray_isempty(vs->va)) {
  761. s = valuearray_size(vs->va);
  762. }
  763. return s;
  764. }
  765. /*
  766. * The value array is passed in by value.
  767. */
  768. void
  769. slapi_valueset_add_valuearray(const Slapi_Attr *a, Slapi_ValueSet *vs, Slapi_Value **addvals)
  770. {
  771. if(!valuearray_isempty(addvals))
  772. {
  773. slapi_valueset_add_attr_valuearray_ext (a, vs, addvals, valuearray_count(addvals), 0, NULL);
  774. }
  775. }
  776. void
  777. valueset_add_valuearray(Slapi_ValueSet *vs, Slapi_Value **addvals)
  778. {
  779. if(!valuearray_isempty(addvals))
  780. {
  781. slapi_valueset_add_attr_valuearray_ext (NULL, vs, addvals, valuearray_count(addvals), 0, NULL);
  782. }
  783. }
  784. /*
  785. * The value is passed in by value.
  786. */
  787. void
  788. slapi_valueset_add_value(Slapi_ValueSet *vs, const Slapi_Value *addval)
  789. {
  790. slapi_valueset_add_value_ext(vs, addval, 0);
  791. }
  792. void
  793. slapi_valueset_add_value_ext(Slapi_ValueSet *vs, const Slapi_Value *addval, unsigned long flags)
  794. {
  795. Slapi_Value *oneval[2];
  796. oneval[0]= (Slapi_Value*)addval;
  797. oneval[1]= NULL;
  798. slapi_valueset_add_attr_valuearray_ext(NULL, vs, oneval, 1, flags, NULL);
  799. }
  800. /* find value v in the sorted array of values, using syntax of attribut a for comparison
  801. *
  802. */
  803. static int
  804. valueset_value_syntax_cmp( const Slapi_Attr *a, const Slapi_Value *v1, const Slapi_Value *v2 )
  805. {
  806. /* this looks like a huge overhead, but there are no simple functions to normalize and
  807. * compare available
  808. */
  809. const Slapi_Value *oneval[3];
  810. Slapi_Value **keyvals;
  811. int rc = -1;
  812. keyvals = NULL;
  813. oneval[0] = v1;
  814. oneval[1] = v2;
  815. oneval[2] = NULL;
  816. if ( slapi_attr_values2keys_sv( a, (Slapi_Value**)oneval, &keyvals, LDAP_FILTER_EQUALITY ) != 0
  817. || keyvals == NULL
  818. || keyvals[0] == NULL || keyvals[1] == NULL)
  819. {
  820. /* this should never happen since always a syntax plugin to
  821. * generate the keys will be found (there exists a default plugin)
  822. * log an error and continue.
  823. */
  824. LDAPDebug( LDAP_DEBUG_ANY, "valueset_value_syntax_cmp: "
  825. "slapi_attr_values2keys_sv failed for type %s\n",
  826. a->a_type, 0, 0 );
  827. } else {
  828. const struct berval *bv1, *bv2;
  829. bv1 = &keyvals[0]->bv;
  830. bv2 = &keyvals[1]->bv;
  831. rc = slapi_berval_cmp (bv1, bv2);
  832. }
  833. if (keyvals != NULL)
  834. valuearray_free( &keyvals );
  835. return (rc);
  836. }
  837. static int
  838. valueset_value_cmp( const Slapi_Attr *a, const Slapi_Value *v1, const Slapi_Value *v2 )
  839. {
  840. if ( a == NULL || slapi_attr_is_dn_syntax_attr((Slapi_Attr *)a)) {
  841. /* if no attr is provided just do a utf8compare */
  842. /* for all the values the first step of normalization is done,
  843. * case folding still needs to be done
  844. */
  845. /* would this be enough ?: return (strcasecmp(v1->bv.bv_val, v2->bv.bv_val)); */
  846. return (slapi_utf8casecmp((unsigned char*)v1->bv.bv_val, (unsigned char*)v2->bv.bv_val));
  847. } else {
  848. /* slapi_value_compare doesn't work, it only returns 0 or -1
  849. return (slapi_value_compare(a, v1, v2));
  850. * use special compare, base on what valuetree_find did
  851. */
  852. return(valueset_value_syntax_cmp(a, v1, v2));
  853. }
  854. }
  855. /* find a value in the sorted valuearray.
  856. * If the value is found the pointer to the value is returned and if index is provided
  857. * it will return the index of the value in the valuearray
  858. * If the value is not found, index will contain the place where the value would be inserted
  859. */
  860. Slapi_Value *
  861. valueset_find_sorted (const Slapi_Attr *a, const Slapi_ValueSet *vs, const Slapi_Value *v, int *index)
  862. {
  863. int cmp = -1;
  864. int bot = -1;
  865. int top;
  866. if (vs->num == 0) {
  867. /* empty valueset */
  868. if (index) *index = 0;
  869. return (NULL);
  870. } else {
  871. top = vs->num;
  872. }
  873. while (top - bot > 1) {
  874. int mid = (top + bot)/2;
  875. if ( (cmp = valueset_value_cmp(a, v, vs->va[vs->sorted[mid]])) > 0)
  876. bot = mid;
  877. else
  878. top = mid;
  879. }
  880. if (index) *index = top;
  881. /* check if the value is found */
  882. if ( top < vs->num && (0 == valueset_value_cmp(a, v, vs->va[vs->sorted[top]])))
  883. return (vs->va[vs->sorted[top]]);
  884. else
  885. return (NULL);
  886. }
  887. void
  888. valueset_array_to_sorted (const Slapi_Attr *a, Slapi_ValueSet *vs)
  889. {
  890. int i, j, swap;
  891. /* initialize sort array */
  892. for (i = 0; i < vs->num; i++)
  893. vs->sorted[i] = i;
  894. /* now sort it, use a simple insertion sort as the array will always
  895. * be very small when initially sorted
  896. */
  897. for (i = 1; i < vs->num; i++) {
  898. swap = vs->sorted[i];
  899. j = i -1;
  900. while ( j >= 0 && valueset_value_cmp (a, vs->va[vs->sorted[j]], vs->va[swap]) > 0 ) {
  901. vs->sorted[j+1] = vs->sorted[j];
  902. j--;
  903. }
  904. vs->sorted[j+1] = swap;
  905. }
  906. PR_ASSERT((vs->sorted == NULL) || (vs->num == 0) || ((vs->sorted[0] >= 0) && (vs->sorted[0] < vs->num)));
  907. }
  908. /* insert a value into a sorted array, if dupcheck is set no duplicate values will be accepted
  909. * (is there a reason to allow duplicates ? LK
  910. * if the value is inserted the the function returns the index where it was inserted
  911. * if the value already exists -index is returned to indicate anerror an the index of the existing value
  912. */
  913. int
  914. valueset_insert_value_to_sorted(const Slapi_Attr *a, Slapi_ValueSet *vs, Slapi_Value *vi, int dupcheck)
  915. {
  916. int index = -1;
  917. Slapi_Value *v;
  918. /* test for pre sorted array and to avoid boundary condition */
  919. if (vs->num == 0) {
  920. vs->sorted[0] = 0;
  921. vs->num++;
  922. PR_ASSERT((vs->sorted == NULL) || (vs->num == 0) || ((vs->sorted[0] >= 0) && (vs->sorted[0] < vs->num)));
  923. return(0);
  924. } else if (valueset_value_cmp (a, vi, vs->va[vs->sorted[vs->num-1]]) > 0 ) {
  925. vs->sorted[vs->num] = vs->num;
  926. vs->num++;
  927. PR_ASSERT((vs->sorted == NULL) || (vs->num == 0) || ((vs->sorted[0] >= 0) && (vs->sorted[0] < vs->num)));
  928. return (vs->num);
  929. }
  930. v = valueset_find_sorted (a, vs, vi, &index);
  931. if (v && dupcheck) {
  932. /* value already exists, do not insert duplicates */
  933. return (-1);
  934. } else {
  935. memmove(&vs->sorted[index+1],&vs->sorted[index],(vs->num - index)* sizeof(int));
  936. vs->sorted[index] = vs->num;
  937. vs->num++;
  938. PR_ASSERT((vs->sorted == NULL) || (vs->num == 0) || ((vs->sorted[0] >= 0) && (vs->sorted[0] < vs->num)));
  939. return(index);
  940. }
  941. }
  942. /*
  943. * If this function returns an error, it is safe to do both
  944. * slapi_valueset_done(vs);
  945. * and
  946. * valuearray_free(&addvals);
  947. * if there is an error and the PASSIN flag is used, the addvals array will own all of the values
  948. * vs will own none of the values - so you should do both slapi_valueset_done(vs) and valuearray_free(&addvals)
  949. * to clean up
  950. */
  951. int
  952. slapi_valueset_add_attr_valuearray_ext(const Slapi_Attr *a, Slapi_ValueSet *vs,
  953. Slapi_Value **addvals, int naddvals, unsigned long flags, int *dup_index)
  954. {
  955. int rc = LDAP_SUCCESS;
  956. int i, dup;
  957. int allocate = 0;
  958. int need;
  959. int passin = flags & SLAPI_VALUE_FLAG_PASSIN;
  960. int dupcheck = flags & SLAPI_VALUE_FLAG_DUPCHECK;
  961. if (naddvals == 0)
  962. return (rc);
  963. need = vs->num + naddvals + 1;
  964. if (need > vs->max) {
  965. /* Expand the array */
  966. allocate= vs->max;
  967. if ( allocate == 0 ) /* initial allocation */
  968. allocate = VALUESET_ARRAY_MINSIZE;
  969. while ( allocate < need )
  970. {
  971. if (allocate > VALUESET_ARRAY_MAXINCREMENT )
  972. /* do not grow exponentially */
  973. allocate += VALUESET_ARRAY_MAXINCREMENT;
  974. else
  975. allocate *= 2;
  976. }
  977. }
  978. if(allocate>0)
  979. {
  980. if(vs->va==NULL)
  981. {
  982. vs->va = (Slapi_Value **) slapi_ch_malloc( allocate * sizeof(Slapi_Value *));
  983. }
  984. else
  985. {
  986. vs->va = (Slapi_Value **) slapi_ch_realloc( (char *) vs->va, allocate * sizeof(Slapi_Value *));
  987. if (vs->sorted) {
  988. vs->sorted = (int *) slapi_ch_realloc( (char *) vs->sorted, allocate * sizeof(int));
  989. }
  990. }
  991. vs->max= allocate;
  992. }
  993. if ( (vs->num + naddvals > VALUESET_ARRAY_SORT_THRESHOLD || dupcheck ) &&
  994. !vs->sorted ) {
  995. /* initialize sort array and do initial sort */
  996. vs->sorted = (int *) slapi_ch_malloc( vs->max* sizeof(int));
  997. valueset_array_to_sorted (a, vs);
  998. }
  999. for ( i = 0; i < naddvals; i++)
  1000. {
  1001. if ( addvals[i]!=NULL )
  1002. {
  1003. if(passin)
  1004. {
  1005. /* We consume the values */
  1006. (vs->va)[vs->num] = addvals[i];
  1007. }
  1008. else
  1009. {
  1010. /* We copy the values */
  1011. (vs->va)[vs->num] = slapi_value_dup(addvals[i]);
  1012. }
  1013. if (vs->sorted) {
  1014. dup = valueset_insert_value_to_sorted(a, vs, (vs->va)[vs->num], dupcheck);
  1015. if (dup < 0 ) {
  1016. rc = LDAP_TYPE_OR_VALUE_EXISTS;
  1017. if (dup_index) *dup_index = i;
  1018. if (passin) {
  1019. PR_ASSERT((i == 0) || dup_index);
  1020. /* caller must provide dup_index to know how far we got in addvals */
  1021. (vs->va)[vs->num] = NULL;
  1022. } else {
  1023. slapi_value_free(&(vs->va)[vs->num]);
  1024. }
  1025. break;
  1026. }
  1027. } else {
  1028. vs->num++;
  1029. }
  1030. }
  1031. }
  1032. (vs->va)[vs->num] = NULL;
  1033. PR_ASSERT((vs->sorted == NULL) || (vs->num == 0) || ((vs->sorted[0] >= 0) && (vs->sorted[0] < vs->num)));
  1034. return (rc);
  1035. }
  1036. int
  1037. slapi_valueset_add_attr_value_ext(const Slapi_Attr *a, Slapi_ValueSet *vs, Slapi_Value *addval, unsigned long flags)
  1038. {
  1039. Slapi_Value *oneval[2];
  1040. int rc;
  1041. oneval[0]= (Slapi_Value*)addval;
  1042. oneval[1]= NULL;
  1043. rc = slapi_valueset_add_attr_valuearray_ext(a, vs, oneval, 1, flags, NULL );
  1044. return (rc);
  1045. }
  1046. /*
  1047. * The string is passed in by value.
  1048. */
  1049. void
  1050. valueset_add_string(const Slapi_Attr *a, Slapi_ValueSet *vs, const char *s, CSNType t, const CSN *csn)
  1051. {
  1052. Slapi_Value v;
  1053. value_init(&v,NULL,t,csn);
  1054. slapi_value_set_string(&v,s);
  1055. slapi_valueset_add_attr_value_ext(a, vs, &v, 0 );
  1056. value_done(&v);
  1057. }
  1058. /*
  1059. * The value set is passed in by value.
  1060. */
  1061. void
  1062. valueset_set_valueset(Slapi_ValueSet *vs1, const Slapi_ValueSet *vs2)
  1063. {
  1064. int i;
  1065. if (vs1 && vs2) {
  1066. int oldmax = vs1->max;
  1067. /* pre-condition - vs1 empty - otherwise, existing data is overwritten */
  1068. PR_ASSERT(vs1->num == 0);
  1069. if (vs2->va) {
  1070. /* need to copy valuearray */
  1071. if (vs2->max == 0) {
  1072. /* temporary hack, not all valuesets were created properly. fix it now */
  1073. vs1->num = valuearray_count(vs2->va);
  1074. vs1->max = vs1->num + 1;
  1075. } else {
  1076. vs1->num = vs2->num;
  1077. vs1->max = vs2->max;
  1078. }
  1079. /* do we need more room? */
  1080. if ((NULL == vs1->va) || (oldmax < vs1->max)) {
  1081. vs1->va = (Slapi_Value **)slapi_ch_realloc((char *)vs1->va, vs1->max * sizeof(Slapi_Value *));
  1082. }
  1083. for (i=0; i< vs1->num;i++) {
  1084. vs1->va[i] = slapi_value_dup(vs2->va[i]);
  1085. }
  1086. vs1->va[vs1->num] = NULL;
  1087. } else {
  1088. valuearray_free(&vs1->va);
  1089. }
  1090. if (vs2->sorted) {
  1091. if ((NULL == vs1->sorted) || (oldmax < vs1->max)) {
  1092. vs1->sorted = (int *)slapi_ch_realloc((char *)vs1->sorted, vs1->max * sizeof(int));
  1093. }
  1094. memcpy(&vs1->sorted[0], &vs2->sorted[0], vs1->num * sizeof(int));
  1095. } else {
  1096. slapi_ch_free((void **)&vs1->sorted);
  1097. }
  1098. /* post-condition */
  1099. PR_ASSERT((vs1->sorted == NULL) || (vs1->num == 0) || ((vs1->sorted[0] >= 0) && (vs1->sorted[0] < vs1->num)));
  1100. }
  1101. }
  1102. void
  1103. valueset_remove_string(const Slapi_Attr *a, Slapi_ValueSet *vs, const char *s)
  1104. {
  1105. Slapi_Value v;
  1106. Slapi_Value *removed;
  1107. value_init(&v,NULL,CSN_TYPE_NONE,NULL);
  1108. slapi_value_set_string(&v,s);
  1109. removed = valueset_remove_value(a, vs, &v);
  1110. if(removed) {
  1111. slapi_value_free(&removed);
  1112. }
  1113. value_done(&v);
  1114. }
  1115. void
  1116. valueset_update_csn(Slapi_ValueSet *vs, CSNType t, const CSN *csn)
  1117. {
  1118. if(!valuearray_isempty(vs->va))
  1119. {
  1120. valuearray_update_csn(vs->va,t,csn);
  1121. }
  1122. }
  1123. /*
  1124. * Remove an array of values from a value set.
  1125. * The removed values are passed back in an array.
  1126. *
  1127. * Flags
  1128. * SLAPI_VALUE_FLAG_PRESERVECSNSET - csnset in the value set is duplicated and
  1129. * preserved in the matched element of the
  1130. * array of values.
  1131. * SLAPI_VALUE_FLAG_IGNOREERROR - ignore an error: Couldn't find the value to
  1132. * be deleted.
  1133. * SLAPI_VALUE_FLAG_USENEWVALUE - replace the value between the value set and
  1134. * the matched element of the array of values
  1135. * (used by entry_add_present_values_wsi).
  1136. *
  1137. * Returns
  1138. * LDAP_SUCCESS - OK.
  1139. * LDAP_NO_SUCH_ATTRIBUTE - A value to be deleted was not in the value set.
  1140. * LDAP_OPERATIONS_ERROR - Something very bad happened.
  1141. */
  1142. int
  1143. valueset_remove_valuearray(Slapi_ValueSet *vs, const Slapi_Attr *a, Slapi_Value **valuestodelete, int flags, Slapi_Value ***va_out)
  1144. {
  1145. int rc= LDAP_SUCCESS;
  1146. if(vs->num > 0)
  1147. {
  1148. int i;
  1149. struct valuearrayfast vaf_out;
  1150. if ( va_out )
  1151. {
  1152. valuearrayfast_init(&vaf_out,*va_out);
  1153. }
  1154. /*
  1155. * For larger valuesets the valuarray is sorted, values can be deleted individually
  1156. *
  1157. */
  1158. for ( i = 0; rc==LDAP_SUCCESS && valuestodelete[i] != NULL; ++i )
  1159. {
  1160. Slapi_Value *found = valueset_remove_value(a, vs, valuestodelete[i]);
  1161. if(found!=NULL)
  1162. {
  1163. if ( va_out )
  1164. {
  1165. if (found->v_csnset &&
  1166. (flags & (SLAPI_VALUE_FLAG_PRESERVECSNSET|
  1167. SLAPI_VALUE_FLAG_USENEWVALUE)))
  1168. {
  1169. valuestodelete[i]->v_csnset = csnset_dup (found->v_csnset);
  1170. }
  1171. if (flags & SLAPI_VALUE_FLAG_USENEWVALUE)
  1172. {
  1173. valuearrayfast_add_value_passin(&vaf_out,valuestodelete[i]);
  1174. valuestodelete[i] = found;
  1175. }
  1176. else
  1177. {
  1178. valuearrayfast_add_value_passin(&vaf_out,found);
  1179. }
  1180. }
  1181. else
  1182. {
  1183. if (flags & SLAPI_VALUE_FLAG_PRESERVECSNSET)
  1184. {
  1185. valuestodelete[i]->v_csnset = found->v_csnset;
  1186. found->v_csnset = NULL;
  1187. }
  1188. slapi_value_free ( & found );
  1189. }
  1190. }
  1191. else
  1192. {
  1193. if((flags & SLAPI_VALUE_FLAG_IGNOREERROR) == 0)
  1194. {
  1195. LDAPDebug( LDAP_DEBUG_ARGS,"could not find value %d for attr %s\n", i-1, a->a_type, 0 );
  1196. rc= LDAP_NO_SUCH_ATTRIBUTE;
  1197. }
  1198. }
  1199. }
  1200. if ( va_out )
  1201. {
  1202. *va_out= vaf_out.va;
  1203. if(rc!=LDAP_SUCCESS)
  1204. {
  1205. valuearray_free(va_out);
  1206. }
  1207. }
  1208. }
  1209. return rc;
  1210. }
  1211. Slapi_ValueSet *
  1212. valueset_dup(const Slapi_ValueSet *dupee)
  1213. {
  1214. Slapi_ValueSet *duped = slapi_valueset_new();
  1215. if (NULL!=duped)
  1216. {
  1217. valueset_set_valuearray_byval(duped,dupee->va);
  1218. }
  1219. return duped;
  1220. }
  1221. /* quickly throw away any old contents of this valueset, and stick in the
  1222. * new ones.
  1223. *
  1224. * return value: LDAP_SUCCESS - OK
  1225. * : LDAP_OPERATIONS_ERROR - duplicated values given
  1226. */
  1227. int
  1228. valueset_replace_valuearray(Slapi_Attr *a, Slapi_ValueSet *vs, Slapi_Value **valstoreplace)
  1229. {
  1230. return (valueset_replace_valuearray_ext(a, vs,valstoreplace, 1));
  1231. }
  1232. int
  1233. valueset_replace_valuearray_ext(Slapi_Attr *a, Slapi_ValueSet *vs, Slapi_Value **valstoreplace, int dupcheck)
  1234. {
  1235. int rc = LDAP_SUCCESS;
  1236. int vals_count = valuearray_count(valstoreplace);
  1237. if (vals_count == 0) {
  1238. /* no new values, just clear the valueset */
  1239. slapi_valueset_done(vs);
  1240. } else if (vals_count == 1 || !dupcheck) {
  1241. /* just repelace the valuearray and adjus num, max */
  1242. slapi_valueset_done(vs);
  1243. vs->va = valstoreplace;
  1244. vs->num = vals_count;
  1245. vs->max = vals_count + 1;
  1246. PR_ASSERT((vs->sorted == NULL) || (vs->num == 0) || ((vs->sorted[0] >= 0) && (vs->sorted[0] < vs->num)));
  1247. } else {
  1248. /* verify the given values are not duplicated. */
  1249. unsigned long flags = SLAPI_VALUE_FLAG_PASSIN|SLAPI_VALUE_FLAG_DUPCHECK;
  1250. int dupindex = 0;
  1251. Slapi_ValueSet *vs_new = slapi_valueset_new();
  1252. rc = slapi_valueset_add_attr_valuearray_ext (a, vs_new, valstoreplace, vals_count, flags, &dupindex);
  1253. if ( rc == LDAP_SUCCESS )
  1254. {
  1255. /* used passin, so vs_new owns all of the Slapi_Value* in valstoreplace
  1256. * so tell valuearray_free_ext to start at index vals_count, which is
  1257. * NULL, then just free valstoreplace
  1258. */
  1259. valuearray_free_ext(&valstoreplace, vals_count);
  1260. /* values look good - replace the values in the attribute */
  1261. if(!valuearray_isempty(vs->va))
  1262. {
  1263. /* remove old values */
  1264. slapi_valueset_done(vs);
  1265. }
  1266. vs->va = vs_new->va;
  1267. vs_new->va = NULL;
  1268. vs->sorted = vs_new->sorted;
  1269. vs_new->sorted = NULL;
  1270. vs->num = vs_new->num;
  1271. vs->max = vs_new->max;
  1272. slapi_valueset_free (vs_new);
  1273. PR_ASSERT((vs->sorted == NULL) || (vs->num == 0) || ((vs->sorted[0] >= 0) && (vs->sorted[0] < vs->num)));
  1274. }
  1275. else
  1276. {
  1277. /* caller expects us to own valstoreplace - since we cannot
  1278. use them, just delete them */
  1279. /* using PASSIN, some of the Slapi_Value* are in vs_new, and the rest
  1280. * after dupindex are in valstoreplace
  1281. */
  1282. slapi_valueset_free(vs_new);
  1283. valuearray_free_ext(&valstoreplace, dupindex);
  1284. PR_ASSERT((vs->sorted == NULL) || (vs->num == 0) || ((vs->sorted[0] >= 0) && (vs->sorted[0] < vs->num)));
  1285. }
  1286. }
  1287. return rc;
  1288. }
  1289. /*
  1290. * Search the value set for each value to be update,
  1291. * and update the value with the CSN provided.
  1292. * Updated values are moved from the valuestoupdate
  1293. * array to the valueupdated array.
  1294. */
  1295. void
  1296. valueset_update_csn_for_valuearray(Slapi_ValueSet *vs, const Slapi_Attr *a, Slapi_Value **valuestoupdate, CSNType t, const CSN *csn, Slapi_Value ***valuesupdated)
  1297. {
  1298. valueset_update_csn_for_valuearray_ext(vs, a, valuestoupdate, t, csn, valuesupdated, 0);
  1299. }
  1300. void
  1301. valueset_update_csn_for_valuearray_ext(Slapi_ValueSet *vs, const Slapi_Attr *a, Slapi_Value **valuestoupdate, CSNType t, const CSN *csn, Slapi_Value ***valuesupdated, int csnref_updated)
  1302. {
  1303. if(!valuearray_isempty(valuestoupdate) &&
  1304. !valuearray_isempty(vs->va))
  1305. {
  1306. struct valuearrayfast vaf_valuesupdated;
  1307. valuearrayfast_init(&vaf_valuesupdated,*valuesupdated);
  1308. int i;
  1309. int del_index = -1, del_count = 0;
  1310. for (i=0;valuestoupdate[i]!=NULL;++i)
  1311. {
  1312. Slapi_Value *v = slapi_valueset_find(a, vs, valuestoupdate[i]);
  1313. if(v)
  1314. {
  1315. value_update_csn(v,t,csn);
  1316. if (csnref_updated) {
  1317. csnset_free(&valuestoupdate[i]->v_csnset);
  1318. valuestoupdate[i]->v_csnset = csnset_dup(value_get_csnset(v));
  1319. }
  1320. valuearrayfast_add_value_passin(&vaf_valuesupdated,valuestoupdate[i]);
  1321. valuestoupdate[i]= NULL;
  1322. del_count++;
  1323. if (del_index < 0) del_index = i;
  1324. }
  1325. else
  1326. { /* keep the value in valuestoupdate, to keep array compressed, move to first free slot*/
  1327. if (del_index >= 0) {
  1328. valuestoupdate[del_index] = valuestoupdate[i];
  1329. del_index++;
  1330. }
  1331. }
  1332. }
  1333. /* complete compression */
  1334. for (i=0; i<del_count;i++)
  1335. valuestoupdate[del_index+i]= NULL;
  1336. *valuesupdated= vaf_valuesupdated.va;
  1337. }
  1338. }
  1339. int
  1340. valuearray_dn_normalize_value(Slapi_Value **vals)
  1341. {
  1342. int rc = 0;
  1343. Slapi_Value **vp = NULL;
  1344. for (vp = vals; vp && *vp; vp++) {
  1345. rc |= value_dn_normalize_value(*vp);
  1346. }
  1347. return rc;
  1348. }