1/* charray.c - routines for dealing with char * arrays */
2/* $OpenLDAP$ */
3/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 *
5 * Copyright 1998-2011 The OpenLDAP Foundation.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted only as authorized by the OpenLDAP
10 * Public License.
11 *
12 * A copy of this license is available in the file LICENSE in the
13 * top-level directory of the distribution or, alternatively, at
14 * <http://www.OpenLDAP.org/license.html>.
15 */
16
17#include "portable.h"
18
19#include <stdio.h>
20
21#include <ac/string.h>
22#include <ac/socket.h>
23
24#include "ldap-int.h"
25
26int
27ldap_charray_add(
28    char	***a,
29    const char *s
30)
31{
32	int	n;
33
34	if ( *a == NULL ) {
35		*a = (char **) LDAP_MALLOC( 2 * sizeof(char *) );
36		n = 0;
37
38		if( *a == NULL ) {
39			return -1;
40		}
41
42	} else {
43		char **new;
44
45		for ( n = 0; *a != NULL && (*a)[n] != NULL; n++ ) {
46			;	/* NULL */
47		}
48
49		new = (char **) LDAP_REALLOC( (char *) *a,
50		    (n + 2) * sizeof(char *) );
51
52		if( new == NULL ) {
53			/* caller is required to call ldap_charray_free(*a) */
54			return -1;
55		}
56
57		*a = new;
58	}
59
60	(*a)[n] = LDAP_STRDUP(s);
61
62	if( (*a)[n] == NULL ) {
63		return 1;
64	}
65
66	(*a)[++n] = NULL;
67
68	return 0;
69}
70
71int
72ldap_charray_merge(
73    char	***a,
74    char	**s
75)
76{
77	int	i, n, nn;
78	char **aa;
79
80	for ( n = 0; *a != NULL && (*a)[n] != NULL; n++ ) {
81		;	/* NULL */
82	}
83	for ( nn = 0; s[nn] != NULL; nn++ ) {
84		;	/* NULL */
85	}
86
87	aa = (char **) LDAP_REALLOC( (char *) *a, (n + nn + 1) * sizeof(char *) );
88
89	if( aa == NULL ) {
90		return -1;
91	}
92
93	*a = aa;
94
95	for ( i = 0; i < nn; i++ ) {
96		(*a)[n + i] = LDAP_STRDUP(s[i]);
97
98		if( (*a)[n + i] == NULL ) {
99			for( --i ; i >= 0 ; i-- ) {
100				LDAP_FREE( (*a)[n + i] );
101				(*a)[n + i] = NULL;
102			}
103			return -1;
104		}
105	}
106
107	(*a)[n + nn] = NULL;
108	return 0;
109}
110
111void
112ldap_charray_free( char **a )
113{
114	char	**p;
115
116	if ( a == NULL ) {
117		return;
118	}
119
120	for ( p = a; *p != NULL; p++ ) {
121		if ( *p != NULL ) {
122			LDAP_FREE( *p );
123		}
124	}
125
126	LDAP_FREE( (char *) a );
127}
128
129int
130ldap_charray_inlist(
131    char	**a,
132    const char *s
133)
134{
135	int	i;
136
137	if( a == NULL ) return 0;
138
139	for ( i=0; a[i] != NULL; i++ ) {
140		if ( strcasecmp( s, a[i] ) == 0 ) {
141			return 1;
142		}
143	}
144
145	return 0;
146}
147
148char **
149ldap_charray_dup( char **a )
150{
151	int	i;
152	char	**new;
153
154	for ( i = 0; a[i] != NULL; i++ )
155		;	/* NULL */
156
157	new = (char **) LDAP_MALLOC( (i + 1) * sizeof(char *) );
158
159	if( new == NULL ) {
160		return NULL;
161	}
162
163	for ( i = 0; a[i] != NULL; i++ ) {
164		new[i] = LDAP_STRDUP( a[i] );
165
166		if( new[i] == NULL ) {
167			for( --i ; i >= 0 ; i-- ) {
168				LDAP_FREE( new[i] );
169			}
170			LDAP_FREE( new );
171			return NULL;
172		}
173	}
174	new[i] = NULL;
175
176	return( new );
177}
178
179char **
180ldap_str2charray( const char *str_in, const char *brkstr )
181{
182	char	**res;
183	char	*str, *s;
184	char	*lasts;
185	int	i;
186
187	/* protect the input string from strtok */
188	str = LDAP_STRDUP( str_in );
189	if( str == NULL ) {
190		return NULL;
191	}
192
193	i = 1;
194	for ( s = str; ; LDAP_UTF8_INCR(s) ) {
195		s = ldap_utf8_strpbrk( s, brkstr );
196		if ( !s ) break;
197		i++;
198	}
199
200	res = (char **) LDAP_MALLOC( (i + 1) * sizeof(char *) );
201
202	if( res == NULL ) {
203		LDAP_FREE( str );
204		return NULL;
205	}
206
207	i = 0;
208
209	for ( s = ldap_utf8_strtok( str, brkstr, &lasts );
210		s != NULL;
211		s = ldap_utf8_strtok( NULL, brkstr, &lasts ) )
212	{
213		res[i] = LDAP_STRDUP( s );
214
215		if(res[i] == NULL) {
216			for( --i ; i >= 0 ; i-- ) {
217				LDAP_FREE( res[i] );
218			}
219			LDAP_FREE( res );
220			LDAP_FREE( str );
221			return NULL;
222		}
223
224		i++;
225	}
226
227	res[i] = NULL;
228
229	LDAP_FREE( str );
230	return( res );
231}
232
233char * ldap_charray2str( char **a, const char *sep )
234{
235	char *s, **v, *p;
236	int len;
237	int slen;
238
239	if( sep == NULL ) sep = " ";
240
241	slen = strlen( sep );
242	len = 0;
243
244	for ( v = a; *v != NULL; v++ ) {
245		len += strlen( *v ) + slen;
246	}
247
248	if ( len == 0 ) {
249		return NULL;
250	}
251
252	/* trim extra sep len */
253	len -= slen;
254
255	s = LDAP_MALLOC ( len + 1 );
256
257	if ( s == NULL ) {
258		return NULL;
259	}
260
261	p = s;
262	for ( v = a; *v != NULL; v++ ) {
263		if ( v != a ) {
264			strncpy( p, sep, slen );
265			p += slen;
266		}
267
268		len = strlen( *v );
269		strncpy( p, *v, len );
270		p += len;
271	}
272
273	*p = '\0';
274	return s;
275}
276