Internal change
PiperOrigin-RevId: 442098384
diff --git a/quiche/common/balsa/simple_buffer.h b/quiche/common/balsa/simple_buffer.h
new file mode 100644
index 0000000..52f3400
--- /dev/null
+++ b/quiche/common/balsa/simple_buffer.h
@@ -0,0 +1,116 @@
+// 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_COMMON_BALSA_SIMPLE_BUFFER_H_
+#define QUICHE_COMMON_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();
+ // Create SimpleBuffer with `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());
+ }
+
+ // Gets a pointer into the buffer that can be written to. Stores the number
+ // of characters which 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_;
+ }
+
+ // Gets a pointer that can be read from. This 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.
+ // `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_;
+ int write_idx_;
+ int read_idx_;
+ int storage_size_;
+};
+
+} // namespace quiche
+
+#endif // QUICHE_COMMON_BALSA_SIMPLE_BUFFER_H_