blob: 03ed18999eda605f63e537304cf6d2aaff72e526 [file] [log] [blame]
#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_