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