From ef7098e75fb132722a36ca19bebcf40830ae46cf Mon Sep 17 00:00:00 2001 From: Mohammad Nejati Date: Tue, 19 Mar 2024 14:16:56 +0000 Subject: [PATCH] Make `source` a nested type of `serializer` --- doc/qbk/3.0.concepts.qbk | 3 - doc/qbk/quickref.xml | 3 - include/boost/http_proto.hpp | 1 - include/boost/http_proto/file_body.hpp | 5 +- include/boost/http_proto/impl/serializer.hpp | 41 +++- include/boost/http_proto/impl/source.hpp | 77 ------- include/boost/http_proto/serializer.hpp | 173 ++++++++++++++- include/boost/http_proto/source.hpp | 206 ------------------ src/serializer.cpp | 44 +++- src/source.cpp | 42 ---- test/unit/Jamfile | 2 +- test/unit/serializer.cpp | 2 +- .../{source.cpp => serializer_source.cpp} | 10 +- 13 files changed, 260 insertions(+), 349 deletions(-) delete mode 100644 include/boost/http_proto/impl/source.hpp delete mode 100644 include/boost/http_proto/source.hpp delete mode 100644 src/source.cpp rename test/unit/{source.cpp => serializer_source.cpp} (93%) diff --git a/doc/qbk/3.0.concepts.qbk b/doc/qbk/3.0.concepts.qbk index 6894f692..a1f921fb 100644 --- a/doc/qbk/3.0.concepts.qbk +++ b/doc/qbk/3.0.concepts.qbk @@ -14,9 +14,6 @@ [section Sink] [endsect] -[section Source] -[endsect] - [section Filter] [endsect] diff --git a/doc/qbk/quickref.xml b/doc/qbk/quickref.xml index 763150f5..66f4b10d 100644 --- a/doc/qbk/quickref.xml +++ b/doc/qbk/quickref.xml @@ -50,7 +50,6 @@ serializer service sink - source string_body Functions @@ -72,7 +71,6 @@ Type Traits is_sink - is_source is_filter Constants @@ -96,7 +94,6 @@ Concepts Sink - Source Filter diff --git a/include/boost/http_proto.hpp b/include/boost/http_proto.hpp index e66fcfe2..8b90aa9b 100644 --- a/include/boost/http_proto.hpp +++ b/include/boost/http_proto.hpp @@ -39,7 +39,6 @@ #include #include #include -#include #include #include #include diff --git a/include/boost/http_proto/file_body.hpp b/include/boost/http_proto/file_body.hpp index 8eae7b3c..ba50aa0a 100644 --- a/include/boost/http_proto/file_body.hpp +++ b/include/boost/http_proto/file_body.hpp @@ -12,7 +12,7 @@ #include #include -#include +#include #include namespace boost { @@ -20,7 +20,7 @@ namespace http_proto { class BOOST_SYMBOL_VISIBLE file_body - : public source + : public serializer::source { file f_; std::uint64_t n_; @@ -44,6 +44,7 @@ class BOOST_SYMBOL_VISIBLE std::uint64_t size = std::uint64_t(-1)) noexcept; +private: BOOST_HTTP_PROTO_DECL results on_read( diff --git a/include/boost/http_proto/impl/serializer.hpp b/include/boost/http_proto/impl/serializer.hpp index d49d69e3..3e702283 100644 --- a/include/boost/http_proto/impl/serializer.hpp +++ b/include/boost/http_proto/impl/serializer.hpp @@ -12,9 +12,6 @@ #include #include -#include -#include -#include namespace boost { namespace http_proto { @@ -123,6 +120,44 @@ make_array(std::size_t n) -> n }; } +//------------------------------------------------ + +template +auto +serializer:: +source:: +read_impl( + T const& bs) -> + results +{ + results rv; + constexpr int SmallArraySize = 16; + buffers::mutable_buffer tmp[SmallArraySize]; + auto const tmp_end = + tmp + SmallArraySize; + auto it = buffers::begin(bs); + auto const end_ = buffers::end(bs); + while(it != end_) + { + auto p = tmp; + do + { + *p++ = *it++; + } + while( + p != tmp_end && + it != end_); + rv += on_read( + buffers::mutable_buffer_span( + tmp, p - tmp)); + if(rv.ec.failed()) + return rv; + if(rv.finished) + break; + } + return rv; +} + } // http_proto } // boost diff --git a/include/boost/http_proto/impl/source.hpp b/include/boost/http_proto/impl/source.hpp deleted file mode 100644 index d7f569c1..00000000 --- a/include/boost/http_proto/impl/source.hpp +++ /dev/null @@ -1,77 +0,0 @@ -// -// Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// -// Official repository: https://github.com/cppalliance/buffers -// - -#ifndef BOOST_BUFFERS_IMPL_SOURCE_HPP -#define BOOST_BUFFERS_IMPL_SOURCE_HPP - -#include -#include -#include -#include - -namespace boost { -namespace http_proto { - -inline -auto -source:: -results:: -operator+=( - results const& rv) noexcept -> - results& -{ - BOOST_ASSERT(! ec.failed()); - BOOST_ASSERT(! finished); - ec = rv.ec; - bytes += rv.bytes; - finished = rv.finished; - return *this; -} - -//------------------------------------------------ - -template -auto -source:: -read_impl( - T const& bs) -> - results -{ - results rv; - constexpr int SmallArraySize = 16; - buffers::mutable_buffer tmp[SmallArraySize]; - auto const tmp_end = - tmp + SmallArraySize; - auto it = buffers::begin(bs); - auto const end_ = buffers::end(bs); - while(it != end_) - { - auto p = tmp; - do - { - *p++ = *it++; - } - while( - p != tmp_end && - it != end_); - rv += on_read( - buffers::mutable_buffer_span( - tmp, p - tmp)); - if(rv.ec.failed()) - return rv; - if(rv.finished) - break; - } - return rv; -} - -} // http_proto -} // boost - -#endif diff --git a/include/boost/http_proto/serializer.hpp b/include/boost/http_proto/serializer.hpp index 5d4b643d..568b303d 100644 --- a/include/boost/http_proto/serializer.hpp +++ b/include/boost/http_proto/serializer.hpp @@ -10,16 +10,17 @@ #ifndef BOOST_HTTP_PROTO_SERIALIZER_HPP #define BOOST_HTTP_PROTO_SERIALIZER_HPP +#include #include -#include #include #include #include #include +#include +#include +#include #include #include -#include -#include #include namespace boost { @@ -47,6 +48,7 @@ class BOOST_SYMBOL_VISIBLE */ class const_buffers_type; + struct source; struct stream; /** Destructor @@ -133,7 +135,9 @@ class BOOST_SYMBOL_VISIBLE class Source #ifndef BOOST_HTTP_PROTO_DOCS ,class = typename std::enable_if< - is_source::value>::type + std::is_convertible< + typename std::decay::type*, + source*>::value>::type #endif > auto @@ -235,6 +239,167 @@ class BOOST_SYMBOL_VISIBLE //------------------------------------------------ +/** An algorithm for producing buffers of data. + + This interface abstracts the production of + a finite stream of data, returned by writing + into caller-provided buffers until there + is no more output data. + + @par Thread Safety + Non-const member functions may not be + called concurrently on the same instance. +*/ +struct BOOST_HTTP_PROTO_DECL + serializer::source + : buffered_base +{ + /** The results of producing data. + */ + struct results + { + /** The error, if any occurred. + */ + system::error_code ec; + + /** The number of bytes produced in the output. + */ + std::size_t bytes = 0; + + /** True if there will be no more output. + */ + bool finished = false; + + /** Accumulate results. + */ + results& + operator+=( + results const& rv) noexcept; + }; + + /** Produce data. + + This function attempts to read from the + source, placing the data into the given + mutable buffer sequence. + The return value indicates the number of + bytes placed into the buffers, the error + if any occurred, and a `bool` indicating + whether or not there is more data + remaining in the source. + + @par Preconditions + @li @ref init was called, and + @li There is more data remaining. + + @return The result of the operation. + + @param bs The buffers to use. + Each buffer in the sequence will + be filled completely before data + is placed in the next buffer. + */ + template + results + read(MutableBufferSequence const& bs) + { + static_assert( + buffers::is_mutable_buffer_sequence< + MutableBufferSequence>::value, + "Type requirements not met"); + + return read_impl(bs); + } + +#ifdef BOOST_HTTP_PROTO_DOCS +protected: +#else +private: +#endif + /** Derived class override. + + This pure virtual function is called by + the implementation and must be overriden. + The callee should attempt to place data + into the given mutable buffer. + The return value must be set to indicate + the number of bytes placed into the + buffers, the error if any occurred, + and a `bool` indicating whether or + not there is more data remaining + in the source. + + @par Preconditions + @li @ref init was called, and + @li There is more data remaining. + + @return The result of the operation. + + @param b The buffer to use. + If this is not filled completely, + then the result must indicate failure + or that no more data remains (or both). + */ + virtual + results + on_read( + buffers::mutable_buffer b) = 0; + + /** Derived class override. + + This pure virtual function is called by + the implementation and must be overriden. + The callee should attempt to place data + into the given mutable buffer sequence. + The return value must be set to indicate + the number of bytes placed into the + buffers, the error if any occurred, + and a `bool` indicating whether or + not there is more data remaining + in the source. + + @par Preconditions + @li @ref init was called, and + @li There is more data remaining. + + @return The result of the operation. + + @param bs The buffer sequence to use. + Each buffer in the sequence must + be filled completely before data + is placed in the next buffer. + If the buffers are not filled + completely, then the result must + indicate failure or that no more + data remains (or both). + */ + virtual + results + on_read( + buffers::mutable_buffer_span bs); + +private: + results + read_impl( + buffers::mutable_buffer const& b) + { + return on_read(b); + } + + results + read_impl( + buffers::mutable_buffer_span const& bs) + { + return on_read(bs); + } + + template + results + read_impl(T const&); +}; + +//------------------------------------------------ + struct serializer::stream { /** Constructor. diff --git a/include/boost/http_proto/source.hpp b/include/boost/http_proto/source.hpp deleted file mode 100644 index ff086df4..00000000 --- a/include/boost/http_proto/source.hpp +++ /dev/null @@ -1,206 +0,0 @@ -// -// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// -// Official repository: https://github.com/cppalliance/http_proto -// - -#ifndef BOOST_HTTP_PROTO_SOURCE_HPP -#define BOOST_HTTP_PROTO_SOURCE_HPP - -#include -#include -#include -#include -#include -#include -#include - -namespace boost { -namespace http_proto { - -/** An algorithm for producing buffers of data. - - This interface abstracts the production of - a finite stream of data, returned by writing - into caller-provided buffers until there - is no more output data. - - @par Thread Safety - Non-const member functions may not be - called concurrently on the same instance. -*/ -struct BOOST_HTTP_PROTO_DECL - source - : buffered_base -{ - /** The results of producing data. - */ - struct results - { - /** The error, if any occurred. - */ - system::error_code ec; - - /** The number of bytes produced in the output. - */ - std::size_t bytes = 0; - - /** True if there will be no more output. - */ - bool finished = false; - - /** Accumulate results. - */ - results& - operator+=( - results const& rv) noexcept; - }; - - /** Produce data. - - This function attempts to read from the - source, placing the data into the given - mutable buffer sequence. - The return value indicates the number of - bytes placed into the buffers, the error - if any occurred, and a `bool` indicating - whether or not there is more data - remaining in the source. - - @par Preconditions - @li @ref init was called, and - @li There is more data remaining. - - @return The result of the operation. - - @param bs The buffers to use. - Each buffer in the sequence will - be filled completely before data - is placed in the next buffer. - */ - template - results - read(MutableBufferSequence const& bs) - { - static_assert( - buffers::is_mutable_buffer_sequence< - MutableBufferSequence>::value, - "Type requirements not met"); - - return read_impl(bs); - } - -#ifdef BOOST_HTTP_PROTO_DOCS -protected: -#else -private: -#endif - /** Derived class override. - - This pure virtual function is called by - the implementation and must be overriden. - The callee should attempt to place data - into the given mutable buffer. - The return value must be set to indicate - the number of bytes placed into the - buffers, the error if any occurred, - and a `bool` indicating whether or - not there is more data remaining - in the source. - - @par Preconditions - @li @ref init was called, and - @li There is more data remaining. - - @return The result of the operation. - - @param b The buffer to use. - If this is not filled completely, - then the result must indicate failure - or that no more data remains (or both). - */ - virtual - results - on_read( - buffers::mutable_buffer b) = 0; - - /** Derived class override. - - This pure virtual function is called by - the implementation and must be overriden. - The callee should attempt to place data - into the given mutable buffer sequence. - The return value must be set to indicate - the number of bytes placed into the - buffers, the error if any occurred, - and a `bool` indicating whether or - not there is more data remaining - in the source. - - @par Preconditions - @li @ref init was called, and - @li There is more data remaining. - - @return The result of the operation. - - @param bs The buffer sequence to use. - Each buffer in the sequence must - be filled completely before data - is placed in the next buffer. - If the buffers are not filled - completely, then the result must - indicate failure or that no more - data remains (or both). - */ - virtual - results - on_read( - buffers::mutable_buffer_span bs); - -private: - results - read_impl( - buffers::mutable_buffer const& b) - { - return on_read(b); - } - - results - read_impl( - buffers::mutable_buffer_span const& bs) - { - return on_read(bs); - } - - template - results - read_impl(T const&); -}; - -//------------------------------------------------ - -/** Metafunction which determines if T is a source - - @see - @ref source. -*/ -#ifdef BOOST_HTTP_PROTO_DOCS -template -using is_source = __see_below__; -#else -template -using is_source = - std::is_convertible< - typename std::decay::type*, - source*>; -#endif - -} // http_proto -} // boost - -#include - -#endif diff --git a/src/serializer.cpp b/src/serializer.cpp index 65b00831..42de0b5d 100644 --- a/src/serializer.cpp +++ b/src/serializer.cpp @@ -14,7 +14,6 @@ #include #include #include -#include namespace boost { namespace http_proto { @@ -521,6 +520,49 @@ start_stream( //------------------------------------------------ +auto +serializer:: +source:: +results:: +operator+=( + results const& rv) noexcept -> + results& +{ + BOOST_ASSERT(! ec.failed()); + BOOST_ASSERT(! finished); + ec = rv.ec; + bytes += rv.bytes; + finished = rv.finished; + return *this; +} + +auto +serializer:: +source:: +on_read( + buffers::mutable_buffer_span bs) -> + results +{ + results rv; + auto it = bs.begin(); + auto const end_ = bs.end(); + if(it == end_) + return rv; + do + { + buffers::mutable_buffer b(*it++); + rv += on_read(b); + if(rv.ec.failed()) + return rv; + if(rv.finished) + break; + } + while(it != end_); + return rv; +} + +//------------------------------------------------ + std::size_t serializer:: stream:: diff --git a/src/source.cpp b/src/source.cpp deleted file mode 100644 index 235003ea..00000000 --- a/src/source.cpp +++ /dev/null @@ -1,42 +0,0 @@ -// -// Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// -// Official repository: https://github.com/cppalliance/buffers -// - -#include -#include -#include - -namespace boost { -namespace http_proto { - -auto -source:: -on_read( - buffers::mutable_buffer_span bs) -> - results -{ - results rv; - auto it = bs.begin(); - auto const end_ = bs.end(); - if(it == end_) - return rv; - do - { - buffers::mutable_buffer b(*it++); - rv += on_read(b); - if(rv.ec.failed()) - return rv; - if(rv.finished) - break; - } - while(it != end_); - return rv; -} - -} // http_proto -} // boost diff --git a/test/unit/Jamfile b/test/unit/Jamfile index c16a7830..6e191548 100644 --- a/test/unit/Jamfile +++ b/test/unit/Jamfile @@ -54,9 +54,9 @@ local SOURCES = response_parser.cpp response_view.cpp sandbox.cpp + serializer_source.cpp serializer.cpp sink.cpp - source.cpp status.cpp string_body.cpp test_helpers.cpp diff --git a/test/unit/serializer.cpp b/test/unit/serializer.cpp index 55d58799..2eb5f50e 100644 --- a/test/unit/serializer.cpp +++ b/test/unit/serializer.cpp @@ -31,7 +31,7 @@ namespace http_proto { struct serializer_test { - struct test_source : source + struct test_source : serializer::source { test_source(core::string_view s) : s_(s) diff --git a/test/unit/source.cpp b/test/unit/serializer_source.cpp similarity index 93% rename from test/unit/source.cpp rename to test/unit/serializer_source.cpp index 9185bf46..3dc9bd2f 100644 --- a/test/unit/source.cpp +++ b/test/unit/serializer_source.cpp @@ -8,16 +8,16 @@ // // Test that header file is self-contained. -#include +#include #include "test_helpers.hpp" namespace boost { namespace http_proto { -struct source_test +struct serializer_source_test { - struct test_source : source + struct test_source : serializer::source { buffers::const_buffer cb_; std::size_t fail_; @@ -116,8 +116,8 @@ struct source_test }; TEST_SUITE( - source_test, - "boost.http_proto.source"); + serializer_source_test, + "boost.http_proto.serializer.source"); } // http_proto } // boost