xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/balsa/simple_buffer.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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