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