diff options
Diffstat (limited to 'deps/cares/src/ares_strsplit.c')
-rw-r--r-- | deps/cares/src/ares_strsplit.c | 174 |
1 files changed, 174 insertions, 0 deletions
diff --git a/deps/cares/src/ares_strsplit.c b/deps/cares/src/ares_strsplit.c new file mode 100644 index 0000000000..b57a30f2a9 --- /dev/null +++ b/deps/cares/src/ares_strsplit.c @@ -0,0 +1,174 @@ +/* Copyright (C) 2018 by John Schember <john@nachtimwald.com> + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" + * without express or implied warranty. + */ + +#include "ares_setup.h" +#include "ares_strsplit.h" +#include "ares.h" +#include "ares_private.h" + +static int list_contains(char * const *list, size_t num_elem, const char *str, int insensitive) +{ + size_t len; + size_t i; + + len = strlen(str); + for (i=0; i<num_elem; i++) + { + if (insensitive) + { +#ifdef WIN32 + if (strnicmp(list[i], str, len) == 0) +#else + if (strncasecmp(list[i], str, len) == 0) +#endif + return 1; + } + else + { + if (strncmp(list[i], str, len) == 0) + return 1; + } + } + + return 0; +} + +static int is_delim(char c, const char *delims, size_t num_delims) +{ + size_t i; + + for (i=0; i<num_delims; i++) + { + if (c == delims[i]) + return 1; + } + return 0; +} + + +void ares_strsplit_free(char **elms, size_t num_elm) +{ + size_t i; + + if (elms == NULL) + return; + + for (i=0; i<num_elm; i++) + ares_free(elms[i]); + ares_free(elms); +} + + +char **ares_strsplit(const char *in, const char *delms, int make_set, size_t *num_elm) +{ + char *parsestr; + char **temp; + char **out; + size_t cnt; + size_t nelms; + size_t in_len; + size_t num_delims; + size_t i; + + if (in == NULL || delms == NULL || num_elm == NULL) + return NULL; + + *num_elm = 0; + + in_len = strlen(in); + num_delims = strlen(delms); + + /* Figure out how many elements. */ + nelms = 1; + for (i=0; i<in_len; i++) + { + if (is_delim(in[i], delms, num_delims)) + { + nelms++; + } + } + + /* Copy of input so we can cut it up. */ + parsestr = ares_strdup(in); + if (parsestr == NULL) + return NULL; + + /* Temporary array to store locations of start of each element + * within parsestr. */ + temp = ares_malloc(nelms * sizeof(*temp)); + if (temp == NULL) + { + ares_free(parsestr); + return NULL; + } + temp[0] = parsestr; + cnt = 1; + for (i=0; i<in_len && cnt<nelms; i++) + { + if (!is_delim(parsestr[i], delms, num_delims)) + continue; + + /* Replace sep with NULL. */ + parsestr[i] = '\0'; + /* Add the pointer to the array of elements */ + temp[cnt] = parsestr+i+1; + cnt++; + } + + /* Copy each element to our output array. */ + out = ares_malloc(nelms * sizeof(*out)); + if (out == NULL) + { + ares_free(parsestr); + ares_free(temp); + return NULL; + } + + nelms = 0; + for (i=0; i<cnt; i++) + { + if (temp[i][0] == '\0') + continue; + + if (make_set && list_contains(out, nelms, temp[i], 1)) + continue; + + out[nelms] = ares_strdup(temp[i]); + if (out[nelms] == NULL) + { + ares_strsplit_free(out, nelms); + ares_free(parsestr); + ares_free(temp); + return NULL; + } + nelms++; + } + + + /* If there are no elements don't return an empty allocated + * array. */ + if (nelms == 0) + { + ares_strsplit_free(out, nelms); + out = NULL; + } + + /* Get the true number of elements (recalculated because of make_set) */ + *num_elm = nelms; + + ares_free(parsestr); + ares_free(temp); + return out; +} |