1 // Copyright 2022 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_BALSA_SIMPLE_BUFFER_H_ 6 #define QUICHE_BALSA_SIMPLE_BUFFER_H_ 7 8 #include <cstddef> 9 #include <memory> 10 11 #include "absl/strings/string_view.h" 12 #include "quiche/common/platform/api/quiche_export.h" 13 14 namespace quiche { 15 16 namespace test { 17 class SimpleBufferTest; 18 } // namespace test 19 20 // SimpleBuffer stores data in a contiguous region. It can grow on demand, 21 // which involves moving its data. It keeps track of a read and a write 22 // position. Reading consumes data. 23 class QUICHE_EXPORT SimpleBuffer { 24 public: 25 struct ReleasedBuffer { 26 std::unique_ptr<char[]> buffer; 27 size_t size; 28 }; 29 30 SimpleBuffer() = default; 31 // Create SimpleBuffer with at least `size` reserved capacity. 32 explicit SimpleBuffer(int size); 33 34 SimpleBuffer(const SimpleBuffer&) = delete; 35 SimpleBuffer& operator=(const SimpleBuffer&) = delete; 36 ~SimpleBuffer()37 virtual ~SimpleBuffer() { delete[] storage_; } 38 39 // Returns the number of bytes that can be read from the buffer. ReadableBytes()40 int ReadableBytes() const { return write_idx_ - read_idx_; } 41 Empty()42 bool Empty() const { return read_idx_ == write_idx_; } 43 44 // Copies `size` bytes to the buffer. Returns size. 45 int Write(const char* bytes, int size); WriteString(absl::string_view piece)46 int WriteString(absl::string_view piece) { 47 return Write(piece.data(), piece.size()); 48 } 49 50 // Stores the pointer into the buffer that can be written to in `*ptr`, and 51 // the number of characters that are allowed to be written in `*size`. The 52 // pointer and size can be used in functions like recv() or read(). If 53 // `*size` is zero upon returning from this function, then it is unsafe to 54 // dereference `*ptr`. Writing to this region after calling any other 55 // non-const method results in undefined behavior. GetWritablePtr(char ** ptr,int * size)56 void GetWritablePtr(char** ptr, int* size) const { 57 *ptr = storage_ + write_idx_; 58 *size = storage_size_ - write_idx_; 59 } 60 61 // Stores the pointer that can be read from in `*ptr`, and the number of bytes 62 // that are allowed to be read in `*size`. The pointer and size can be used 63 // in functions like send() or write(). If `*size` is zero upon returning 64 // from this function, then it is unsafe to dereference `*ptr`. Reading from 65 // this region after calling any other non-const method results in undefined 66 // behavior. GetReadablePtr(char ** ptr,int * size)67 void GetReadablePtr(char** ptr, int* size) const { 68 *ptr = storage_ + read_idx_; 69 *size = write_idx_ - read_idx_; 70 } 71 72 // Returns the readable region as a string_view. Reading from this region 73 // after calling any other non-const method results in undefined behavior. GetReadableRegion()74 absl::string_view GetReadableRegion() const { 75 return absl::string_view(storage_ + read_idx_, write_idx_ - read_idx_); 76 } 77 78 // Reads bytes out of the buffer, and writes them into `bytes`. Returns the 79 // number of bytes read. Consumes bytes from the buffer. 80 int Read(char* bytes, int size); 81 82 // Marks all data consumed, making the entire reserved buffer available for 83 // write. Does not resize or free up any memory. Clear()84 void Clear() { read_idx_ = write_idx_ = 0; } 85 86 // Makes sure at least `size` bytes can be written into the buffer. This can 87 // be an expensive operation: costing a new and a delete, and copying of all 88 // existing data. Even if the existing buffer does not need to be resized, 89 // unread data may need to be moved to consolidate fragmented free space. 90 void Reserve(int size); 91 92 // Marks the oldest `amount_to_advance` bytes as consumed. 93 // `amount_to_advance` must not be negative and it must not exceed 94 // ReadableBytes(). 95 void AdvanceReadablePtr(int amount_to_advance); 96 97 // Marks the first `amount_to_advance` bytes of the writable area written. 98 // `amount_to_advance` must not be negative and it must not exceed the size of 99 // the writable area, returned as the `size` outparam of GetWritablePtr(). 100 void AdvanceWritablePtr(int amount_to_advance); 101 102 // Releases the current contents of the SimpleBuffer and returns them as a 103 // unique_ptr<char[]>. Logically, has the same effect as calling Clear(). 104 ReleasedBuffer Release(); 105 106 private: 107 friend class test::SimpleBufferTest; 108 109 // The buffer owned by this class starts at `*storage_` and is `storage_size_` 110 // bytes long. 111 // If `storage_` is nullptr, then `storage_size_` must be zero. 112 // `0 <= read_idx_ <= write_idx_ <= storage_size_` must always hold. 113 // If `read_idx_ == write_idx_`, then they must be equal to zero. 114 // The first `read_idx_` bytes of the buffer are consumed, 115 // the next `write_idx_ - read_idx_` bytes are the readable region, and the 116 // remaining `storage_size_ - write_idx_` bytes are the writable region. 117 char* storage_ = nullptr; 118 int write_idx_ = 0; 119 int read_idx_ = 0; 120 int storage_size_ = 0; 121 }; 122 123 } // namespace quiche 124 125 #endif // QUICHE_BALSA_SIMPLE_BUFFER_H_ 126