GRPC C++  1.62.0
slice.h
Go to the documentation of this file.
1 // Copyright 2022 gRPC authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef GRPC_EVENT_ENGINE_SLICE_H
16 #define GRPC_EVENT_ENGINE_SLICE_H
17 
19 
20 #include <string.h>
21 
22 #include <cstdint>
23 #include <string>
24 #include <utility>
25 
26 #include "absl/strings/string_view.h"
27 
29 #include <grpc/slice.h>
30 #include <grpc/support/log.h>
31 
32 // This public slice definition largely based of the internal grpc_core::Slice
33 // implementation. Changes to this implementation might warrant changes to the
34 // internal grpc_core::Slice type as well.
35 
36 namespace grpc_event_engine {
37 namespace experimental {
38 
39 // Forward declarations
40 class Slice;
41 class MutableSlice;
42 
43 namespace slice_detail {
44 
45 // Returns an empty slice.
46 static constexpr grpc_slice EmptySlice() { return {nullptr, {}}; }
47 
48 // BaseSlice holds the grpc_slice object, but does not apply refcounting policy.
49 // It does export immutable access into the slice, such that this can be shared
50 // by all storage policies.
51 class BaseSlice {
52  public:
53  BaseSlice(const BaseSlice&) = delete;
54  BaseSlice& operator=(const BaseSlice&) = delete;
55  BaseSlice(BaseSlice&& other) = delete;
56  BaseSlice& operator=(BaseSlice&& other) = delete;
57 
58  // Iterator access to the underlying bytes
59  const uint8_t* begin() const { return GRPC_SLICE_START_PTR(c_slice()); }
60  const uint8_t* end() const { return GRPC_SLICE_END_PTR(c_slice()); }
61  const uint8_t* cbegin() const { return GRPC_SLICE_START_PTR(c_slice()); }
62  const uint8_t* cend() const { return GRPC_SLICE_END_PTR(c_slice()); }
63 
64  // Retrieve a borrowed reference to the underlying grpc_slice.
65  const grpc_slice& c_slice() const { return slice_; }
66 
67  // Retrieve the underlying grpc_slice, and replace the one in this object with
68  // EmptySlice().
70  grpc_slice out = slice_;
71  slice_ = EmptySlice();
72  return out;
73  }
74 
75  // As other things... borrowed references.
76  absl::string_view as_string_view() const {
77  return absl::string_view(reinterpret_cast<const char*>(data()), size());
78  }
79 
80  // Array access
81  uint8_t operator[](size_t i) const {
82  return GRPC_SLICE_START_PTR(c_slice())[i];
83  }
84 
85  // Access underlying data
86  const uint8_t* data() const { return GRPC_SLICE_START_PTR(c_slice()); }
87 
88  // Size of the slice
89  size_t size() const { return GRPC_SLICE_LENGTH(c_slice()); }
90  size_t length() const { return size(); }
91  bool empty() const { return size() == 0; }
92 
93  // For inlined slices - are these two slices equal?
94  // For non-inlined slices - do these two slices refer to the same block of
95  // memory?
96  bool is_equivalent(const BaseSlice& other) const {
97  return grpc_slice_is_equivalent(slice_, other.slice_);
98  }
99 
100  uint32_t Hash() const;
101 
102  protected:
103  BaseSlice() : slice_(EmptySlice()) {}
104  explicit BaseSlice(const grpc_slice& slice) : slice_(slice) {}
105  ~BaseSlice() = default;
106 
107  void Swap(BaseSlice* other) { std::swap(slice_, other->slice_); }
108  void SetCSlice(const grpc_slice& slice) { slice_ = slice; }
109 
110  uint8_t* mutable_data() { return GRPC_SLICE_START_PTR(slice_); }
111 
112  grpc_slice* c_slice_ptr() { return &slice_; }
113 
114  private:
115  grpc_slice slice_;
116 };
117 
118 inline bool operator==(const BaseSlice& a, const BaseSlice& b) {
119  return grpc_slice_eq(a.c_slice(), b.c_slice()) != 0;
120 }
121 
122 inline bool operator!=(const BaseSlice& a, const BaseSlice& b) {
123  return grpc_slice_eq(a.c_slice(), b.c_slice()) == 0;
124 }
125 
126 inline bool operator==(const BaseSlice& a, absl::string_view b) {
127  return a.as_string_view() == b;
128 }
129 
130 inline bool operator!=(const BaseSlice& a, absl::string_view b) {
131  return a.as_string_view() != b;
132 }
133 
134 inline bool operator==(absl::string_view a, const BaseSlice& b) {
135  return a == b.as_string_view();
136 }
137 
138 inline bool operator!=(absl::string_view a, const BaseSlice& b) {
139  return a != b.as_string_view();
140 }
141 
142 inline bool operator==(const BaseSlice& a, const grpc_slice& b) {
143  return grpc_slice_eq(a.c_slice(), b) != 0;
144 }
145 
146 inline bool operator!=(const BaseSlice& a, const grpc_slice& b) {
147  return grpc_slice_eq(a.c_slice(), b) == 0;
148 }
149 
150 inline bool operator==(const grpc_slice& a, const BaseSlice& b) {
151  return grpc_slice_eq(a, b.c_slice()) != 0;
152 }
153 
154 inline bool operator!=(const grpc_slice& a, const BaseSlice& b) {
155  return grpc_slice_eq(a, b.c_slice()) == 0;
156 }
157 
158 template <typename Out>
160  static Out FromCopiedString(const char* s) {
161  return FromCopiedBuffer(s, strlen(s));
162  }
163  static Out FromCopiedString(absl::string_view s) {
164  return FromCopiedBuffer(s.data(), s.size());
165  }
166  static Out FromCopiedString(std::string s);
167 
168  static Out FromCopiedBuffer(const char* p, size_t len) {
169  return Out(grpc_slice_from_copied_buffer(p, len));
170  }
171 
172  static Out FromCopiedBuffer(const uint8_t* p, size_t len) {
173  return Out(
174  grpc_slice_from_copied_buffer(reinterpret_cast<const char*>(p), len));
175  }
176 
177  template <typename Buffer>
178  static Out FromCopiedBuffer(const Buffer& buffer) {
179  return FromCopiedBuffer(reinterpret_cast<const char*>(buffer.data()),
180  buffer.size());
181  }
182 };
183 
184 } // namespace slice_detail
185 
187  : public slice_detail::BaseSlice,
188  public slice_detail::CopyConstructors<MutableSlice> {
189  public:
190  MutableSlice() = default;
191  explicit MutableSlice(const grpc_slice& slice);
192  ~MutableSlice();
193 
194  MutableSlice(const MutableSlice&) = delete;
195  MutableSlice& operator=(const MutableSlice&) = delete;
196  MutableSlice(MutableSlice&& other) noexcept
197  : slice_detail::BaseSlice(other.TakeCSlice()) {}
198  MutableSlice& operator=(MutableSlice&& other) noexcept {
199  Swap(&other);
200  return *this;
201  }
202 
203  static MutableSlice CreateUninitialized(size_t length) {
204  return MutableSlice(grpc_slice_malloc(length));
205  }
206 
207  // Return a sub slice of this one. Leaves this slice in an indeterminate but
208  // valid state.
209  MutableSlice TakeSubSlice(size_t pos, size_t n) {
210  return MutableSlice(grpc_slice_sub_no_ref(TakeCSlice(), pos, pos + n));
211  }
212 
213  // Iterator access to the underlying bytes
214  uint8_t* begin() { return mutable_data(); }
215  uint8_t* end() { return mutable_data() + size(); }
216  uint8_t* data() { return mutable_data(); }
217 
218  // Array access
219  uint8_t& operator[](size_t i) { return mutable_data()[i]; }
220 };
221 
223  : public slice_detail::BaseSlice,
224  public slice_detail::CopyConstructors<Slice> {
225  public:
226  Slice() = default;
227  ~Slice();
228  explicit Slice(const grpc_slice& slice) : slice_detail::BaseSlice(slice) {}
229  explicit Slice(slice_detail::BaseSlice&& other)
230  : slice_detail::BaseSlice(other.TakeCSlice()) {}
231 
232  Slice(const Slice&) = delete;
233  Slice& operator=(const Slice&) = delete;
234  Slice(Slice&& other) noexcept : slice_detail::BaseSlice(other.TakeCSlice()) {}
235  Slice& operator=(Slice&& other) noexcept {
236  Swap(&other);
237  return *this;
238  }
239 
240  // A slice might refer to some memory that we keep a refcount to (this is
241  // owned), or some memory that's inlined into the slice (also owned), or some
242  // other block of memory that we know will be available for the lifetime of
243  // some operation in the common case (not owned). In the *less common* case
244  // that we need to keep that slice text for longer than our API's guarantee us
245  // access, we need to take a copy and turn this into something that we do own.
246 
247  // TakeOwned returns an owned slice regardless of current ownership, and
248  // leaves the current slice in a valid but externally unpredictable state - in
249  // doing so it can avoid adding a ref to the underlying slice.
250  Slice TakeOwned();
251 
252  // AsOwned returns an owned slice but does not mutate the current slice,
253  // meaning that it may add a reference to the underlying slice.
254  Slice AsOwned() const;
255 
256  // TakeMutable returns a MutableSlice, and leaves the current slice in an
257  // indeterminate but valid state.
258  // A mutable slice requires only one reference to the bytes of the slice -
259  // this can be achieved either with inlined storage or with a single
260  // reference.
261  // If the current slice is refcounted and there are more than one references
262  // to that slice, then the slice is copied in order to achieve a mutable
263  // version.
264  MutableSlice TakeMutable();
265 
266  // Return a sub slice of this one. Leaves this slice in an indeterminate but
267  // valid state.
268  Slice TakeSubSlice(size_t pos, size_t n) {
269  return Slice(grpc_slice_sub_no_ref(TakeCSlice(), pos, pos + n));
270  }
271 
272  // Return a sub slice of this one. Adds a reference to the underlying slice.
273  Slice RefSubSlice(size_t pos, size_t n) const {
274  return Slice(grpc_slice_sub(c_slice(), pos, pos + n));
275  }
276 
277  // Split this slice, returning a new slice containing (split:end] and
278  // leaving this slice with [begin:split).
279  Slice Split(size_t split) {
280  return Slice(grpc_slice_split_tail(c_slice_ptr(), split));
281  }
282 
283  Slice Ref() const;
284 
285  Slice Copy() const { return Slice(grpc_slice_copy(c_slice())); }
286 
287  static Slice FromRefcountAndBytes(grpc_slice_refcount* r,
288  const uint8_t* begin, const uint8_t* end);
289 };
290 
291 namespace internal {
292 template <>
294 template <>
296 
297 template <>
299 template <>
301 
302 template <>
304 template <>
306 } // namespace internal
307 
308 } // namespace experimental
309 } // namespace grpc_event_engine
310 
311 #endif // GRPC_EVENT_ENGINE_SLICE_H
grpc_slice_eq
GPRAPI int grpc_slice_eq(grpc_slice a, grpc_slice b)
grpc_event_engine::experimental::slice_detail::BaseSlice::BaseSlice
BaseSlice()
Definition: slice.h:103
grpc_event_engine::experimental::slice_detail::CopyConstructors::FromCopiedBuffer
static Out FromCopiedBuffer(const char *p, size_t len)
Definition: slice.h:168
grpc_event_engine::experimental::slice_detail::operator==
bool operator==(const BaseSlice &a, const BaseSlice &b)
Definition: slice.h:118
grpc_event_engine::experimental::MutableSlice
Definition: slice.h:186
GRPC_SLICE_START_PTR
#define GRPC_SLICE_START_PTR(slice)
Definition: slice_type.h:99
GRPC_SLICE_END_PTR
#define GRPC_SLICE_END_PTR(slice)
Definition: slice_type.h:108
grpc_event_engine::experimental::Slice
Definition: slice.h:222
grpc_event_engine::experimental::MutableSlice::operator[]
uint8_t & operator[](size_t i)
Definition: slice.h:219
grpc_event_engine::experimental::MutableSlice::operator=
MutableSlice & operator=(MutableSlice &&other) noexcept
Definition: slice.h:198
grpc_event_engine::experimental::slice_detail::BaseSlice
Definition: slice.h:51
grpc_event_engine::experimental::slice_detail::BaseSlice::~BaseSlice
~BaseSlice()=default
grpc_event_engine::experimental::slice_detail::BaseSlice::BaseSlice
BaseSlice(const grpc_slice &slice)
Definition: slice.h:104
grpc_slice_malloc
GPRAPI grpc_slice grpc_slice_malloc(size_t length)
Equivalent to grpc_slice_new(malloc(len), len, free), but saves one malloc() call.
grpc_event_engine::experimental::Slice::RefSubSlice
Slice RefSubSlice(size_t pos, size_t n) const
Definition: slice.h:273
grpc_event_engine::experimental::Slice::Slice
Slice(slice_detail::BaseSlice &&other)
Definition: slice.h:229
grpc_event_engine::experimental::slice_detail::BaseSlice::cbegin
const uint8_t * cbegin() const
Definition: slice.h:61
grpc_slice_from_copied_buffer
GPRAPI grpc_slice grpc_slice_from_copied_buffer(const char *source, size_t len)
Create a slice by copying a buffer.
grpc_event_engine::experimental::Slice::operator=
Slice & operator=(Slice &&other) noexcept
Definition: slice.h:235
grpc_event_engine::experimental::slice_detail::CopyConstructors::FromCopiedBuffer
static Out FromCopiedBuffer(const Buffer &buffer)
Definition: slice.h:178
log.h
grpc_event_engine::experimental::slice_detail::BaseSlice::begin
const uint8_t * begin() const
Definition: slice.h:59
grpc_event_engine::experimental::internal::SliceCastable
Definition: slice_cast.h:30
grpc_event_engine::experimental::slice_detail::BaseSlice::c_slice
const grpc_slice & c_slice() const
Definition: slice.h:65
grpc_event_engine::experimental::slice_detail::BaseSlice::operator[]
uint8_t operator[](size_t i) const
Definition: slice.h:81
grpc_event_engine::experimental::slice_detail::operator!=
bool operator!=(const BaseSlice &a, const BaseSlice &b)
Definition: slice.h:122
grpc_event_engine::experimental::slice_detail::BaseSlice::operator=
BaseSlice & operator=(const BaseSlice &)=delete
grpc_event_engine::experimental::MutableSlice::end
uint8_t * end()
Definition: slice.h:215
grpc_event_engine::experimental::Slice::Slice
Slice(Slice &&other) noexcept
Definition: slice.h:234
slice_cast.h
grpc_event_engine::experimental::slice_detail::CopyConstructors::FromCopiedBuffer
static Out FromCopiedBuffer(const uint8_t *p, size_t len)
Definition: slice.h:172
grpc_event_engine::experimental::Slice::TakeSubSlice
Slice TakeSubSlice(size_t pos, size_t n)
Definition: slice.h:268
grpc_event_engine::experimental::slice_detail::CopyConstructors::FromCopiedString
static Out FromCopiedString(const char *s)
Definition: slice.h:160
grpc_slice
A grpc_slice s, if initialized, represents the byte range s.bytes[0..s.length-1].
Definition: slice_type.h:63
grpc_event_engine::experimental::MutableSlice::CreateUninitialized
static MutableSlice CreateUninitialized(size_t length)
Definition: slice.h:203
grpc_event_engine::experimental::MutableSlice::begin
uint8_t * begin()
Definition: slice.h:214
grpc_event_engine::experimental::Slice::Copy
Slice Copy() const
Definition: slice.h:285
grpc_event_engine::experimental::Slice::Split
Slice Split(size_t split)
Definition: slice.h:279
grpc_slice_sub
GPRAPI grpc_slice grpc_slice_sub(grpc_slice s, size_t begin, size_t end)
Return a result slice derived from s, which shares a ref count with s, where result....
grpc_event_engine::experimental::slice_detail::BaseSlice::Swap
void Swap(BaseSlice *other)
Definition: slice.h:107
grpc_event_engine::experimental::slice_detail::BaseSlice::Hash
uint32_t Hash() const
grpc_event_engine::experimental::slice_detail::BaseSlice::length
size_t length() const
Definition: slice.h:90
slice.h
grpc_event_engine::experimental::slice_detail::BaseSlice::empty
bool empty() const
Definition: slice.h:91
grpc_slice_split_tail
GPRAPI grpc_slice grpc_slice_split_tail(grpc_slice *s, size_t split)
Splits s into two: modifies s to be s[0:split], and returns a new slice, sharing a refcount with s,...
grpc_event_engine::experimental::slice_detail::BaseSlice::data
const uint8_t * data() const
Definition: slice.h:86
grpc_event_engine::experimental::slice_detail::CopyConstructors
Definition: slice.h:159
grpc_event_engine
Definition: endpoint_config.h:24
grpc_event_engine::experimental::slice_detail::BaseSlice::is_equivalent
bool is_equivalent(const BaseSlice &other) const
Definition: slice.h:96
grpc_event_engine::experimental::slice_detail::BaseSlice::cend
const uint8_t * cend() const
Definition: slice.h:62
grpc_slice_sub_no_ref
GPRAPI grpc_slice grpc_slice_sub_no_ref(grpc_slice s, size_t begin, size_t end)
The same as grpc_slice_sub, but without altering the ref count.
GRPC_SLICE_LENGTH
#define GRPC_SLICE_LENGTH(slice)
Definition: slice_type.h:102
grpc_event_engine::experimental::MutableSlice::data
uint8_t * data()
Definition: slice.h:216
grpc_slice_is_equivalent
GPRAPI int grpc_slice_is_equivalent(grpc_slice a, grpc_slice b)
Do two slices point at the same memory, with the same length If a or b is inlined,...
grpc_event_engine::experimental::MutableSlice::TakeSubSlice
MutableSlice TakeSubSlice(size_t pos, size_t n)
Definition: slice.h:209
grpc_event_engine::experimental::slice_detail::CopyConstructors::FromCopiedString
static Out FromCopiedString(absl::string_view s)
Definition: slice.h:163
grpc_slice_copy
GPRAPI grpc_slice grpc_slice_copy(grpc_slice s)
Copy slice - create a new slice that contains the same data as s.
GPR_MSVC_EMPTY_BASE_CLASS_WORKAROUND
#define GPR_MSVC_EMPTY_BASE_CLASS_WORKAROUND
Definition: port_platform.h:844
grpc_event_engine::experimental::Slice::Slice
Slice(const grpc_slice &slice)
Definition: slice.h:228
grpc_event_engine::experimental::slice_detail::BaseSlice::end
const uint8_t * end() const
Definition: slice.h:60
grpc_event_engine::experimental::MutableSlice::MutableSlice
MutableSlice(MutableSlice &&other) noexcept
Definition: slice.h:196
grpc_event_engine::experimental::slice_detail::BaseSlice::mutable_data
uint8_t * mutable_data()
Definition: slice.h:110
grpc_event_engine::experimental::slice_detail::BaseSlice::TakeCSlice
grpc_slice TakeCSlice()
Definition: slice.h:69
grpc_event_engine::experimental::slice_detail::BaseSlice::as_string_view
absl::string_view as_string_view() const
Definition: slice.h:76
grpc_event_engine::experimental::slice_detail::BaseSlice::c_slice_ptr
grpc_slice * c_slice_ptr()
Definition: slice.h:112
port_platform.h
grpc_event_engine::experimental::slice_detail::BaseSlice::SetCSlice
void SetCSlice(const grpc_slice &slice)
Definition: slice.h:108
grpc_event_engine::experimental::slice_detail::BaseSlice::size
size_t size() const
Definition: slice.h:89