commit dd9a0a974fdbff71185094ef93890dde5427adcc Author: flamingcow Date: Sat May 4 23:21:11 2019 -0700 Building diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9eca6c8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.a +*.o diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..e99441e --- /dev/null +++ b/Makefile @@ -0,0 +1,15 @@ +FIRE_CXX ?= clang++ +FIRE_CXXFLAGS ?= -O3 -std=gnu++2a -Wall -Werror + +all: firebuf.a + +objects = stream_buffer.o buffer.o + +firebuf.a: $(objects) + ar rcs $@ $^ + +%.o: %.cc *.h Makefile + $(FIRE_CXX) $(FIRE_CXXFLAGS) -c -o $@ $< + +clean: + rm --force firebuf.a *.o diff --git a/buffer.cc b/buffer.cc new file mode 100644 index 0000000..96f3ca6 --- /dev/null +++ b/buffer.cc @@ -0,0 +1,83 @@ +#include "buffer.h" + +namespace firebuf { + +ConstBuffer::ConstBuffer(const char *buf, size_t len) + : const_buf_(buf), + len_(len) {} + +size_t ConstBuffer::ReadMaxLen() const { + return len_ - start_; +} + +const char *ConstBuffer::Read(size_t len) { + if (ReadMaxLen() < len) { + return nullptr; + } + const auto *ret = &const_buf_[start_]; + start_ += len; + return ret; +} + +bool ConstBuffer::Discard(size_t len) { + if (len > ReadMaxLen()) { + return false; + } + static_cast(Read(len)); + return true; +} + +void ConstBuffer::ResetRead() { + start_ = commit_; +} + +void ConstBuffer::Commit() { + commit_ = start_; +} + + +Buffer::Buffer(char *buf, size_t size, size_t len) + : ConstBuffer(buf, size), + buf_(buf), + size_(size) { + len_ = len; +} + +Buffer::Buffer(size_t size) + : Buffer(new char[size], size, 0) { + own_buf_.reset(buf_); +} + +char *Buffer::WritePtr() { + return &buf_[len_]; +} + +size_t Buffer::WriteMaxLen() const { + return size_ - len_; +} + +bool Buffer::Write(const std::string_view& str) { + if (WriteMaxLen() < str.size()) { + return false; + } + memcpy(WritePtr(), str.data(), str.size()); + Wrote(str.size()); + return true; +} + +void Buffer::Wrote(size_t len) { + CHECK_LE(len, WriteMaxLen()); + len_ += len; +} + +void Buffer::Consume() { + if (commit_ == 0) { + return; + } + memmove(buf_, &buf_[commit_], len_ - commit_); + len_ -= commit_; + start_ -= commit_; + commit_ = 0; +} + +} // namespace firebuf diff --git a/buffer.h b/buffer.h new file mode 100644 index 0000000..c3cab8a --- /dev/null +++ b/buffer.h @@ -0,0 +1,53 @@ +#pragma once + +#include +#include +#include + +namespace firebuf { + +class ConstBuffer { + public: + ConstBuffer(const char *buf, size_t len); + + [[nodiscard]] size_t ReadMaxLen() const; + [[nodiscard]] virtual const char *Read(size_t len); + template [[nodiscard]] const T *ReadObj(); + + bool Discard(size_t len); // like Read() but don't use the result + void ResetRead(); // next read from last commit + void Commit(); // commit read position + + protected: + const char *const_buf_; + size_t len_; + size_t start_ = 0; + size_t commit_ = 0; +}; + +class Buffer : public ConstBuffer { + public: + Buffer(char *buf, size_t size, size_t len); + Buffer(size_t size); + + [[nodiscard]] char *WritePtr(); + [[nodiscard]] size_t WriteMaxLen() const; + bool Write(const std::string_view& str); + void Wrote(size_t len); + + void Consume(); // discard up to last commit + + protected: + std::unique_ptr own_buf_; + char *buf_; + const size_t size_; +}; + +template const T *ConstBuffer::ReadObj() { + if (ReadMaxLen() < sizeof(T)) { + return nullptr; + } + return reinterpret_cast(Read(sizeof(T))); +} + +} // namespace firebuf diff --git a/stream_buffer.cc b/stream_buffer.cc new file mode 100644 index 0000000..606d199 --- /dev/null +++ b/stream_buffer.cc @@ -0,0 +1,18 @@ +#include "stream_buffer.h" + +namespace firebuf { + +StreamBuffer::StreamBuffer(int sock, size_t size) + : Buffer(size), + sock_(sock) {} + +bool StreamBuffer::Refill() { + auto read_len = read(sock_, WritePtr(), WriteMaxLen()); + if (read_len == 0) { + return false; + } + Wrote(read_len); + return true; +} + +} // namespace firebuf diff --git a/stream_buffer.h b/stream_buffer.h new file mode 100644 index 0000000..bc68187 --- /dev/null +++ b/stream_buffer.h @@ -0,0 +1,17 @@ +#pragma once + +#include "buffer.h" + +namespace firebuf { + +class StreamBuffer : public Buffer { + public: + StreamBuffer(int sock, size_t size); + + [[nodiscard]] bool Refill(); + + private: + int sock_; +}; + +} // namespace firebuf