| #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_ |