| #ifndef QUICHE_HTTP2_ADAPTER_CHUNKED_BUFFER_H_ | 
 | #define QUICHE_HTTP2_ADAPTER_CHUNKED_BUFFER_H_ | 
 |  | 
 | #include <memory> | 
 | #include <vector> | 
 |  | 
 | #include "absl/strings/string_view.h" | 
 | #include "quiche/common/platform/api/quiche_export.h" | 
 | #include "quiche/common/quiche_circular_deque.h" | 
 |  | 
 | namespace http2 { | 
 | namespace adapter { | 
 |  | 
 | // A simple buffer class that organizes its memory as a queue of contiguous | 
 | // regions. Data is written to the end, and read from the beginning. | 
 | class QUICHE_EXPORT ChunkedBuffer { | 
 |  public: | 
 |   ChunkedBuffer() = default; | 
 |  | 
 |   // Appends data to the buffer. | 
 |   void Append(absl::string_view data); | 
 |   void Append(std::unique_ptr<char[]> data, size_t size); | 
 |  | 
 |   // Reads data from the buffer non-destructively. | 
 |   absl::string_view GetPrefix() const; | 
 |   std::vector<absl::string_view> Read() const; | 
 |  | 
 |   // Removes the first `n` bytes of the buffer. Invalidates any `string_view`s | 
 |   // read from the buffer. | 
 |   void RemovePrefix(size_t n); | 
 |  | 
 |   // Returns true iff the buffer contains no data to read. | 
 |   bool Empty() const; | 
 |  | 
 |  private: | 
 |   static constexpr size_t kDefaultChunkSize = 1024; | 
 |  | 
 |   // Describes a contiguous region of memory contained in the ChunkedBuffer. In | 
 |   // the common case, data is appended to the buffer by copying it to the final | 
 |   // chunk, or adding a unique_ptr to the list of chunks. Data is consumed from | 
 |   // the beginning of the buffer, so the first chunk may have a nonzero offset | 
 |   // from the start of the memory region to the first byte of readable data. | 
 |   struct Chunk { | 
 |     // A contiguous region of memory. | 
 |     std::unique_ptr<char[]> data; | 
 |     // The size of the contiguous memory. | 
 |     const size_t size; | 
 |     // The region occupied by live data that can be read from the buffer. A | 
 |     // subset of `data`. | 
 |     absl::string_view live; | 
 |  | 
 |     void RemovePrefix(size_t n); | 
 |     void AppendSuffix(absl::string_view to_append); | 
 |  | 
 |     bool Empty() const { return live.empty(); } | 
 |  | 
 |     // Returns the offset of the live data from the beginning of the chunk. | 
 |     size_t LiveDataOffset() const { return live.data() - data.get(); } | 
 |     // Returns the size of the free space at the end of the chunk. | 
 |     size_t TailBytesFree() const { | 
 |       return size - live.size() - LiveDataOffset(); | 
 |     } | 
 |   }; | 
 |  | 
 |   // Returns the number of tail bytes free in the last chunk in the buffer, or | 
 |   // zero. | 
 |   size_t TailBytesFree() const; | 
 |  | 
 |   // Ensures that the last chunk in the buffer has at least this many tail bytes | 
 |   // free. | 
 |   void EnsureTailBytesFree(size_t n); | 
 |  | 
 |   // Removes the first chunk, unless it is the last chunk in the buffer and its | 
 |   // size is kDefaultChunkSize. | 
 |   void TrimFirstChunk(); | 
 |  | 
 |   quiche::QuicheCircularDeque<Chunk> chunks_; | 
 | }; | 
 |  | 
 | }  // namespace adapter | 
 | }  // namespace http2 | 
 |  | 
 | #endif  // QUICHE_HTTP2_ADAPTER_CHUNKED_BUFFER_H_ |