diff options
Diffstat (limited to 'src/lib/ares_strsplit.c')
-rw-r--r-- | src/lib/ares_strsplit.c | 221 |
1 files changed, 80 insertions, 141 deletions
diff --git a/src/lib/ares_strsplit.c b/src/lib/ares_strsplit.c index 97b4e5d..117fc62 100644 --- a/src/lib/ares_strsplit.c +++ b/src/lib/ares_strsplit.c @@ -1,178 +1,117 @@ -/* Copyright (C) 2018 by John Schember <john@nachtimwald.com> +/* MIT License * - * 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. + * Copyright (c) 2018 John Schember + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * SPDX-License-Identifier: MIT */ #if defined(__MVS__) -#include <strings.h> +# include <strings.h> #endif #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) +void ares__strsplit_free(char **elms, size_t num_elm) { size_t i; - if (elms == NULL) + if (elms == NULL) { return; + } - for (i=0; i<num_elm; i++) + 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 **ares__strsplit(const char *in, const char *delms, 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) + const char *p; + char **table; + void *tmp; + size_t i; + size_t j; + size_t k; + size_t count; + + 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++; + /* count non-empty delimited substrings */ + count = 0; + p = in; + do { + i = strcspn(p, delms); + if (i != 0) { + /* string is non-empty */ + count++; + p += i; } - } + } while (*p++ != 0); - /* 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); + if (count == 0) { 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); + table = ares_malloc(count * sizeof(*table)); + if (table == NULL) { 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; + j = 0; /* current table entry */ + /* re-calculate indices and allocate new strings for table */ + for (p = in; j < count; p += i + 1) { + i = strcspn(p, delms); + if (i != 0) { + for (k = 0; k < j; k++) { + if (strncasecmp(table[k], p, i) == 0 && table[k][i] == 0) { + break; + } + } + if (k == j) { + /* copy unique strings only */ + table[j] = ares_malloc(i + 1); + if (table[j] == NULL) { + ares__strsplit_free(table, j); + return NULL; + } + ares_strcpy(table[j], p, i + 1); + j++; + } else { + count--; + } } - nelms++; } - - /* If there are no elements don't return an empty allocated - * array. */ - if (nelms == 0) - { - ares_strsplit_free(out, nelms); - out = NULL; + tmp = ares_realloc(table, count * sizeof(*table)); + if (tmp != NULL) { + table = tmp; } - /* Get the true number of elements (recalculated because of make_set) */ - *num_elm = nelms; - - ares_free(parsestr); - ares_free(temp); - return out; + *num_elm = count; + return table; } |