| // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #ifndef QUICHE_COMMON_QUICHE_BUFFER_ALLOCATOR_H_ | 
 | #define QUICHE_COMMON_QUICHE_BUFFER_ALLOCATOR_H_ | 
 |  | 
 | #include <stddef.h> | 
 |  | 
 | #include <memory> | 
 |  | 
 | #include "absl/strings/string_view.h" | 
 | #include "common/platform/api/quiche_export.h" | 
 | #include "common/platform/api/quiche_iovec.h" | 
 |  | 
 | namespace quiche { | 
 |  | 
 | // Abstract base class for classes which allocate and delete buffers. | 
 | class QUICHE_EXPORT_PRIVATE QuicheBufferAllocator { | 
 |  public: | 
 |   virtual ~QuicheBufferAllocator() = default; | 
 |  | 
 |   // Returns or allocates a new buffer of |size|. Never returns null. | 
 |   virtual char* New(size_t size) = 0; | 
 |  | 
 |   // Returns or allocates a new buffer of |size| if |flag_enable| is true. | 
 |   // Otherwise, returns a buffer that is compatible with this class directly | 
 |   // with operator new. Never returns null. | 
 |   virtual char* New(size_t size, bool flag_enable) = 0; | 
 |  | 
 |   // Releases a buffer. | 
 |   virtual void Delete(char* buffer) = 0; | 
 |  | 
 |   // Marks the allocator as being idle. Serves as a hint to notify the allocator | 
 |   // that it should release any resources it's still holding on to. | 
 |   virtual void MarkAllocatorIdle() {} | 
 | }; | 
 |  | 
 | // A deleter that can be used to manage ownership of buffers allocated via | 
 | // QuicheBufferAllocator through std::unique_ptr. | 
 | class QUICHE_EXPORT_PRIVATE QuicheBufferDeleter { | 
 |  public: | 
 |   explicit QuicheBufferDeleter(QuicheBufferAllocator* allocator) | 
 |       : allocator_(allocator) {} | 
 |  | 
 |   QuicheBufferAllocator* allocator() { return allocator_; } | 
 |   void operator()(char* buffer) { allocator_->Delete(buffer); } | 
 |  | 
 |  private: | 
 |   QuicheBufferAllocator* allocator_; | 
 | }; | 
 |  | 
 | using QuicheUniqueBufferPtr = std::unique_ptr<char[], QuicheBufferDeleter>; | 
 |  | 
 | inline QuicheUniqueBufferPtr MakeUniqueBuffer(QuicheBufferAllocator* allocator, | 
 |                                               size_t size) { | 
 |   return QuicheUniqueBufferPtr(allocator->New(size), | 
 |                                QuicheBufferDeleter(allocator)); | 
 | } | 
 |  | 
 | // QuicheUniqueBufferPtr with a length attached to it.  Similar to | 
 | // QuicheMemSlice, except unlike QuicheMemSlice, QuicheBuffer is mutable and is | 
 | // not platform-specific.  Also unlike QuicheMemSlice, QuicheBuffer can be | 
 | // empty. | 
 | class QUICHE_EXPORT_PRIVATE QuicheBuffer { | 
 |  public: | 
 |   QuicheBuffer() : buffer_(nullptr, QuicheBufferDeleter(nullptr)), size_(0) {} | 
 |   QuicheBuffer(QuicheBufferAllocator* allocator, size_t size) | 
 |       : buffer_(MakeUniqueBuffer(allocator, size)), size_(size) {} | 
 |  | 
 |   QuicheBuffer(QuicheUniqueBufferPtr buffer, size_t size) | 
 |       : buffer_(std::move(buffer)), size_(size) {} | 
 |  | 
 |   // Make sure the move constructor zeroes out the size field. | 
 |   QuicheBuffer(QuicheBuffer&& other) | 
 |       : buffer_(std::move(other.buffer_)), size_(other.size_) { | 
 |     other.buffer_ = nullptr; | 
 |     other.size_ = 0; | 
 |   } | 
 |   QuicheBuffer& operator=(QuicheBuffer&& other) { | 
 |     buffer_ = std::move(other.buffer_); | 
 |     size_ = other.size_; | 
 |  | 
 |     other.buffer_ = nullptr; | 
 |     other.size_ = 0; | 
 |     return *this; | 
 |   } | 
 |  | 
 |   // Factory method to create a QuicheBuffer that holds a copy of `data`. | 
 |   static QuicheBuffer Copy(QuicheBufferAllocator* allocator, | 
 |                            absl::string_view data) { | 
 |     QuicheBuffer buffer(allocator, data.size()); | 
 |     memcpy(buffer.data(), data.data(), data.size()); | 
 |     return buffer; | 
 |   } | 
 |  | 
 |   // Factory method to create a QuicheBuffer of length `buffer_length` that | 
 |   // holds a copy of `buffer_length` bytes from `iov` starting at offset | 
 |   // `iov_offset`.  `iov` must be at least `iov_offset + buffer_length` total | 
 |   // length. | 
 |   static QuicheBuffer CopyFromIovec(QuicheBufferAllocator* allocator, | 
 |                                     const struct iovec* iov, int iov_count, | 
 |                                     size_t iov_offset, size_t buffer_length); | 
 |  | 
 |   const char* data() const { return buffer_.get(); } | 
 |   char* data() { return buffer_.get(); } | 
 |   size_t size() const { return size_; } | 
 |   bool empty() const { return size_ == 0; } | 
 |   absl::string_view AsStringView() const { | 
 |     return absl::string_view(data(), size()); | 
 |   } | 
 |  | 
 |   // Releases the ownership of the underlying buffer. | 
 |   QuicheUniqueBufferPtr Release() { | 
 |     size_ = 0; | 
 |     return std::move(buffer_); | 
 |   } | 
 |  | 
 |  private: | 
 |   QuicheUniqueBufferPtr buffer_; | 
 |   size_t size_; | 
 | }; | 
 |  | 
 | }  // namespace quiche | 
 |  | 
 | #endif  // QUICHE_COMMON_QUICHE_BUFFER_ALLOCATOR_H_ |