summaryrefslogtreecommitdiff
path: root/src/lib/ares_strsplit.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/ares_strsplit.c')
-rw-r--r--src/lib/ares_strsplit.c221
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;
}