| // Copyright 2022 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_BALSA_SIMPLE_BUFFER_H_ | |
| #define QUICHE_BALSA_SIMPLE_BUFFER_H_ | |
| #include "absl/strings/string_view.h" | |
| #include "quiche/common/platform/api/quiche_export.h" | |
| #include "quiche/common/platform/api/quiche_mem_slice.h" | |
| namespace quiche { | |
| namespace test { | |
| class SimpleBufferTest; | |
| } // namespace test | |
| // SimpleBuffer stores data in a contiguous region. It can grow on demand, | |
| // which involves moving its data. It keeps track of a read and a write | |
| // position. Reading consumes data. | |
| class QUICHE_EXPORT_PRIVATE SimpleBuffer { | |
| public: | |
| SimpleBuffer() = default; | |
| // Create SimpleBuffer with at least `size` reserved capacity. | |
| explicit SimpleBuffer(int size); | |
| SimpleBuffer(const SimpleBuffer&) = delete; | |
| SimpleBuffer& operator=(const SimpleBuffer&) = delete; | |
| virtual ~SimpleBuffer() { delete[] storage_; } | |
| // Returns the number of bytes that can be read from the buffer. | |
| int ReadableBytes() const { return write_idx_ - read_idx_; } | |
| bool Empty() const { return read_idx_ == write_idx_; } | |
| // Copies `size` bytes to the buffer. Returns size. | |
| int Write(const char* bytes, int size); | |
| int WriteString(absl::string_view piece) { | |
| return Write(piece.data(), piece.size()); | |
| } | |
| // Stores the pointer into the buffer that can be written to in `*ptr`, and | |
| // the number of characters that are allowed to be written in `*size`. The | |
| // pointer and size can be used in functions like recv() or read(). If | |
| // `*size` is zero upon returning from this function, then it is unsafe to | |
| // dereference `*ptr`. Writing to this region after calling any other | |
| // non-const method results in undefined behavior. | |
| void GetWritablePtr(char** ptr, int* size) const { | |
| *ptr = storage_ + write_idx_; | |
| *size = storage_size_ - write_idx_; | |
| } | |
| // Stores the pointer that can be read from in `*ptr`, and the number of bytes | |
| // that are allowed to be read in `*size`. The pointer and size can be used | |
| // in functions like send() or write(). If `*size` is zero upon returning | |
| // from this function, then it is unsafe to dereference `*ptr`. Reading from | |
| // this region after calling any other non-const method results in undefined | |
| // behavior. | |
| void GetReadablePtr(char** ptr, int* size) const { | |
| *ptr = storage_ + read_idx_; | |
| *size = write_idx_ - read_idx_; | |
| } | |
| // Returns the readable region as a string_view. Reading from this region | |
| // after calling any other non-const method results in undefined behavior. | |
| absl::string_view GetReadableRegion() const { | |
| return absl::string_view(storage_ + read_idx_, write_idx_ - read_idx_); | |
| } | |
| // Reads bytes out of the buffer, and writes them into `bytes`. Returns the | |
| // number of bytes read. Consumes bytes from the buffer. | |
| int Read(char* bytes, int size); | |
| // Marks all data consumed, making the entire reserved buffer available for | |
| // write. Does not resize or free up any memory. | |
| void Clear() { read_idx_ = write_idx_ = 0; } | |
| // Makes sure at least `size` bytes can be written into the buffer. This can | |
| // be an expensive operation: costing a new and a delete, and copying of all | |
| // existing data. Even if the existing buffer does not need to be resized, | |
| // unread data may need to be moved to consolidate fragmented free space. | |
| void Reserve(int size); | |
| // Marks the oldest `amount_to_advance` bytes as consumed. | |
| // `amount_to_advance` must not be negative and it must not exceed | |
| // ReadableBytes(). | |
| void AdvanceReadablePtr(int amount_to_advance); | |
| // Marks the first `amount_to_advance` bytes of the writable area written. | |
| // `amount_to_advance` must not be negative and it must not exceed the size of | |
| // the writable area, returned as the `size` outparam of GetWritablePtr(). | |
| void AdvanceWritablePtr(int amount_to_advance); | |
| // Releases the current contents of the SimpleBuffer and returns them as a | |
| // MemSlice. Logically, has the same effect as calling Clear(). | |
| QuicheMemSlice ReleaseAsSlice(); | |
| private: | |
| friend class test::SimpleBufferTest; | |
| // The buffer owned by this class starts at `*storage_` and is `storage_size_` | |
| // bytes long. | |
| // If `storage_` is nullptr, then `storage_size_` must be zero. | |
| // `0 <= read_idx_ <= write_idx_ <= storage_size_` must always hold. | |
| // If `read_idx_ == write_idx_`, then they must be equal to zero. | |
| // The first `read_idx_` bytes of the buffer are consumed, | |
| // the next `write_idx_ - read_idx_` bytes are the readable region, and the | |
| // remaining `storage_size_ - write_idx_` bytes are the writable region. | |
| char* storage_ = nullptr; | |
| int write_idx_ = 0; | |
| int read_idx_ = 0; | |
| int storage_size_ = 0; | |
| }; | |
| } // namespace quiche | |
| #endif // QUICHE_BALSA_SIMPLE_BUFFER_H_ |