aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/core/support/string.c22
-rw-r--r--src/core/support/string.h4
-rw-r--r--test/core/support/string_test.c53
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;
}