mirror of https://github.com/c-ares/c-ares.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
174 lines
3.5 KiB
174 lines
3.5 KiB
/* 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; |
|
}
|
|
|