#include #include #include #include #include #include "util/Buffer.hpp" class memory_buffer : public std::streambuf { public: explicit memory_buffer(size_t initial_size = 64) : buffer(std::make_unique(initial_size)), capacity(initial_size) { setp(buffer.get(), buffer.get() + initial_size); } std::string_view view() const { return std::string_view(pbase(), pptr() - pbase()); } util::Buffer release() { return {std::move(buffer), size()}; } size_t size() const { return pptr() - pbase(); } protected: int_type overflow(int_type c) override { if (c == traits_type::eof()) return traits_type::eof(); const size_t data_size = pptr() - pbase(); const size_t new_capacity = std::max(capacity * 2, data_size + 1); auto new_buffer = std::make_unique(new_capacity); std::memcpy(new_buffer.get(), pbase(), data_size); buffer = std::move(new_buffer); capacity = new_capacity; setp(buffer.get(), buffer.get() + new_capacity); pbump(data_size); *pptr() = traits_type::to_char_type(c); pbump(1); return c; } std::streamsize xsputn(const char* s, std::streamsize count) override { const std::streamsize avail = epptr() - pptr(); if (avail >= count) { std::memcpy(pptr(), s, count); pbump(count); return count; } std::streamsize written = 0; if (avail > 0) { std::memcpy(pptr(), s, avail); written += avail; s += avail; count -= avail; pbump(avail); } const size_t data_size = pptr() - pbase(); const size_t required_capacity = data_size + count; const size_t new_capacity = std::max(capacity * 2, required_capacity); auto new_buffer = std::make_unique(new_capacity); std::memcpy(new_buffer.get(), pbase(), data_size); std::memcpy(new_buffer.get() + data_size, s, count); buffer = std::move(new_buffer); capacity = new_capacity; setp(buffer.get(), buffer.get() + new_capacity); pbump(data_size + count); written += count; return written; } private: std::unique_ptr buffer; size_t capacity; }; class memory_ostream : public std::ostream { public: explicit memory_ostream(size_t initialCapacity = 64) : std::ostream(&buffer), buffer(initialCapacity) {} std::string_view view() const { return buffer.view(); } util::Buffer release() { return buffer.release(); } private: memory_buffer buffer; };