charray.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468
  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. #ifdef HAVE_CONFIG_H
  39. # include <config.h>
  40. #endif
  41. /* charray.c - routines for dealing with char * arrays */
  42. #include <stdio.h>
  43. #include <string.h>
  44. #include <sys/types.h>
  45. #ifndef _WIN32
  46. #include <sys/socket.h>
  47. #endif
  48. #include "slap.h"
  49. void
  50. charray_add(
  51. char ***a,
  52. char *s
  53. )
  54. {
  55. int n;
  56. if ( *a == NULL ) {
  57. *a = (char **) slapi_ch_malloc( 2 * sizeof(char *) );
  58. n = 0;
  59. } else {
  60. for ( n = 0; *a != NULL && (*a)[n] != NULL; n++ ) {
  61. ; /* NULL */
  62. }
  63. *a = (char **) slapi_ch_realloc( (char *) *a,
  64. (n + 2) * sizeof(char *) );
  65. }
  66. /* At this point, *a may be different from the value it had when this
  67. * function is called. Furthermore, *a[n] may contain an arbitrary
  68. * value, such as a pointer to the middle of a unallocated area.
  69. */
  70. #ifdef TEST_BELLATON
  71. (*a)[n+1] = NULL;
  72. (*a)[n] = s;
  73. #endif
  74. /* Putting code back so that thread conflict can be made visible */
  75. (*a)[n++] = s;
  76. (*a)[n] = NULL;
  77. }
  78. void
  79. charray_merge(
  80. char ***a,
  81. char **s,
  82. int copy_strs
  83. )
  84. {
  85. int i, n, nn;
  86. if ( (s == NULL) || (s[0] == NULL) )
  87. return;
  88. for ( n = 0; *a != NULL && (*a)[n] != NULL; n++ ) {
  89. ; /* NULL */
  90. }
  91. for ( nn = 0; s[nn] != NULL; nn++ ) {
  92. ; /* NULL */
  93. }
  94. *a = (char **) slapi_ch_realloc( (char *) *a, (n + nn + 1) * sizeof(char *) );
  95. for ( i = 0; i < nn; i++ ) {
  96. if ( copy_strs ) {
  97. (*a)[n + i] = slapi_ch_strdup( s[i] );
  98. } else {
  99. (*a)[n + i] = s[i];
  100. }
  101. }
  102. (*a)[n + nn] = NULL;
  103. }
  104. /*
  105. * charray_merge_nodup:
  106. * merge a string array (second arg) into the first string array
  107. * unless the each string is in the first string array.
  108. */
  109. void
  110. charray_merge_nodup(
  111. char ***a,
  112. char **s,
  113. int copy_strs
  114. )
  115. {
  116. int i, j, n, nn;
  117. char **dupa;
  118. if ( (s == NULL) || (s[0] == NULL) )
  119. return;
  120. for ( n = 0; *a != NULL && (*a)[n] != NULL; n++ ) {
  121. ; /* NULL */
  122. }
  123. for ( nn = 0; s[nn] != NULL; nn++ ) {
  124. ; /* NULL */
  125. }
  126. dupa = (char **)slapi_ch_calloc(1, (n+nn+1) * sizeof(char *));
  127. memcpy(dupa, *a, sizeof(char *) * n);
  128. slapi_ch_free((void **)a);
  129. for ( i = 0, j = 0; i < nn; i++ ) {
  130. if (!charray_inlist(dupa, s[i])) { /* skip if s[i] is already in *a */
  131. if ( copy_strs ) {
  132. dupa[n+j] = slapi_ch_strdup( s[i] );
  133. } else {
  134. dupa[n+j] = s[i];
  135. }
  136. j++;
  137. }
  138. }
  139. *a = dupa;
  140. }
  141. /* Routines which don't pound on malloc. Don't interchange the arrays with the
  142. * regular calls---they can end up freeing non-heap memory, which is wrong */
  143. void
  144. cool_charray_free( char **array )
  145. {
  146. slapi_ch_free((void**)&array);
  147. }
  148. /* Like strcpy, but returns a pointer to the next byte after the last one written to */
  149. static char *strcpy_len(char *dest, char *source)
  150. {
  151. if('\0' == (*source)) {
  152. return(dest);
  153. }
  154. do {
  155. *dest++ = *source++;
  156. } while (*source);
  157. return dest;
  158. }
  159. char **
  160. cool_charray_dup( char **a )
  161. {
  162. int i,size, num_strings;
  163. char **newa;
  164. char *p;
  165. if ( a == NULL ) {
  166. return( NULL );
  167. }
  168. for ( i = 0; a[i] != NULL; i++ )
  169. ; /* NULL */
  170. num_strings = i;
  171. size = (i + 1) * sizeof(char *);
  172. for ( i = 0; a[i] != NULL; i++ ) {
  173. size += strlen( a[i] ) + 1;
  174. }
  175. newa = (char **) slapi_ch_malloc( size );
  176. p = (char *) &(newa[num_strings + 1]);
  177. for ( i = 0; a[i] != NULL; i++ ) {
  178. newa[i] = p;
  179. p = strcpy_len(p, a[i] );
  180. *p++ = '\0';
  181. }
  182. newa[i] = NULL;
  183. return( newa );
  184. }
  185. void
  186. charray_free( char **array )
  187. {
  188. char **a;
  189. if ( array == NULL ) {
  190. return;
  191. }
  192. for ( a = array; *a != NULL; a++ )
  193. {
  194. char *tmp= *a;
  195. slapi_ch_free((void**)&tmp);
  196. }
  197. slapi_ch_free( (void**)&array );
  198. }
  199. /*
  200. * charray_free version for plugins: there is a need for plugins to free
  201. * the ch_arrays returned by functions like:
  202. * slapi_get_supported_extended_ops_copy
  203. * slapi_get_supported_saslmechanisms_copy
  204. * slapi_get_supported_controls_copy
  205. */
  206. void
  207. slapi_ch_array_free( char **array )
  208. {
  209. charray_free (array);
  210. }
  211. void
  212. slapi_ch_array_add( char ***a, char *s )
  213. {
  214. charray_add(a, s);
  215. }
  216. /* case insensitive search */
  217. int
  218. charray_inlist(
  219. char **a,
  220. char *s
  221. )
  222. {
  223. int i;
  224. if ( a == NULL ) {
  225. return( 0 );
  226. }
  227. for ( i = 0; a[i] != NULL; i++ ) {
  228. if ( strcasecmp( s, a[i] ) == 0 ) {
  229. return( 1 );
  230. }
  231. }
  232. return( 0 );
  233. }
  234. /* case insensitive search covering non-ascii */
  235. int
  236. charray_utf8_inlist(
  237. char **a,
  238. char *s
  239. )
  240. {
  241. int i;
  242. if ( a == NULL ) {
  243. return( 0 );
  244. }
  245. for ( i = 0; a[i] != NULL; i++ ) {
  246. if (!slapi_UTF8CASECMP(a[i], s)) {
  247. return( 1 );
  248. }
  249. }
  250. return( 0 );
  251. }
  252. char **
  253. charray_dup( char **a )
  254. {
  255. int i;
  256. char **newa;
  257. if ( a == NULL ) {
  258. return( NULL );
  259. }
  260. for ( i = 0; a[i] != NULL; i++ )
  261. ; /* NULL */
  262. newa = (char **) slapi_ch_malloc( (i + 1) * sizeof(char *) );
  263. for ( i = 0; a[i] != NULL; i++ ) {
  264. newa[i] = slapi_ch_strdup( a[i] );
  265. }
  266. newa[i] = NULL;
  267. return( newa );
  268. }
  269. char **
  270. str2charray( char *str, char *brkstr )
  271. {
  272. return( str2charray_ext( str, brkstr, 1 ));
  273. }
  274. /*
  275. * extended version of str2charray lets you disallow
  276. * duplicate values into the array.
  277. */
  278. char **
  279. str2charray_ext( char *str, char *brkstr, int allow_dups )
  280. {
  281. char **res;
  282. char *s;
  283. int i, j;
  284. int dup_found = 0;
  285. char * iter = NULL;
  286. i = 1;
  287. for ( s = str; *s; s++ ) {
  288. if ( strchr( brkstr, *s ) != NULL ) {
  289. i++;
  290. }
  291. }
  292. res = (char **) slapi_ch_malloc( (i + 1) * sizeof(char *) );
  293. i = 0;
  294. for ( s = ldap_utf8strtok_r( str, brkstr , &iter); s != NULL;
  295. s = ldap_utf8strtok_r( NULL, brkstr , &iter) ) {
  296. dup_found = 0;
  297. /* Always copy the first value into the array */
  298. if ( (!allow_dups) && (i != 0) ) {
  299. /* Check for duplicates */
  300. for ( j = 0; j < i; j++ ) {
  301. if ( strncmp( res[j], s, strlen( s ) ) == 0 ) {
  302. dup_found = 1;
  303. break;
  304. }
  305. }
  306. }
  307. if ( !dup_found )
  308. res[i++] = slapi_ch_strdup( s );
  309. }
  310. res[i] = NULL;
  311. return( res );
  312. }
  313. void
  314. charray_print( char **a )
  315. {
  316. int i;
  317. printf( "charray_print:\n");
  318. for ( i = 0; a!= NULL && a[i] != NULL; i++ ) {
  319. printf( "\t%s\n", a[i]);
  320. }
  321. }
  322. /*
  323. * Remove the char string from the array of char strings.
  324. * Performs a case *insensitive* comparison!
  325. * Just shunts the strings down to cover the deleted string.
  326. * freeit: none zero -> free the found string
  327. * : zero -> Doesn't free up the unused memory.
  328. * Returns 1 if the entry found and removed, 0 if not.
  329. */
  330. int
  331. charray_remove(
  332. char **a,
  333. const char *s,
  334. int freeit
  335. )
  336. {
  337. int i;
  338. int found= 0;
  339. for ( i=0; a!= NULL && a[i] != NULL; i++ )
  340. {
  341. if ( !found && strcasecmp (a[i],s) == 0 )
  342. {
  343. found= 1;
  344. if (freeit)
  345. {
  346. slapi_ch_free_string(&a[i]);
  347. }
  348. }
  349. if (found)
  350. {
  351. a[i]= a[i+1];
  352. }
  353. }
  354. return found;
  355. }
  356. /*
  357. * if c == NULL, a = a - b
  358. * if c != NULL, *c = a - b
  359. */
  360. #define SUBTRACT_DEL (char *)(-1)
  361. void
  362. charray_subtract(char **a, char **b, char ***c)
  363. {
  364. char **bp, **cp, **tmp;
  365. char **p;
  366. if (c)
  367. tmp = *c = cool_charray_dup(a);
  368. else
  369. tmp = a;
  370. for (cp = tmp; cp && *cp; cp++) {
  371. for (bp = b; bp && *bp; bp++) {
  372. if (!slapi_UTF8CASECMP(*cp, *bp)) {
  373. slapi_ch_free((void **)&*cp);
  374. *cp = SUBTRACT_DEL;
  375. break;
  376. }
  377. }
  378. }
  379. for (cp = tmp; cp && *cp; cp++) {
  380. if (*cp == SUBTRACT_DEL) {
  381. for (p = cp+1; *p && *p == (char *)SUBTRACT_DEL; p++)
  382. ;
  383. *cp = *p;
  384. if (*p == NULL)
  385. break;
  386. else
  387. *p = SUBTRACT_DEL;
  388. }
  389. }
  390. }
  391. int
  392. charray_get_index(char **array, char *s)
  393. {
  394. int i;
  395. for (i = 0; array && array[i]; i++)
  396. {
  397. if (!slapi_UTF8CASECMP(array[i], s))
  398. return i;
  399. }
  400. return -1;
  401. }