Fix build splitup for slices. (#27452)
* slice fix * fix properlike * Automated change: Fix sanity tests * actually delete the code that should have been * fixes Co-authored-by: ctiller <ctiller@users.noreply.github.com>pull/27471/head
parent
d4407b7e59
commit
c5172a134e
26 changed files with 661 additions and 330 deletions
@ -0,0 +1,100 @@ |
||||
// Copyright 2021 gRPC authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <grpc/support/port_platform.h> |
||||
|
||||
#include "src/core/lib/slice/slice_split.h" |
||||
|
||||
#include <string.h> |
||||
|
||||
#include <grpc/support/log.h> |
||||
|
||||
/** Finds the initial (\a begin) and final (\a end) offsets of the next
|
||||
* substring from \a str + \a read_offset until the next \a sep or the end of \a |
||||
* str. |
||||
* |
||||
* Returns 1 and updates \a begin and \a end. Returns 0 otherwise. */ |
||||
static int slice_find_separator_offset(const grpc_slice str, const char* sep, |
||||
const size_t read_offset, size_t* begin, |
||||
size_t* end) { |
||||
size_t i; |
||||
const uint8_t* str_ptr = GRPC_SLICE_START_PTR(str) + read_offset; |
||||
const size_t str_len = GRPC_SLICE_LENGTH(str) - read_offset; |
||||
const size_t sep_len = strlen(sep); |
||||
if (str_len < sep_len) { |
||||
return 0; |
||||
} |
||||
|
||||
for (i = 0; i <= str_len - sep_len; i++) { |
||||
if (memcmp(str_ptr + i, sep, sep_len) == 0) { |
||||
*begin = read_offset; |
||||
*end = read_offset + i; |
||||
return 1; |
||||
} |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
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, 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, begin, end)); |
||||
} else { /* no sep found, add whole input */ |
||||
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); |
||||
} |
@ -0,0 +1,40 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2015 gRPC authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
* |
||||
*/ |
||||
|
||||
#ifndef GRPC_CORE_LIB_SLICE_SLICE_SPLIT_H |
||||
#define GRPC_CORE_LIB_SLICE_SLICE_SPLIT_H |
||||
|
||||
#include <grpc/support/port_platform.h> |
||||
|
||||
#include <stdbool.h> |
||||
#include <stddef.h> |
||||
|
||||
#include <grpc/slice.h> |
||||
#include <grpc/slice_buffer.h> |
||||
|
||||
/** Split \a str by the separator \a sep. Results are stored in \a dst, which
|
||||
* 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); |
||||
|
||||
#endif /* GRPC_CORE_LIB_SLICE_SLICE_SPLIT_H */ |
@ -0,0 +1,101 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2015 gRPC authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
* |
||||
*/ |
||||
|
||||
#include <grpc/support/port_platform.h> |
||||
|
||||
#include <inttypes.h> |
||||
#include <string.h> |
||||
|
||||
#include <grpc/grpc.h> |
||||
#include <grpc/slice.h> |
||||
#include <grpc/support/alloc.h> |
||||
#include <grpc/support/log.h> |
||||
|
||||
#include "src/core/lib/gprpp/memory.h" |
||||
#include "src/core/lib/slice/slice_internal.h" |
||||
#include "src/core/lib/transport/static_metadata.h" |
||||
#include "test/core/util/test_config.h" |
||||
|
||||
#define LOG_TEST_NAME(x) gpr_log(GPR_INFO, "%s", x); |
||||
|
||||
static void test_slice_interning(void) { |
||||
LOG_TEST_NAME("test_slice_interning"); |
||||
|
||||
grpc_init(); |
||||
grpc_slice src1 = grpc_slice_from_copied_string("hello123456789123456789"); |
||||
grpc_slice src2 = grpc_slice_from_copied_string("hello123456789123456789"); |
||||
|
||||
// Explicitly checking that the slices are at different addresses prevents
|
||||
// failure with windows opt 64bit build.
|
||||
// See https://github.com/grpc/grpc/issues/20519
|
||||
GPR_ASSERT(&src1 != &src2); |
||||
GPR_ASSERT(GRPC_SLICE_START_PTR(src1) != GRPC_SLICE_START_PTR(src2)); |
||||
|
||||
grpc_slice interned1 = grpc_slice_intern(src1); |
||||
grpc_slice interned2 = grpc_slice_intern(src2); |
||||
GPR_ASSERT(GRPC_SLICE_START_PTR(interned1) == |
||||
GRPC_SLICE_START_PTR(interned2)); |
||||
GPR_ASSERT(GRPC_SLICE_START_PTR(interned1) != GRPC_SLICE_START_PTR(src1)); |
||||
GPR_ASSERT(GRPC_SLICE_START_PTR(interned2) != GRPC_SLICE_START_PTR(src2)); |
||||
grpc_slice_unref(src1); |
||||
grpc_slice_unref(src2); |
||||
grpc_slice_unref(interned1); |
||||
grpc_slice_unref(interned2); |
||||
grpc_shutdown(); |
||||
} |
||||
|
||||
static void test_static_slice_interning(void) { |
||||
LOG_TEST_NAME("test_static_slice_interning"); |
||||
|
||||
// grpc_init/grpc_shutdown deliberately omitted: they should not be necessary
|
||||
// to intern a static slice
|
||||
|
||||
for (size_t i = 0; i < GRPC_STATIC_MDSTR_COUNT; i++) { |
||||
GPR_ASSERT(grpc_slice_is_equivalent( |
||||
grpc_core::g_static_metadata_slice_table[i], |
||||
grpc_slice_intern(grpc_core::g_static_metadata_slice_table[i]))); |
||||
} |
||||
} |
||||
|
||||
static void test_static_slice_copy_interning(void) { |
||||
LOG_TEST_NAME("test_static_slice_copy_interning"); |
||||
|
||||
grpc_init(); |
||||
|
||||
for (size_t i = 0; i < GRPC_STATIC_MDSTR_COUNT; i++) { |
||||
grpc_slice copy = |
||||
grpc_slice_dup(grpc_core::g_static_metadata_slice_table[i]); |
||||
GPR_ASSERT(grpc_core::g_static_metadata_slice_table[i].refcount != |
||||
copy.refcount); |
||||
GPR_ASSERT(grpc_core::g_static_metadata_slice_table[i].refcount == |
||||
grpc_slice_intern(copy).refcount); |
||||
grpc_slice_unref(copy); |
||||
} |
||||
|
||||
grpc_shutdown(); |
||||
} |
||||
|
||||
int main(int argc, char** argv) { |
||||
grpc::testing::TestEnvironment env(argc, argv); |
||||
grpc_init(); |
||||
test_slice_interning(); |
||||
test_static_slice_interning(); |
||||
test_static_slice_copy_interning(); |
||||
grpc_shutdown(); |
||||
return 0; |
||||
} |
@ -0,0 +1,174 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2015 gRPC authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
* |
||||
*/ |
||||
|
||||
#include "src/core/lib/slice/slice_split.h" |
||||
|
||||
#include <limits.h> |
||||
#include <stddef.h> |
||||
#include <stdlib.h> |
||||
#include <string.h> |
||||
|
||||
#include <grpc/support/alloc.h> |
||||
#include <grpc/support/log.h> |
||||
#include <grpc/support/string_util.h> |
||||
|
||||
#include "src/core/lib/gpr/string.h" |
||||
#include "test/core/util/test_config.h" |
||||
|
||||
#define LOG_TEST_NAME(x) gpr_log(GPR_INFO, "%s", x) |
||||
|
||||
static void test_strsplit(void) { |
||||
grpc_slice_buffer* parts; |
||||
grpc_slice str; |
||||
|
||||
LOG_TEST_NAME("test_strsplit"); |
||||
|
||||
parts = |
||||
static_cast<grpc_slice_buffer*>(gpr_malloc(sizeof(grpc_slice_buffer))); |
||||
grpc_slice_buffer_init(parts); |
||||
|
||||
str = grpc_slice_from_copied_string("one, two, three, four"); |
||||
grpc_slice_split(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(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(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(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(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(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); |
||||
} |
||||
|
||||
static void test_strsplit_nospace(void) { |
||||
grpc_slice_buffer* parts; |
||||
grpc_slice str; |
||||
|
||||
LOG_TEST_NAME("test_strsplit_nospace"); |
||||
|
||||
parts = |
||||
static_cast<grpc_slice_buffer*>(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::testing::TestEnvironment env(argc, argv); |
||||
test_strsplit(); |
||||
test_strsplit_nospace(); |
||||
return 0; |
||||
} |
Loading…
Reference in new issue