1 /*
2  * The contents of this file are subject to the Netscape Public
3  * License Version 1.1 (the "License"); you may not use this file
4  * except in compliance with the License. You may obtain a copy of
5  * the License at http://www.mozilla.org/NPL/
6  *
7  * Software distributed under the License is distributed on an "AS
8  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
9  * implied. See the License for the specific language governing
10  * rights and limitations under the License.
11  *
12  * The Original Code is Mozilla Communicator client code, released
13  * March 31, 1998.
14  *
15  * The Initial Developer of the Original Code is Netscape
16  * Communications Corporation. Portions created by Netscape are
17  * Copyright (C) 1998-1999 Netscape Communications Corporation. All
18  * Rights Reserved.
19  *
20  * Contributor(s):
21  */
22 /* charray.c - routines for dealing with char * arrays */
23 
24 
25 #include "ldap-int.h"
26 
27 /*
28  * Add s at the end of the array of strings *a.
29  * Return 0 for success, -1 for failure.
30  */
31 int
32 LDAP_CALL
ldap_charray_add(char *** a,char * s)33 ldap_charray_add(
34     char	***a,
35     char	*s
36 )
37 {
38 	int	n;
39 
40 	if ( *a == NULL ) {
41 		*a = (char **)NSLDAPI_MALLOC( 2 * sizeof(char *) );
42 		if ( *a == NULL ) {
43 			return -1;
44 		}
45 		n = 0;
46 	} else {
47 		for ( n = 0; *a != NULL && (*a)[n] != NULL; n++ ) {
48 			;	/* NULL */
49 		}
50 
51 		*a = (char **)NSLDAPI_REALLOC( (char *) *a,
52 		    (n + 2) * sizeof(char *) );
53 		if ( *a == NULL ) {
54 			return -1;
55 		}
56 	}
57 
58 	(*a)[n++] = s;
59 	(*a)[n] = NULL;
60 	return 0;
61 }
62 
63 /*
64  * Add array of strings s at the end of the array of strings *a.
65  * Return 0 for success, -1 for failure.
66  */
67 int
68 LDAP_CALL
ldap_charray_merge(char *** a,char ** s)69 ldap_charray_merge(
70     char	***a,
71     char	**s
72 )
73 {
74 	int	i, n, nn;
75 
76 	if ( (s == NULL) || (s[0] == NULL) )
77 	    return 0;
78 
79 	for ( n = 0; *a != NULL && (*a)[n] != NULL; n++ ) {
80 		;	/* NULL */
81 	}
82 	for ( nn = 0; s[nn] != NULL; nn++ ) {
83 		;	/* NULL */
84 	}
85 
86 	*a = (char **)NSLDAPI_REALLOC( (char *) *a,
87 	    (n + nn + 1) * sizeof(char *) );
88 	if ( *a == NULL ) {
89 		return -1;
90 	}
91 
92 	for ( i = 0; i < nn; i++ ) {
93 		(*a)[n + i] = s[i];
94 	}
95 	(*a)[n + nn] = NULL;
96 	return 0;
97 }
98 
99 void
100 LDAP_CALL
ldap_charray_free(char ** array)101 ldap_charray_free( char **array )
102 {
103 	char	**a;
104 
105 	if ( array == NULL ) {
106 		return;
107 	}
108 
109 	for ( a = array; *a != NULL; a++ ) {
110 		if ( *a != NULL ) {
111 			NSLDAPI_FREE( *a );
112 		}
113 	}
114 	NSLDAPI_FREE( (char *) array );
115 }
116 
117 int
118 LDAP_CALL
ldap_charray_inlist(char ** a,char * s)119 ldap_charray_inlist(
120     char	**a,
121     char	*s
122 )
123 {
124 	int	i;
125 
126 	if ( a == NULL )
127 		return( 0 );
128 
129 	for ( i = 0; a[i] != NULL; i++ ) {
130 		if ( strcasecmp( s, a[i] ) == 0 ) {
131 			return( 1 );
132 		}
133 	}
134 
135 	return( 0 );
136 }
137 
138 /*
139  * Duplicate the array of strings a, return NULL upon any memory failure.
140  */
141 char **
142 LDAP_CALL
ldap_charray_dup(char ** a)143 ldap_charray_dup( char **a )
144 {
145 	int	i;
146 	char	**new;
147 
148 	for ( i = 0; a[i] != NULL; i++ )
149 		;	/* NULL */
150 
151 	new = (char **)NSLDAPI_MALLOC( (i + 1) * sizeof(char *) );
152 	if ( new == NULL ) {
153 		return NULL;
154 	}
155 
156 	for ( i = 0; a[i] != NULL; i++ ) {
157 		new[i] = nsldapi_strdup( a[i] );
158 		if ( new[i] == NULL ) {
159 			int	j;
160 
161 			for ( j = 0; j < i; j++ )
162 			    NSLDAPI_FREE( new[j] );
163 			NSLDAPI_FREE( new );
164 			return NULL;
165 		}
166 	}
167 	new[i] = NULL;
168 
169 	return( new );
170 }
171 
172 /*
173  * Tokenize the string str, return NULL upon any memory failure.
174  * XXX: on many platforms this function is not thread safe because it
175  *	uses strtok().
176  */
177 char **
178 LDAP_CALL
ldap_str2charray(char * str,char * brkstr)179 ldap_str2charray( char *str, char *brkstr )
180      /* This implementation fails if brkstr contains multibyte characters.
181         But it works OK if str is UTF-8 and brkstr is 7-bit ASCII.
182       */
183 {
184 	char	**res;
185 	char	*s;
186 	int	i;
187 
188 	i = 1;
189 	for ( s = str; *s; s++ ) {
190 		if ( strchr( brkstr, *s ) != NULL ) {
191 			i++;
192 		}
193 	}
194 
195 	res = (char **)NSLDAPI_MALLOC( (i + 1) * sizeof(char *) );
196 	if ( res == NULL ) {
197 		return NULL;
198 	}
199 	i = 0;
200 	for ( s = strtok( str, brkstr ); s != NULL; s = strtok( NULL,
201 	    brkstr ) ) {
202 		res[i++] = nsldapi_strdup( s );
203 		if ( res[i - 1] == NULL ) {
204 			int	j;
205 
206 			for ( j = 0; j < (i - 1); j++ )
207 			    NSLDAPI_FREE( res[j] );
208 			NSLDAPI_FREE( res );
209 			return NULL;
210 		}
211 	}
212 	res[i] = NULL;
213 
214 	return( res );
215 }
216 
217 int
218 LDAP_CALL
ldap_charray_position(char ** a,char * s)219 ldap_charray_position( char **a, char *s )
220 {
221 	int     i;
222 
223 	for ( i = 0; a[i] != NULL; i++ ) {
224 		if ( strcasecmp( s, a[i] ) == 0 ) {
225 			return( i );
226 		}
227 	}
228 
229 	return( -1 );
230 }
231