• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_SRC_CORE_LIB_SLICE_SLICE_BUFFER_H
16 #define GRPC_SRC_CORE_LIB_SLICE_SLICE_BUFFER_H
17 
18 #include <grpc/slice.h>
19 #include <grpc/slice_buffer.h>
20 #include <grpc/support/port_platform.h>
21 #include <stdint.h>
22 #include <string.h>
23 
24 #include <memory>
25 #include <string>
26 
27 #include "src/core/lib/slice/slice.h"
28 
29 // Copy the first n bytes of src into memory pointed to by dst.
30 void grpc_slice_buffer_copy_first_into_buffer(grpc_slice_buffer* src, size_t n,
31                                               void* dst);
32 
33 void grpc_slice_buffer_move_first_no_inline(grpc_slice_buffer* src, size_t n,
34                                             grpc_slice_buffer* dst);
35 
36 void grpc_slice_buffer_trim_end_no_inline(grpc_slice_buffer* sb, size_t n,
37                                           grpc_slice_buffer* garbage);
38 
39 namespace grpc_core {
40 
41 /// A slice buffer holds the memory for a collection of slices.
42 /// The SliceBuffer object itself is meant to only hide the C-style API,
43 /// and won't hold the data itself. In terms of lifespan, the
44 /// grpc_slice_buffer ought to be kept somewhere inside the caller's objects,
45 /// like a transport or an endpoint.
46 ///
47 /// This lifespan rule is likely to change in the future, as we may
48 /// collapse the grpc_slice_buffer structure straight into this class.
49 ///
50 /// The SliceBuffer API is basically a replica of the grpc_slice_buffer's,
51 /// and its documentation will move here once we remove the C structure,
52 /// which should happen before the EventEngine's API is no longer
53 /// an experimental API.
54 class SliceBuffer {
55  public:
SliceBuffer()56   explicit SliceBuffer() { grpc_slice_buffer_init(&slice_buffer_); }
SliceBuffer(Slice slice)57   explicit SliceBuffer(Slice slice) : SliceBuffer() {
58     Append(std::move(slice));
59   }
60   SliceBuffer(const SliceBuffer& other) = delete;
SliceBuffer(SliceBuffer && other)61   SliceBuffer(SliceBuffer&& other) noexcept {
62     grpc_slice_buffer_init(&slice_buffer_);
63     grpc_slice_buffer_swap(&slice_buffer_, &other.slice_buffer_);
64   }
65   /// Upon destruction, the underlying raw slice buffer is cleaned out and all
66   /// slices are unreffed.
~SliceBuffer()67   ~SliceBuffer() { grpc_slice_buffer_destroy(&slice_buffer_); }
68 
69   SliceBuffer& operator=(const SliceBuffer&) = delete;
70   SliceBuffer& operator=(SliceBuffer&& other) noexcept {
71     grpc_slice_buffer_swap(&slice_buffer_, &other.slice_buffer_);
72     return *this;
73   }
74 
75   /// Appends a new slice into the SliceBuffer and makes an attempt to merge
76   /// this slice with the last slice in the SliceBuffer.
77   void Append(Slice slice);
78   /// Appends a SliceBuffer into the SliceBuffer and makes an attempt to merge
79   /// this slice with the last slice in the SliceBuffer.
80   void Append(const SliceBuffer& other);
TakeAndAppend(SliceBuffer & other)81   void TakeAndAppend(SliceBuffer& other) {
82     grpc_slice_buffer_move_into(&other.slice_buffer_, &slice_buffer_);
83   }
84 
85   /// Adds a new slice into the SliceBuffer at the next available index.
86   /// Returns the index at which the new slice is added.
87   size_t AppendIndexed(Slice slice);
88 
89   /// Returns the number of slices held by the SliceBuffer.
Count()90   size_t Count() const { return slice_buffer_.count; }
91 
92   /// Copy the entire contents to a memory buffer.
CopyToBuffer(uint8_t * dst)93   void CopyToBuffer(uint8_t* dst) {
94     grpc_slice_buffer_copy_first_into_buffer(&slice_buffer_,
95                                              slice_buffer_.length, dst);
96   }
97 
98   /// Removes/deletes the last n bytes in the SliceBuffer.
RemoveLastNBytes(size_t n)99   void RemoveLastNBytes(size_t n) {
100     grpc_slice_buffer_trim_end(&slice_buffer_, n, nullptr);
101   }
102 
103   /// Removes/deletes the last n bytes in the SliceBuffer while avoiding the
104   /// the creation of inline slices.
RemoveLastNBytesNoInline(size_t n)105   void RemoveLastNBytesNoInline(size_t n) {
106     grpc_slice_buffer_trim_end_no_inline(&slice_buffer_, n, nullptr);
107   }
108 
109   /// Move the first n bytes of the SliceBuffer into a memory pointed to by
110   /// dst.
MoveFirstNBytesIntoBuffer(size_t n,void * dst)111   void MoveFirstNBytesIntoBuffer(size_t n, void* dst) {
112     grpc_slice_buffer_move_first_into_buffer(&slice_buffer_, n, dst);
113   }
114 
115   /// Removes/deletes the last n bytes in the SliceBuffer and add it to the
116   /// other SliceBuffer
MoveLastNBytesIntoSliceBuffer(size_t n,SliceBuffer & other)117   void MoveLastNBytesIntoSliceBuffer(size_t n, SliceBuffer& other) {
118     grpc_slice_buffer_trim_end(&slice_buffer_, n, &other.slice_buffer_);
119   }
120 
121   /// Move the first n bytes of the SliceBuffer into the other SliceBuffer
MoveFirstNBytesIntoSliceBuffer(size_t n,SliceBuffer & other)122   void MoveFirstNBytesIntoSliceBuffer(size_t n, SliceBuffer& other) {
123     grpc_slice_buffer_move_first(&slice_buffer_, n, &other.slice_buffer_);
124   }
125 
126   /// Removes and unrefs all slices in the SliceBuffer.
Clear()127   GRPC_REINITIALIZES void Clear() {
128     grpc_slice_buffer_reset_and_unref(&slice_buffer_);
129   }
130 
131   /// Removes the first slice in the SliceBuffer and returns it.
132   Slice TakeFirst();
133 
134   /// Prepends the slice to the the front of the SliceBuffer.
135   void Prepend(Slice slice);
136 
137   /// Increased the ref-count of slice at the specified index and returns the
138   /// associated slice.
139   Slice RefSlice(size_t index) const;
140 
141   const Slice& operator[](size_t index) const {
142     return grpc_event_engine::experimental::internal::SliceCast<Slice>(
143         slice_buffer_.slices[index]);
144   }
145 
146   /// The total number of bytes held by the SliceBuffer
Length()147   size_t Length() const { return slice_buffer_.length; }
148 
149   /// Swap with another slice buffer
Swap(SliceBuffer * other)150   void Swap(SliceBuffer* other) {
151     grpc_slice_buffer_swap(c_slice_buffer(), other->c_slice_buffer());
152   }
153 
154   /// Concatenate all slices and return the resulting string.
155   std::string JoinIntoString() const;
156 
157   /// Concatenate all slices and return the resulting slice.
158   Slice JoinIntoSlice() const;
159 
160   // Return a copy of the slice buffer
Copy()161   SliceBuffer Copy() const {
162     SliceBuffer copy;
163     for (size_t i = 0; i < Count(); i++) {
164       copy.Append(RefSlice(i));
165     }
166     return copy;
167   }
168 
169   /// Add a small amount to the end of the slice buffer.
AddTiny(size_t n)170   uint8_t* AddTiny(size_t n) {
171     return grpc_slice_buffer_tiny_add(&slice_buffer_, n);
172   }
173 
174   /// Return a pointer to the back raw grpc_slice_buffer
c_slice_buffer()175   grpc_slice_buffer* c_slice_buffer() { return &slice_buffer_; }
176 
177   /// Return a pointer to the back raw grpc_slice_buffer
c_slice_buffer()178   const grpc_slice_buffer* c_slice_buffer() const { return &slice_buffer_; }
179 
c_slice_at(size_t index)180   const grpc_slice& c_slice_at(size_t index) {
181     return slice_buffer_.slices[index];
182   }
183 
184  private:
185   /// The backing raw slice buffer.
186   grpc_slice_buffer slice_buffer_;
187 
188 // Make failure to destruct show up in ASAN builds.
189 #ifndef NDEBUG
190   std::unique_ptr<int> asan_canary_ = std::make_unique<int>(0);
191 #endif
192 };
193 
194 }  // namespace grpc_core
195 
196 #endif  // GRPC_SRC_CORE_LIB_SLICE_SLICE_BUFFER_H
197