1 /* 2 * 3 * Copyright 2015 gRPC authors. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 */ 18 19 #include <grpc/support/port_platform.h> 20 21 #include "src/core/lib/slice/slice_string_helpers.h" 22 23 #include <string.h> 24 25 #include <grpc/support/log.h> 26 27 #include "src/core/lib/gpr/string.h" 28 #include "src/core/lib/slice/slice_internal.h" 29 30 char* grpc_dump_slice(grpc_slice s, uint32_t flags) { 31 return gpr_dump(reinterpret_cast<const char*> GRPC_SLICE_START_PTR(s), 32 GRPC_SLICE_LENGTH(s), flags); 33 } 34 35 /** Finds the initial (\a begin) and final (\a end) offsets of the next 36 * substring from \a str + \a read_offset until the next \a sep or the end of \a 37 * str. 38 * 39 * Returns 1 and updates \a begin and \a end. Returns 0 otherwise. */ 40 static int slice_find_separator_offset(const grpc_slice str, const char* sep, 41 const size_t read_offset, size_t* begin, 42 size_t* end) { 43 size_t i; 44 const uint8_t* str_ptr = GRPC_SLICE_START_PTR(str) + read_offset; 45 const size_t str_len = GRPC_SLICE_LENGTH(str) - read_offset; 46 const size_t sep_len = strlen(sep); 47 if (str_len < sep_len) { 48 return 0; 49 } 50 51 for (i = 0; i <= str_len - sep_len; i++) { 52 if (memcmp(str_ptr + i, sep, sep_len) == 0) { 53 *begin = read_offset; 54 *end = read_offset + i; 55 return 1; 56 } 57 } 58 return 0; 59 } 60 61 static void skip_leading_trailing_spaces(const uint8_t* str_buffer, 62 size_t* begin, size_t* end) { 63 while (*begin < *end && str_buffer[*begin] == ' ') { 64 (*begin)++; 65 } 66 while (*begin < *end && str_buffer[*end - 1] == ' ') { 67 (*end)--; 68 } 69 } 70 71 static void grpc_slice_split_inner(grpc_slice str, const char* sep, 72 grpc_slice_buffer* dst, bool no_space) { 73 const size_t sep_len = strlen(sep); 74 size_t begin, end; 75 const uint8_t* str_buffer = GRPC_SLICE_START_PTR(str); 76 size_t sep_pos; 77 78 GPR_ASSERT(sep_len > 0); 79 80 if (slice_find_separator_offset(str, sep, 0, &begin, &end) != 0) { 81 do { 82 sep_pos = end; 83 if (no_space) { 84 skip_leading_trailing_spaces(str_buffer, &begin, &end); 85 } 86 grpc_slice_buffer_add_indexed(dst, grpc_slice_sub(str, begin, end)); 87 } while (slice_find_separator_offset(str, sep, sep_pos + sep_len, &begin, 88 &end) != 0); 89 begin = sep_pos + sep_len; 90 end = GRPC_SLICE_LENGTH(str); 91 if (no_space) { 92 skip_leading_trailing_spaces(str_buffer, &begin, &end); 93 } 94 grpc_slice_buffer_add_indexed(dst, grpc_slice_sub(str, begin, end)); 95 } else { /* no sep found, add whole input */ 96 begin = 0; 97 end = GRPC_SLICE_LENGTH(str); 98 if (no_space) { 99 skip_leading_trailing_spaces(str_buffer, &begin, &end); 100 } 101 grpc_slice_buffer_add_indexed(dst, grpc_slice_sub(str, begin, end)); 102 } 103 } 104 105 void grpc_slice_split(grpc_slice str, const char* sep, grpc_slice_buffer* dst) { 106 grpc_slice_split_inner(str, sep, dst, false); 107 } 108 109 void grpc_slice_split_without_space(grpc_slice str, const char* sep, 110 grpc_slice_buffer* dst) { 111 grpc_slice_split_inner(str, sep, dst, true); 112 } 113 114 bool grpc_parse_slice_to_uint32(grpc_slice str, uint32_t* result) { 115 return gpr_parse_bytes_to_uint32( 116 reinterpret_cast<const char*> GRPC_SLICE_START_PTR(str), 117 GRPC_SLICE_LENGTH(str), result) != 0; 118 } 119