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_internal.h" 22 23 #include <grpc/slice.h> 24 #include <grpc/support/alloc.h> 25 #include <grpc/support/log.h> 26 27 #include <string.h> 28 29 #include "src/core/lib/gprpp/memory.h" 30 #include "src/core/lib/gprpp/ref_counted.h" 31 #include "src/core/lib/iomgr/exec_ctx.h" 32 grpc_slice_to_c_string(grpc_slice slice)33 char* grpc_slice_to_c_string(grpc_slice slice) { 34 char* out = static_cast<char*>(gpr_malloc(GRPC_SLICE_LENGTH(slice) + 1)); 35 memcpy(out, GRPC_SLICE_START_PTR(slice), GRPC_SLICE_LENGTH(slice)); 36 out[GRPC_SLICE_LENGTH(slice)] = 0; 37 return out; 38 } 39 grpc_empty_slice(void)40 grpc_slice grpc_empty_slice(void) { return grpc_core::UnmanagedMemorySlice(); } 41 grpc_slice_copy(grpc_slice s)42 grpc_slice grpc_slice_copy(grpc_slice s) { 43 grpc_slice out = GRPC_SLICE_MALLOC(GRPC_SLICE_LENGTH(s)); 44 memcpy(GRPC_SLICE_START_PTR(out), GRPC_SLICE_START_PTR(s), 45 GRPC_SLICE_LENGTH(s)); 46 return out; 47 } 48 49 /* Public API */ grpc_slice_ref(grpc_slice slice)50 grpc_slice grpc_slice_ref(grpc_slice slice) { 51 return grpc_slice_ref_internal(slice); 52 } 53 54 /* Public API */ grpc_slice_unref(grpc_slice slice)55 void grpc_slice_unref(grpc_slice slice) { 56 if (grpc_core::ExecCtx::Get() == nullptr) { 57 grpc_core::ExecCtx exec_ctx; 58 grpc_slice_unref_internal(slice); 59 } else { 60 grpc_slice_unref_internal(slice); 61 } 62 } 63 64 namespace grpc_core { 65 66 /* grpc_slice_from_static_string support structure - a refcount that does 67 nothing */ 68 grpc_slice_refcount kNoopRefcount(grpc_slice_refcount::Type::NOP); 69 static_assert(std::is_trivially_destructible<decltype(kNoopRefcount)>::value, 70 "kNoopRefcount must be trivially destructible."); 71 72 /* grpc_slice_new support structures - we create a refcount object extended 73 with the user provided data pointer & destroy function */ 74 class NewSliceRefcount { 75 public: Destroy(void * arg)76 static void Destroy(void* arg) { delete static_cast<NewSliceRefcount*>(arg); } 77 NewSliceRefcount(void (* destroy)(void *),void * user_data)78 NewSliceRefcount(void (*destroy)(void*), void* user_data) 79 : base_(grpc_slice_refcount::Type::REGULAR, &refs_, Destroy, this, 80 &base_), 81 user_destroy_(destroy), 82 user_data_(user_data) {} ~NewSliceRefcount()83 ~NewSliceRefcount() { user_destroy_(user_data_); } 84 base_refcount()85 grpc_slice_refcount* base_refcount() { return &base_; } 86 87 private: 88 grpc_slice_refcount base_; 89 RefCount refs_; 90 void (*user_destroy_)(void*); 91 void* user_data_; 92 }; 93 94 } // namespace grpc_core 95 grpc_slice_memory_usage(grpc_slice s)96 size_t grpc_slice_memory_usage(grpc_slice s) { 97 if (s.refcount == nullptr || s.refcount == &grpc_core::kNoopRefcount) { 98 return 0; 99 } else { 100 return s.data.refcounted.length; 101 } 102 } 103 grpc_slice_from_static_buffer(const void * s,size_t len)104 grpc_slice grpc_slice_from_static_buffer(const void* s, size_t len) { 105 return grpc_core::ExternallyManagedSlice(s, len); 106 } 107 grpc_slice_from_static_string(const char * s)108 grpc_slice grpc_slice_from_static_string(const char* s) { 109 return grpc_core::ExternallyManagedSlice(s, strlen(s)); 110 } 111 grpc_slice_new_with_user_data(void * p,size_t len,void (* destroy)(void *),void * user_data)112 grpc_slice grpc_slice_new_with_user_data(void* p, size_t len, 113 void (*destroy)(void*), 114 void* user_data) { 115 grpc_slice slice; 116 slice.refcount = 117 (new grpc_core::NewSliceRefcount(destroy, user_data))->base_refcount(); 118 slice.data.refcounted.bytes = static_cast<uint8_t*>(p); 119 slice.data.refcounted.length = len; 120 return slice; 121 } 122 grpc_slice_new(void * p,size_t len,void (* destroy)(void *))123 grpc_slice grpc_slice_new(void* p, size_t len, void (*destroy)(void*)) { 124 /* Pass "p" to *destroy when the slice is no longer needed. */ 125 return grpc_slice_new_with_user_data(p, len, destroy, p); 126 } 127 128 namespace grpc_core { 129 /* grpc_slice_new_with_len support structures - we create a refcount object 130 extended with the user provided data pointer & destroy function */ 131 class NewWithLenSliceRefcount { 132 public: Destroy(void * arg)133 static void Destroy(void* arg) { 134 delete static_cast<NewWithLenSliceRefcount*>(arg); 135 } 136 NewWithLenSliceRefcount(void (* destroy)(void *,size_t),void * user_data,size_t user_length)137 NewWithLenSliceRefcount(void (*destroy)(void*, size_t), void* user_data, 138 size_t user_length) 139 : base_(grpc_slice_refcount::Type::REGULAR, &refs_, Destroy, this, 140 &base_), 141 user_data_(user_data), 142 user_length_(user_length), 143 user_destroy_(destroy) {} ~NewWithLenSliceRefcount()144 ~NewWithLenSliceRefcount() { user_destroy_(user_data_, user_length_); } 145 base_refcount()146 grpc_slice_refcount* base_refcount() { return &base_; } 147 148 private: 149 grpc_slice_refcount base_; 150 RefCount refs_; 151 void* user_data_; 152 size_t user_length_; 153 void (*user_destroy_)(void*, size_t); 154 }; 155 156 /** grpc_slice_from_moved_(string|buffer) ref count .*/ 157 class MovedStringSliceRefCount { 158 public: MovedStringSliceRefCount(grpc_core::UniquePtr<char> && str)159 explicit MovedStringSliceRefCount(grpc_core::UniquePtr<char>&& str) 160 : base_(grpc_slice_refcount::Type::REGULAR, &refs_, Destroy, this, 161 &base_), 162 str_(std::move(str)) {} 163 base_refcount()164 grpc_slice_refcount* base_refcount() { return &base_; } 165 166 private: Destroy(void * arg)167 static void Destroy(void* arg) { 168 delete static_cast<MovedStringSliceRefCount*>(arg); 169 } 170 171 grpc_slice_refcount base_; 172 grpc_core::RefCount refs_; 173 grpc_core::UniquePtr<char> str_; 174 }; 175 176 // grpc_slice_from_cpp_string() ref count. 177 class MovedCppStringSliceRefCount { 178 public: MovedCppStringSliceRefCount(std::string && str)179 explicit MovedCppStringSliceRefCount(std::string&& str) 180 : base_(grpc_slice_refcount::Type::REGULAR, &refs_, Destroy, this, 181 &base_), 182 str_(std::move(str)) {} 183 base_refcount()184 grpc_slice_refcount* base_refcount() { return &base_; } 185 186 private: Destroy(void * arg)187 static void Destroy(void* arg) { 188 delete static_cast<MovedCppStringSliceRefCount*>(arg); 189 } 190 191 grpc_slice_refcount base_; 192 grpc_core::RefCount refs_; 193 std::string str_; 194 }; 195 196 } // namespace grpc_core 197 grpc_slice_new_with_len(void * p,size_t len,void (* destroy)(void *,size_t))198 grpc_slice grpc_slice_new_with_len(void* p, size_t len, 199 void (*destroy)(void*, size_t)) { 200 grpc_slice slice; 201 slice.refcount = (new grpc_core::NewWithLenSliceRefcount(destroy, p, len)) 202 ->base_refcount(); 203 slice.data.refcounted.bytes = static_cast<uint8_t*>(p); 204 slice.data.refcounted.length = len; 205 return slice; 206 } 207 UnmanagedMemorySlice(const char * source,size_t length)208 grpc_core::UnmanagedMemorySlice::UnmanagedMemorySlice(const char* source, 209 size_t length) { 210 if (length <= sizeof(data.inlined.bytes)) { 211 refcount = nullptr; 212 data.inlined.length = static_cast<uint8_t>(length); 213 } else { 214 HeapInit(length); 215 } 216 if (length > 0) { 217 memcpy(GRPC_SLICE_START_PTR(*this), source, length); 218 } 219 } 220 UnmanagedMemorySlice(const char * source)221 grpc_core::UnmanagedMemorySlice::UnmanagedMemorySlice(const char* source) 222 : grpc_core::UnmanagedMemorySlice::UnmanagedMemorySlice(source, 223 strlen(source)) {} 224 grpc_slice_from_copied_buffer(const char * source,size_t length)225 grpc_slice grpc_slice_from_copied_buffer(const char* source, size_t length) { 226 return grpc_core::UnmanagedMemorySlice(source, length); 227 } 228 grpc_slice_from_copied_string(const char * source)229 grpc_slice grpc_slice_from_copied_string(const char* source) { 230 return grpc_core::UnmanagedMemorySlice(source, strlen(source)); 231 } 232 grpc_slice_from_moved_buffer(grpc_core::UniquePtr<char> p,size_t len)233 grpc_slice grpc_slice_from_moved_buffer(grpc_core::UniquePtr<char> p, 234 size_t len) { 235 uint8_t* ptr = reinterpret_cast<uint8_t*>(p.get()); 236 grpc_slice slice; 237 if (len <= sizeof(slice.data.inlined.bytes)) { 238 slice.refcount = nullptr; 239 slice.data.inlined.length = len; 240 memcpy(GRPC_SLICE_START_PTR(slice), ptr, len); 241 } else { 242 slice.refcount = (new grpc_core::MovedStringSliceRefCount(std::move(p))) 243 ->base_refcount(); 244 slice.data.refcounted.bytes = ptr; 245 slice.data.refcounted.length = len; 246 } 247 return slice; 248 } 249 grpc_slice_from_moved_string(grpc_core::UniquePtr<char> p)250 grpc_slice grpc_slice_from_moved_string(grpc_core::UniquePtr<char> p) { 251 const size_t len = strlen(p.get()); 252 return grpc_slice_from_moved_buffer(std::move(p), len); 253 } 254 grpc_slice_from_cpp_string(std::string str)255 grpc_slice grpc_slice_from_cpp_string(std::string str) { 256 grpc_slice slice; 257 if (str.size() <= sizeof(slice.data.inlined.bytes)) { 258 slice.refcount = nullptr; 259 slice.data.inlined.length = str.size(); 260 memcpy(GRPC_SLICE_START_PTR(slice), str.data(), str.size()); 261 } else { 262 slice.data.refcounted.bytes = 263 reinterpret_cast<uint8_t*>(const_cast<char*>(str.data())); 264 slice.data.refcounted.length = str.size(); 265 slice.refcount = 266 (new grpc_core::MovedCppStringSliceRefCount(std::move(str))) 267 ->base_refcount(); 268 } 269 return slice; 270 } 271 272 namespace { 273 274 class MallocRefCount { 275 public: Destroy(void * arg)276 static void Destroy(void* arg) { 277 MallocRefCount* r = static_cast<MallocRefCount*>(arg); 278 r->~MallocRefCount(); 279 gpr_free(r); 280 } 281 MallocRefCount()282 MallocRefCount() 283 : base_(grpc_slice_refcount::Type::REGULAR, &refs_, Destroy, this, 284 &base_) {} 285 ~MallocRefCount() = default; 286 base_refcount()287 grpc_slice_refcount* base_refcount() { return &base_; } 288 289 private: 290 grpc_slice_refcount base_; 291 grpc_core::RefCount refs_; 292 }; 293 294 } // namespace 295 grpc_slice_malloc_large(size_t length)296 grpc_slice grpc_slice_malloc_large(size_t length) { 297 return grpc_core::UnmanagedMemorySlice( 298 length, grpc_core::UnmanagedMemorySlice::ForceHeapAllocation()); 299 } 300 HeapInit(size_t length)301 void grpc_core::UnmanagedMemorySlice::HeapInit(size_t length) { 302 /* Memory layout used by the slice created here: 303 304 +-----------+----------------------------------------------------------+ 305 | refcount | bytes | 306 +-----------+----------------------------------------------------------+ 307 308 refcount is a malloc_refcount 309 bytes is an array of bytes of the requested length 310 Both parts are placed in the same allocation returned from gpr_malloc */ 311 auto* rc = 312 static_cast<MallocRefCount*>(gpr_malloc(sizeof(MallocRefCount) + length)); 313 314 /* Initial refcount on rc is 1 - and it's up to the caller to release 315 this reference. */ 316 new (rc) MallocRefCount(); 317 318 /* Build up the slice to be returned. */ 319 /* The slices refcount points back to the allocated block. */ 320 refcount = rc->base_refcount(); 321 /* The data bytes are placed immediately after the refcount struct */ 322 data.refcounted.bytes = reinterpret_cast<uint8_t*>(rc + 1); 323 /* And the length of the block is set to the requested length */ 324 data.refcounted.length = length; 325 } 326 grpc_slice_malloc(size_t length)327 grpc_slice grpc_slice_malloc(size_t length) { 328 return grpc_core::UnmanagedMemorySlice(length); 329 } 330 UnmanagedMemorySlice(size_t length)331 grpc_core::UnmanagedMemorySlice::UnmanagedMemorySlice(size_t length) { 332 if (length > sizeof(data.inlined.bytes)) { 333 HeapInit(length); 334 } else { 335 /* small slice: just inline the data */ 336 refcount = nullptr; 337 data.inlined.length = static_cast<uint8_t>(length); 338 } 339 } 340 341 template <typename Slice> sub_no_ref(const Slice & source,size_t begin,size_t end)342 static Slice sub_no_ref(const Slice& source, size_t begin, size_t end) { 343 Slice subset; 344 345 GPR_ASSERT(end >= begin); 346 347 if (source.refcount) { 348 /* Enforce preconditions */ 349 GPR_ASSERT(source.data.refcounted.length >= end); 350 351 /* Build the result */ 352 subset.refcount = source.refcount->sub_refcount(); 353 /* Point into the source array */ 354 subset.data.refcounted.bytes = source.data.refcounted.bytes + begin; 355 subset.data.refcounted.length = end - begin; 356 } else { 357 /* Enforce preconditions */ 358 GPR_ASSERT(source.data.inlined.length >= end); 359 subset.refcount = nullptr; 360 subset.data.inlined.length = static_cast<uint8_t>(end - begin); 361 memcpy(subset.data.inlined.bytes, source.data.inlined.bytes + begin, 362 end - begin); 363 } 364 return subset; 365 } 366 grpc_slice_sub_no_ref(grpc_slice source,size_t begin,size_t end)367 grpc_slice grpc_slice_sub_no_ref(grpc_slice source, size_t begin, size_t end) { 368 return sub_no_ref(source, begin, end); 369 } 370 grpc_slice_sub_no_ref(const grpc_core::UnmanagedMemorySlice & source,size_t begin,size_t end)371 grpc_core::UnmanagedMemorySlice grpc_slice_sub_no_ref( 372 const grpc_core::UnmanagedMemorySlice& source, size_t begin, size_t end) { 373 return sub_no_ref(source, begin, end); 374 } 375 grpc_slice_sub(grpc_slice source,size_t begin,size_t end)376 grpc_slice grpc_slice_sub(grpc_slice source, size_t begin, size_t end) { 377 grpc_slice subset; 378 379 if (end - begin <= sizeof(subset.data.inlined.bytes)) { 380 subset.refcount = nullptr; 381 subset.data.inlined.length = static_cast<uint8_t>(end - begin); 382 memcpy(subset.data.inlined.bytes, GRPC_SLICE_START_PTR(source) + begin, 383 end - begin); 384 } else { 385 subset = grpc_slice_sub_no_ref(source, begin, end); 386 /* Bump the refcount */ 387 subset.refcount->Ref(); 388 } 389 return subset; 390 } 391 grpc_slice_split_tail_maybe_ref(grpc_slice * source,size_t split,grpc_slice_ref_whom ref_whom)392 grpc_slice grpc_slice_split_tail_maybe_ref(grpc_slice* source, size_t split, 393 grpc_slice_ref_whom ref_whom) { 394 grpc_slice tail; 395 396 if (source->refcount == nullptr) { 397 /* inlined data, copy it out */ 398 GPR_ASSERT(source->data.inlined.length >= split); 399 tail.refcount = nullptr; 400 tail.data.inlined.length = 401 static_cast<uint8_t>(source->data.inlined.length - split); 402 memcpy(tail.data.inlined.bytes, source->data.inlined.bytes + split, 403 tail.data.inlined.length); 404 source->data.inlined.length = static_cast<uint8_t>(split); 405 } else { 406 size_t tail_length = source->data.refcounted.length - split; 407 GPR_ASSERT(source->data.refcounted.length >= split); 408 if (tail_length < sizeof(tail.data.inlined.bytes) && 409 ref_whom != GRPC_SLICE_REF_TAIL) { 410 /* Copy out the bytes - it'll be cheaper than refcounting */ 411 tail.refcount = nullptr; 412 tail.data.inlined.length = static_cast<uint8_t>(tail_length); 413 memcpy(tail.data.inlined.bytes, source->data.refcounted.bytes + split, 414 tail_length); 415 source->refcount = source->refcount->sub_refcount(); 416 } else { 417 /* Build the result */ 418 switch (ref_whom) { 419 case GRPC_SLICE_REF_TAIL: 420 tail.refcount = source->refcount->sub_refcount(); 421 source->refcount = &grpc_core::kNoopRefcount; 422 break; 423 case GRPC_SLICE_REF_HEAD: 424 tail.refcount = &grpc_core::kNoopRefcount; 425 source->refcount = source->refcount->sub_refcount(); 426 break; 427 case GRPC_SLICE_REF_BOTH: 428 tail.refcount = source->refcount->sub_refcount(); 429 source->refcount = source->refcount->sub_refcount(); 430 /* Bump the refcount */ 431 tail.refcount->Ref(); 432 break; 433 } 434 /* Point into the source array */ 435 tail.data.refcounted.bytes = source->data.refcounted.bytes + split; 436 tail.data.refcounted.length = tail_length; 437 } 438 source->data.refcounted.length = split; 439 } 440 441 return tail; 442 } 443 grpc_slice_split_tail(grpc_slice * source,size_t split)444 grpc_slice grpc_slice_split_tail(grpc_slice* source, size_t split) { 445 return grpc_slice_split_tail_maybe_ref(source, split, GRPC_SLICE_REF_BOTH); 446 } 447 grpc_slice_split_head(grpc_slice * source,size_t split)448 grpc_slice grpc_slice_split_head(grpc_slice* source, size_t split) { 449 grpc_slice head; 450 451 if (source->refcount == nullptr) { 452 GPR_ASSERT(source->data.inlined.length >= split); 453 454 head.refcount = nullptr; 455 head.data.inlined.length = static_cast<uint8_t>(split); 456 memcpy(head.data.inlined.bytes, source->data.inlined.bytes, split); 457 source->data.inlined.length = 458 static_cast<uint8_t>(source->data.inlined.length - split); 459 memmove(source->data.inlined.bytes, source->data.inlined.bytes + split, 460 source->data.inlined.length); 461 } else if (split < sizeof(head.data.inlined.bytes)) { 462 GPR_ASSERT(source->data.refcounted.length >= split); 463 464 head.refcount = nullptr; 465 head.data.inlined.length = static_cast<uint8_t>(split); 466 memcpy(head.data.inlined.bytes, source->data.refcounted.bytes, split); 467 source->refcount = source->refcount->sub_refcount(); 468 source->data.refcounted.bytes += split; 469 source->data.refcounted.length -= split; 470 } else { 471 GPR_ASSERT(source->data.refcounted.length >= split); 472 473 /* Build the result */ 474 head.refcount = source->refcount->sub_refcount(); 475 /* Bump the refcount */ 476 head.refcount->Ref(); 477 /* Point into the source array */ 478 head.data.refcounted.bytes = source->data.refcounted.bytes; 479 head.data.refcounted.length = split; 480 source->refcount = source->refcount->sub_refcount(); 481 source->data.refcounted.bytes += split; 482 source->data.refcounted.length -= split; 483 } 484 485 return head; 486 } 487 grpc_slice_default_eq_impl(grpc_slice a,grpc_slice b)488 int grpc_slice_default_eq_impl(grpc_slice a, grpc_slice b) { 489 if (GRPC_SLICE_LENGTH(a) != GRPC_SLICE_LENGTH(b)) return false; 490 if (GRPC_SLICE_LENGTH(a) == 0) return true; 491 return 0 == memcmp(GRPC_SLICE_START_PTR(a), GRPC_SLICE_START_PTR(b), 492 GRPC_SLICE_LENGTH(a)); 493 } 494 grpc_slice_eq(grpc_slice a,grpc_slice b)495 int grpc_slice_eq(grpc_slice a, grpc_slice b) { 496 if (a.refcount && b.refcount && 497 a.refcount->GetType() == b.refcount->GetType()) { 498 return a.refcount->Eq(a, b); 499 } 500 return grpc_slice_default_eq_impl(a, b); 501 } 502 grpc_slice_differs_refcounted(const grpc_slice & a,const grpc_slice & b_not_inline)503 int grpc_slice_differs_refcounted(const grpc_slice& a, 504 const grpc_slice& b_not_inline) { 505 size_t a_len; 506 const uint8_t* a_ptr; 507 if (a.refcount) { 508 a_len = a.data.refcounted.length; 509 a_ptr = a.data.refcounted.bytes; 510 } else { 511 a_len = a.data.inlined.length; 512 a_ptr = &a.data.inlined.bytes[0]; 513 } 514 if (a_len != b_not_inline.data.refcounted.length) { 515 return true; 516 } 517 if (a_len == 0) { 518 return false; 519 } 520 // This check *must* occur after the a_len == 0 check 521 // to retain compatibility with grpc_slice_eq. 522 if (a_ptr == nullptr) { 523 return true; 524 } 525 return memcmp(a_ptr, b_not_inline.data.refcounted.bytes, a_len); 526 } 527 grpc_slice_cmp(grpc_slice a,grpc_slice b)528 int grpc_slice_cmp(grpc_slice a, grpc_slice b) { 529 int d = static_cast<int>(GRPC_SLICE_LENGTH(a) - GRPC_SLICE_LENGTH(b)); 530 if (d != 0) return d; 531 return memcmp(GRPC_SLICE_START_PTR(a), GRPC_SLICE_START_PTR(b), 532 GRPC_SLICE_LENGTH(a)); 533 } 534 grpc_slice_str_cmp(grpc_slice a,const char * b)535 int grpc_slice_str_cmp(grpc_slice a, const char* b) { 536 size_t b_length = strlen(b); 537 int d = static_cast<int>(GRPC_SLICE_LENGTH(a) - b_length); 538 if (d != 0) return d; 539 return memcmp(GRPC_SLICE_START_PTR(a), b, b_length); 540 } 541 grpc_slice_is_equivalent(grpc_slice a,grpc_slice b)542 int grpc_slice_is_equivalent(grpc_slice a, grpc_slice b) { 543 if (a.refcount == nullptr || b.refcount == nullptr) { 544 return grpc_slice_eq(a, b); 545 } 546 return a.data.refcounted.length == b.data.refcounted.length && 547 a.data.refcounted.bytes == b.data.refcounted.bytes; 548 } 549 grpc_slice_buf_start_eq(grpc_slice a,const void * b,size_t len)550 int grpc_slice_buf_start_eq(grpc_slice a, const void* b, size_t len) { 551 if (GRPC_SLICE_LENGTH(a) < len) return 0; 552 return 0 == memcmp(GRPC_SLICE_START_PTR(a), b, len); 553 } 554 grpc_slice_rchr(grpc_slice s,char c)555 int grpc_slice_rchr(grpc_slice s, char c) { 556 const char* b = reinterpret_cast<const char*> GRPC_SLICE_START_PTR(s); 557 int i; 558 for (i = static_cast<int> GRPC_SLICE_LENGTH(s) - 1; i != -1 && b[i] != c; 559 i--) { 560 } 561 return i; 562 } 563 grpc_slice_chr(grpc_slice s,char c)564 int grpc_slice_chr(grpc_slice s, char c) { 565 const char* b = reinterpret_cast<const char*> GRPC_SLICE_START_PTR(s); 566 const char* p = static_cast<const char*>(memchr(b, c, GRPC_SLICE_LENGTH(s))); 567 return p == nullptr ? -1 : static_cast<int>(p - b); 568 } 569 grpc_slice_slice(grpc_slice haystack,grpc_slice needle)570 int grpc_slice_slice(grpc_slice haystack, grpc_slice needle) { 571 size_t haystack_len = GRPC_SLICE_LENGTH(haystack); 572 const uint8_t* haystack_bytes = GRPC_SLICE_START_PTR(haystack); 573 size_t needle_len = GRPC_SLICE_LENGTH(needle); 574 const uint8_t* needle_bytes = GRPC_SLICE_START_PTR(needle); 575 576 if (haystack_len == 0 || needle_len == 0) return -1; 577 if (haystack_len < needle_len) return -1; 578 if (haystack_len == needle_len) { 579 return grpc_slice_eq(haystack, needle) ? 0 : -1; 580 } 581 if (needle_len == 1) { 582 return grpc_slice_chr(haystack, static_cast<char>(*needle_bytes)); 583 } 584 585 const uint8_t* last = haystack_bytes + haystack_len - needle_len; 586 for (const uint8_t* cur = haystack_bytes; cur != last; ++cur) { 587 if (0 == memcmp(cur, needle_bytes, needle_len)) { 588 return static_cast<int>(cur - haystack_bytes); 589 } 590 } 591 return -1; 592 } 593 grpc_slice_dup(grpc_slice a)594 grpc_slice grpc_slice_dup(grpc_slice a) { 595 grpc_slice copy = GRPC_SLICE_MALLOC(GRPC_SLICE_LENGTH(a)); 596 memcpy(GRPC_SLICE_START_PTR(copy), GRPC_SLICE_START_PTR(a), 597 GRPC_SLICE_LENGTH(a)); 598 return copy; 599 } 600