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