diff options
-rw-r--r-- | src/core/support/string.c | 22 | ||||
-rw-r--r-- | src/core/support/string.h | 4 | ||||
-rw-r--r-- | test/core/support/string_test.c | 53 |
3 files changed, 79 insertions, 0 deletions
diff --git a/src/core/support/string.c b/src/core/support/string.c index 8f59945c59..8bf091d8d2 100644 --- a/src/core/support/string.c +++ b/src/core/support/string.c @@ -38,6 +38,7 @@ #include <string.h> #include <grpc/support/alloc.h> +#include <grpc/support/log.h> #include <grpc/support/port_platform.h> #include <grpc/support/useful.h> @@ -187,6 +188,27 @@ char *gpr_strjoin_sep(const char **strs, size_t nstrs, const char *sep, return out; } +static void do_nothing(void *ignored) {} +gpr_slice_buffer *gpr_strsplit(const char *str, const char *sep) { + const size_t sep_len = strlen(sep); + const char *splitpoint = str; + gpr_slice_buffer *parts; + + GPR_ASSERT(sep_len > 0); + + parts = gpr_malloc(sizeof(gpr_slice_buffer)); + gpr_slice_buffer_init(parts); + + for (; (splitpoint = strstr(str, sep)) != NULL; splitpoint += sep_len) { + gpr_slice_buffer_add( + parts, gpr_slice_new((void *)str, splitpoint - str, do_nothing)); + str += (splitpoint - str + sep_len); + } + gpr_slice_buffer_add(parts, + gpr_slice_new((void *)str, strlen(str), do_nothing)); + return parts; +} + void gpr_strvec_init(gpr_strvec *sv) { memset(sv, 0, sizeof(*sv)); } diff --git a/src/core/support/string.h b/src/core/support/string.h index a4da485dce..efb11778b9 100644 --- a/src/core/support/string.h +++ b/src/core/support/string.h @@ -37,6 +37,7 @@ #include <stddef.h> #include <grpc/support/port_platform.h> +#include <grpc/support/slice_buffer.h> #ifdef __cplusplus extern "C" { @@ -78,6 +79,9 @@ char *gpr_strjoin(const char **strs, size_t nstrs, size_t *total_length); char *gpr_strjoin_sep(const char **strs, size_t nstrs, const char *sep, size_t *total_length); +/** Split \a str at separator \a sep. */ +gpr_slice_buffer *gpr_strsplit(const char *str, const char *sep); + /* A vector of strings... for building up a final string one piece at a time */ typedef struct { char **strs; diff --git a/test/core/support/string_test.c b/test/core/support/string_test.c index 30d97de1a5..b7ee7cad3b 100644 --- a/test/core/support/string_test.c +++ b/test/core/support/string_test.c @@ -192,6 +192,58 @@ static void test_strjoin_sep(void) { gpr_free(joined); } +static void test_strsplit(void) { + gpr_slice_buffer* parts; + LOG_TEST_NAME("test_strsplit"); + + parts = gpr_strsplit("one, two, three, four", ", "); + GPR_ASSERT(4 == parts->count); + GPR_ASSERT(0 == gpr_slice_str_cmp(parts->slices[0], "one")); + GPR_ASSERT(0 == gpr_slice_str_cmp(parts->slices[1], "two")); + GPR_ASSERT(0 == gpr_slice_str_cmp(parts->slices[2], "three")); + GPR_ASSERT(0 == gpr_slice_str_cmp(parts->slices[3], "four")); + gpr_slice_buffer_destroy(parts); + gpr_free(parts); + + /* separator not present in string */ + parts = gpr_strsplit("one two three four", ", "); + GPR_ASSERT(1 == parts->count); + GPR_ASSERT(0 == gpr_slice_str_cmp(parts->slices[0], "one two three four")); + gpr_slice_buffer_destroy(parts); + gpr_free(parts); + + /* separator at the end */ + parts = gpr_strsplit("foo,", ","); + GPR_ASSERT(2 == parts->count); + GPR_ASSERT(0 == gpr_slice_str_cmp(parts->slices[0], "foo")); + GPR_ASSERT(0 == gpr_slice_str_cmp(parts->slices[1], "")); + gpr_slice_buffer_destroy(parts); + gpr_free(parts); + + /* separator at the beginning */ + parts = gpr_strsplit(",foo", ","); + GPR_ASSERT(2 == parts->count); + GPR_ASSERT(0 == gpr_slice_str_cmp(parts->slices[0], "")); + GPR_ASSERT(0 == gpr_slice_str_cmp(parts->slices[1], "foo")); + gpr_slice_buffer_destroy(parts); + gpr_free(parts); + + /* standalone separator */ + parts = gpr_strsplit(",", ","); + GPR_ASSERT(2 == parts->count); + GPR_ASSERT(0 == gpr_slice_str_cmp(parts->slices[0], "")); + GPR_ASSERT(0 == gpr_slice_str_cmp(parts->slices[1], "")); + gpr_slice_buffer_destroy(parts); + gpr_free(parts); + + /* empty input */ + parts = gpr_strsplit("", ","); + GPR_ASSERT(1 == parts->count); + GPR_ASSERT(0 == gpr_slice_str_cmp(parts->slices[0], "")); + gpr_slice_buffer_destroy(parts); + gpr_free(parts); +} + int main(int argc, char **argv) { grpc_test_init(argc, argv); test_strdup(); @@ -200,5 +252,6 @@ int main(int argc, char **argv) { test_asprintf(); test_strjoin(); test_strjoin_sep(); + test_strsplit(); return 0; } |