• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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