diff options
-rw-r--r-- | src/core/lib/slice/slice_string_helpers.c | 41 | ||||
-rw-r--r-- | src/core/lib/slice/slice_string_helpers.h | 5 | ||||
-rw-r--r-- | src/core/lib/surface/call.c | 2 | ||||
-rw-r--r-- | test/core/slice/slice_string_helpers_test.c | 67 |
4 files changed, 110 insertions, 5 deletions
diff --git a/src/core/lib/slice/slice_string_helpers.c b/src/core/lib/slice/slice_string_helpers.c index d461c474d2..e2d8c662f3 100644 --- a/src/core/lib/slice/slice_string_helpers.c +++ b/src/core/lib/slice/slice_string_helpers.c @@ -56,24 +56,57 @@ static int slice_find_separator_offset(const grpc_slice str, const char *sep, return 0; } -void grpc_slice_split(grpc_slice str, const char *sep, grpc_slice_buffer *dst) { +static void skip_leading_trailing_spaces(const uint8_t *str_buffer, size_t *begin, size_t *end) { + while (*begin < *end && str_buffer[*begin] == ' ') { + (*begin)++; + } + while (*begin < *end && str_buffer[*end - 1] == ' ') { + (*end)--; + } +} + +static void grpc_slice_split_inner(grpc_slice str, const char *sep, grpc_slice_buffer *dst, bool no_space) { const size_t sep_len = strlen(sep); size_t begin, end; + const uint8_t *str_buffer = GRPC_SLICE_START_PTR(str); + size_t sep_pos; GPR_ASSERT(sep_len > 0); if (slice_find_separator_offset(str, sep, 0, &begin, &end) != 0) { do { + sep_pos = end; + if (no_space) { + skip_leading_trailing_spaces(str_buffer, &begin, &end); + } grpc_slice_buffer_add_indexed(dst, grpc_slice_sub(str, begin, end)); - } while (slice_find_separator_offset(str, sep, end + sep_len, &begin, + } while (slice_find_separator_offset(str, sep, sep_pos + sep_len, &begin, &end) != 0); + begin = sep_pos + sep_len; + end = GRPC_SLICE_LENGTH(str); + if (no_space) { + skip_leading_trailing_spaces(str_buffer, &begin, &end); + } grpc_slice_buffer_add_indexed( - dst, grpc_slice_sub(str, end + sep_len, GRPC_SLICE_LENGTH(str))); + dst, grpc_slice_sub(str, begin, end)); } else { /* no sep found, add whole input */ - grpc_slice_buffer_add_indexed(dst, grpc_slice_ref_internal(str)); + begin = 0; + end = GRPC_SLICE_LENGTH(str); + if (no_space) { + skip_leading_trailing_spaces(str_buffer, &begin, &end); + } + grpc_slice_buffer_add_indexed(dst, grpc_slice_sub(str, begin, end)); } } +void grpc_slice_split(grpc_slice str, const char *sep, grpc_slice_buffer *dst) { + grpc_slice_split_inner(str, sep, dst, false); +} + +void grpc_slice_split_without_space(grpc_slice str, const char *sep, grpc_slice_buffer *dst) { + grpc_slice_split_inner(str, sep, dst, true); +} + bool grpc_parse_slice_to_uint32(grpc_slice str, uint32_t *result) { return gpr_parse_bytes_to_uint32((const char *)GRPC_SLICE_START_PTR(str), GRPC_SLICE_LENGTH(str), result) != 0; diff --git a/src/core/lib/slice/slice_string_helpers.h b/src/core/lib/slice/slice_string_helpers.h index bcfb33bfb3..86125abec3 100644 --- a/src/core/lib/slice/slice_string_helpers.h +++ b/src/core/lib/slice/slice_string_helpers.h @@ -39,6 +39,11 @@ char *grpc_dump_slice(grpc_slice slice, uint32_t flags); * should be a properly initialized instance. */ void grpc_slice_split(grpc_slice str, const char *sep, grpc_slice_buffer *dst); +/** Split \a str by the separator \a sep and remove the leading and trailing + * spaces of each resulting token. Results are stored in \a dst, which should be + * a properly initialized instance. */ +void grpc_slice_split_without_space(grpc_slice str, const char *sep, grpc_slice_buffer *dst); + bool grpc_parse_slice_to_uint32(grpc_slice str, uint32_t *result); #ifdef __cplusplus diff --git a/src/core/lib/surface/call.c b/src/core/lib/surface/call.c index 797c5cf914..d4c2568c51 100644 --- a/src/core/lib/surface/call.c +++ b/src/core/lib/surface/call.c @@ -875,7 +875,7 @@ static void set_encodings_accepted_by_peer(grpc_exec_ctx *exec_ctx, accept_encoding_slice = GRPC_MDVALUE(mdel); grpc_slice_buffer_init(&accept_encoding_parts); - grpc_slice_split(accept_encoding_slice, ",", &accept_encoding_parts); + grpc_slice_split_without_space(accept_encoding_slice, ",", &accept_encoding_parts); GPR_BITSET(encodings_accepted_by_peer, GRPC_COMPRESS_NONE); for (i = 0; i < accept_encoding_parts.count; i++) { diff --git a/test/core/slice/slice_string_helpers_test.c b/test/core/slice/slice_string_helpers_test.c index 504acf8f84..48f3701c0a 100644 --- a/test/core/slice/slice_string_helpers_test.c +++ b/test/core/slice/slice_string_helpers_test.c @@ -127,9 +127,76 @@ static void test_strsplit(void) { gpr_free(parts); } +static void test_strsplit_nospace(void) { + grpc_slice_buffer *parts; + grpc_slice str; + + LOG_TEST_NAME("test_strsplit_nospace"); + + parts = gpr_malloc(sizeof(grpc_slice_buffer)); + grpc_slice_buffer_init(parts); + + str = grpc_slice_from_copied_string("one ,two, three , four"); + grpc_slice_split_without_space(str, ",", parts); + GPR_ASSERT(4 == parts->count); + GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[0], "one")); + GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[1], "two")); + GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[2], "three")); + GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[3], "four")); + grpc_slice_buffer_reset_and_unref(parts); + grpc_slice_unref(str); + + /* separator not present in string */ + str = grpc_slice_from_copied_string("one two three four "); + grpc_slice_split_without_space(str, ",", parts); + GPR_ASSERT(1 == parts->count); + GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[0], "one two three four")); + grpc_slice_buffer_reset_and_unref(parts); + grpc_slice_unref(str); + + /* separator at the end */ + str = grpc_slice_from_copied_string("foo,"); + grpc_slice_split_without_space(str, ",", parts); + GPR_ASSERT(2 == parts->count); + GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[0], "foo")); + GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[1], "")); + grpc_slice_buffer_reset_and_unref(parts); + grpc_slice_unref(str); + + /* separator at the beginning */ + str = grpc_slice_from_copied_string(" , foo"); + grpc_slice_split_without_space(str, ",", parts); + GPR_ASSERT(2 == parts->count); + GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[0], "")); + GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[1], "foo")); + grpc_slice_buffer_reset_and_unref(parts); + grpc_slice_unref(str); + + /* standalone separator */ + str = grpc_slice_from_copied_string(", "); + grpc_slice_split_without_space(str, ", ", parts); + GPR_ASSERT(2 == parts->count); + GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[0], "")); + GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[1], "")); + grpc_slice_buffer_reset_and_unref(parts); + grpc_slice_unref(str); + + /* empty input */ + str = grpc_slice_from_copied_string(""); + grpc_slice_split_without_space(str, ",", parts); + GPR_ASSERT(1 == parts->count); + GPR_ASSERT(0 == grpc_slice_str_cmp(parts->slices[0], "")); + grpc_slice_buffer_reset_and_unref(parts); + grpc_slice_unref(str); + + grpc_slice_buffer_destroy(parts); + gpr_free(parts); +} + int main(int argc, char **argv) { grpc_test_init(argc, argv); test_dump_slice(); test_strsplit(); + test_strsplit_nospace(); return 0; } |