1 /* Copyright (C) 2018 by John Schember <john@nachtimwald.com>
2 *
3 * Permission to use, copy, modify, and distribute this
4 * software and its documentation for any purpose and without
5 * fee is hereby granted, provided that the above copyright
6 * notice appear in all copies and that both that copyright
7 * notice and this permission notice appear in supporting
8 * documentation, and that the name of M.I.T. not be used in
9 * advertising or publicity pertaining to distribution of the
10 * software without specific, written prior permission.
11 * M.I.T. makes no representations about the suitability of
12 * this software for any purpose. It is provided "as is"
13 * without express or implied warranty.
14 */
15
16 #if defined(__MVS__)
17 #include <strings.h>
18 #endif
19
20 #include "ares_setup.h"
21 #include "ares_strsplit.h"
22 #include "ares.h"
23 #include "ares_private.h"
24
list_contains(char * const * list,size_t num_elem,const char * str,int insensitive)25 static int list_contains(char * const *list, size_t num_elem, const char *str, int insensitive)
26 {
27 size_t len;
28 size_t i;
29
30 len = strlen(str);
31 for (i=0; i<num_elem; i++)
32 {
33 if (insensitive)
34 {
35 #ifdef WIN32
36 if (strnicmp(list[i], str, len) == 0)
37 #else
38 if (strncasecmp(list[i], str, len) == 0)
39 #endif
40 return 1;
41 }
42 else
43 {
44 if (strncmp(list[i], str, len) == 0)
45 return 1;
46 }
47 }
48
49 return 0;
50 }
51
is_delim(char c,const char * delims,size_t num_delims)52 static int is_delim(char c, const char *delims, size_t num_delims)
53 {
54 size_t i;
55
56 for (i=0; i<num_delims; i++)
57 {
58 if (c == delims[i])
59 return 1;
60 }
61 return 0;
62 }
63
64
ares_strsplit_free(char ** elms,size_t num_elm)65 void ares_strsplit_free(char **elms, size_t num_elm)
66 {
67 size_t i;
68
69 if (elms == NULL)
70 return;
71
72 for (i=0; i<num_elm; i++)
73 ares_free(elms[i]);
74 ares_free(elms);
75 }
76
77
ares_strsplit(const char * in,const char * delms,int make_set,size_t * num_elm)78 char **ares_strsplit(const char *in, const char *delms, int make_set, size_t *num_elm)
79 {
80 char *parsestr;
81 char **temp;
82 char **out;
83 size_t cnt;
84 size_t nelms;
85 size_t in_len;
86 size_t num_delims;
87 size_t i;
88
89 if (in == NULL || delms == NULL || num_elm == NULL)
90 return NULL;
91
92 *num_elm = 0;
93
94 in_len = strlen(in);
95 num_delims = strlen(delms);
96
97 /* Figure out how many elements. */
98 nelms = 1;
99 for (i=0; i<in_len; i++)
100 {
101 if (is_delim(in[i], delms, num_delims))
102 {
103 nelms++;
104 }
105 }
106
107 /* Copy of input so we can cut it up. */
108 parsestr = ares_strdup(in);
109 if (parsestr == NULL)
110 return NULL;
111
112 /* Temporary array to store locations of start of each element
113 * within parsestr. */
114 temp = ares_malloc(nelms * sizeof(*temp));
115 if (temp == NULL)
116 {
117 ares_free(parsestr);
118 return NULL;
119 }
120 temp[0] = parsestr;
121 cnt = 1;
122 for (i=0; i<in_len && cnt<nelms; i++)
123 {
124 if (!is_delim(parsestr[i], delms, num_delims))
125 continue;
126
127 /* Replace sep with NULL. */
128 parsestr[i] = '\0';
129 /* Add the pointer to the array of elements */
130 temp[cnt] = parsestr+i+1;
131 cnt++;
132 }
133
134 /* Copy each element to our output array. */
135 out = ares_malloc(nelms * sizeof(*out));
136 if (out == NULL)
137 {
138 ares_free(parsestr);
139 ares_free(temp);
140 return NULL;
141 }
142
143 nelms = 0;
144 for (i=0; i<cnt; i++)
145 {
146 if (temp[i][0] == '\0')
147 continue;
148
149 if (make_set && list_contains(out, nelms, temp[i], 1))
150 continue;
151
152 out[nelms] = ares_strdup(temp[i]);
153 if (out[nelms] == NULL)
154 {
155 ares_strsplit_free(out, nelms);
156 ares_free(parsestr);
157 ares_free(temp);
158 return NULL;
159 }
160 nelms++;
161 }
162
163
164 /* If there are no elements don't return an empty allocated
165 * array. */
166 if (nelms == 0)
167 {
168 ares_strsplit_free(out, nelms);
169 out = NULL;
170 }
171
172 /* Get the true number of elements (recalculated because of make_set) */
173 *num_elm = nelms;
174
175 ares_free(parsestr);
176 ares_free(temp);
177 return out;
178 }
179