csnset.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. /** BEGIN COPYRIGHT BLOCK
  2. * This Program is free software; you can redistribute it and/or modify it under
  3. * the terms of the GNU General Public License as published by the Free Software
  4. * Foundation; version 2 of the License.
  5. *
  6. * This Program is distributed in the hope that it will be useful, but WITHOUT
  7. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  8. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  9. *
  10. * You should have received a copy of the GNU General Public License along with
  11. * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
  12. * Place, Suite 330, Boston, MA 02111-1307 USA.
  13. *
  14. * In addition, as a special exception, Red Hat, Inc. gives You the additional
  15. * right to link the code of this Program with code not covered under the GNU
  16. * General Public License ("Non-GPL Code") and to distribute linked combinations
  17. * including the two, subject to the limitations in this paragraph. Non-GPL Code
  18. * permitted under this exception must only link to the code of this Program
  19. * through those well defined interfaces identified in the file named EXCEPTION
  20. * found in the source code files (the "Approved Interfaces"). The files of
  21. * Non-GPL Code may instantiate templates or use macros or inline functions from
  22. * the Approved Interfaces without causing the resulting work to be covered by
  23. * the GNU General Public License. Only Red Hat, Inc. may make changes or
  24. * additions to the list of Approved Interfaces. You must obey the GNU General
  25. * Public License in all respects for all of the Program code and other code used
  26. * in conjunction with the Program except the Non-GPL Code covered by this
  27. * exception. If you modify this file, you may extend this exception to your
  28. * version of the file, but you are not obligated to do so. If you do not wish to
  29. * provide this exception without modification, you must delete this exception
  30. * statement from your version and license this file solely under the GPL without
  31. * exception.
  32. *
  33. *
  34. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  35. * Copyright (C) 2005 Red Hat, Inc.
  36. * All rights reserved.
  37. * END COPYRIGHT BLOCK **/
  38. #include "slap.h"
  39. #include "slapi-private.h"
  40. static const CSNSet *csnset_get_csnset_node_from_csn(const CSNSet *csnset, const CSN *csn);
  41. static const CSNSet *csnset_get_csnset_node_from_type(const CSNSet *csnset, CSNType t);
  42. static CSNSet *csnset_get_previous_csnset_node(CSNSet *csnset, const CSN *csn);
  43. /*
  44. * The CSN is always added to the end of the list.
  45. */
  46. void
  47. csnset_add_csn(CSNSet **csnset, CSNType t, const CSN *csn)
  48. {
  49. if(csn!=NULL)
  50. {
  51. CSNSet *newcsn= (CSNSet*)slapi_ch_malloc(sizeof(CSNSet));
  52. newcsn->type= t;
  53. csn_init_by_csn(&newcsn->csn,csn);
  54. newcsn->next= NULL;
  55. {
  56. CSNSet **p= csnset;
  57. CSNSet *n= *csnset;
  58. while(n!=NULL)
  59. {
  60. p= &(n->next);
  61. n= n->next;
  62. }
  63. *p= newcsn;
  64. }
  65. }
  66. }
  67. /*
  68. * The CSN is inserted into the list at the appropriate point..
  69. */
  70. void
  71. csnset_insert_csn(CSNSet **csnset, CSNType t, const CSN *csn)
  72. {
  73. if((csn!=NULL) && (*csnset==NULL))
  74. {
  75. csnset_add_csn(csnset, t, csn);
  76. }
  77. else if(csn!=NULL)
  78. {
  79. CSNSet *newcsn= (CSNSet*)slapi_ch_malloc(sizeof(CSNSet));
  80. CSNSet *f= csnset_get_previous_csnset_node(*csnset, csn);
  81. newcsn->type= t;
  82. csn_init_by_csn(&newcsn->csn,csn);
  83. if(f==NULL)
  84. {
  85. /* adding to the list head */
  86. newcsn->next= *csnset;
  87. *csnset= newcsn;
  88. }
  89. else
  90. {
  91. newcsn->next= f->next;
  92. f->next= newcsn;
  93. }
  94. }
  95. }
  96. /*
  97. * Find the CSN of the given type and update it.
  98. */
  99. void
  100. csnset_update_csn(CSNSet **csnset, CSNType t, const CSN *csn)
  101. {
  102. const CSNSet *f= csnset_get_csnset_node_from_type(*csnset, t);
  103. if(f==NULL)
  104. {
  105. csnset_add_csn(csnset,t,csn);
  106. }
  107. else
  108. {
  109. if (csn_compare(csn, (CSN*)(&f->csn)) > 0)
  110. {
  111. csn_init_by_csn((CSN*)(&f->csn),csn);
  112. }
  113. }
  114. }
  115. /*
  116. * Check if the set CSN of CSNs contains a given CSN.
  117. */
  118. int
  119. csnset_contains(const CSNSet *csnset, const CSN *csn)
  120. {
  121. const CSNSet *f= csnset_get_csnset_node_from_csn(csnset, csn);
  122. return(f!=NULL);
  123. }
  124. /*
  125. * Remove the first CSN of the given type.
  126. */
  127. void
  128. csnset_remove_csn(CSNSet **csnset, CSNType t)
  129. {
  130. CSNSet **p= csnset;
  131. CSNSet *n= *csnset;
  132. while(n!=NULL)
  133. {
  134. if(n->type==t)
  135. {
  136. *p= n->next;
  137. slapi_ch_free((void**)&n);
  138. }
  139. else
  140. {
  141. p= &n->next;
  142. n= n->next;
  143. }
  144. }
  145. }
  146. void
  147. csnset_free(CSNSet **csnset)
  148. {
  149. csnset_purge(csnset, NULL);
  150. }
  151. /*
  152. * Get the first CSN of the given type.
  153. */
  154. const CSN *
  155. csnset_get_csn_of_type(const CSNSet *csnset, CSNType t)
  156. {
  157. const CSN *csn= NULL;
  158. const CSNSet *f= csnset_get_csnset_node_from_type(csnset, t);
  159. if(f!=NULL)
  160. {
  161. csn= &f->csn;
  162. }
  163. return csn;
  164. }
  165. const CSN *
  166. csnset_get_previous_csn(const CSNSet *csnset, const CSN *csn)
  167. {
  168. const CSN *prevcsn= NULL;
  169. CSNSet *f= csnset_get_previous_csnset_node((CSNSet*)csnset, csn);
  170. if(f!=NULL)
  171. {
  172. prevcsn= &f->csn;
  173. }
  174. return prevcsn;
  175. }
  176. const CSN *
  177. csnset_get_last_csn(const CSNSet *csnset)
  178. {
  179. const CSN *csn= NULL;
  180. const CSNSet *n= csnset;
  181. while(n!=NULL)
  182. {
  183. if(n->next==NULL)
  184. {
  185. csn= &n->csn;
  186. }
  187. n= n->next;
  188. }
  189. return csn;
  190. }
  191. void*
  192. csnset_get_first_csn (const CSNSet *csnset, CSN **csn, CSNType *t)
  193. {
  194. if (csnset)
  195. {
  196. *csn = (CSN*)&csnset->csn;
  197. *t = csnset->type;
  198. return (void*)csnset;
  199. }
  200. else
  201. return NULL;
  202. }
  203. void*
  204. csnset_get_next_csn (const CSNSet *csnset, void *cookie, CSN **csn, CSNType *t)
  205. {
  206. CSNSet *node;
  207. if (csnset && cookie)
  208. {
  209. node = ((CSNSet*)cookie)->next;
  210. if (node)
  211. {
  212. *csn = (CSN*)&node->csn;
  213. *t = node->type;
  214. return node;
  215. }
  216. else
  217. return NULL;
  218. }
  219. else
  220. return NULL;
  221. }
  222. static CSNSet *
  223. csnset_get_previous_csnset_node(CSNSet *csnset, const CSN *csn)
  224. {
  225. CSNSet *f= NULL;
  226. CSNSet *p= NULL;
  227. CSNSet *n= csnset;
  228. while(n!=NULL)
  229. {
  230. if(csn_compare(&n->csn, csn)>0)
  231. {
  232. f= p;
  233. n= NULL;
  234. }
  235. else
  236. {
  237. p= n;
  238. n= n->next;
  239. if(n==NULL)
  240. {
  241. /* Got to the end of the list... */
  242. f= p;
  243. }
  244. }
  245. }
  246. return f;
  247. }
  248. static const CSNSet *
  249. csnset_get_csnset_node_from_csn(const CSNSet *csnset, const CSN *csn)
  250. {
  251. const CSNSet *f= NULL;
  252. const CSNSet *n= csnset;
  253. while(n!=NULL)
  254. {
  255. if(csn_compare(&n->csn, csn)==0)
  256. {
  257. f= n;
  258. n= NULL;
  259. }
  260. else
  261. {
  262. n= n->next;
  263. }
  264. }
  265. return f;
  266. }
  267. static const CSNSet *
  268. csnset_get_csnset_node_from_type(const CSNSet *csnset, CSNType t)
  269. {
  270. const CSNSet *f= NULL;
  271. const CSNSet *n= csnset;
  272. while(n!=NULL)
  273. {
  274. if(n->type==t)
  275. {
  276. f= n;
  277. n= NULL;
  278. }
  279. else
  280. {
  281. n= n->next;
  282. }
  283. }
  284. return f;
  285. }
  286. /*
  287. * Remove any CSNs older than csnUpTo. If csnUpTo is NULL,
  288. * remove all CSNs.
  289. */
  290. void
  291. csnset_purge(CSNSet **csnset, const CSN *csnUpTo)
  292. {
  293. if (csnset != NULL)
  294. {
  295. CSNSet *n = *csnset, *nprev = NULL, *nnext;
  296. while (n != NULL)
  297. {
  298. if (NULL == csnUpTo || (csn_compare(&n->csn, csnUpTo) < 0))
  299. {
  300. nnext = n->next;
  301. if (*csnset == n)
  302. {
  303. /* Deletion of head */
  304. *csnset = nnext;
  305. }
  306. else if (nprev)
  307. {
  308. /* nprev was not purged, but n will be */
  309. nprev->next = nnext;
  310. }
  311. slapi_ch_free((void**)&n);
  312. n = nnext;
  313. }
  314. else
  315. {
  316. nprev = n;
  317. n = n->next;
  318. }
  319. }
  320. }
  321. }
  322. size_t
  323. csnset_string_size(CSNSet *csnset)
  324. {
  325. size_t s= 0;
  326. CSNSet *n= csnset;
  327. while(n!=NULL)
  328. {
  329. /* sizeof(;vucsn-011111111222233334444) */
  330. s+= 1 + LDIF_CSNPREFIX_MAXLENGTH + _CSN_VALIDCSN_STRLEN;
  331. n= n->next;
  332. }
  333. return s;
  334. }
  335. size_t
  336. csnset_size(CSNSet *csnset)
  337. {
  338. size_t s= 0;
  339. CSNSet *n= csnset;
  340. while(n!=NULL)
  341. {
  342. s+= sizeof(CSNSet);
  343. n= n->next;
  344. }
  345. return s;
  346. }
  347. CSNSet *
  348. csnset_dup(const CSNSet *csnset)
  349. {
  350. CSNSet *newcsnset= NULL;
  351. const CSNSet *n= csnset;
  352. while(n!=NULL)
  353. {
  354. csnset_add_csn(&newcsnset,n->type,&n->csn);
  355. n= n->next;
  356. }
  357. return newcsnset;
  358. }
  359. void
  360. csnset_as_string(const CSNSet *csnset,char *s)
  361. {
  362. const CSNSet *n= csnset;
  363. while(n!=NULL)
  364. {
  365. csn_as_attr_option_string(n->type,&n->csn,s);
  366. /* sizeof(;vucsn-011111111222233334444) */
  367. s+= 1 + LDIF_CSNPREFIX_MAXLENGTH + _CSN_VALIDCSN_STRLEN;
  368. n= n->next;
  369. }
  370. }