summaryrefslogtreecommitdiff
path: root/src/str_buffer.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/str_buffer.cc')
-rw-r--r--src/str_buffer.cc92
1 files changed, 92 insertions, 0 deletions
diff --git a/src/str_buffer.cc b/src/str_buffer.cc
new file mode 100644
index 0000000..6771cad
--- /dev/null
+++ b/src/str_buffer.cc
@@ -0,0 +1,92 @@
+#include "common.hh"
+
+#include "str_buffer.hh"
+
+#include <utility>
+
+namespace {
+
+template<typename T>
+class StringBuffer : public RoBuffer {
+public:
+ explicit StringBuffer(T str)
+ : str_(std::move(str)), offset_(0) {}
+
+ bool empty() const override {
+ return offset_ >= str_.size();
+ }
+
+ char const* rbuf(size_t /* want */, size_t& avail) override {
+ avail = str_.size() - offset_;
+ return str_.data() + offset_;
+ }
+
+ void rcommit(size_t bytes) override {
+ assert(str_.size() - offset_ >= bytes);
+ offset_ += bytes;
+ }
+
+private:
+ T str_;
+ size_t offset_;
+};
+
+class SharedStringBuffer : public Buffer {
+public:
+ explicit SharedStringBuffer(std::shared_ptr<std::string> content)
+ : content_(std::move(content)), read_ptr_(0), write_ptr_(content_->size()) {
+ }
+
+ bool empty() const override {
+ return read_ptr_ >= content_->size();
+ }
+
+ char const* rbuf(size_t /* want */, size_t& avail) override {
+ avail = content_->size() - read_ptr_;
+ return content_->data() + read_ptr_;
+ }
+
+ void rcommit(size_t bytes) override {
+ assert(content_->size() - read_ptr_ >= bytes);
+ read_ptr_ += bytes;
+ }
+
+ bool full() const override {
+ return false;
+ }
+
+ void clear() override {
+ content_->clear();
+ read_ptr_ = write_ptr_ = 0;
+ }
+
+ char* wbuf(size_t request, size_t& avail) override {
+ avail = request;
+ content_->resize(write_ptr_ + request);
+ return content_->data() + write_ptr_;
+ }
+
+ void wcommit(size_t bytes) override {
+ assert(content_->size() - write_ptr_ >= bytes);
+ write_ptr_ += bytes;
+ }
+
+private:
+ std::shared_ptr<std::string> content_;
+ size_t read_ptr_;
+ size_t write_ptr_;
+};
+
+} // namespace
+
+std::unique_ptr<RoBuffer> make_strbuffer(std::string content) {
+ return std::make_unique<StringBuffer<std::string>>(std::move(content));
+}
+
+std::unique_ptr<RoBuffer> make_strbuffer(std::string_view content) {
+ return std::make_unique<StringBuffer<std::string_view>>(content);
+}
+
+std::unique_ptr<Buffer> make_strbuffer(std::shared_ptr<std::string> content) {
+ return std::make_unique<SharedStringBuffer>(std::move(content));
+}