1 /* Licensed to the Apache Software Foundation (ASF) under one
2 * or more contributor license agreements. See the NOTICE file
3 * distributed with this work for additional information
4 * regarding copyright ownership. The ASF licenses this file
5 * to you under the Apache License, Version 2.0 (the
6 * "License"); you may not use this file except in compliance
7 * with the License. You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing,
12 * software distributed under the License is distributed on an
13 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 * KIND, either express or implied. See the License for the
15 * specific language governing permissions and limitations
21 #include "apr_strings.h"
22 #include "apr_fnmatch.h"
24 #define APR_WANT_STDIO
25 #define APR_WANT_STRFUNC
30 APR_DECLARE(void) apr_cstr_split_append(apr_array_header_t *array,
32 const char *sep_chars,
39 pats = apr_pstrdup(pool, input); /* strtok wants non-const data */
40 p = apr_cstr_tokenize(sep_chars, &pats);
46 while (apr_isspace(*p))
50 char *e = p + (strlen(p) - 1);
51 while ((e >= p) && (apr_isspace(*e)))
58 APR_ARRAY_PUSH(array, const char *) = p;
60 p = apr_cstr_tokenize(sep_chars, &pats);
67 APR_DECLARE(apr_array_header_t *) apr_cstr_split(const char *input,
68 const char *sep_chars,
72 apr_array_header_t *a = apr_array_make(pool, 5, sizeof(input));
73 apr_cstr_split_append(a, input, sep_chars, chop_whitespace, pool);
78 APR_DECLARE(int) apr_cstr_match_glob_list(const char *str,
79 const apr_array_header_t *list)
83 for (i = 0; i < list->nelts; i++)
85 const char *this_pattern = APR_ARRAY_IDX(list, i, char *);
87 if (apr_fnmatch(this_pattern, str, 0) == APR_SUCCESS)
94 APR_DECLARE(int) apr_cstr_match_list(const char *str,
95 const apr_array_header_t *list)
99 for (i = 0; i < list->nelts; i++)
101 const char *this_str = APR_ARRAY_IDX(list, i, char *);
103 if (strcmp(this_str, str) == 0)
110 APR_DECLARE(char *) apr_cstr_tokenize(const char *sep, char **str)
116 /* check parameters */
117 if ((sep == NULL) || (str == NULL) || (*str == NULL))
120 /* let APR handle edge cases and multiple separators */
122 if (csep == '\0' || sep[1] != '\0')
123 return apr_strtok(NULL, sep, str);
125 /* skip characters in sep (will terminate at '\0') */
127 while (*token == csep)
130 if (!*token) /* no more tokens */
133 /* skip valid token characters to terminate token and
134 * prepare for the next call (will terminate at '\0)
136 next = strchr(token, csep);
139 *str = token + strlen(token);
150 APR_DECLARE(int) apr_cstr_count_newlines(const char *msg)
155 for (p = msg; *p; p++)
160 if (*(p + 1) == '\r')
166 if (*(p + 1) == '\n')
174 #if 0 /* XXX: stringbuf logic is not present in APR */
175 APR_DECLARE(char *) apr_cstr_join(const apr_array_header_t *strings,
176 const char *separator,
179 svn_stringbuf_t *new_str = svn_stringbuf_create_empty(pool);
180 size_t sep_len = strlen(separator);
183 for (i = 0; i < strings->nelts; i++)
185 const char *string = APR_ARRAY_IDX(strings, i, const char *);
186 svn_stringbuf_appendbytes(new_str, string, strlen(string));
187 svn_stringbuf_appendbytes(new_str, separator, sep_len);
189 return new_str->data;
193 #if !APR_CHARSET_EBCDIC
195 * Our own known-fast translation table for casecmp by character.
196 * Only ASCII alpha characters 41-5A are folded to 61-7A, other
197 * octets (such as extended latin alphabetics) are never case-folded.
198 * NOTE: Other than Alpha A-Z/a-z, each code point is unique!
200 static const short ucharmap[] = {
201 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
202 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
203 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
204 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
205 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
206 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
207 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
208 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
209 0x40, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
210 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
211 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
212 'x', 'y', 'z', 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
213 0x60, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
214 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
215 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
216 'x', 'y', 'z', 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
217 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
218 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
219 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
220 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
221 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
222 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
223 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
224 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
225 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
226 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
227 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
228 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
229 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
230 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
231 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
232 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
234 #else /* APR_CHARSET_EBCDIC */
236 * Derived from apr-iconv/ccs/cp037.c for EBCDIC case comparison,
237 * provides unique identity of every char value (strict ISO-646
238 * conformance, arbitrary election of an ISO-8859-1 ordering, and
239 * very arbitrary control code assignments into C1 to achieve
240 * identity and a reversible mapping of code points),
241 * then folding the equivalences of ASCII 41-5A into 61-7A,
242 * presenting comparison results in a somewhat ISO/IEC 10646
243 * (ASCII-like) order, depending on the EBCDIC code page in use.
245 * NOTE: Other than Alpha A-Z/a-z, each code point is unique!
247 static const short ucharmap[] = {
248 0x00, 0x01, 0x02, 0x03, 0x9C, 0x09, 0x86, 0x7F,
249 0x97, 0x8D, 0x8E, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
250 0x10, 0x11, 0x12, 0x13, 0x9D, 0x85, 0x08, 0x87,
251 0x18, 0x19, 0x92, 0x8F, 0x1C, 0x1D, 0x1E, 0x1F,
252 0x80, 0x81, 0x82, 0x83, 0x84, 0x0A, 0x17, 0x1B,
253 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x05, 0x06, 0x07,
254 0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04,
255 0x98, 0x99, 0x9A, 0x9B, 0x14, 0x15, 0x9E, 0x1A,
256 0x20, 0xA0, 0xE2, 0xE4, 0xE0, 0xE1, 0xE3, 0xE5,
257 0xE7, 0xF1, 0xA2, 0x2E, 0x3C, 0x28, 0x2B, 0x7C,
258 0x26, 0xE9, 0xEA, 0xEB, 0xE8, 0xED, 0xEE, 0xEF,
259 0xEC, 0xDF, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0xAC,
260 0x2D, 0x2F, 0xC2, 0xC4, 0xC0, 0xC1, 0xC3, 0xC5,
261 0xC7, 0xD1, 0xA6, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,
262 0xF8, 0xC9, 0xCA, 0xCB, 0xC8, 0xCD, 0xCE, 0xCF,
263 0xCC, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22,
264 0xD8, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
265 0x68, 0x69, 0xAB, 0xBB, 0xF0, 0xFD, 0xFE, 0xB1,
266 0xB0, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,
267 0x71, 0x72, 0xAA, 0xBA, 0xE6, 0xB8, 0xC6, 0xA4,
268 0xB5, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
269 0x79, 0x7A, 0xA1, 0xBF, 0xD0, 0xDD, 0xDE, 0xAE,
270 0x5E, 0xA3, 0xA5, 0xB7, 0xA9, 0xA7, 0xB6, 0xBC,
271 0xBD, 0xBE, 0x5B, 0x5D, 0xAF, 0xA8, 0xB4, 0xD7,
272 0x7B, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
273 0x68, 0x69, 0xAD, 0xF4, 0xF6, 0xF2, 0xF3, 0xF5,
274 0x7D, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,
275 0x71, 0x72, 0xB9, 0xFB, 0xFC, 0xF9, 0xFA, 0xFF,
276 0x5C, 0xF7, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
277 0x79, 0x7A, 0xB2, 0xD4, 0xD6, 0xD2, 0xD3, 0xD5,
278 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
279 0x38, 0x39, 0xB3, 0xDB, 0xDC, 0xD9, 0xDA, 0x9F
283 APR_DECLARE(int) apr_cstr_casecmp(const char *s1, const char *s2)
285 const unsigned char *str1 = (const unsigned char *)s1;
286 const unsigned char *str2 = (const unsigned char *)s2;
289 const int c1 = (int)(*str1);
290 const int c2 = (int)(*str2);
291 const int cmp = ucharmap[c1] - ucharmap[c2];
292 /* Not necessary to test for !c2, this is caught by cmp */
300 APR_DECLARE(int) apr_cstr_casecmpn(const char *s1, const char *s2, apr_size_t n)
302 const unsigned char *str1 = (const unsigned char *)s1;
303 const unsigned char *str2 = (const unsigned char *)s2;
306 const int c1 = (int)(*str1);
307 const int c2 = (int)(*str2);
308 const int cmp = ucharmap[c1] - ucharmap[c2];
309 /* Not necessary to test for !c2, this is caught by cmp */
318 APR_DECLARE(apr_status_t) apr_cstr_strtoui64(apr_uint64_t *n, const char *str,
319 apr_uint64_t minval, apr_uint64_t maxval,
325 /* We assume errno is thread-safe. */
326 errno = 0; /* APR-0.9 doesn't always set errno */
328 /* ### We're throwing away half the number range here.
329 * ### APR needs a apr_strtoui64() function. */
330 val = apr_strtoi64(str, &endptr, base);
331 if (errno == EINVAL || endptr == str || str[0] == '\0' || *endptr != '\0')
333 if ((errno == ERANGE && (val == APR_INT64_MIN || val == APR_INT64_MAX)) ||
334 val < 0 || (apr_uint64_t)val < minval || (apr_uint64_t)val > maxval)
340 APR_DECLARE(apr_status_t) apr_cstr_atoui64(apr_uint64_t *n, const char *str)
342 return apr_cstr_strtoui64(n, str, 0, APR_UINT64_MAX, 10);
345 APR_DECLARE(apr_status_t) apr_cstr_atoui(unsigned int *n, const char *str)
348 apr_status_t rv = apr_cstr_strtoui64(&val, str, 0, APR_UINT32_MAX, 10);
349 if (rv == APR_SUCCESS)
350 *n = (unsigned int)val;
354 APR_DECLARE(apr_status_t) apr_cstr_strtoi64(apr_int64_t *n, const char *str,
355 apr_int64_t minval, apr_int64_t maxval,
361 /* We assume errno is thread-safe. */
362 errno = 0; /* APR-0.9 doesn't always set errno */
364 val = apr_strtoi64(str, &endptr, base);
365 if (errno == EINVAL || endptr == str || str[0] == '\0' || *endptr != '\0')
367 if ((errno == ERANGE && (val == APR_INT64_MIN || val == APR_INT64_MAX)) ||
368 val < minval || val > maxval)
374 APR_DECLARE(apr_status_t) apr_cstr_atoi64(apr_int64_t *n, const char *str)
376 return apr_cstr_strtoi64(n, str, APR_INT64_MIN, APR_INT64_MAX, 10);
379 APR_DECLARE(apr_status_t) apr_cstr_atoi(int *n, const char *str)
384 rv = apr_cstr_strtoi64(&val, str, APR_INT32_MIN, APR_INT32_MAX, 10);
385 if (rv == APR_SUCCESS)
390 APR_DECLARE(const char *) apr_cstr_skip_prefix(const char *str,
393 apr_size_t len = strlen(prefix);
395 if (strncmp(str, prefix, len) == 0)