xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/common/quiche_buffer_allocator.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef QUICHE_COMMON_QUICHE_BUFFER_ALLOCATOR_H_
6 #define QUICHE_COMMON_QUICHE_BUFFER_ALLOCATOR_H_
7 
8 #include <stddef.h>
9 
10 #include <memory>
11 
12 #include "absl/strings/string_view.h"
13 #include "quiche/common/platform/api/quiche_export.h"
14 #include "quiche/common/platform/api/quiche_iovec.h"
15 
16 namespace quiche {
17 
18 // Abstract base class for classes which allocate and delete buffers.
19 class QUICHE_EXPORT QuicheBufferAllocator {
20  public:
21   virtual ~QuicheBufferAllocator() = default;
22 
23   // Returns or allocates a new buffer of |size|. Never returns null.
24   virtual char* New(size_t size) = 0;
25 
26   // Returns or allocates a new buffer of |size| if |flag_enable| is true.
27   // Otherwise, returns a buffer that is compatible with this class directly
28   // with operator new. Never returns null.
29   virtual char* New(size_t size, bool flag_enable) = 0;
30 
31   // Releases a buffer.
32   virtual void Delete(char* buffer) = 0;
33 
34   // Marks the allocator as being idle. Serves as a hint to notify the allocator
35   // that it should release any resources it's still holding on to.
MarkAllocatorIdle()36   virtual void MarkAllocatorIdle() {}
37 };
38 
39 // A deleter that can be used to manage ownership of buffers allocated via
40 // QuicheBufferAllocator through std::unique_ptr.
41 class QUICHE_EXPORT QuicheBufferDeleter {
42  public:
QuicheBufferDeleter(QuicheBufferAllocator * allocator)43   explicit QuicheBufferDeleter(QuicheBufferAllocator* allocator)
44       : allocator_(allocator) {}
45 
allocator()46   QuicheBufferAllocator* allocator() { return allocator_; }
operator()47   void operator()(char* buffer) { allocator_->Delete(buffer); }
48 
49  private:
50   QuicheBufferAllocator* allocator_;
51 };
52 
53 using QuicheUniqueBufferPtr = std::unique_ptr<char[], QuicheBufferDeleter>;
54 
MakeUniqueBuffer(QuicheBufferAllocator * allocator,size_t size)55 inline QuicheUniqueBufferPtr MakeUniqueBuffer(QuicheBufferAllocator* allocator,
56                                               size_t size) {
57   return QuicheUniqueBufferPtr(allocator->New(size),
58                                QuicheBufferDeleter(allocator));
59 }
60 
61 // QuicheUniqueBufferPtr with a length attached to it.  Similar to
62 // QuicheMemSlice, except unlike QuicheMemSlice, QuicheBuffer is mutable and is
63 // not platform-specific.  Also unlike QuicheMemSlice, QuicheBuffer can be
64 // empty.
65 class QUICHE_EXPORT QuicheBuffer {
66  public:
QuicheBuffer()67   QuicheBuffer() : buffer_(nullptr, QuicheBufferDeleter(nullptr)), size_(0) {}
QuicheBuffer(QuicheBufferAllocator * allocator,size_t size)68   QuicheBuffer(QuicheBufferAllocator* allocator, size_t size)
69       : buffer_(MakeUniqueBuffer(allocator, size)), size_(size) {}
70 
QuicheBuffer(QuicheUniqueBufferPtr buffer,size_t size)71   QuicheBuffer(QuicheUniqueBufferPtr buffer, size_t size)
72       : buffer_(std::move(buffer)), size_(size) {}
73 
74   // Make sure the move constructor zeroes out the size field.
QuicheBuffer(QuicheBuffer && other)75   QuicheBuffer(QuicheBuffer&& other)
76       : buffer_(std::move(other.buffer_)), size_(other.size_) {
77     other.buffer_ = nullptr;
78     other.size_ = 0;
79   }
80   QuicheBuffer& operator=(QuicheBuffer&& other) {
81     buffer_ = std::move(other.buffer_);
82     size_ = other.size_;
83 
84     other.buffer_ = nullptr;
85     other.size_ = 0;
86     return *this;
87   }
88 
89   // Factory method to create a QuicheBuffer that holds a copy of `data`.
Copy(QuicheBufferAllocator * allocator,absl::string_view data)90   static QuicheBuffer Copy(QuicheBufferAllocator* allocator,
91                            absl::string_view data) {
92     QuicheBuffer buffer(allocator, data.size());
93     memcpy(buffer.data(), data.data(), data.size());
94     return buffer;
95   }
96 
97   // Factory method to create a QuicheBuffer of length `buffer_length` that
98   // holds a copy of `buffer_length` bytes from `iov` starting at offset
99   // `iov_offset`.  `iov` must be at least `iov_offset + buffer_length` total
100   // length.
101   static QuicheBuffer CopyFromIovec(QuicheBufferAllocator* allocator,
102                                     const struct iovec* iov, int iov_count,
103                                     size_t iov_offset, size_t buffer_length);
104 
data()105   const char* data() const { return buffer_.get(); }
data()106   char* data() { return buffer_.get(); }
size()107   size_t size() const { return size_; }
empty()108   bool empty() const { return size_ == 0; }
AsStringView()109   absl::string_view AsStringView() const {
110     return absl::string_view(data(), size());
111   }
112 
113   // Releases the ownership of the underlying buffer.
Release()114   QuicheUniqueBufferPtr Release() {
115     size_ = 0;
116     return std::move(buffer_);
117   }
118 
119  private:
120   QuicheUniqueBufferPtr buffer_;
121   size_t size_;
122 };
123 
124 }  // namespace quiche
125 
126 #endif  // QUICHE_COMMON_QUICHE_BUFFER_ALLOCATOR_H_
127