123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174 |
- /* 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;
- }
|