diff --git a/include/ircd/buffer.h b/include/ircd/buffer.h index 7d3af70a0..18ab0f2e9 100644 --- a/include/ircd/buffer.h +++ b/include/ircd/buffer.h @@ -110,7 +110,8 @@ template struct ircd::buffer::buffer :std::tuple { - using value_type = it; + using iterator = it; + using value_type = typename std::remove_pointer::type; operator string_view() const; operator std::string_view() const; @@ -140,72 +141,122 @@ struct ircd::buffer::buffer {} template - buffer(typename std::remove_pointer::type (&buf)[SIZE]) + buffer(value_type (&buf)[SIZE]) :buffer{buf, SIZE} {} + template + buffer(std::array &buf) + :buffer{buf.data(), SIZE} + {} + buffer() :buffer{nullptr, nullptr} {} }; -struct ircd::buffer::mutable_buffer -:buffer +namespace ircd::buffer { + template struct mutable_buffer_base; +} + +template +struct ircd::buffer::mutable_buffer_base +:buffer +{ + using iterator = typename buffer::iterator; + using value_type = typename buffer::value_type; + + // Allows boost::spirit to append to the buffer; this means the size() of + // this buffer becomes a consumption counter and the real size of the buffer + // must be kept separately. This is the lowlevel basis for a stream buffer. + void insert(const iterator &it, const value_type &v) + { + assert(it >= this->begin() && it <= this->end()); + memmove(it + 1, it, std::distance(it, this->end())); + *it = v; + ++std::get<1>(*this); + } + + using buffer::buffer; + + // lvalue string reference offered to write through to a std::string as + // the buffer. not explicit; should be hard to bind by accident... + mutable_buffer_base(std::string &buf) + :mutable_buffer_base{const_cast(buf.data()), buf.size()} + {} +}; + +struct ircd::buffer::mutable_buffer +:mutable_buffer_base +{ + // Conversion offered for the analogous asio buffer operator boost::asio::mutable_buffer() const; - using buffer::buffer; + using mutable_buffer_base::mutable_buffer_base; }; struct ircd::buffer::mutable_raw_buffer -:buffer +:mutable_buffer_base { + // Conversion offered for the analogous asio buffer operator boost::asio::mutable_buffer() const; - using buffer::buffer; + using mutable_buffer_base::mutable_buffer_base; mutable_raw_buffer(const mutable_buffer &b) - :buffer{reinterpret_cast(data(b)), size(b)} + :mutable_buffer_base{reinterpret_cast(data(b)), size(b)} + {} +}; + +namespace ircd::buffer +{ + template struct const_buffer_base; +} + +template +struct ircd::buffer::const_buffer_base +:buffer +{ + using iterator = typename buffer::iterator; + using value_type = typename buffer::value_type; + + using buffer::buffer; + + const_buffer_base(const mutable_buffer &b) + :buffer{data(b), size(b)} + {} + + const_buffer_base(const string_view &s) + :buffer{std::begin(s), std::end(s)} + {} + + explicit const_buffer_base(const std::string &s) + :buffer{s.data(), s.size()} {} }; struct ircd::buffer::const_buffer -:buffer +:const_buffer_base { operator boost::asio::const_buffer() const; - using buffer::buffer; - - const_buffer(const mutable_buffer &b) - :buffer{data(b), size(b)} - {} - - const_buffer(const string_view &s) - :buffer{std::begin(s), std::end(s)} - {} - - explicit const_buffer(const std::string &s) - :buffer{s.data(), s.size()} - {} + using const_buffer_base::const_buffer_base; }; struct ircd::buffer::const_raw_buffer -:buffer +:const_buffer_base { operator boost::asio::const_buffer() const; - using buffer::buffer; + using const_buffer_base::const_buffer_base; const_raw_buffer(const const_buffer &b) - :buffer{reinterpret_cast(data(b)), size(b)} + :const_buffer_base{reinterpret_cast(data(b)), size(b)} {} const_raw_buffer(const mutable_raw_buffer &b) - :buffer{data(b), size(b)} - {} - - const_raw_buffer(const mutable_buffer &b) - :const_raw_buffer{mutable_raw_buffer{b}} + :const_buffer_base{reinterpret_cast(data(b)), size(b)} {} }; @@ -231,7 +282,7 @@ ircd::buffer::unique_buffer::unique_buffer(std::unique_ptr &b, for(auto it(std::begin(b)); it != std::end(b) && remain > 0; ++it) { using buffer = typename buffers::value_type; - using iterator = typename buffer::value_type; + using iterator = typename buffer::iterator; buffer &b(const_cast(*it)); remain -= consume(b, remain);