charray.c 9.3 KB

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