#ifndef REMOTING_BASE_COMPOUND_BUFFER_H_
#define REMOTING_BASE_COMPOUND_BUFFER_H_
#include <stddef.h>
#include <stdint.h>
#include "base/containers/circular_deque.h"
#include "base/containers/span.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/raw_span.h"
#include "base/memory/scoped_refptr.h"
#include "google/protobuf/io/zero_copy_stream.h"
namespace net {
class IOBuffer;
class IOBufferWithSize;
}
namespace remoting {
class CompoundBuffer {
public:
CompoundBuffer();
CompoundBuffer(const CompoundBuffer&) = delete;
CompoundBuffer& operator=(const CompoundBuffer&) = delete;
~CompoundBuffer();
void Clear();
void Append(scoped_refptr<net::IOBuffer> buffer, size_t size);
void Append(scoped_refptr<net::IOBuffer> buffer,
base::span<const uint8_t> data);
void Append(const CompoundBuffer& buffer);
void Prepend(scoped_refptr<net::IOBuffer> buffer, size_t size);
void Prepend(scoped_refptr<net::IOBuffer> buffer,
base::span<const uint8_t> data);
void Prepend(const CompoundBuffer& buffer);
void AppendCopyOf(base::span<const uint8_t> data);
void PrependCopyOf(base::span<const uint8_t> data);
void CropFront(size_t bytes);
void CropBack(size_t bytes);
size_t total_bytes() const { return total_bytes_; }
void Lock();
bool locked() const { return locked_; }
scoped_refptr<net::IOBufferWithSize> ToIOBufferWithSize() const;
void CopyTo(base::span<uint8_t> data) const;
void CopyFrom(const CompoundBuffer& source, size_t start, size_t end);
private:
friend class CompoundBufferInputStream;
struct DataChunk {
DataChunk(scoped_refptr<net::IOBuffer> buffer,
base::span<const uint8_t> data);
DataChunk(const DataChunk& other);
~DataChunk();
scoped_refptr<net::IOBuffer> buffer;
base::raw_span<const uint8_t> data;
};
using DataChunkList = base::circular_deque<DataChunk>;
DataChunkList chunks_;
size_t total_bytes_ = 0;
bool locked_ = false;
};
class CompoundBufferInputStream
: public google::protobuf::io::ZeroCopyInputStream {
public:
explicit CompoundBufferInputStream(const CompoundBuffer* buffer);
~CompoundBufferInputStream() override;
size_t position() const { return position_; }
bool Next(const void** data, int* size) override;
void BackUp(int count) override;
bool Skip(int count) override;
int64_t ByteCount() const override;
private:
raw_ptr<const CompoundBuffer> buffer_;
size_t current_chunk_ = 0;
size_t current_chunk_position_ = 0;
size_t position_ = 0;
size_t last_returned_size_ = 0;
};
}
#endif