From 2425c60973d923a7d215fd465531f061eca2c954 Mon Sep 17 00:00:00 2001 From: Mohammad Nejati Date: Fri, 3 Oct 2025 05:42:44 +0000 Subject: [PATCH] container hierarchy is refactored --- doc/modules/ROOT/pages/reference.adoc | 16 +- doc/tagfiles/boost-http_proto-doxygen.tag.xml | 1167 +++-------------- include/boost/http_proto.hpp | 6 - include/boost/http_proto/fields.hpp | 110 +- include/boost/http_proto/fields_base.hpp | 492 ++++++- include/boost/http_proto/fields_view.hpp | 217 --- include/boost/http_proto/fields_view_base.hpp | 476 ------- include/boost/http_proto/http_proto.natvis | 6 +- .../{fields_view_base.hpp => fields_base.hpp} | 49 +- include/boost/http_proto/impl/serializer.hpp | 4 +- include/boost/http_proto/message_base.hpp | 99 +- .../boost/http_proto/message_view_base.hpp | 130 -- include/boost/http_proto/parser.hpp | 9 +- include/boost/http_proto/request.hpp | 55 +- include/boost/http_proto/request_base.hpp | 85 +- include/boost/http_proto/request_parser.hpp | 8 +- include/boost/http_proto/request_view.hpp | 251 ---- include/boost/http_proto/response.hpp | 67 +- include/boost/http_proto/response_base.hpp | 77 +- include/boost/http_proto/response_parser.hpp | 8 +- include/boost/http_proto/response_view.hpp | 247 ---- .../http_proto/rfc/combine_field_values.hpp | 4 +- include/boost/http_proto/serializer.hpp | 24 +- include/boost/http_proto/static_fields.hpp | 281 ---- include/boost/http_proto/static_request.hpp | 235 +--- include/boost/http_proto/static_response.hpp | 217 +-- src/detail/header.cpp | 1 - src/fields.cpp | 89 -- src/fields_base.cpp | 531 +++++++- src/fields_view_base.cpp | 395 ------ src/message_base.cpp | 16 +- src/message_view_base.cpp | 16 - src/parser.cpp | 100 +- src/request.cpp | 84 -- src/request_parser.cpp | 5 +- src/response.cpp | 102 -- src/response_parser.cpp | 5 +- src/rfc/combine_field_values.cpp | 2 +- src/serializer.cpp | 34 +- test/unit/Jamfile | 6 - test/unit/compression.cpp | 8 +- test/unit/fields.cpp | 82 -- test/unit/fields_base.cpp | 259 ++++ test/unit/fields_view.cpp | 63 - test/unit/fields_view_base.cpp | 276 ---- test/unit/message_view_base.cpp | 11 - test/unit/natvis.cpp | 9 +- test/unit/request.cpp | 106 +- test/unit/request_parser.cpp | 48 +- test/unit/request_view.cpp | 54 - test/unit/response.cpp | 97 +- test/unit/response_view.cpp | 55 - test/unit/static_fields.cpp | 249 ---- test/unit/static_request.cpp | 549 +------- test/unit/static_response.cpp | 273 +--- test/unit/test_helpers.cpp | 2 +- test/unit/test_helpers.hpp | 2 +- 57 files changed, 1958 insertions(+), 5911 deletions(-) delete mode 100644 include/boost/http_proto/fields_view.hpp delete mode 100644 include/boost/http_proto/fields_view_base.hpp rename include/boost/http_proto/impl/{fields_view_base.hpp => fields_base.hpp} (90%) delete mode 100644 include/boost/http_proto/message_view_base.hpp delete mode 100644 include/boost/http_proto/request_view.hpp delete mode 100644 include/boost/http_proto/response_view.hpp delete mode 100644 include/boost/http_proto/static_fields.hpp delete mode 100644 src/fields.cpp delete mode 100644 src/fields_view_base.cpp delete mode 100644 src/message_view_base.cpp delete mode 100644 src/request.cpp delete mode 100644 src/response.cpp delete mode 100644 test/unit/fields_view.cpp delete mode 100644 test/unit/fields_view_base.cpp delete mode 100644 test/unit/message_view_base.cpp delete mode 100644 test/unit/request_view.cpp delete mode 100644 test/unit/response_view.cpp delete mode 100644 test/unit/static_fields.cpp diff --git a/doc/modules/ROOT/pages/reference.adoc b/doc/modules/ROOT/pages/reference.adoc index e2d0de29..75fb2387 100644 --- a/doc/modules/ROOT/pages/reference.adoc +++ b/doc/modules/ROOT/pages/reference.adoc @@ -21,10 +21,6 @@ cpp:boost::http_proto::fields[fields] cpp:boost::http_proto::fields_base[fields_base] -cpp:boost::http_proto::fields_view[fields_view] - -cpp:boost::http_proto::fields_view_base[fields_view_base] - cpp:boost::http_proto::file[file] cpp:boost::http_proto::file_sink[file_sink] @@ -35,8 +31,6 @@ cpp:boost::http_proto::header_limits[header_limits] cpp:boost::http_proto::message_base[message_base] -cpp:boost::http_proto::message_view_base[message_view_base] - cpp:boost::http_proto::metadata[metadata] cpp:boost::http_proto::parser[parser] @@ -47,26 +41,20 @@ cpp:boost::http_proto::request_base[request_base] cpp:boost::http_proto::request_parser[request_parser] -cpp:boost::http_proto::request_view[request_view] - cpp:boost::http_proto::response[response] cpp:boost::http_proto::response_base[response_base] cpp:boost::http_proto::response_parser[response_parser] -| **Types (2/2)** - -cpp:boost::http_proto::response_view[response_view] - cpp:boost::http_proto::serializer[serializer] +| **Types (2/2)** + cpp:boost::http_proto::sink[sink] cpp:boost::http_proto::source[source] -cpp:boost::http_proto::static_fields[static_fields] - cpp:boost::http_proto::static_request[static_request] cpp:boost::http_proto::static_response[static_response] diff --git a/doc/tagfiles/boost-http_proto-doxygen.tag.xml b/doc/tagfiles/boost-http_proto-doxygen.tag.xml index c52e205f..88ccc858 100644 --- a/doc/tagfiles/boost-http_proto-doxygen.tag.xml +++ b/doc/tagfiles/boost-http_proto-doxygen.tag.xml @@ -8,14 +8,11 @@ boost::http_proto::is_source boost::http_proto::fields boost::http_proto::fields_base - boost::http_proto::fields_view - boost::http_proto::fields_view_base boost::http_proto::file boost::http_proto::file_sink boost::http_proto::file_source boost::http_proto::header_limits boost::http_proto::message_base - boost::http_proto::message_view_base boost::http_proto::metadata boost::http_proto::parameter boost::http_proto::parser @@ -23,15 +20,12 @@ boost::http_proto::request boost::http_proto::request_base boost::http_proto::request_parser - boost::http_proto::request_view boost::http_proto::response boost::http_proto::response_base boost::http_proto::response_parser - boost::http_proto::response_view boost::http_proto::serializer boost::http_proto::sink boost::http_proto::source - boost::http_proto::static_fields boost::http_proto::static_request boost::http_proto::static_response boost::http_proto::string_body @@ -61,7 +55,7 @@ combine_field_values boost/http_proto/combine_field_values.adoc - (const fields_view_base::subrange& vr, grammar::recycled_ptr<std::string>& temp) + (const fields_base::subrange& vr, grammar::recycled_ptr<std::string>& temp) void @@ -145,14 +139,14 @@ iterator begin - boost/http_proto/fields_view_base/begin.adoc + boost/http_proto/fields_base/begin.adoc () core::string_view buffer - boost/http_proto/fields_view_base/buffer.adoc + boost/http_proto/fields_base/buffer.adoc () @@ -173,7 +167,7 @@ iterator end - boost/http_proto/fields_view_base/end.adoc + boost/http_proto/fields_base/end.adoc () @@ -187,14 +181,14 @@ reverse_iterator rbegin - boost/http_proto/fields_view_base/rbegin.adoc + boost/http_proto/fields_base/rbegin.adoc () reverse_iterator rend - boost/http_proto/fields_view_base/rend.adoc + boost/http_proto/fields_base/rend.adoc () @@ -222,7 +216,7 @@ std::size_t size - boost/http_proto/fields_view_base/size.adoc + boost/http_proto/fields_base/size.adoc () @@ -233,17 +227,10 @@ (fields& other) - - fields_view - operator fields_view - boost/http_proto/fields/2conversion.adoc - - () - std::size_t max_size - boost/http_proto/fields_view_base/max_size.adoc + boost/http_proto/fields_base/max_size.adoc () @@ -261,14 +248,14 @@ iterator begin - boost/http_proto/fields_view_base/begin.adoc + boost/http_proto/fields_base/begin.adoc () core::string_view buffer - boost/http_proto/fields_view_base/buffer.adoc + boost/http_proto/fields_base/buffer.adoc () @@ -289,7 +276,7 @@ iterator end - boost/http_proto/fields_view_base/end.adoc + boost/http_proto/fields_base/end.adoc () @@ -303,14 +290,14 @@ reverse_iterator rbegin - boost/http_proto/fields_view_base/rbegin.adoc + boost/http_proto/fields_base/rbegin.adoc () reverse_iterator rend - boost/http_proto/fields_view_base/rend.adoc + boost/http_proto/fields_base/rend.adoc () @@ -338,162 +325,28 @@ std::size_t size - boost/http_proto/fields_view_base/size.adoc + boost/http_proto/fields_base/size.adoc () std::size_t max_size - boost/http_proto/fields_view_base/max_size.adoc + boost/http_proto/fields_base/max_size.adoc () - boost::http_proto::fields_view - boost/http_proto/fields_view.adoc - - void - ~fields_view - boost/http_proto/fields_view/2destructor.adoc - - () - - - fields_view& - operator= - boost/http_proto/fields_view/operator_assign.adoc - - (const fields_view& other) - - - iterator - begin - boost/http_proto/fields_view_base/begin.adoc - - () - - - core::string_view - buffer - boost/http_proto/fields_view_base/buffer.adoc - - () - - - iterator - end - boost/http_proto/fields_view_base/end.adoc - - () - - - reverse_iterator - rbegin - boost/http_proto/fields_view_base/rbegin.adoc - - () - - - reverse_iterator - rend - boost/http_proto/fields_view_base/rend.adoc - - () - - - std::size_t - size - boost/http_proto/fields_view_base/size.adoc - - () - - - void - swap - boost/http_proto/fields_view/swap.adoc - - (fields_view& other) - - - std::size_t - max_size - boost/http_proto/fields_view_base/max_size.adoc - - () - + boost::http_proto::file + boost/http_proto/file.adoc void - fields_view - boost/http_proto/fields_view/2constructor-0c.adoc - - (const detail::header* ph) - - - - boost::http_proto::fields_view_base - boost/http_proto/fields_view_base.adoc - - iterator - begin - boost/http_proto/fields_view_base/begin.adoc - - () - - - core::string_view - buffer - boost/http_proto/fields_view_base/buffer.adoc - - () - - - iterator - end - boost/http_proto/fields_view_base/end.adoc - - () - - - reverse_iterator - rbegin - boost/http_proto/fields_view_base/rbegin.adoc - - () - - - reverse_iterator - rend - boost/http_proto/fields_view_base/rend.adoc - - () - - - std::size_t - size - boost/http_proto/fields_view_base/size.adoc - - () - - - std::size_t - max_size - boost/http_proto/fields_view_base/max_size.adoc + ~file + boost/http_proto/file/2destructor.adoc () - - fields_view_base& - operator= - boost/http_proto/fields_view_base/operator_assign.adoc - - (const fields_view_base& ) - - - - boost::http_proto::file - boost/http_proto/file.adoc file& operator= @@ -501,13 +354,6 @@ (file&& other) - - void - close - boost/http_proto/file/close.adoc - - (system::error_code& ec) - bool is_open @@ -515,48 +361,6 @@ () - - void - open - boost/http_proto/file/open.adoc - - (const char* path, file_mode mode, system::error_code& ec) - - - std::uint64_t - pos - boost/http_proto/file/pos.adoc - - (system::error_code& ec) - - - std::size_t - read - boost/http_proto/file/read.adoc - - (void* buffer, std::size_t n, system::error_code& ec) - - - void - seek - boost/http_proto/file/seek.adoc - - (std::uint64_t offset, system::error_code& ec) - - - std::uint64_t - size - boost/http_proto/file/size.adoc - - (system::error_code& ec) - - - std::size_t - write - boost/http_proto/file/write.adoc - - (const void* buffer, std::size_t n, system::error_code& ec) - boost::http_proto::file_sink @@ -611,14 +415,14 @@ iterator begin - boost/http_proto/fields_view_base/begin.adoc + boost/http_proto/fields_base/begin.adoc () core::string_view buffer - boost/http_proto/fields_view_base/buffer.adoc + boost/http_proto/fields_base/buffer.adoc () @@ -632,7 +436,7 @@ bool chunked - boost/http_proto/message_view_base/chunked.adoc + boost/http_proto/message_base/chunked.adoc () @@ -646,14 +450,14 @@ iterator end - boost/http_proto/fields_view_base/end.adoc + boost/http_proto/fields_base/end.adoc () bool keep_alive - boost/http_proto/message_view_base/keep_alive.adoc + boost/http_proto/message_base/keep_alive.adoc () @@ -667,35 +471,35 @@ const http_proto::metadata& metadata - boost/http_proto/message_view_base/metadata.adoc + boost/http_proto/message_base/metadata.adoc () http_proto::payload payload - boost/http_proto/message_view_base/payload.adoc + boost/http_proto/message_base/payload.adoc () - std::uint64_t + uint64_t payload_size - boost/http_proto/message_view_base/payload_size.adoc + boost/http_proto/message_base/payload_size.adoc () reverse_iterator rbegin - boost/http_proto/fields_view_base/rbegin.adoc + boost/http_proto/fields_base/rbegin.adoc () reverse_iterator rend - boost/http_proto/fields_view_base/rend.adoc + boost/http_proto/fields_base/rend.adoc () @@ -718,7 +522,7 @@ set_content_length boost/http_proto/message_base/set_content_length.adoc - (std::uint64_t n) + (uint64_t n) void @@ -739,7 +543,7 @@ set_payload_size boost/http_proto/message_base/set_payload_size.adoc - (std::uint64_t n) + (uint64_t n) void @@ -751,116 +555,21 @@ std::size_t size - boost/http_proto/fields_view_base/size.adoc - - () - - - http_proto::version - version - boost/http_proto/message_view_base/version.adoc - - () - - - std::size_t - max_size - boost/http_proto/fields_view_base/max_size.adoc - - () - - - - boost::http_proto::message_view_base - boost/http_proto/message_view_base.adoc - - iterator - begin - boost/http_proto/fields_view_base/begin.adoc - - () - - - core::string_view - buffer - boost/http_proto/fields_view_base/buffer.adoc - - () - - - bool - chunked - boost/http_proto/message_view_base/chunked.adoc - - () - - - iterator - end - boost/http_proto/fields_view_base/end.adoc - - () - - - bool - keep_alive - boost/http_proto/message_view_base/keep_alive.adoc - - () - - - const http_proto::metadata& - metadata - boost/http_proto/message_view_base/metadata.adoc - - () - - - http_proto::payload - payload - boost/http_proto/message_view_base/payload.adoc - - () - - - std::uint64_t - payload_size - boost/http_proto/message_view_base/payload_size.adoc - - () - - - reverse_iterator - rbegin - boost/http_proto/fields_view_base/rbegin.adoc - - () - - - reverse_iterator - rend - boost/http_proto/fields_view_base/rend.adoc - - () - - - std::size_t - size - boost/http_proto/fields_view_base/size.adoc + boost/http_proto/fields_base/size.adoc () http_proto::version version - boost/http_proto/message_view_base/version.adoc + boost/http_proto/message_base/version.adoc () std::size_t max_size - boost/http_proto/fields_view_base/max_size.adoc + boost/http_proto/fields_base/max_size.adoc () @@ -883,27 +592,6 @@ boost::http_proto::parser boost/http_proto/parser.adoc - - void - parser - boost/http_proto/parser/2constructor-0f.adoc - - (parser&& other) - - - void - ~parser - boost/http_proto/parser/2destructor.adoc - - () - - - parser& - operator= - boost/http_proto/parser/operator_assign.adoc - - (parser&& other) - core::string_view body @@ -986,7 +674,7 @@ set_body_limit boost/http_proto/parser/set_body_limit.adoc - (std::uint64_t n) + (uint64_t n) void @@ -997,43 +685,29 @@ void - parser - boost/http_proto/parser/2constructor-0b.adoc - - (rts::context& , detail::kind ) - - - std::size_t - apply_filter - boost/http_proto/parser/apply_filter.adoc - - (system::error_code& , std::size_t , bool ) - - - std::uint64_t - body_limit_remain - boost/http_proto/parser/body_limit_remain.adoc + ~parser + boost/http_proto/parser/2destructor.adoc () bool - is_plain - boost/http_proto/parser/is_plain.adoc + is_body_set + boost/http_proto/parser/is_body_set.adoc () - void - on_set_body - boost/http_proto/parser/on_set_body.adoc + const static_request& + safe_get_request + boost/http_proto/parser/safe_get_request.adoc () - const detail::header* - safe_get_header - boost/http_proto/parser/safe_get_header.adoc + const static_response& + safe_get_response + boost/http_proto/parser/safe_get_response.adoc () @@ -1044,6 +718,13 @@ (bool ) + + detail::workspace& + ws + boost/http_proto/parser/ws.adoc + + () + boost::http_proto::quoted_token_view @@ -1237,14 +918,14 @@ iterator begin - boost/http_proto/fields_view_base/begin.adoc + boost/http_proto/fields_base/begin.adoc () core::string_view buffer - boost/http_proto/fields_view_base/buffer.adoc + boost/http_proto/fields_base/buffer.adoc () @@ -1258,7 +939,7 @@ bool chunked - boost/http_proto/message_view_base/chunked.adoc + boost/http_proto/message_base/chunked.adoc () @@ -1272,14 +953,14 @@ iterator end - boost/http_proto/fields_view_base/end.adoc + boost/http_proto/fields_base/end.adoc () bool keep_alive - boost/http_proto/message_view_base/keep_alive.adoc + boost/http_proto/message_base/keep_alive.adoc () @@ -1293,7 +974,7 @@ const http_proto::metadata& metadata - boost/http_proto/message_view_base/metadata.adoc + boost/http_proto/message_base/metadata.adoc () @@ -1314,28 +995,28 @@ http_proto::payload payload - boost/http_proto/message_view_base/payload.adoc + boost/http_proto/message_base/payload.adoc () - std::uint64_t + uint64_t payload_size - boost/http_proto/message_view_base/payload_size.adoc + boost/http_proto/message_base/payload_size.adoc () reverse_iterator rbegin - boost/http_proto/fields_view_base/rbegin.adoc + boost/http_proto/fields_base/rbegin.adoc () reverse_iterator rend - boost/http_proto/fields_view_base/rend.adoc + boost/http_proto/fields_base/rend.adoc () @@ -1358,7 +1039,7 @@ set_content_length boost/http_proto/message_base/set_content_length.adoc - (std::uint64_t n) + (uint64_t n) void @@ -1386,7 +1067,7 @@ set_payload_size boost/http_proto/message_base/set_payload_size.adoc - (std::uint64_t n) + (uint64_t n) void @@ -1412,7 +1093,7 @@ std::size_t size - boost/http_proto/fields_view_base/size.adoc + boost/http_proto/fields_base/size.adoc () @@ -1433,21 +1114,14 @@ http_proto::version version - boost/http_proto/message_view_base/version.adoc + boost/http_proto/message_base/version.adoc () - request_view - operator request_view - boost/http_proto/request_base/2conversion.adoc - - () - - - std::size_t - max_size - boost/http_proto/fields_view_base/max_size.adoc + std::size_t + max_size + boost/http_proto/fields_base/max_size.adoc () @@ -1458,14 +1132,14 @@ iterator begin - boost/http_proto/fields_view_base/begin.adoc + boost/http_proto/fields_base/begin.adoc () core::string_view buffer - boost/http_proto/fields_view_base/buffer.adoc + boost/http_proto/fields_base/buffer.adoc () @@ -1479,7 +1153,7 @@ bool chunked - boost/http_proto/message_view_base/chunked.adoc + boost/http_proto/message_base/chunked.adoc () @@ -1493,14 +1167,14 @@ iterator end - boost/http_proto/fields_view_base/end.adoc + boost/http_proto/fields_base/end.adoc () bool keep_alive - boost/http_proto/message_view_base/keep_alive.adoc + boost/http_proto/message_base/keep_alive.adoc () @@ -1514,7 +1188,7 @@ const http_proto::metadata& metadata - boost/http_proto/message_view_base/metadata.adoc + boost/http_proto/message_base/metadata.adoc () @@ -1535,28 +1209,28 @@ http_proto::payload payload - boost/http_proto/message_view_base/payload.adoc + boost/http_proto/message_base/payload.adoc () - std::uint64_t + uint64_t payload_size - boost/http_proto/message_view_base/payload_size.adoc + boost/http_proto/message_base/payload_size.adoc () reverse_iterator rbegin - boost/http_proto/fields_view_base/rbegin.adoc + boost/http_proto/fields_base/rbegin.adoc () reverse_iterator rend - boost/http_proto/fields_view_base/rend.adoc + boost/http_proto/fields_base/rend.adoc () @@ -1579,7 +1253,7 @@ set_content_length boost/http_proto/message_base/set_content_length.adoc - (std::uint64_t n) + (uint64_t n) void @@ -1607,7 +1281,7 @@ set_payload_size boost/http_proto/message_base/set_payload_size.adoc - (std::uint64_t n) + (uint64_t n) void @@ -1633,7 +1307,7 @@ std::size_t size - boost/http_proto/fields_view_base/size.adoc + boost/http_proto/fields_base/size.adoc () @@ -1647,21 +1321,14 @@ http_proto::version version - boost/http_proto/message_view_base/version.adoc - - () - - - request_view - operator request_view - boost/http_proto/request_base/2conversion.adoc + boost/http_proto/message_base/version.adoc () std::size_t max_size - boost/http_proto/fields_view_base/max_size.adoc + boost/http_proto/fields_base/max_size.adoc () @@ -1676,13 +1343,6 @@ boost::http_proto::request_parser boost/http_proto/request_parser.adoc - - void - request_parser - boost/http_proto/request_parser/2constructor.adoc - - (rts::context& ctx) - void ~request_parser @@ -1690,13 +1350,6 @@ () - - parser& - operator= - boost/http_proto/parser/operator_assign.adoc - - (parser&& other) - core::string_view body @@ -1726,7 +1379,7 @@ (std::size_t n) - request_view + const static_request& get boost/http_proto/request_parser/get.adoc @@ -1786,7 +1439,7 @@ set_body_limit boost/http_proto/parser/set_body_limit.adoc - (std::uint64_t n) + (uint64_t n) void @@ -1796,164 +1449,20 @@ () - - boost::http_proto::request_view - boost/http_proto/request_view.adoc - - void - ~request_view - boost/http_proto/request_view/2destructor.adoc - - () - - - request_view& - operator= - boost/http_proto/request_view/operator_assign.adoc - - (const request_view& other) - - - iterator - begin - boost/http_proto/fields_view_base/begin.adoc - - () - - - core::string_view - buffer - boost/http_proto/fields_view_base/buffer.adoc - - () - - - bool - chunked - boost/http_proto/message_view_base/chunked.adoc - - () - - - iterator - end - boost/http_proto/fields_view_base/end.adoc - - () - - - bool - keep_alive - boost/http_proto/message_view_base/keep_alive.adoc - - () - - - const http_proto::metadata& - metadata - boost/http_proto/message_view_base/metadata.adoc - - () - - - http_proto::method - method - boost/http_proto/request_view/method.adoc - - () - - - core::string_view - method_text - boost/http_proto/request_view/method_text.adoc - - () - - - http_proto::payload - payload - boost/http_proto/message_view_base/payload.adoc - - () - - - std::uint64_t - payload_size - boost/http_proto/message_view_base/payload_size.adoc - - () - - - reverse_iterator - rbegin - boost/http_proto/fields_view_base/rbegin.adoc - - () - - - reverse_iterator - rend - boost/http_proto/fields_view_base/rend.adoc - - () - - - std::size_t - size - boost/http_proto/fields_view_base/size.adoc - - () - - - void - swap - boost/http_proto/request_view/swap.adoc - - (request_view& other) - - - core::string_view - target - boost/http_proto/request_view/target.adoc - - () - - - http_proto::version - version - boost/http_proto/message_view_base/version.adoc - - () - - - std::size_t - max_size - boost/http_proto/fields_view_base/max_size.adoc - - () - - - void - request_view - boost/http_proto/request_view/2constructor-00.adoc - - (const detail::header* ph) - - boost::http_proto::response boost/http_proto/response.adoc iterator begin - boost/http_proto/fields_view_base/begin.adoc + boost/http_proto/fields_base/begin.adoc () core::string_view buffer - boost/http_proto/fields_view_base/buffer.adoc + boost/http_proto/fields_base/buffer.adoc () @@ -1967,7 +1476,7 @@ bool chunked - boost/http_proto/message_view_base/chunked.adoc + boost/http_proto/message_base/chunked.adoc () @@ -1981,14 +1490,14 @@ iterator end - boost/http_proto/fields_view_base/end.adoc + boost/http_proto/fields_base/end.adoc () bool keep_alive - boost/http_proto/message_view_base/keep_alive.adoc + boost/http_proto/message_base/keep_alive.adoc () @@ -2002,28 +1511,28 @@ const http_proto::metadata& metadata - boost/http_proto/message_view_base/metadata.adoc + boost/http_proto/message_base/metadata.adoc () http_proto::payload payload - boost/http_proto/message_view_base/payload.adoc + boost/http_proto/message_base/payload.adoc () - std::uint64_t + uint64_t payload_size - boost/http_proto/message_view_base/payload_size.adoc + boost/http_proto/message_base/payload_size.adoc () reverse_iterator rbegin - boost/http_proto/fields_view_base/rbegin.adoc + boost/http_proto/fields_base/rbegin.adoc () @@ -2037,7 +1546,7 @@ reverse_iterator rend - boost/http_proto/fields_view_base/rend.adoc + boost/http_proto/fields_base/rend.adoc () @@ -2060,7 +1569,7 @@ set_content_length boost/http_proto/message_base/set_content_length.adoc - (std::uint64_t n) + (uint64_t n) void @@ -2081,7 +1590,7 @@ set_payload_size boost/http_proto/message_base/set_payload_size.adoc - (std::uint64_t n) + (uint64_t n) void @@ -2093,7 +1602,7 @@ std::size_t size - boost/http_proto/fields_view_base/size.adoc + boost/http_proto/fields_base/size.adoc () @@ -2121,21 +1630,14 @@ http_proto::version version - boost/http_proto/message_view_base/version.adoc - - () - - - response_view - operator response_view - boost/http_proto/response_base/2conversion.adoc + boost/http_proto/message_base/version.adoc () std::size_t max_size - boost/http_proto/fields_view_base/max_size.adoc + boost/http_proto/fields_base/max_size.adoc () @@ -2146,14 +1648,14 @@ iterator begin - boost/http_proto/fields_view_base/begin.adoc + boost/http_proto/fields_base/begin.adoc () core::string_view buffer - boost/http_proto/fields_view_base/buffer.adoc + boost/http_proto/fields_base/buffer.adoc () @@ -2167,7 +1669,7 @@ bool chunked - boost/http_proto/message_view_base/chunked.adoc + boost/http_proto/message_base/chunked.adoc () @@ -2181,14 +1683,14 @@ iterator end - boost/http_proto/fields_view_base/end.adoc + boost/http_proto/fields_base/end.adoc () bool keep_alive - boost/http_proto/message_view_base/keep_alive.adoc + boost/http_proto/message_base/keep_alive.adoc () @@ -2202,28 +1704,28 @@ const http_proto::metadata& metadata - boost/http_proto/message_view_base/metadata.adoc + boost/http_proto/message_base/metadata.adoc () http_proto::payload payload - boost/http_proto/message_view_base/payload.adoc + boost/http_proto/message_base/payload.adoc () - std::uint64_t + uint64_t payload_size - boost/http_proto/message_view_base/payload_size.adoc + boost/http_proto/message_base/payload_size.adoc () reverse_iterator rbegin - boost/http_proto/fields_view_base/rbegin.adoc + boost/http_proto/fields_base/rbegin.adoc () @@ -2237,7 +1739,7 @@ reverse_iterator rend - boost/http_proto/fields_view_base/rend.adoc + boost/http_proto/fields_base/rend.adoc () @@ -2260,7 +1762,7 @@ set_content_length boost/http_proto/message_base/set_content_length.adoc - (std::uint64_t n) + (uint64_t n) void @@ -2281,7 +1783,7 @@ set_payload_size boost/http_proto/message_base/set_payload_size.adoc - (std::uint64_t n) + (uint64_t n) void @@ -2293,7 +1795,7 @@ std::size_t size - boost/http_proto/fields_view_base/size.adoc + boost/http_proto/fields_base/size.adoc () @@ -2314,21 +1816,14 @@ http_proto::version version - boost/http_proto/message_view_base/version.adoc - - () - - - response_view - operator response_view - boost/http_proto/response_base/2conversion.adoc + boost/http_proto/message_base/version.adoc () std::size_t max_size - boost/http_proto/fields_view_base/max_size.adoc + boost/http_proto/fields_base/max_size.adoc () @@ -2343,13 +1838,6 @@ boost::http_proto::response_parser boost/http_proto/response_parser.adoc - - void - response_parser - boost/http_proto/response_parser/2constructor.adoc - - (rts::context& ctx) - void ~response_parser @@ -2357,13 +1845,6 @@ () - - parser& - operator= - boost/http_proto/parser/operator_assign.adoc - - (parser&& other) - core::string_view body @@ -2393,7 +1874,7 @@ (std::size_t n) - response_view + const static_response& get boost/http_proto/response_parser/get.adoc @@ -2453,7 +1934,7 @@ set_body_limit boost/http_proto/parser/set_body_limit.adoc - (std::uint64_t n) + (uint64_t n) void @@ -2470,150 +1951,6 @@ () - - boost::http_proto::response_view - boost/http_proto/response_view.adoc - - void - ~response_view - boost/http_proto/response_view/2destructor.adoc - - () - - - response_view& - operator= - boost/http_proto/response_view/operator_assign.adoc - - (const response_view& other) - - - iterator - begin - boost/http_proto/fields_view_base/begin.adoc - - () - - - core::string_view - buffer - boost/http_proto/fields_view_base/buffer.adoc - - () - - - bool - chunked - boost/http_proto/message_view_base/chunked.adoc - - () - - - iterator - end - boost/http_proto/fields_view_base/end.adoc - - () - - - bool - keep_alive - boost/http_proto/message_view_base/keep_alive.adoc - - () - - - const http_proto::metadata& - metadata - boost/http_proto/message_view_base/metadata.adoc - - () - - - http_proto::payload - payload - boost/http_proto/message_view_base/payload.adoc - - () - - - std::uint64_t - payload_size - boost/http_proto/message_view_base/payload_size.adoc - - () - - - reverse_iterator - rbegin - boost/http_proto/fields_view_base/rbegin.adoc - - () - - - core::string_view - reason - boost/http_proto/response_view/reason.adoc - - () - - - reverse_iterator - rend - boost/http_proto/fields_view_base/rend.adoc - - () - - - std::size_t - size - boost/http_proto/fields_view_base/size.adoc - - () - - - http_proto::status - status - boost/http_proto/response_view/status.adoc - - () - - - unsigned short - status_int - boost/http_proto/response_view/status_int.adoc - - () - - - void - swap - boost/http_proto/response_view/swap.adoc - - (response_view& other) - - - http_proto::version - version - boost/http_proto/message_view_base/version.adoc - - () - - - std::size_t - max_size - boost/http_proto/fields_view_base/max_size.adoc - - () - - - void - response_view - boost/http_proto/response_view/2constructor-09.adoc - - (const detail::header* ph) - - boost::http_proto::serializer boost/http_proto/serializer.adoc @@ -2624,13 +1961,6 @@ () - - serializer& - operator= - boost/http_proto/serializer/operator_assign.adoc - - (serializer&& other) - void consume @@ -2664,84 +1994,35 @@ start_stream boost/http_proto/serializer/start_stream.adoc - (const message_view_base& m) - - - bool - is_header_done - boost/http_proto/serializer/is_header_done.adoc - - () - - - detail::array_of_const_buffers - make_array - boost/http_proto/serializer/make_array.adoc - - (std::size_t n) - - - std::size_t - out_capacity - boost/http_proto/serializer/out_capacity.adoc - - () - - - void - out_commit - boost/http_proto/serializer/out_commit.adoc - - (std::size_t ) - - - void - out_finish - boost/http_proto/serializer/out_finish.adoc - - () - - - void - out_init - boost/http_proto/serializer/out_init.adoc - - () - - - buffers::mutable_buffer_pair - out_prepare - boost/http_proto/serializer/out_prepare.adoc - - () + (const message_base& m) void start_buffers boost/http_proto/serializer/start_buffers.adoc - (const message_view_base& ) - - - void - start_empty - boost/http_proto/serializer/start_empty.adoc - - (const message_view_base& ) + (const message_base& , cbs_gen& ) void start_init boost/http_proto/serializer/start_init.adoc - (const message_view_base& ) + (const message_base& ) void start_source boost/http_proto/serializer/start_source.adoc - (const message_view_base& ) + (const message_base& , source& ) + + + detail::workspace& + ws + boost/http_proto/serializer/ws.adoc + + () @@ -2766,122 +2047,20 @@ (const MutableBufferSequence& bs) - - boost::http_proto::static_fields - boost/http_proto/static_fields.adoc - - iterator - begin - boost/http_proto/fields_view_base/begin.adoc - - () - - - core::string_view - buffer - boost/http_proto/fields_view_base/buffer.adoc - - () - - - std::size_t - capacity_in_bytes - boost/http_proto/fields_base/capacity_in_bytes.adoc - - () - - - void - clear - boost/http_proto/fields_base/clear.adoc - - () - - - iterator - end - boost/http_proto/fields_view_base/end.adoc - - () - - - std::size_t - max_capacity_in_bytes - boost/http_proto/fields_base/max_capacity_in_bytes.adoc - - () - - - reverse_iterator - rbegin - boost/http_proto/fields_view_base/rbegin.adoc - - () - - - reverse_iterator - rend - boost/http_proto/fields_view_base/rend.adoc - - () - - - void - reserve_bytes - boost/http_proto/fields_base/reserve_bytes.adoc - - (std::size_t n) - - - void - set_max_capacity_in_bytes - boost/http_proto/fields_base/set_max_capacity_in_bytes.adoc - - (std::size_t n) - - - void - shrink_to_fit - boost/http_proto/fields_base/shrink_to_fit.adoc - - () - - - std::size_t - size - boost/http_proto/fields_view_base/size.adoc - - () - - - fields_view - operator fields_view - boost/http_proto/static_fields/2conversion.adoc - - () - - - std::size_t - max_size - boost/http_proto/fields_view_base/max_size.adoc - - () - - boost::http_proto::static_request boost/http_proto/static_request.adoc iterator begin - boost/http_proto/fields_view_base/begin.adoc + boost/http_proto/fields_base/begin.adoc () core::string_view buffer - boost/http_proto/fields_view_base/buffer.adoc + boost/http_proto/fields_base/buffer.adoc () @@ -2895,7 +2074,7 @@ bool chunked - boost/http_proto/message_view_base/chunked.adoc + boost/http_proto/message_base/chunked.adoc () @@ -2909,14 +2088,14 @@ iterator end - boost/http_proto/fields_view_base/end.adoc + boost/http_proto/fields_base/end.adoc () bool keep_alive - boost/http_proto/message_view_base/keep_alive.adoc + boost/http_proto/message_base/keep_alive.adoc () @@ -2930,7 +2109,7 @@ const http_proto::metadata& metadata - boost/http_proto/message_view_base/metadata.adoc + boost/http_proto/message_base/metadata.adoc () @@ -2951,28 +2130,28 @@ http_proto::payload payload - boost/http_proto/message_view_base/payload.adoc + boost/http_proto/message_base/payload.adoc () - std::uint64_t + uint64_t payload_size - boost/http_proto/message_view_base/payload_size.adoc + boost/http_proto/message_base/payload_size.adoc () reverse_iterator rbegin - boost/http_proto/fields_view_base/rbegin.adoc + boost/http_proto/fields_base/rbegin.adoc () reverse_iterator rend - boost/http_proto/fields_view_base/rend.adoc + boost/http_proto/fields_base/rend.adoc () @@ -2995,7 +2174,7 @@ set_content_length boost/http_proto/message_base/set_content_length.adoc - (std::uint64_t n) + (uint64_t n) void @@ -3023,7 +2202,7 @@ set_payload_size boost/http_proto/message_base/set_payload_size.adoc - (std::uint64_t n) + (uint64_t n) void @@ -3049,7 +2228,7 @@ std::size_t size - boost/http_proto/fields_view_base/size.adoc + boost/http_proto/fields_base/size.adoc () @@ -3063,21 +2242,14 @@ http_proto::version version - boost/http_proto/message_view_base/version.adoc - - () - - - request_view - operator request_view - boost/http_proto/request_base/2conversion.adoc + boost/http_proto/message_base/version.adoc () std::size_t max_size - boost/http_proto/fields_view_base/max_size.adoc + boost/http_proto/fields_base/max_size.adoc () @@ -3088,14 +2260,14 @@ iterator begin - boost/http_proto/fields_view_base/begin.adoc + boost/http_proto/fields_base/begin.adoc () core::string_view buffer - boost/http_proto/fields_view_base/buffer.adoc + boost/http_proto/fields_base/buffer.adoc () @@ -3109,7 +2281,7 @@ bool chunked - boost/http_proto/message_view_base/chunked.adoc + boost/http_proto/message_base/chunked.adoc () @@ -3123,14 +2295,14 @@ iterator end - boost/http_proto/fields_view_base/end.adoc + boost/http_proto/fields_base/end.adoc () bool keep_alive - boost/http_proto/message_view_base/keep_alive.adoc + boost/http_proto/message_base/keep_alive.adoc () @@ -3144,28 +2316,28 @@ const http_proto::metadata& metadata - boost/http_proto/message_view_base/metadata.adoc + boost/http_proto/message_base/metadata.adoc () http_proto::payload payload - boost/http_proto/message_view_base/payload.adoc + boost/http_proto/message_base/payload.adoc () - std::uint64_t + uint64_t payload_size - boost/http_proto/message_view_base/payload_size.adoc + boost/http_proto/message_base/payload_size.adoc () reverse_iterator rbegin - boost/http_proto/fields_view_base/rbegin.adoc + boost/http_proto/fields_base/rbegin.adoc () @@ -3179,7 +2351,7 @@ reverse_iterator rend - boost/http_proto/fields_view_base/rend.adoc + boost/http_proto/fields_base/rend.adoc () @@ -3202,7 +2374,7 @@ set_content_length boost/http_proto/message_base/set_content_length.adoc - (std::uint64_t n) + (uint64_t n) void @@ -3223,7 +2395,7 @@ set_payload_size boost/http_proto/message_base/set_payload_size.adoc - (std::uint64_t n) + (uint64_t n) void @@ -3235,7 +2407,7 @@ std::size_t size - boost/http_proto/fields_view_base/size.adoc + boost/http_proto/fields_base/size.adoc () @@ -3256,21 +2428,14 @@ http_proto::version version - boost/http_proto/message_view_base/version.adoc - - () - - - response_view - operator response_view - boost/http_proto/response_base/2conversion.adoc + boost/http_proto/message_base/version.adoc () std::size_t max_size - boost/http_proto/fields_view_base/max_size.adoc + boost/http_proto/fields_base/max_size.adoc () diff --git a/include/boost/http_proto.hpp b/include/boost/http_proto.hpp index 41ffe717..38dca128 100644 --- a/include/boost/http_proto.hpp +++ b/include/boost/http_proto.hpp @@ -14,27 +14,21 @@ #include #include #include -#include -#include #include #include #include #include #include #include -#include #include #include #include #include -#include #include #include -#include #include #include #include -#include #include #include #include diff --git a/include/boost/http_proto/fields.hpp b/include/boost/http_proto/fields.hpp index dc0ae554..607e8e51 100644 --- a/include/boost/http_proto/fields.hpp +++ b/include/boost/http_proto/fields.hpp @@ -14,8 +14,6 @@ #include #include -#include -#include namespace boost { namespace http_proto { @@ -46,8 +44,7 @@ namespace http_proto { @endcode @see - @ref static_fields, - @ref fields_view. + @ref fields_base. */ class fields final : public fields_base @@ -78,8 +75,11 @@ class fields final @par Complexity Constant. */ - BOOST_HTTP_PROTO_DECL - fields() noexcept; + fields() noexcept + : fields_base(detail::kind::fields) + { + } + /** Constructor. @@ -116,10 +116,12 @@ class fields final @param s The string to parse. */ - BOOST_HTTP_PROTO_DECL explicit fields( - core::string_view s); + core::string_view s) + : fields_base(detail::kind::fields, s) + { + } /** Constructor. @@ -147,11 +149,15 @@ class fields final @param max_cap Maximum allowed capacity in bytes. */ - BOOST_HTTP_PROTO_DECL explicit fields( std::size_t cap, - std::size_t max_cap = std::size_t(-1)); + std::size_t max_cap = std::size_t(-1)) + : fields() + { + reserve_bytes(cap); + set_max_capacity_in_bytes(max_cap); + } /** Constructor. @@ -172,29 +178,12 @@ class fields final @param f The fields to move from. */ - BOOST_HTTP_PROTO_DECL - fields(fields&& f) noexcept; - - /** Constructor. - - The newly constructed object contains - a copy of `f`. - - @par Postconditions - @code - this->buffer() == f.buffer() && this->buffer().data() != f.buffer().data() - @endcode - - @par Complexity - Linear in `f.size()`. - - @par Exception Safety - Calls to allocate may throw. + fields(fields&& f) noexcept + : fields_base(f.h_.kind) + { + swap(f); + } - @param f The fields to copy. - */ - BOOST_HTTP_PROTO_DECL - fields(fields const& f); /** Constructor. @@ -210,13 +199,11 @@ class fields final Linear in `f.size()`. @par Exception Safety - Strong guarantee. Calls to allocate may throw. @param f The fields to copy. */ - BOOST_HTTP_PROTO_DECL - fields(fields_view const& f); + fields(fields const& f) = default; /** Assignment. @@ -239,40 +226,11 @@ class fields final @return A reference to this object. */ - BOOST_HTTP_PROTO_DECL - fields& - operator=(fields&& f) noexcept; - - /** Assignment. - - The contents of `f` are copied and - the previous contents of `this` are - discarded. - - @par Postconditions - @code - this->buffer() == f.buffer() && this->buffer().data() != f.buffer().data() - @endcode - - @par Complexity - Linear in `f.size()`. - - @par Exception Safety - Strong guarantee. - Calls to allocate may throw. - Exception thrown if max capacity exceeded. - - @throw std::length_error - Max capacity would be exceeded. - - @return A reference to this object. - - @param f The fields to copy. - */ fields& - operator=(fields const& f) noexcept + operator=(fields&& f) noexcept { - copy_impl(*f.ph_); + fields tmp(std::move(f)); + tmp.swap(*this); return *this; } @@ -288,7 +246,7 @@ class fields final @endcode @par Complexity - Linear in `r.size()`. + Linear in `f.size()`. @par Exception Safety Strong guarantee. @@ -303,24 +261,12 @@ class fields final @param f The fields to copy. */ fields& - operator=(fields_view const& f) + operator=(fields const& f) noexcept { - copy_impl(*f.ph_); + copy_impl(f.h_); return *this; } - /** Conversion. - - @see - @ref fields_view. - - @return A view of the fields. - */ - operator fields_view() const noexcept - { - return fields_view(ph_); - } - //-------------------------------------------- /** Swap. diff --git a/include/boost/http_proto/fields_base.hpp b/include/boost/http_proto/fields_base.hpp index ce9f25f8..e9c4e4bc 100644 --- a/include/boost/http_proto/fields_base.hpp +++ b/include/boost/http_proto/fields_base.hpp @@ -14,9 +14,11 @@ #include #include -#include +#include #include +#include + namespace boost { namespace http_proto { @@ -31,7 +33,6 @@ namespace http_proto { @note HTTP field names are case-insensitive. */ class fields_base - : public virtual fields_view_base { detail::header h_; std::size_t max_cap_ = @@ -63,17 +64,15 @@ class fields_base }; friend class fields; - template - friend class static_fields; + friend class message_base; friend class request_base; friend class request; - template friend class static_request; friend class response_base; friend class response; - template friend class static_response; - friend class message_base; + friend class parser; + friend class serializer; BOOST_HTTP_PROTO_DECL explicit @@ -83,7 +82,7 @@ class fields_base BOOST_HTTP_PROTO_DECL fields_base( detail::kind k, - char* storage, + void* storage, std::size_t cap) noexcept; BOOST_HTTP_PROTO_DECL @@ -92,29 +91,398 @@ class fields_base core::string_view s); BOOST_HTTP_PROTO_DECL + explicit fields_base( - detail::kind k, - char* storage, - std::size_t cap, - core::string_view s); + detail::header const& h); BOOST_HTTP_PROTO_DECL - explicit fields_base( - detail::header const& h); + fields_base const&); BOOST_HTTP_PROTO_DECL fields_base( detail::header const& h, - char* storage, + void* storage, std::size_t cap); public: + //-------------------------------------------- + // + // Types + // + //-------------------------------------------- + + /** A view to an HTTP field. + + The view will be invalidated when the + underlying container is modified. + + The caller is responsible for ensuring + that the lifetime of the container extends + until it is no longer referenced. + */ + struct reference + { + /** Field name constant. + + Set to `boost::none` if the constant + does not exist in @ref field. + */ + boost::optional const id; + + /// A view to the field name. + core::string_view const name; + + /// A view to the field value. + core::string_view const value; + + reference const* + operator->() const noexcept + { + return this; + } + }; + + /// @copydoc reference + typedef reference const_reference; + + /** A value type which represent an HTTP field. + + This type allows for making a copy of + a field where ownership is retained + in the copy. + */ + struct value_type + { + /** Field name constant. + + Set to `boost::none` if the + constant does not exist in @ref field. + */ + boost::optional id; + + /// Field name. + std::string name; + + /// Field value. + std::string value; + + /// Constructor. + BOOST_HTTP_PROTO_DECL + value_type( + reference const& other); + + /** Conversion. + + @see + @ref reference. + + @return A view to the fields. + */ + operator reference() const noexcept; + }; + + /** A bidirectional iterator to HTTP fields. + */ + class iterator; + + /// @copydoc iterator + using const_iterator = iterator; + + /** A bidirectional reverse iterator to HTTP fields. + */ + class reverse_iterator; + + /// @copydoc iterator + using const_reverse_iterator = reverse_iterator; + + /** A forward range of matching fields. + + Objects of this type are returned by + the function @ref find_all. + */ + class subrange; + + //-------------------------------------------- + // + // Special Members + // + //-------------------------------------------- + /** Destructor. */ BOOST_HTTP_PROTO_DECL ~fields_base(); + //-------------------------------------------- + // + // Observers + // + //-------------------------------------------- + + /** Return the largest possible serialized message. + */ + static + constexpr + std::size_t + max_size() noexcept + { + // TODO: this doesn't take into account + // the start-line + return detail::header::max_offset; + } + + /** Return an iterator to the beginning. + */ + iterator + begin() const noexcept; + + /** Return an iterator to the end. + */ + iterator + end() const noexcept; + + /** Return a reverse iterator to the beginning. + */ + reverse_iterator + rbegin() const noexcept; + + /** Return a reverse iterator to the end. + */ + reverse_iterator + rend() const noexcept; + + /** Return a string view representing the serialized data. + */ + core::string_view + buffer() const noexcept + { + return core::string_view( + h_.cbuf, h_.size); + } + + /** Return the number of fields in the container. + */ + std::size_t + size() const noexcept + { + return h_.count; + } + + /** Return the value of a field, or throws an exception. + + If more than one field with the specified + name exists, the first field defined by + insertion order is returned. + + @par Exception Safety + Strong guarantee. + + @throw std::out_of_range + Field is not found. + + @param id The field name constant. + */ + BOOST_HTTP_PROTO_DECL + core::string_view + at(field id) const; + + /** Return the value of a field, or throws an exception. + + If more than one field with the specified + name exists, the first field defined by + insertion order is returned. + + If `name` refers to a known field, it is + faster to call @ref at with a field id + instead of a string. + + @par Exception Safety + Strong guarantee. + + @throw std::out_of_range + Field is not found. + + @param name The field name. + */ + BOOST_HTTP_PROTO_DECL + core::string_view + at(core::string_view name) const; + + /** Return true if a field exists. + */ + BOOST_HTTP_PROTO_DECL + bool + exists(field id) const noexcept; + + /** Return true if a field exists. + + If `name` refers to a known field, + it is faster to call @ref exists + with a field id instead of a string. + + @param name The field name. + */ + BOOST_HTTP_PROTO_DECL + bool + exists( + core::string_view name) const noexcept; + + /** Return the number of matching fields. + + @param id The field name constant. + */ + BOOST_HTTP_PROTO_DECL + std::size_t + count(field id) const noexcept; + + /** Return the number of matching fields. + + If `name` refers to a known field, + it is faster to call @ref count + with a field id instead of a string. + + @param name The field name. + */ + BOOST_HTTP_PROTO_DECL + std::size_t + count( + core::string_view name) const noexcept; + + /** Return an iterator to the matching element if it exists. + + @param id The field name constant. + */ + BOOST_HTTP_PROTO_DECL + iterator + find(field id) const noexcept; + + /** Return an iterator to the matching element if it exists. + + If `name` refers to a known field, + it is faster to call @ref find + with a field id instead of a string. + + @param name The field name. + */ + BOOST_HTTP_PROTO_DECL + iterator + find( + core::string_view name) const noexcept; + + /** Return an iterator to the matching element if it exists. + + @param from The position to begin the + search from. This can be `end()`. + + @param id The field name constant. + */ + BOOST_HTTP_PROTO_DECL + iterator + find( + iterator from, + field id) const noexcept; + + /** Return an iterator to the matching element if it exists. + + If `name` refers to a known field, + it is faster to call @ref find + with a field id instead of a string. + + @param from The position to begin the + search from. This can be `end()`. + + @param name The field name. + */ + BOOST_HTTP_PROTO_DECL + iterator + find( + iterator from, + core::string_view name) const noexcept; + + /** Return an iterator to the matching element if it exists. + + @param before One past the position + to begin the search from. This can + be `end()`. + + @param id The field name constant. + */ + BOOST_HTTP_PROTO_DECL + iterator + find_last( + iterator before, + field id) const noexcept; + + /** Return an iterator to the matching element if it exists. + + If `name` refers to a known field, + it is faster to call @ref find_last + with a field id instead of a string. + + @param before One past the position + to begin the search from. This can + be `end()`. + + @param name The field name. + */ + BOOST_HTTP_PROTO_DECL + iterator + find_last( + iterator before, + core::string_view name) const noexcept; + + /** Return the value of a field or a default if missing. + + @param id The field name constant. + + @param s The value to be returned if + field does not exist. + */ + BOOST_HTTP_PROTO_DECL + core::string_view + value_or( + field id, + core::string_view s) const noexcept; + + /** Return the value of a field or a default if missing. + + If `name` refers to a known field, + it is faster to call @ref value_or + with a field id instead of a string. + + @param name The field name. + + @param s The value to be returned if + field does not exist. + */ + BOOST_HTTP_PROTO_DECL + core::string_view + value_or( + core::string_view name, + core::string_view s) const noexcept; + + /** Return a forward range containing values for all matching fields. + + @param id The field name constant. + */ + BOOST_HTTP_PROTO_DECL + subrange + find_all(field id) const noexcept; + + /** Return a forward range containing values for all matching fields. + + If `name` refers to a known field, + it is faster to call @ref find_all + with a field id instead of a string. + + @param name The field name. + */ + BOOST_HTTP_PROTO_DECL + subrange + find_all( + core::string_view name) const noexcept; + //-------------------------------------------- // // Capacity @@ -467,19 +835,12 @@ class fields_base @param value The value which must be semantically valid for the message. */ + BOOST_HTTP_PROTO_DECL iterator insert( iterator before, field id, - core::string_view value) - { - system::error_code ec; - auto const it = insert( - before, id, value, ec); - if(ec.failed()) - detail::throw_system_error(ec); - return it; - } + core::string_view value); /** Insert a header. @@ -523,21 +884,13 @@ class fields_base @param ec Set to the error if input is invalid. */ + BOOST_HTTP_PROTO_DECL iterator insert( iterator before, field id, core::string_view value, - system::error_code& ec) - { - insert_impl( - id, - to_string(id), - value, - before.i_, - ec); - return before; - } + system::error_code& ec); /** Insert a header. @@ -583,18 +936,12 @@ class fields_base @param value The value which must be semantically valid for the message. */ + BOOST_HTTP_PROTO_DECL iterator insert( iterator before, core::string_view name, - core::string_view value) - { - system::error_code ec; - insert(before, name, value, ec); - if(ec.failed()) - detail::throw_system_error(ec); - return before; - } + core::string_view value); /** Insert a header. @@ -638,21 +985,13 @@ class fields_base @param ec Set to the error if input is invalid. */ + BOOST_HTTP_PROTO_DECL iterator insert( iterator before, core::string_view name, core::string_view value, - system::error_code& ec) - { - insert_impl( - string_to_field(name), - name, - value, - before.i_, - ec); - return before; - } + system::error_code& ec); //-------------------------------------------- @@ -752,16 +1091,9 @@ class fields_base @param value The value which must be semantically valid for the message. */ + BOOST_HTTP_PROTO_DECL void - set( - iterator it, - core::string_view value) - { - system::error_code ec; - set(it, value, ec); - if(ec.failed()) - detail::throw_system_error(ec); - } + set(iterator it, core::string_view value); /** Set a header value. @@ -1020,7 +1352,45 @@ class fields_base std::size_t i) const noexcept; }; +/** Format the container to the output stream + + This function serializes the container to + the specified output stream. + + @par Example + @code + request req; + std::stringstream ss; + ss << req; + assert( ss.str() == "GET / HTTP/1.1\r\n\r\n" ); + @endcode + + @par Effects + @code + return os << f.buffer(); + @endcode + + @par Complexity + Linear in `f.buffer().size()` + + @par Exception Safety + Basic guarantee. + + @return A reference to the output stream, for chaining + + @param os The output stream to write to. + + @param f The container to write. +*/ +BOOST_HTTP_PROTO_DECL +std::ostream& +operator<<( + std::ostream& os, + const fields_base& f); + } // http_proto } // boost +#include + #endif diff --git a/include/boost/http_proto/fields_view.hpp b/include/boost/http_proto/fields_view.hpp deleted file mode 100644 index c2c8d40e..00000000 --- a/include/boost/http_proto/fields_view.hpp +++ /dev/null @@ -1,217 +0,0 @@ -// -// Copyright (c) 2021 Vinnie Falco (vinnie.falco@gmail.com) -// Copyright (c) 2025 Mohammad Nejati -// -// 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_FIELDS_VIEW_HPP -#define BOOST_HTTP_PROTO_FIELDS_VIEW_HPP - -#include -#include -#include - -namespace boost { -namespace http_proto { - -/** A view to a valid HTTP headers section. - - Objects of this type represent a view to - an HTTP fields container. That is, it acts - like a `core::string_view` in terms of - ownership. The caller is responsible for - ensuring that the lifetime of the underlying - buffer extends until it is no - longer referenced. - - @see - @ref fields, - @ref static_fields, -*/ -class fields_view - : public fields_view_base -{ - friend class fields; - template - friend class static_fields; - - fields_view( - detail::header const* ph) noexcept - : fields_view_base(ph) - { - BOOST_ASSERT(ph_->kind == - detail::kind::fields); - } - -public: - - //-------------------------------------------- - // - // Special Members - // - //-------------------------------------------- - - /** Constructor. - - A default-constructed fields views refer to - a valid HTTP headers section that contains - no name-value pairs, which always remains - valid. - - @par Example - @code - fields fs; - @endcode - - @par Postconditions - @code - this->buffer() == "\r\n" - @endcode - - @par Complexity - Constant. - */ - fields_view() noexcept - : fields_view_base( - detail::header::get_default( - detail::kind::fields)) - { - } - - /** Constructor. - - After construction, both fields views - reference the same underlying buffer. - Ownership is not transferred. - - @par Postconditions - @code - this->buffer().data() == other.buffer().data() - @endcode - - @par Complexity - Constant. - - @param other The other view. - */ - fields_view( - fields_view const& other) noexcept = default; - - /** Assignment. - - After assignment, both fields views - reference the same underlying buffer. - Ownership is not transferred. - - @par Postconditions - @code - this->buffer().data() == other.buffer().data() - @endcode - - @par Complexity - Constant. - - @return A reference to this object. - - @param other The other view. - */ - fields_view& - operator=( - fields_view const& other) noexcept = default; - - /** Destructor - - Any reference, iterator, or other view - which reference the same underlying - buffer remain valid. - */ - ~fields_view() = default; - - //-------------------------------------------- - - /** Swap. - - Exchanges the view with that of `other`. - All iterators and references remain valid. - - If `this == &other`, this function call has no effect. - - @par Example - @code - fields f1; - f1.set(field::accept, "text/html"); - fields f2; - f2.set(field::connection, "keep-alive"); - fields_view v1 = f1; - fields_view v2 = f2; - v1.swap(v2); - assert(v1.buffer() == "Connection: keep-alive\r\n\r\n" ); - assert(v2.buffer() == "Accept: text/html\r\n\r\n" ); - @endcode - - @par Complexity - Constant. - - @param other The object to swap with. - */ - void - swap(fields_view& other) noexcept - { - auto ph = ph_; - ph_ = other.ph_; - other.ph_ = ph; - } - - /** Swap. - - Exchanges the view of `v0` with - another `v1`. All iterators and - references remain valid. - - If `&v0 == &v1`, this function call has no effect. - - @par Example - @code - fields f1; - f1.set(field::accept, "text/html"); - fields f2; - f2.set(field::connection, "keep-alive"); - fields_view v1 = f1; - fields_view v2 = f2; - std::swap(v1, v2); - assert(v1.buffer() == "Connection: keep-alive\r\n\r\n" ); - assert(v2.buffer() == "Accept: text/html\r\n\r\n" ); - @endcode - - @par Effects - @code - v0.swap(v1); - @endcode - - @par Complexity - Constant. - - @param v0 The first object to swap. - @param v1 The second object to swap. - - @see - @ref fields_view::swap - */ - friend - void - swap( - fields_view& v0, - fields_view& v1) noexcept - { - v0.swap(v1); - } -}; - -} // http_proto -} // boost - -#endif diff --git a/include/boost/http_proto/fields_view_base.hpp b/include/boost/http_proto/fields_view_base.hpp deleted file mode 100644 index 8bf213e3..00000000 --- a/include/boost/http_proto/fields_view_base.hpp +++ /dev/null @@ -1,476 +0,0 @@ -// -// Copyright (c) 2021 Vinnie Falco (vinnie.falco@gmail.com) -// Copyright (c) 2025 Mohammad Nejati -// -// 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_FIELDS_VIEW_BASE_HPP -#define BOOST_HTTP_PROTO_FIELDS_VIEW_BASE_HPP - -#include -#include - -#include -#include -#include - -#include -#include - -namespace boost { -namespace http_proto { - -/** A read-only, bidirectional range of HTTP fields. - - This is a mix-in used to add common - functionality to derived classes. -*/ -class fields_view_base -{ - detail::header const* ph_; - - friend class fields; - template - friend class static_fields; - friend class fields_base; - friend class fields_view; - friend class message_base; - friend class message_view_base; - friend class request_base; - friend class request; - template - friend class static_request; - friend class request_view; - friend class response_base; - friend class response; - template - friend class static_response; - friend class response_view; - friend class serializer; - - explicit - fields_view_base( - detail::header const* ph) noexcept - : ph_(ph) - { - } - - fields_view_base( - fields_view_base const&) = default; - fields_view_base& - operator=(fields_view_base const&) = default; - -public: - //-------------------------------------------- - // - // Types - // - //-------------------------------------------- - - /** A view to an HTTP field. - - The view will be invalidated when the - underlying container is modified. - - The caller is responsible for ensuring - that the lifetime of the container extends - until it is no longer referenced. - */ - struct reference - { - /** Field name constant. - - Set to `boost::none` if the constant - does not exist in @ref field. - */ - boost::optional const id; - - /// A view to the field name. - core::string_view const name; - - /// A view to the field value. - core::string_view const value; - - reference const* - operator->() const noexcept - { - return this; - } - }; - - /// @copydoc reference - typedef reference const_reference; - - /** A value type which represent an HTTP field. - - This type allows for making a copy of - a field where ownership is retained - in the copy. - */ - struct value_type - { - /** Field name constant. - - Set to `boost::none` if the - constant does not exist in @ref field. - */ - boost::optional id; - - /// Field name. - std::string name; - - /// Field value. - std::string value; - - /// Constructor. - BOOST_HTTP_PROTO_DECL - value_type( - reference const& other); - - /** Conversion. - - @see - @ref reference. - - @return A view to the fields. - */ - operator reference() const noexcept; - }; - - /** A bidirectional iterator to HTTP fields. - */ - class iterator; - - /// @copydoc iterator - using const_iterator = iterator; - - /** A bidirectional reverse iterator to HTTP fields. - */ - class reverse_iterator; - - /// @copydoc iterator - using const_reverse_iterator = reverse_iterator; - - /** A forward range of matching fields. - - Objects of this type are returned by - the function @ref find_all. - */ - class subrange; - - //-------------------------------------------- - // - // Observers - // - //-------------------------------------------- - - /** Return the largest possible serialized message. - */ - static - constexpr - std::size_t - max_size() noexcept - { - // TODO: this doesn't take into account - // the start-line - return detail::header::max_offset; - } - - /** Return an iterator to the beginning. - */ - iterator - begin() const noexcept; - - /** Return an iterator to the end. - */ - iterator - end() const noexcept; - - /** Return a reverse iterator to the beginning. - */ - reverse_iterator - rbegin() const noexcept; - - /** Return a reverse iterator to the end. - */ - reverse_iterator - rend() const noexcept; - - /** Return a string view representing the serialized data. - */ - core::string_view - buffer() const noexcept - { - return core::string_view( - ph_->cbuf, ph_->size); - } - - /** Return the number of fields in the container. - */ - std::size_t - size() const noexcept - { - return ph_->count; - } - - /** Return the value of a field, or throws an exception. - - If more than one field with the specified - name exists, the first field defined by - insertion order is returned. - - @par Exception Safety - Strong guarantee. - - @throw std::out_of_range - Field is not found. - - @param id The field name constant. - */ - BOOST_HTTP_PROTO_DECL - core::string_view - at(field id) const; - - /** Return the value of a field, or throws an exception. - - If more than one field with the specified - name exists, the first field defined by - insertion order is returned. - - If `name` refers to a known field, it is - faster to call @ref at with a field id - instead of a string. - - @par Exception Safety - Strong guarantee. - - @throw std::out_of_range - Field is not found. - - @param name The field name. - */ - BOOST_HTTP_PROTO_DECL - core::string_view - at(core::string_view name) const; - - /** Return true if a field exists. - */ - BOOST_HTTP_PROTO_DECL - bool - exists(field id) const noexcept; - - /** Return true if a field exists. - - If `name` refers to a known field, - it is faster to call @ref exists - with a field id instead of a string. - - @param name The field name. - */ - BOOST_HTTP_PROTO_DECL - bool - exists( - core::string_view name) const noexcept; - - /** Return the number of matching fields. - - @param id The field name constant. - */ - BOOST_HTTP_PROTO_DECL - std::size_t - count(field id) const noexcept; - - /** Return the number of matching fields. - - If `name` refers to a known field, - it is faster to call @ref count - with a field id instead of a string. - - @param name The field name. - */ - BOOST_HTTP_PROTO_DECL - std::size_t - count( - core::string_view name) const noexcept; - - /** Return an iterator to the matching element if it exists. - - @param id The field name constant. - */ - BOOST_HTTP_PROTO_DECL - iterator - find(field id) const noexcept; - - /** Return an iterator to the matching element if it exists. - - If `name` refers to a known field, - it is faster to call @ref find - with a field id instead of a string. - - @param name The field name. - */ - BOOST_HTTP_PROTO_DECL - iterator - find( - core::string_view name) const noexcept; - - /** Return an iterator to the matching element if it exists. - - @param from The position to begin the - search from. This can be `end()`. - - @param id The field name constant. - */ - BOOST_HTTP_PROTO_DECL - iterator - find( - iterator from, - field id) const noexcept; - - /** Return an iterator to the matching element if it exists. - - If `name` refers to a known field, - it is faster to call @ref find - with a field id instead of a string. - - @param from The position to begin the - search from. This can be `end()`. - - @param name The field name. - */ - BOOST_HTTP_PROTO_DECL - iterator - find( - iterator from, - core::string_view name) const noexcept; - - /** Return an iterator to the matching element if it exists. - - @param before One past the position - to begin the search from. This can - be `end()`. - - @param id The field name constant. - */ - BOOST_HTTP_PROTO_DECL - iterator - find_last( - iterator before, - field id) const noexcept; - - /** Return an iterator to the matching element if it exists. - - If `name` refers to a known field, - it is faster to call @ref find_last - with a field id instead of a string. - - @param before One past the position - to begin the search from. This can - be `end()`. - - @param name The field name. - */ - BOOST_HTTP_PROTO_DECL - iterator - find_last( - iterator before, - core::string_view name) const noexcept; - - /** Return the value of a field or a default if missing. - - @param id The field name constant. - - @param s The value to be returned if - field does not exist. - */ - BOOST_HTTP_PROTO_DECL - core::string_view - value_or( - field id, - core::string_view s) const noexcept; - - /** Return the value of a field or a default if missing. - - If `name` refers to a known field, - it is faster to call @ref value_or - with a field id instead of a string. - - @param name The field name. - - @param s The value to be returned if - field does not exist. - */ - BOOST_HTTP_PROTO_DECL - core::string_view - value_or( - core::string_view name, - core::string_view s) const noexcept; - - /** Return a forward range containing values for all matching fields. - - @param id The field name constant. - */ - BOOST_HTTP_PROTO_DECL - subrange - find_all(field id) const noexcept; - - /** Return a forward range containing values for all matching fields. - - If `name` refers to a known field, - it is faster to call @ref find_all - with a field id instead of a string. - - @param name The field name. - */ - BOOST_HTTP_PROTO_DECL - subrange - find_all( - core::string_view name) const noexcept; -}; - -/** Format the container to the output stream - - This function serializes the container to - the specified output stream. - - @par Example - @code - request req; - std::stringstream ss; - ss << req; - assert( ss.str() == "GET / HTTP/1.1\r\n\r\n" ); - @endcode - - @par Effects - @code - return os << f.buffer(); - @endcode - - @par Complexity - Linear in `f.buffer().size()` - - @par Exception Safety - Basic guarantee. - - @return A reference to the output stream, for chaining - - @param os The output stream to write to. - - @param f The container to write. -*/ -BOOST_HTTP_PROTO_DECL -std::ostream& -operator<<( - std::ostream& os, - const fields_view_base& f); - -} // http_proto -} // boost - -#include - -#endif diff --git a/include/boost/http_proto/http_proto.natvis b/include/boost/http_proto/http_proto.natvis index 4a830bfb..efd3005c 100644 --- a/include/boost/http_proto/http_proto.natvis +++ b/include/boost/http_proto/http_proto.natvis @@ -32,10 +32,10 @@ - - { *ph_ } + + { h_ } - *ph_ + h_ diff --git a/include/boost/http_proto/impl/fields_view_base.hpp b/include/boost/http_proto/impl/fields_base.hpp similarity index 90% rename from include/boost/http_proto/impl/fields_view_base.hpp rename to include/boost/http_proto/impl/fields_base.hpp index 02883cb4..576780b9 100644 --- a/include/boost/http_proto/impl/fields_view_base.hpp +++ b/include/boost/http_proto/impl/fields_base.hpp @@ -7,8 +7,8 @@ // Official repository: https://github.com/cppalliance/http_proto // -#ifndef BOOST_HTTP_PROTO_IMPL_FIELDS_VIEW_BASE_HPP -#define BOOST_HTTP_PROTO_IMPL_FIELDS_VIEW_BASE_HPP +#ifndef BOOST_HTTP_PROTO_IMPL_FIELDS_BASE_HPP +#define BOOST_HTTP_PROTO_IMPL_FIELDS_BASE_HPP #include #include @@ -22,13 +22,12 @@ namespace http_proto { // //------------------------------------------------ -class fields_view_base::iterator +class fields_base::iterator { detail::header const* ph_ = nullptr; std::size_t i_ = 0; friend class fields_base; - friend class fields_view_base; iterator( detail::header const* ph, @@ -40,9 +39,9 @@ class fields_view_base::iterator public: using value_type = - fields_view_base::value_type; + fields_base::value_type; using reference = - fields_view_base::reference; + fields_base::reference; using pointer = reference; using difference_type = std::ptrdiff_t; @@ -118,13 +117,12 @@ class fields_view_base::iterator //------------------------------------------------ -class fields_view_base::reverse_iterator +class fields_base::reverse_iterator { detail::header const* ph_ = nullptr; std::size_t i_ = 0; friend class fields_base; - friend class fields_view_base; reverse_iterator( detail::header const* ph, @@ -136,9 +134,9 @@ class fields_view_base::reverse_iterator public: using value_type = - fields_view_base::value_type; + fields_base::value_type; using reference = - fields_view_base::reference; + fields_base::reference; using pointer = reference; using difference_type = std::ptrdiff_t; @@ -226,13 +224,12 @@ class fields_view_base::reverse_iterator // //------------------------------------------------ -class fields_view_base::subrange +class fields_base::subrange { detail::header const* ph_ = nullptr; std::size_t i_ = 0; - friend class fields_view; - friend class fields_view_base; + friend class fields_base; friend struct detail::header; subrange( @@ -273,13 +270,13 @@ class fields_view_base::subrange // //------------------------------------------------ -class fields_view_base::subrange:: +class fields_base::subrange:: iterator { detail::header const* ph_ = nullptr; std::size_t i_ = 0; - friend class fields_view_base::subrange; + friend class fields_base::subrange; BOOST_HTTP_PROTO_DECL iterator( @@ -307,7 +304,7 @@ class fields_view_base::subrange:: // conversion to regular iterator operator - fields_view_base:: + fields_base:: iterator() const noexcept { return {ph_, i_}; @@ -357,7 +354,7 @@ class fields_view_base::subrange:: inline auto -fields_view_base:: +fields_base:: subrange:: begin() const noexcept -> iterator @@ -367,7 +364,7 @@ begin() const noexcept -> inline auto -fields_view_base:: +fields_base:: subrange:: end() const noexcept -> iterator @@ -378,10 +375,10 @@ end() const noexcept -> //------------------------------------------------ inline -fields_view_base:: +fields_base:: value_type:: operator -fields_view_base:: +fields_base:: reference() const noexcept { return reference{ @@ -392,25 +389,25 @@ reference() const noexcept inline auto -fields_view_base:: +fields_base:: begin() const noexcept -> iterator { - return iterator(ph_, 0); + return iterator(&h_, 0); } inline auto -fields_view_base:: +fields_base:: end() const noexcept -> iterator { - return iterator(ph_, ph_->count); + return iterator(&h_, h_.count); } inline auto -fields_view_base:: +fields_base:: rbegin() const noexcept -> reverse_iterator { @@ -419,7 +416,7 @@ rbegin() const noexcept -> inline auto -fields_view_base:: +fields_base:: rend() const noexcept -> reverse_iterator { diff --git a/include/boost/http_proto/impl/serializer.hpp b/include/boost/http_proto/impl/serializer.hpp index f3273fe7..1613dc6b 100644 --- a/include/boost/http_proto/impl/serializer.hpp +++ b/include/boost/http_proto/impl/serializer.hpp @@ -117,7 +117,7 @@ template< void serializer:: start( - message_view_base const& m, + message_base const& m, ConstBufferSequence&& cbs) { static_assert(buffers::is_const_buffer_sequence< @@ -139,7 +139,7 @@ template< Source& serializer:: start( - message_view_base const& m, + message_base const& m, Args&&... args) { static_assert( diff --git a/include/boost/http_proto/message_base.hpp b/include/boost/http_proto/message_base.hpp index c46c3fdc..24e3a995 100644 --- a/include/boost/http_proto/message_base.hpp +++ b/include/boost/http_proto/message_base.hpp @@ -13,7 +13,6 @@ #include #include -#include #include namespace boost { @@ -27,7 +26,6 @@ namespace http_proto { and responses. @see - @ref message_view_base, @ref response, @ref request, @ref static_response, @@ -36,74 +34,83 @@ namespace http_proto { */ class message_base : public fields_base - , public message_view_base { friend class request_base; friend class response_base; - explicit - message_base( - detail::kind k) noexcept - : fields_view_base( - &this->fields_base::h_) - , fields_base(k) + using fields_base::fields_base; + +public: + //-------------------------------------------- + // + // Observers + // + //-------------------------------------------- + + /** Return the type of payload of this message. + */ + auto + payload() const noexcept -> + http_proto::payload { + return h_.md.payload; } - message_base( - detail::kind k, - char* storage, - std::size_t cap) noexcept - : fields_view_base(&this->fields_base::h_) - , fields_base( - k, storage, cap) + /** Return the payload size. + + When @ref payload returns @ref payload::size, + this function returns the number of octets + in the actual message payload. + + @return The number of octets in the + actual message payload. + */ + std::uint64_t + payload_size() const noexcept { + BOOST_ASSERT( + payload() == payload::size); + return h_.md.payload_size; } - message_base( - detail::kind k, - core::string_view s) - : fields_view_base( - &this->fields_base::h_) - , fields_base(k, s) + /** Return true if semantics indicate + connection persistence. + */ + bool + keep_alive() const noexcept { + return h_.keep_alive(); } - message_base( - detail::kind k, - char* storage, - std::size_t cap, - core::string_view s) - : fields_view_base( - &this->fields_base::h_) - , fields_base( - k, storage, cap, s) + /** Return metadata about the message. + */ + auto + metadata() const noexcept -> + http_proto::metadata const& { + return h_.md; } - explicit - message_base( - detail::header const& ph) - : fields_view_base( - &this->fields_base::h_) - , fields_base(ph) + /** Return true if the message is using a chunked + transfer encoding. + */ + bool + chunked() const noexcept { + return h_.md.transfer_encoding.is_chunked; } - message_base( - detail::header const& ph, - char* storage, - std::size_t cap) - : fields_view_base( - &this->fields_base::h_) - , fields_base(ph, storage, cap) + /** Return the HTTP-version. + */ + http_proto::version + version() const noexcept { + return h_.version; } -public: //-------------------------------------------- // - // Metadata + // Modifiers // //-------------------------------------------- diff --git a/include/boost/http_proto/message_view_base.hpp b/include/boost/http_proto/message_view_base.hpp deleted file mode 100644 index 99daea98..00000000 --- a/include/boost/http_proto/message_view_base.hpp +++ /dev/null @@ -1,130 +0,0 @@ -// -// Copyright (c) 2021 Vinnie Falco (vinnie.falco@gmail.com) -// Copyright (c) 2024 Christian Mazakas -// Copyright (c) 2025 Mohammad Nejati -// -// 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_MESSAGE_VIEW_BASE_HPP -#define BOOST_HTTP_PROTO_MESSAGE_VIEW_BASE_HPP - -#include -#include - -namespace boost { -namespace http_proto { - -/** Provides read-only access to common metadata - in HTTP request and response messages. - - This type is useful for accessing common - properties shared by request and response - messages. - - @see - @ref message_base, - @ref response_view, - @ref request_view, - @ref metadata, - @ref response_parser, - @ref request_parser. -*/ -class message_view_base - : public virtual fields_view_base -{ - friend class request_view; - friend class response_view; - friend class message_base; - - message_view_base() noexcept - // VFALCO This ctor-init has to be - // here even though it isn't called, - // so nullptr doesn't matter. - : fields_view_base(nullptr) - { - } - - explicit - message_view_base( - detail::header const* ph) noexcept - : fields_view_base(ph) - { - } - -public: - //-------------------------------------------- - // - // Metadata - // - //-------------------------------------------- - - /** Return the type of payload of this message. - */ - auto - payload() const noexcept -> - http_proto::payload - { - return ph_->md.payload; - } - - /** Return the payload size. - - When @ref payload returns @ref payload::size, - this function returns the number of octets - in the actual message payload. - - @return The number of octets in the - actual message payload. - */ - std::uint64_t - payload_size() const noexcept - { - BOOST_ASSERT( - payload() == payload::size); - return ph_->md.payload_size; - } - - /** Return true if semantics indicate - connection persistence. - */ - bool - keep_alive() const noexcept - { - return ph_->keep_alive(); - } - - /** Return metadata about the message. - */ - auto - metadata() const noexcept -> - http_proto::metadata const& - { - return ph_->md; - } - - /** Return true if the message is using a chunked - transfer encoding. - */ - bool - chunked() const noexcept - { - return ph_->md.transfer_encoding.is_chunked; - } - - /** Return the HTTP-version. - */ - http_proto::version - version() const noexcept - { - return ph_->version; - } -}; - -} // http_proto -} // boost - -#endif diff --git a/include/boost/http_proto/parser.hpp b/include/boost/http_proto/parser.hpp index 5a347eb8..c2552fa8 100644 --- a/include/boost/http_proto/parser.hpp +++ b/include/boost/http_proto/parser.hpp @@ -32,6 +32,8 @@ namespace http_proto { // Forward declaration class request_parser; class response_parser; +class static_request; +class static_response; /** A parser for HTTP/1 messages. @@ -627,8 +629,11 @@ class parser void start_impl(bool); - detail::header const* - safe_get_header() const; + static_request const& + safe_get_request() const; + + static_response const& + safe_get_response() const; BOOST_HTTP_PROTO_DECL detail::workspace& diff --git a/include/boost/http_proto/request.hpp b/include/boost/http_proto/request.hpp index d9c43d93..e9741b0f 100644 --- a/include/boost/http_proto/request.hpp +++ b/include/boost/http_proto/request.hpp @@ -43,13 +43,12 @@ namespace http_proto { @see @ref static_request, - @ref request_view. + @ref request_base. */ class request : public request_base { public: - //-------------------------------------------- // // Special Members @@ -74,8 +73,7 @@ class request @par Complexity Constant. */ - BOOST_HTTP_PROTO_DECL - request() noexcept; + request() noexcept = default; /** Constructor. @@ -111,10 +109,12 @@ class request @param s The string to parse. */ - BOOST_HTTP_PROTO_DECL explicit request( - core::string_view s); + core::string_view s) + : request_base(s) + { + } /** Constructor. @@ -203,10 +203,14 @@ class request @param max_cap Maximum allowed capacity in bytes. */ - BOOST_HTTP_PROTO_DECL request( std::size_t cap, - std::size_t max_cap = std::size_t(-1)); + std::size_t max_cap = std::size_t(-1)) + : request() + { + reserve_bytes(cap); + set_max_capacity_in_bytes(max_cap); + } /** Constructor. @@ -227,8 +231,12 @@ class request @param r The request to move from. */ - BOOST_HTTP_PROTO_DECL - request(request&& r) noexcept; + request( + request&& other) noexcept + : request() + { + swap(other); + } /** Constructor. @@ -248,8 +256,8 @@ class request @param r The request to copy. */ - BOOST_HTTP_PROTO_DECL - request(request const& r); + request( + request const& r) = default; /** Constructor. @@ -265,14 +273,15 @@ class request Linear in `r.size()`. @par Exception Safety - Strong guarantee. Calls to allocate may throw. @param r The request to copy. */ - BOOST_HTTP_PROTO_DECL request( - request_view const& r); + request_base const& r) + : request_base(r) + { + } /** Assignment @@ -295,10 +304,13 @@ class request @return A reference to this object. */ - BOOST_HTTP_PROTO_DECL request& - operator=(request&& r) noexcept; - + operator=(request&& r) noexcept + { + request temp(std::move(r)); + temp.swap(*this); + return *this; + } /** Assignment. @@ -330,7 +342,7 @@ class request operator=( request const& r) { - copy_impl(*r.ph_); + copy_impl(r.h_); return *this; } @@ -362,9 +374,9 @@ class request */ request& operator=( - request_view const& r) + request_base const& r) { - copy_impl(*r.ph_); + copy_impl(r.h_); return *this; } @@ -399,7 +411,6 @@ class request std::swap(max_cap_, other.max_cap_); } - /** Swap. Exchanges the contents of `v0` with diff --git a/include/boost/http_proto/request_base.hpp b/include/boost/http_proto/request_base.hpp index d7587fb8..450158d3 100644 --- a/include/boost/http_proto/request_base.hpp +++ b/include/boost/http_proto/request_base.hpp @@ -13,7 +13,6 @@ #include #include -#include namespace boost { namespace http_proto { @@ -29,86 +28,28 @@ class request_base : public message_base { friend class request; - template friend class static_request; request_base() noexcept - : fields_view_base( - &this->fields_base::h_) - , message_base(detail::kind::request) + : message_base(detail::kind::request) { } explicit request_base(core::string_view s) - : fields_view_base( - &this->fields_base::h_) - , message_base(detail::kind::request, s) + : message_base(detail::kind::request, s) { } - explicit - request_base(detail::header const& ph) - : fields_view_base( - &this->fields_base::h_) - , message_base(ph) - { - } - - request_base( - detail::header const& ph, - char* storage, - std::size_t cap) - : fields_view_base( - &this->fields_base::h_) - , message_base(ph, storage, cap) - { - } - -public: request_base( - char* storage, + void* storage, std::size_t cap) noexcept - : fields_view_base( - &this->fields_base::h_) - , message_base( + : message_base( detail::kind::request, storage, cap) { } - request_base( - core::string_view s, - char* storage, - std::size_t cap) - : fields_view_base( - &this->fields_base::h_) - , message_base( - detail::kind::request, storage, cap, s) - { - } - - request_base( - request_view const& other, - char* storage, - std::size_t cap) - : fields_view_base( - &this->fields_base::h_) - , message_base(*other.ph_, storage, cap) - { - } - - /** Conversion. - - @see - @ref request_view. - - @return A view of the request. - */ - operator request_view() const noexcept - { - return request_view(ph_); - } - +public: //-------------------------------------------- // // Observers @@ -125,7 +66,7 @@ class request_base http_proto::method method() const noexcept { - return ph_->req.method; + return h_.req.method; } /** Return the method as a string. @@ -134,8 +75,8 @@ class request_base method_text() const noexcept { return core::string_view( - ph_->cbuf, - ph_->req.method_len); + h_.cbuf, + h_.req.method_len); } /** Return the request-target string. @@ -144,9 +85,9 @@ class request_base target() const noexcept { return core::string_view( - ph_->cbuf + - ph_->req.method_len + 1, - ph_->req.target_len); + h_.cbuf + + h_.req.method_len + 1, + h_.req.target_len); } //-------------------------------------------- @@ -233,7 +174,7 @@ class request_base core::string_view s) { set_start_line_impl( - ph_->req.method, + h_.req.method, method_text(), s, version()); @@ -256,7 +197,7 @@ class request_base http_proto::version v) { set_start_line_impl( - ph_->req.method, + h_.req.method, method_text(), target(), v); diff --git a/include/boost/http_proto/request_parser.hpp b/include/boost/http_proto/request_parser.hpp index e329e67e..7ad99bfb 100644 --- a/include/boost/http_proto/request_parser.hpp +++ b/include/boost/http_proto/request_parser.hpp @@ -15,7 +15,7 @@ #include #include #include -#include +#include namespace boost { namespace http_proto { @@ -114,9 +114,9 @@ class request_parser */ ~request_parser() = default; - /** Return a read-only view to the parsed request headers. + /** Return a reference to the parsed request headers. - The returned view remains valid until: + The returned reference remains valid until: @li @ref start is called @li @ref reset is called @li The parser instance is destroyed @@ -133,7 +133,7 @@ class request_parser @ref got_header. */ BOOST_HTTP_PROTO_DECL - request_view + static_request const& get() const; }; diff --git a/include/boost/http_proto/request_view.hpp b/include/boost/http_proto/request_view.hpp deleted file mode 100644 index 23de7d29..00000000 --- a/include/boost/http_proto/request_view.hpp +++ /dev/null @@ -1,251 +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_REQUEST_VIEW_HPP -#define BOOST_HTTP_PROTO_REQUEST_VIEW_HPP - -#include -#include -#include - -namespace boost { -namespace http_proto { - -/** A view to a valid HTTP request. - - Objects of this type represent a view to - a HTTP request container. That is, it acts - like a `core::string_view` in terms of - ownership. The caller is responsible for - ensuring that the lifetime of the underlying - buffer extends until it is no - longer referenced. - - @see - @ref request, - @ref static_request, - @ref request_parser, -*/ -class request_view - : public message_view_base -{ - friend class request_base; - friend class request_parser; - - explicit - request_view( - detail::header const* ph) noexcept - : fields_view_base(ph) - { - BOOST_ASSERT(ph_->kind == - detail::kind::request); - } - -public: - //-------------------------------------------- - // - // Special Members - // - //-------------------------------------------- - - /** Constructor. - - A default-constructed request views refer - to a valid HTTP `GET` request with no - headers, which always remains valid. - - @par Example - @code - request_view reqv; - @endcode - - @par Postconditions - @code - this->buffer() == "GET / HTTP/1.1\r\n\r\n" - @endcode - - @par Complexity - Constant. - */ - request_view() noexcept - : fields_view_base( - detail::header::get_default( - detail::kind::request)) - { - } - - /** Constructor. - - After construction, both request views - reference the same underlying buffer. - Ownership is not transferred. - - @par Postconditions - @code - this->buffer().data() == other.buffer().data() - @endcode - - @par Complexity - Constant. - - @param other The other view. - */ - request_view( - request_view const& other) noexcept = default; - - /** Assignment. - - After assignment, both request views - reference the same underlying buffer. - Ownership is not transferred. - - @par Postconditions - @code - this->buffer().data() == other.buffer().data() - @endcode - - @par Complexity - Constant. - - @return A reference to this object. - - @param other The other view. - */ - request_view& - operator=( - request_view const& other) noexcept = default; - - /** Destructor - - Any reference, iterators, or other views - which reference the same underlying - buffer remain valid. - */ - ~request_view() = default; - - //-------------------------------------------- - // - // Observers - // - //-------------------------------------------- - - /** Return the method as an integral constant - - If the method returned is equal to - @ref method::unknown, the method may - be obtained as a string instead, by - calling @ref method_text. - */ - http_proto::method - method() const noexcept - { - return ph_->req.method; - }; - - /** Return the method as a string - */ - core::string_view - method_text() const noexcept - { - return core::string_view( - ph_->cbuf, - ph_->req.method_len); - } - - /** Return the request-target string. - */ - core::string_view - target() const noexcept - { - return core::string_view( - ph_->cbuf + - ph_->req.method_len + 1, - ph_->req.target_len); - } - - //-------------------------------------------- - - /** Swap. - - Exchanges the view with that of `other`. - All iterators and references remain valid. - - If `this == &other`, this function call has no effect. - - @par Example - @code - request r1(method::get, "/"); - request r2(method::delete_, "/item/42"); - request_view v1 = r1; - request_view v2 = r2; - v1.swap(v2); - assert(v1.buffer() == "DELETE /item/42 HTTP/1.1\r\n\r\n" ); - assert(v2.buffer() == "GET / HTTP/1.1\r\n\r\n" ); - @endcode - - @par Complexity - Constant. - - @param other The object to swap with. - */ - void - swap(request_view& other) noexcept - { - auto ph = ph_; - ph_ = other.ph_; - ph_ = ph; - } - - /** Swap. - - Exchanges the view of `v0` with - another `v1`. All iterators and - references remain valid. - - If `&v0 == &v1`, this function call has no effect. - - @par Example - @code - request r1(method::get, "/"); - request r2(method::delete_, "/item/42"); - request_view v1 = r1; - request_view v2 = r2; - std::swap(v1, v2); - assert(v1.buffer() == "DELETE /item/42 HTTP/1.1\r\n\r\n" ); - assert(v2.buffer() == "GET / HTTP/1.1\r\n\r\n" ); - @endcode - - @par Effects - @code - v0.swap(v1); - @endcode - - @par Complexity - Constant. - - @param v0 The first object to swap. - @param v1 The second object to swap. - - @see - @ref request_view::swap. - */ - friend - void - swap( - request_view& v0, - request_view& v1) noexcept - { - v0.swap(v1); - } -}; - -} // http_proto -} // boost - -#endif diff --git a/include/boost/http_proto/response.hpp b/include/boost/http_proto/response.hpp index 71dc6dd1..0650abb7 100644 --- a/include/boost/http_proto/response.hpp +++ b/include/boost/http_proto/response.hpp @@ -45,13 +45,12 @@ namespace http_proto { @see @ref static_response, - @ref response_view. + @ref response_base. */ class response : public response_base { public: - //-------------------------------------------- // // Special Members @@ -76,8 +75,7 @@ class response @par Complexity Constant. */ - BOOST_HTTP_PROTO_DECL - response() noexcept; + response() noexcept = default; /** Constructor. @@ -113,10 +111,12 @@ class response @param s The string to parse. */ - BOOST_HTTP_PROTO_DECL explicit response( - core::string_view s); + core::string_view s) + : response_base(s) + { + } /** Constructor. @@ -143,10 +143,15 @@ class response @param max_cap Maximum allowed capacity in bytes. */ - BOOST_HTTP_PROTO_DECL + explicit response( std::size_t cap, - std::size_t max_cap = std::size_t(-1)); + std::size_t max_cap = std::size_t(-1)) + : response() + { + reserve_bytes(cap); + set_max_capacity_in_bytes(max_cap); + } /** Constructor. @@ -169,10 +174,13 @@ class response @param v The HTTP version. */ - BOOST_HTTP_PROTO_DECL response( http_proto::status sc, - http_proto::version v); + http_proto::version v) + : response() + { + set_start_line(sc, v); + } /** Constructor. @@ -194,10 +202,13 @@ class response @param sc The status code. */ - BOOST_HTTP_PROTO_DECL explicit response( - http_proto::status sc); + http_proto::status sc) + : response( + sc, http_proto::version::http_1_1) + { + } /** Constructor. @@ -218,8 +229,11 @@ class response @param r The response to move from. */ - BOOST_HTTP_PROTO_DECL - response(response&& r) noexcept; + response(response&& r) noexcept + : response() + { + swap(r); + } /** Constructor. @@ -239,8 +253,7 @@ class response @param r The response to copy. */ - BOOST_HTTP_PROTO_DECL - response(response const& r); + response(response const&) = default; /** Constructor. @@ -256,14 +269,14 @@ class response Linear in `r.size()`. @par Exception Safety - Strong guarantee. Calls to allocate may throw. @param r The response to copy. */ - BOOST_HTTP_PROTO_DECL - response( - response_view const& r); + response(response_base const& r) + : response_base(r) + { + } /** Assignment @@ -286,10 +299,14 @@ class response @return A reference to this object. */ - BOOST_HTTP_PROTO_DECL response& operator=( - response&& r) noexcept; + response&& r) noexcept + { + response temp(std::move(r)); + temp.swap(*this); + return *this; + } /** Assignment. @@ -321,7 +338,7 @@ class response operator=( response const& r) { - copy_impl(*r.ph_); + copy_impl(r.h_); return *this; } @@ -353,9 +370,9 @@ class response */ response& operator=( - response_view const& r) + response_base const& r) { - copy_impl(*r.ph_); + copy_impl(r.h_); return *this; } diff --git a/include/boost/http_proto/response_base.hpp b/include/boost/http_proto/response_base.hpp index 8bc18211..3708b0d9 100644 --- a/include/boost/http_proto/response_base.hpp +++ b/include/boost/http_proto/response_base.hpp @@ -14,7 +14,6 @@ #include #include -#include #include namespace boost { @@ -31,86 +30,28 @@ class response_base : public message_base { friend class response; - template friend class static_response; response_base() noexcept - : fields_view_base( - &this->fields_base::h_) - , message_base(detail::kind::response) + : message_base(detail::kind::response) { } explicit response_base(core::string_view s) - : fields_view_base( - &this->fields_base::h_) - , message_base(detail::kind::response, s) + : message_base(detail::kind::response, s) { } - explicit - response_base(detail::header const& ph) - : fields_view_base( - &this->fields_base::h_) - , message_base(ph) - { - } - - response_base( - detail::header const& ph, - char* storage, - std::size_t cap) - : fields_view_base( - &this->fields_base::h_) - , message_base(ph, storage, cap) - { - } - -public: response_base( - char* storage, + void* storage, std::size_t cap) noexcept - : fields_view_base( - &this->fields_base::h_) - , message_base( + : message_base( detail::kind::response, storage, cap) { } - response_base( - core::string_view s, - char* storage, - std::size_t cap) - : fields_view_base( - &this->fields_base::h_) - , message_base( - detail::kind::response, storage, cap, s) - { - } - - response_base( - response_view const& other, - char* storage, - std::size_t cap) - : fields_view_base( - &this->fields_base::h_) - , message_base(*other.ph_, storage, cap) - { - } - - /** Conversion. - - @see - @ref response_view. - - @return A view of the response. - */ - operator response_view() const noexcept - { - return response_view(ph_); - } - +public: //-------------------------------------------- // // Observers @@ -127,8 +68,8 @@ class response_base reason() const noexcept { return core::string_view( - ph_->cbuf + 13, - ph_->prefix - 15); + h_.cbuf + 13, + h_.prefix - 15); } /** Return the status code. @@ -136,7 +77,7 @@ class response_base http_proto::status status() const noexcept { - return ph_->res.status; + return h_.res.status; } /** Return the status code as an integral. @@ -144,7 +85,7 @@ class response_base unsigned short status_int() const noexcept { - return ph_->res.status_int; + return h_.res.status_int; } //-------------------------------------------- diff --git a/include/boost/http_proto/response_parser.hpp b/include/boost/http_proto/response_parser.hpp index 00e0b772..6d3380e5 100644 --- a/include/boost/http_proto/response_parser.hpp +++ b/include/boost/http_proto/response_parser.hpp @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include namespace boost { @@ -143,9 +143,9 @@ class response_parser start_impl(true); } - /** Return a read-only view to the parsed response headers. + /** Return a reference to the parsed response headers. - The returned view remains valid until: + The returned reference remains valid until: @li @ref start or @ref start_head_response is called @li @ref reset is called @li The parser instance is destroyed @@ -162,7 +162,7 @@ class response_parser @ref got_header. */ BOOST_HTTP_PROTO_DECL - response_view + static_response const& get() const; }; diff --git a/include/boost/http_proto/response_view.hpp b/include/boost/http_proto/response_view.hpp deleted file mode 100644 index 4a52d7fc..00000000 --- a/include/boost/http_proto/response_view.hpp +++ /dev/null @@ -1,247 +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_RESPONSE_VIEW_HPP -#define BOOST_HTTP_PROTO_RESPONSE_VIEW_HPP - -#include -#include -#include - -namespace boost { -namespace http_proto { - -/** A view to a valid HTTP response. - - Objects of this type represent a view to - a HTTP response container. That is, it acts - like a `core::string_view` in terms of - ownership. The caller is responsible for - ensuring that the lifetime of the underlying - buffer extends until it is no - longer referenced. - - @see - @ref response, - @ref static_response, - @ref response_parser, -*/ -class response_view - : public message_view_base -{ - friend class response_base; - friend class response_parser; - - explicit - response_view( - detail::header const* ph) noexcept - : fields_view_base(ph) - { - BOOST_ASSERT(ph_->kind == - detail::kind::response); - } - -public: - - //-------------------------------------------- - // - // Special Members - // - //-------------------------------------------- - - /** Constructor. - - A default-constructed response view refer - to a valid HTTP 200 OK response with no - headers, which always remains valid. - - @par Example - @code - response_view resv; - @endcode - - @par Postconditions - @code - this->buffer() == "HTTP/1.1 200 OK\r\n\r\n" - @endcode - - @par Complexity - Constant. - */ - response_view() noexcept - : fields_view_base( - detail::header::get_default( - detail::kind::response)) - { - } - - /** Constructor. - - After construction, both response views - reference the same underlying buffer. - Ownership is not transferred. - - @par Postconditions - @code - this->buffer().data() == other.buffer().data() - @endcode - - @par Complexity - Constant. - - @param other The other view. - */ - response_view( - response_view const& other) noexcept = default; - - /** Assignment. - - After assignment, both response views - reference the same underlying buffer. - Ownership is not transferred. - - @par Postconditions - @code - this->buffer().data() == other.buffer().data() - @endcode - - @par Complexity - Constant. - - @param other The other view. - @return A reference to this object. - */ - response_view& - operator=( - response_view const& other) noexcept = default; - - /** Destructor - - Any reference, iterators, or other views - which reference the same underlying - buffer remain valid. - */ - ~response_view() = default; - - //-------------------------------------------- - // - // Observers - // - //-------------------------------------------- - - /** Return the reason string - - This field is obsolete in `HTTP/1.1` - and should only be used for display - purposes. - */ - core::string_view - reason() const noexcept - { - return core::string_view( - ph_->cbuf + 13, - ph_->prefix - 15); - } - - /** Return the status code. - */ - http_proto::status - status() const noexcept - { - return ph_->res.status; - } - - /** Return the status code integer. - */ - unsigned short - status_int() const noexcept - { - return ph_->res.status_int; - } - - //-------------------------------------------- - - /** Swap. - - Exchanges the view with that of `other`. - All iterators and references remain valid. - - If `this == &other`, this function call has no effect. - - @par Example - @code - response r1(status::ok); - response r2(status::bad_request); - response_view v1 = r1; - response_view v2 = r2; - v1.swap(v2); - assert(v1.buffer() == "HTTP/1.1 400 Bad Request\r\n\r\n" ); - assert(v2.buffer() == "HTTP/1.1 200 OK\r\n\r\n" ); - @endcode - - @par Complexity - Constant. - - @param other The object to swap with. - */ - void - swap(response_view& other) noexcept - { - auto ph = ph_; - ph_ = other.ph_; - ph_ = ph; - } - - /** Swap. - - Exchanges the view of `v0` with - another `v1`. All iterators and - references remain valid. - - If `&v0 == &v1`, this function call has no effect. - - @par Example - @code - response r1(status::ok); - response r2(status::bad_request); - response_view v1 = r1; - response_view v2 = r2; - std::swap(v1, v2); - assert(v1.buffer() == "HTTP/1.1 400 Bad Request\r\n\r\n" ); - assert(v2.buffer() == "HTTP/1.1 200 OK\r\n\r\n" ); - @endcode - - @par Effects - @code - v0.swap(v1); - @endcode - - @par Complexity - Constant. - - @param v0 The first object to swap. - @param v1 The second object to swap. - - @see - @ref response_view::swap. - */ - friend - void - swap( - response_view& v0, - response_view& v1) noexcept - { - v0.swap(v1); - } -}; - -} // http_proto -} // boost - -#endif diff --git a/include/boost/http_proto/rfc/combine_field_values.hpp b/include/boost/http_proto/rfc/combine_field_values.hpp index 0e0e1152..1811a870 100644 --- a/include/boost/http_proto/rfc/combine_field_values.hpp +++ b/include/boost/http_proto/rfc/combine_field_values.hpp @@ -11,7 +11,7 @@ #define BOOST_HTTP_PROTO_RFC_COMBINE_FIELD_VALUES_HPP #include -#include +#include #include #include #include @@ -55,7 +55,7 @@ namespace http_proto { BOOST_HTTP_PROTO_DECL core::string_view combine_field_values( - fields_view_base::subrange const& vr, + fields_base::subrange const& vr, grammar::recycled_ptr& temp); } // http_proto diff --git a/include/boost/http_proto/serializer.hpp b/include/boost/http_proto/serializer.hpp index 0d3fbfc0..f65f13ad 100644 --- a/include/boost/http_proto/serializer.hpp +++ b/include/boost/http_proto/serializer.hpp @@ -27,7 +27,7 @@ namespace boost { namespace http_proto { // Forward declaration -class message_view_base; +class message_base; /** A serializer for HTTP/1 messages @@ -191,11 +191,11 @@ class serializer start-line and headers from. @see - @ref message_view_base. + @ref message_base. */ void BOOST_HTTP_PROTO_DECL - start(message_view_base const& m); + start(message_base const& m); /** Prepare the serializer for a new message with a ConstBufferSequence body. @@ -248,7 +248,7 @@ class serializer until @ref is_done returns `true`. @see - @ref message_view_base. + @ref message_base. */ template< class ConstBufferSequence, @@ -258,7 +258,7 @@ class serializer > void start( - message_view_base const& m, + message_base const& m, ConstBufferSequence&& buffers); /** Prepare the serializer for a new message with a Source body. @@ -321,7 +321,7 @@ class serializer @see @ref source, @ref file_source, - @ref message_view_base. + @ref message_base. */ template< class Source, @@ -330,7 +330,7 @@ class serializer is_source::value>::type> Source& start( - message_view_base const& m, + message_base const& m, Args&&... args); /** Prepare the serializer for a new message using a stream interface. @@ -402,12 +402,12 @@ class serializer @see @ref stream, - @ref message_view_base. + @ref message_base. */ BOOST_HTTP_PROTO_DECL stream start_stream( - message_view_base const& m); + message_base const& m); /** Return the output area. @@ -527,18 +527,18 @@ class serializer BOOST_HTTP_PROTO_DECL void start_init( - message_view_base const&); + message_base const&); BOOST_HTTP_PROTO_DECL void start_buffers( - message_view_base const&, + message_base const&, cbs_gen&); BOOST_HTTP_PROTO_DECL void start_source( - message_view_base const&, + message_base const&, source&); impl* impl_; diff --git a/include/boost/http_proto/static_fields.hpp b/include/boost/http_proto/static_fields.hpp deleted file mode 100644 index 24b71904..00000000 --- a/include/boost/http_proto/static_fields.hpp +++ /dev/null @@ -1,281 +0,0 @@ -// -// Copyright (c) 2025 Mohammad Nejati -// -// 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_STATIC_FIELDS_HPP -#define BOOST_HTTP_PROTO_STATIC_FIELDS_HPP - -#include -#include -#include -#include - -namespace boost { -namespace http_proto { - -/** A modifiable static container of HTTP fields. - - This container owns a collection of HTTP fields, - represented by an inline buffer with fixed capacity. - The contents may be inspected and modified, - and the implementation maintains a useful - invariant: changes to the fields always - leave it in a valid state. - - @par Example - @code - static_fields<1024> fs; - - fs.set(field::host, "example.com"); - fs.set(field::accept_encoding, "gzip, deflate, br"); - fs.set(field::cache_control, "no-cache"); - - assert(fs.buffer() == - "Host: example.com\r\n" - "Accept-Encoding: gzip, deflate, br\r\n" - "Cache-Control: no-cache\r\n" - "\r\n"); - @endcode - - @par Invariants - @code - this->capacity_in_bytes() == Capacity && this->max_capacity_in_bytes() == Capacity - @endcode - - @tparam Capacity The maximum capacity in bytes. - - @see - @ref fields, - @ref fields_view. -*/ -template -class static_fields final - : public fields_base -{ - alignas(entry) - char buf_[Capacity]; - -public: - - //-------------------------------------------- - // - // Special Members - // - //-------------------------------------------- - - /** Constructor. - - A default-constructed fields container - contains no name-value pairs. - - @par Example - @code - static_fields<1024> fs; - @endcode - - @par Postconditions - @code - this->buffer() == "\r\n" - @endcode - - @par Complexity - Constant. - */ - static_fields() noexcept - : fields_view_base( - &this->fields_base::h_) - , fields_base( - detail::kind::fields, - buf_, - Capacity) - { - } - - - /** Constructor. - - Constructs a fields container from the - string `s`, which must contain valid - HTTP fields or else an exception is thrown. - The new fields container retains ownership - by making a copy of the passed string. - - @par Example - @code - static_fields<1024> fs( - "Server: Boost.HttpProto\r\n" - "Content-Type: text/plain\r\n" - "\r\n"); - @endcode - - @par Postconditions - @code - this->buffer.data() != s.data() - @endcode - - @par Complexity - Linear in `s.size()`. - - @par Exception Safety - Exception thrown on invalid input. - Exception thrown if max capacity exceeded. - - @throw system_error - The input does not contain a valid HTTP fields. - - @throw std::length_error - Max capacity would be exceeded. - - @param s The string to parse. - */ - explicit static_fields( - core::string_view s) - : fields_view_base( - &this->fields_base::h_) - , fields_base( - detail::kind::fields, - buf_, - Capacity, - s) - { - } - - /** Constructor. - - The newly constructed object contains - a copy of `f`. - - @par Postconditions - @code - this->buffer() == f.buffer() && this->buffer.data() != f.buffer().data() - @endcode - - @par Complexity - Linear in `f.size()`. - - @param f The fields container to copy. - */ - static_fields( - static_fields const& f) noexcept - : fields_view_base( - &this->fields_base::h_) - , fields_base( - *f.ph_, - buf_, - Capacity) - { - } - - /** Constructor. - - The newly constructed object contains - a copy of `f`. - - @par Postconditions - @code - this->buffer() == f.buffer() && this->buffer.data() != f.buffer().data() - @endcode - - @par Complexity - Linear in `f.size()`. - - @par Exception Safety - Exception thrown if max capacity exceeded. - - @throw std::length_error - Max capacity would be exceeded. - - @param f The fields container to copy. - */ - /** Constructor - */ - static_fields( - fields_view const& f) - : fields_view_base( - &this->fields_base::h_) - , fields_base( - *f.ph_, - buf_, - Capacity) - { - } - - /** Assignment. - - The contents of `f` are copied and - the previous contents of `this` are - discarded. - - @par Postconditions - @code - this->buffer() == f.buffer() && this->buffer().data() != f.buffer().data() - @endcode - - @par Complexity - Linear in `f.size()`. - - @param f The fields container to copy. - - @return A reference to this object. - */ - static_fields& - operator=(static_fields const& f) noexcept - { - copy_impl(*f.ph_); - return *this; - } - - /** Assignment. - - The contents of `f` are copied and - the previous contents of `this` are - discarded. - - @par Postconditions - @code - this->buffer() == f.buffer() && this->buffer().data() != f.buffer().data() - @endcode - - @par Complexity - Linear in `f.size()`. - - @par Exception Safety - Strong guarantee. - Exception thrown if max capacity exceeded. - - @throw std::length_error - Max capacity would be exceeded. - - @param f The fields container to copy. - - @return A reference to this object. - */ - static_fields& - operator=(fields_view const& f) - { - copy_impl(*f.ph_); - return *this; - } - - /** Conversion. - - @see - @ref fields_view. - - @return A view of the fields. - */ - operator fields_view() const noexcept - { - return fields_view(ph_); - } -}; - -} // http_proto -} // boost - -#endif diff --git a/include/boost/http_proto/static_request.hpp b/include/boost/http_proto/static_request.hpp index 366f148f..b13ff1a4 100644 --- a/include/boost/http_proto/static_request.hpp +++ b/include/boost/http_proto/static_request.hpp @@ -17,8 +17,8 @@ namespace http_proto { /** A modifiable static container for HTTP requests. - This container owns a request, represented - by an inline buffer with fixed capacity. + This container uses an external memory + storage with fixed capacity. The contents may be inspected and modified, and the implementation maintains a useful invariant: changes to the request always @@ -26,40 +26,38 @@ namespace http_proto { @par Example @code - static_request<1024> req(method::get, "/"); + char buf[1024]; + static_request req(buf, sizeof(buf)); + req.set_start_line(method::get, "/"); req.set(field::host, "example.com"); req.set(field::accept_encoding, "gzip, deflate, br"); req.set(field::cache_control, "no-cache"); assert(req.buffer() == - "GET / HTTP/1.1\r\n" - "Host: example.com\r\n" - "Accept-Encoding: gzip, deflate, br\r\n" - "Cache-Control: no-cache\r\n" - "\r\n"); + "GET / HTTP/1.1\r\n" + "Host: example.com\r\n" + "Accept-Encoding: gzip, deflate, br\r\n" + "Cache-Control: no-cache\r\n" + "\r\n"); @endcode @par Invariants @code - this->capacity_in_bytes() == Capacity && this->max_capacity_in_bytes() == Capacity + this->capacity_in_bytes() == Capacity && this->max_capacity_in_bytes() == + Capacity @endcode @tparam Capacity The maximum capacity in bytes. @see @ref request, - @ref request_view. + @ref request_base. */ -template class static_request : public request_base { - alignas(entry) - char buf_[Capacity]; - public: - //-------------------------------------------- // // Special Members @@ -68,214 +66,91 @@ class static_request /** Constructor. - A default-constructed request contains - a valid HTTP `GET` request with no headers. - - @par Example - @code - static_request<1024> req; - @endcode - - @par Postconditions - @code - this->buffer() == "GET / HTTP/1.1\r\n\r\n" - @endcode - - @par Complexity - Constant. - */ - static_request() noexcept - : fields_view_base(&this->fields_base::h_) - , request_base(buf_, Capacity) - { - } - - /** Constructor. - - Constructs a request from the string `s`, - which must contain valid HTTP request - or else an exception is thrown. - The new request retains ownership by - making a copy of the passed string. + Constructs a request object that uses an + external memory storage and does not perform + any allocations during its lifetime. - @par Example - @code - static_request<1024> req( - "GET / HTTP/1.1\r\n" - "Accept-Encoding: gzip, deflate, br\r\n" - "Cache-Control: no-cache\r\n" - "\r\n"); - @endcode + The caller is responsible for ensuring that the + lifetime of the storage extends until the + request object is destroyed. - @par Postconditions + @par Postcondition @code - this->buffer.data() != s.data() + this->capacity_in_bytes() == cap + this->max_capacity_in_bytes() == cap @endcode - @par Complexity - Linear in `s.size()`. - - @par Exception Safety - Exception thrown on invalid input. - Exception thrown if max capacity exceeded. - - @throw system_error - The input does not contain a valid request. - - @throw std::length_error - Max capacity would be exceeded. - - @param s The string to parse. - */ - explicit - static_request( - core::string_view s) - : fields_view_base(&this->fields_base::h_) - , request_base(s, buf_, Capacity) - { - } - - /** Constructor. - - The start-line of the request will - contain the standard text for the - supplied method, target and HTTP version. - - @par Example - @code - static_request<1024> req(method::get, "/index.html", version::http_1_0); - @endcode - - @par Complexity - Linear in `to_string(m).size() + t.size()`. - - @par Exception Safety - Exception thrown if max capacity exceeded. - - @throw std::length_error - Max capacity would be exceeded. - - @param m The method to set. - - @param t The string representing a target. - - @param v The version to set. + @param storage The storage to use. + @param cap The capacity of the storage. */ static_request( - http_proto::method m, - core::string_view t, - http_proto::version v) noexcept - : static_request() + void* storage, + std::size_t cap) + : request_base(storage, cap) { - set_start_line(m, t, v); } - /** Constructor. - - The start-line of the request will - contain the standard text for the - supplied method and target with the HTTP - version defaulted to `HTTP/1.1`. - - @par Example - @code - static_request<1024> req(method::get, "/index.html"); - @endcode - - @par Complexity - Linear in `obsolete_reason(s).size()`. - - @par Exception Safety - Exception thrown if max capacity exceeded. - - @throw std::length_error - Max capacity would be exceeded. - - @param m The method to set. - - @param t The string representing a target. + /** Constructor (deleted) */ static_request( - http_proto::method m, - core::string_view t) - : static_request( - m, t, http_proto::version::http_1_1) - { - } + static_request const&) = delete; /** Constructor. - The newly constructed object contains - a copy of `r`. - - @par Postconditions - @code - this->buffer() == r.buffer() && this->buffer.data() != r.buffer().data() - @endcode + The contents of `r` are transferred + to the newly constructed object, + which includes the underlying + character buffer. + After construction, the moved-from + object has a valid but unspecified + state where the only safe operation + is destruction. @par Complexity - Linear in `r.size()`. + Constant. - @param r The request to copy. + @param r The request to move from. */ static_request( - static_request const& r) noexcept - : fields_view_base(&this->fields_base::h_) - , request_base(*r.ph_, buf_, Capacity) + static_request&& r) noexcept + : request_base() { + h_.swap(r.h_); + external_storage_ = true; + max_cap_ = r.max_cap_; + r.max_cap_ = 0; } - /** Constructor. + /** Assignment. - The newly constructed object contains - a copy of `r`. + The contents of `r` are copied and + the previous contents of `this` are + discarded. @par Postconditions @code - this->buffer() == r.buffer() && this->buffer.data() != r.buffer().data() + this->buffer() == r.buffer() && this->buffer().data() != r.buffer().data() @endcode @par Complexity Linear in `r.size()`. @par Exception Safety + Strong guarantee. Exception thrown if max capacity exceeded. @throw std::length_error Max capacity would be exceeded. @param r The request to copy. - */ - static_request( - request_view const& r) - : fields_view_base(&this->fields_base::h_) - , request_base(*r.ph_, buf_, Capacity) - { - } - - /** Assignment. - - The contents of `r` are copied and - the previous contents of `this` are - discarded. - - @par Postconditions - @code - this->buffer() == r.buffer() && this->buffer().data() != r.buffer().data() - @endcode - - @par Complexity - Linear in `r.size()`. - - @param r The request to copy. @return A reference to this object. */ static_request& operator=( - static_request const& r) noexcept + static_request const& r) { - copy_impl(*r.ph_); + copy_impl(r.h_); return *this; } @@ -306,9 +181,9 @@ class static_request */ static_request& operator=( - request_view const& r) + request_base const& r) { - copy_impl(*r.ph_); + copy_impl(r.h_); return *this; } }; diff --git a/include/boost/http_proto/static_response.hpp b/include/boost/http_proto/static_response.hpp index 4efee020..3a9e2702 100644 --- a/include/boost/http_proto/static_response.hpp +++ b/include/boost/http_proto/static_response.hpp @@ -17,8 +17,8 @@ namespace http_proto { /** A modifiable static container for HTTP responses. - This container owns a response, represented - by an inline buffer with fixed capacity. + This container uses an external memory + storage with fixed capacity. The contents may be inspected and modified, and the implementation maintains a useful invariant: changes to the response always @@ -26,8 +26,10 @@ namespace http_proto { @par Example @code - static_response<1024> res(status::not_found); + char buf[1024]; + static_response res(buf, sizeof(buf)); + res.set_start_line(status::not_found); res.set(field::server, "Boost.HttpProto"); res.set(field::content_type, "text/plain"); res.set_content_length(80); @@ -49,17 +51,12 @@ namespace http_proto { @see @ref response, - @ref response_view. + @ref response_base. */ -template class static_response : public response_base { - alignas(entry) - char buf_[Capacity]; - public: - //-------------------------------------------- // // Special Members @@ -68,209 +65,91 @@ class static_response /** Constructor. - A default-constructed response contains - a valid HTTP 200 OK response with no headers. - - @par Example - @code - static_response<1024> res; - @endcode - - @par Postconditions - @code - this->buffer() == "HTTP/1.1 200 OK\r\n\r\n" - @endcode - - @par Complexity - Constant. - */ - static_response() noexcept - : fields_view_base(&this->fields_base::h_) - , response_base(buf_, Capacity) - { - } - - /** Constructor. - - Constructs a response from the string `s`, - which must contain valid HTTP response - or else an exception is thrown. - The new response retains ownership by - making a copy of the passed string. - - @par Example - @code - static_response<1024> res( - "HTTP/1.1 404 Not Found\r\n" - "Server: Boost.HttpProto\r\n" - "Content-Type: text/plain\r\n" - "\r\n"); - @endcode - - @par Postconditions - @code - this->buffer.data() != s.data() - @endcode - - @par Complexity - Linear in `s.size()`. + Constructs a response object that uses an + external memory storage and does not perform + any allocations during its lifetime. - @par Exception Safety - Exception thrown on invalid input. - Exception thrown if max capacity exceeded. - - @throw system_error - The input does not contain a valid response. - - @throw std::length_error - Max capacity would be exceeded. - - @param s The string to parse. - */ - explicit - static_response( - core::string_view s) - : fields_view_base(&this->fields_base::h_) - , response_base(s, buf_, Capacity) - { - } + The caller is responsible for ensuring that the + lifetime of the storage extends until the + response object is destroyed. - /** Constructor. - - The start-line of the response will - contain the standard text for the - supplied status code and HTTP version. - - @par Example + @par Postcondition @code - static_response<1024> res(status::not_found, version::http_1_0); + this->capacity_in_bytes() == cap + this->max_capacity_in_bytes() == cap @endcode - @par Complexity - Linear in `obsolete_reason(s).size()`. - - @par Exception Safety - Exception thrown if max capacity exceeded. - - @throw std::length_error - Max capacity would be exceeded. - - @param sc The status code. - - @param v The HTTP version. + @param storage The storage to use. + @param cap The capacity of the storage. */ static_response( - http_proto::status sc, - http_proto::version v) - : static_response() + void* storage, + std::size_t cap) + : response_base(storage, cap) { - set_start_line(sc, v); } - /** Constructor. - - The start-line of the response will - contain the standard text for the - supplied status code with the HTTP version - defaulted to `HTTP/1.1`. - - @par Example - @code - static_response<1024> res(status::not_found); - @endcode - - @par Complexity - Linear in `obsolete_reason(s).size()`. - - @par Exception Safety - Exception thrown if max capacity exceeded. - - @throw std::length_error - Max capacity would be exceeded. - - @param sc The status code. + /** Constructor (deleted) */ - explicit static_response( - http_proto::status sc) - : static_response( - sc, http_proto::version::http_1_1) - { - } + static_response const&) = delete; /** Constructor. - The newly constructed object contains - a copy of `r`. - - @par Postconditions - @code - this->buffer() == r.buffer() && this->buffer.data() != r.buffer().data() - @endcode + The contents of `r` are transferred + to the newly constructed object, + which includes the underlying + character buffer. + After construction, the moved-from + object has a valid but unspecified + state where the only safe operation + is destruction. @par Complexity - Linear in `r.size()`. + Constant. - @param r The response to copy. + @param r The response to move from. */ static_response( - static_response const& r) noexcept - : fields_view_base(&this->fields_base::h_) - , response_base(*r.ph_, buf_, Capacity) + static_response&& r) noexcept + : response_base() { + h_.swap(r.h_); + external_storage_ = true; + max_cap_ = r.max_cap_; + r.max_cap_ = 0; } - /** Constructor. + /** Assignment. - The newly constructed object contains - a copy of `r`. + The contents of `r` are copied and + the previous contents of `this` are + discarded. @par Postconditions @code - this->buffer() == r.buffer() && this->buffer.data() != r.buffer().data() + this->buffer() == r.buffer() && this->buffer().data() != r.buffer().data() @endcode @par Complexity Linear in `r.size()`. @par Exception Safety + Strong guarantee. Exception thrown if max capacity exceeded. @throw std::length_error Max capacity would be exceeded. @param r The response to copy. - */ - static_response( - response_view const& r) - : fields_view_base(&this->fields_base::h_) - , response_base(*r.ph_, buf_, Capacity) - { - } - - /** Assignment. - - The contents of `r` are copied and - the previous contents of `this` are - discarded. - - @par Postconditions - @code - this->buffer() == r.buffer() && this->buffer().data() != r.buffer().data() - @endcode - - @par Complexity - Linear in `r.size()`. - - @param r The response to copy. @return A reference to this object. */ static_response& operator=( - static_response const& r) noexcept + static_response const& r) { - copy_impl(*r.ph_); + copy_impl(r.h_); return *this; } @@ -301,9 +180,9 @@ class static_response */ static_response& operator=( - response_view const& r) + response_base const& r) { - copy_impl(*r.ph_); + copy_impl(r.h_); return *this; } }; diff --git a/src/detail/header.cpp b/src/detail/header.cpp index 7f14f30d..64cfeb79 100644 --- a/src/detail/header.cpp +++ b/src/detail/header.cpp @@ -13,7 +13,6 @@ #include #include -#include #include #include #include diff --git a/src/fields.cpp b/src/fields.cpp deleted file mode 100644 index 5ba67e21..00000000 --- a/src/fields.cpp +++ /dev/null @@ -1,89 +0,0 @@ -// -// Copyright (c) 2021 Vinnie Falco (vinnie.falco@gmail.com) -// Copyright (c) 2024 Christian Mazakas -// -// 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 -// - -#include -#include -#include -#include -#include -#include - -namespace boost { -namespace http_proto { - -fields:: -fields() noexcept - : fields_view_base( - &this->fields_base::h_) - , fields_base( - detail::kind::fields) -{ -} - -fields:: -fields( - core::string_view s) - : fields_view_base( - &this->fields_base::h_) - , fields_base( - detail::kind::fields, s) -{ -} - -fields:: -fields( - std::size_t cap, - std::size_t max_cap) - : fields() -{ - reserve_bytes(cap); - set_max_capacity_in_bytes(max_cap); -} - -fields:: -fields( - fields&& other) noexcept - : fields_view_base( - &this->fields_base::h_) - , fields_base(other.h_.kind) -{ - swap(other); -} - -fields:: -fields( - fields const& other) - : fields_view_base( - &this->fields_base::h_) - , fields_base(*other.ph_) -{ -} - -fields:: -fields( - fields_view const& other) - : fields_view_base( - &this->fields_base::h_) - , fields_base(*other.ph_) -{ -} - -fields& -fields:: -operator=( - fields&& other) noexcept -{ - fields tmp(std::move(other)); - tmp.swap(*this); - return *this; -} - -} // http_proto -} // boost diff --git a/src/fields_base.cpp b/src/fields_base.cpp index c98b9f62..a58e4a81 100644 --- a/src/fields_base.cpp +++ b/src/fields_base.cpp @@ -306,15 +306,14 @@ prefix_op_t:: fields_base:: fields_base( detail::kind k) noexcept - : fields_view_base(&h_) - , h_(k) + : h_(k) { } fields_base:: fields_base( detail::kind k, - char* storage, + void* storage, std::size_t cap) noexcept : fields_base( *detail::header::get_default(k), storage, cap) @@ -326,8 +325,7 @@ fields_base:: fields_base( detail::kind k, core::string_view s) - : fields_view_base(&h_) - , h_(detail::empty{k}) + : h_(detail::empty{k}) { auto n = detail::header::count_crlf(s); if(h_.kind == detail::kind::fields) @@ -353,59 +351,11 @@ fields_base( detail::throw_system_error(ec); } -// copy s and parse it -fields_base:: -fields_base( - detail::kind k, - char* storage, - std::size_t cap, - core::string_view s) - : fields_view_base(&h_) - , h_(detail::empty{k}) - , external_storage_(true) -{ - h_.cbuf = storage; - h_.buf = storage; - h_.cap = align_down( - storage, - cap, - alignof(detail::header::entry)); - max_cap_ = h_.cap; - - auto n = detail::header::count_crlf(s); - if(h_.kind == detail::kind::fields) - { - if(n < 1) - detail::throw_invalid_argument(); - n -= 1; - } - else - { - if(n < 2) - detail::throw_invalid_argument(); - n -= 2; - } - - if(detail::header::bytes_needed( - s.size(), n) - >= h_.cap) - detail::throw_length_error(); - - s.copy(h_.buf, s.size()); - system::error_code ec; - // VFALCO This is using defaults? - header_limits lim; - h_.parse(s.size(), lim, ec); - if(ec.failed()) - detail::throw_system_error(ec); -} - // construct a complete copy of h fields_base:: fields_base( detail::header const& h) - : fields_view_base(&h_) - , h_(h.kind) + : h_(h.kind) { if(h.is_default()) return; @@ -423,14 +373,13 @@ fields_base( fields_base:: fields_base( detail::header const& h, - char* storage, + void* storage, std::size_t cap) - : fields_view_base(&h_) - , h_(h.kind) + : h_(h.kind) , external_storage_(true) { - h_.cbuf = storage; - h_.buf = storage; + h_.cbuf = static_cast(storage); + h_.buf = static_cast(storage); h_.cap = align_down( storage, cap, @@ -450,6 +399,12 @@ fields_base( //------------------------------------------------ +fields_base:: +fields_base(fields_base const& other) + : fields_base(other.h_) +{ +} + fields_base:: ~fields_base() { @@ -526,6 +481,385 @@ set_max_capacity_in_bytes(std::size_t n) max_cap_ = n; } +//-------------------------------------------- +// +// Observers +// +//-------------------------------------------- + + +fields_base:: +value_type:: +value_type( + reference const& other) + : id(other.id) + , name(other.name) + , value(other.value) +{ +} + +//------------------------------------------------ + +auto +fields_base:: +iterator:: +operator*() const noexcept -> + reference +{ + BOOST_ASSERT(i_ < ph_->count); + auto tab = + ph_->tab(); + auto const& e = + tab[i_]; + auto const* p = + ph_->cbuf + ph_->prefix; + return { + (e.id == detail::header::unknown_field) + ? optional{} : e.id, + core::string_view( + p + e.np, e.nn), + core::string_view( + p + e.vp, e.vn) }; +} + +//------------------------------------------------ + +auto +fields_base:: +reverse_iterator:: +operator*() const noexcept -> + reference +{ + BOOST_ASSERT(i_ > 0); + auto tab = + ph_->tab(); + auto const& e = + tab[i_-1]; + auto const* p = + ph_->cbuf + ph_->prefix; + return { + (e.id == detail::header::unknown_field) + ? optional{} : e.id, + core::string_view( + p + e.np, e.nn), + core::string_view( + p + e.vp, e.vn) }; +} + +//------------------------------------------------ + +fields_base:: +subrange:: +iterator:: +iterator( + detail::header const* ph, + std::size_t i) noexcept + : ph_(ph) + , i_(i) +{ + BOOST_ASSERT(i <= ph_->count); +} + +fields_base:: +subrange:: +iterator:: +iterator( + detail::header const* ph) noexcept + : ph_(ph) + , i_(ph->count) +{ +} + +auto +fields_base:: +subrange:: +iterator:: +operator*() const noexcept -> + reference const +{ + auto tab = + ph_->tab(); + auto const& e = + tab[i_]; + auto const p = + ph_->cbuf + ph_->prefix; + return core::string_view( + p + e.vp, e.vn); +} + +auto +fields_base:: +subrange:: +iterator:: +operator++() noexcept -> + iterator& +{ + BOOST_ASSERT(i_ < ph_->count); + auto const* e = &ph_->tab()[i_]; + auto const id = e->id; + if(id != detail::header::unknown_field) + { + ++i_; + --e; + while(i_ != ph_->count) + { + if(e->id == id) + break; + ++i_; + --e; + } + return *this; + } + auto const p = + ph_->cbuf + ph_->prefix; + auto name = core::string_view( + p + e->np, e->nn); + ++i_; + --e; + while(i_ != ph_->count) + { + if(grammar::ci_is_equal( + name, core::string_view( + p + e->np, e->nn))) + break; + ++i_; + --e; + } + return *this; +} + +//------------------------------------------------ +// +// fields_base +// +//------------------------------------------------ + +core::string_view +fields_base:: +at( + field id) const +{ + auto const it = find(id); + if(it == end()) + BOOST_THROW_EXCEPTION( + std::out_of_range{ "field not found" }); + return it->value; +} + +core::string_view +fields_base:: +at( + core::string_view name) const +{ + auto const it = find(name); + if(it == end()) + BOOST_THROW_EXCEPTION( + std::out_of_range{ "field not found" }); + return it->value; +} + +bool +fields_base:: +exists( + field id) const noexcept +{ + return find(id) != end(); +} + +bool +fields_base:: +exists( + core::string_view name) const noexcept +{ + return find(name) != end(); +} + +std::size_t +fields_base:: +count(field id) const noexcept +{ + std::size_t n = 0; + for(auto v : *this) + if(v.id == id) + ++n; + return n; +} + +std::size_t +fields_base:: +count( + core::string_view name) const noexcept +{ + std::size_t n = 0; + for(auto v : *this) + if(grammar::ci_is_equal( + v.name, name)) + ++n; + return n; +} + +auto +fields_base:: +find(field id) const noexcept -> + iterator +{ + auto it = begin(); + auto const last = end(); + while(it != last) + { + if(it->id == id) + break; + ++it; + } + return it; +} + +auto +fields_base:: +find( + core::string_view name) const noexcept -> + iterator +{ + auto it = begin(); + auto const last = end(); + while(it != last) + { + if(grammar::ci_is_equal( + it->name, name)) + break; + ++it; + } + return it; +} + +auto +fields_base:: +find( + iterator from, + field id) const noexcept -> + iterator +{ + auto const last = end(); + while(from != last) + { + if(from->id == id) + break; + ++from; + } + return from; +} + +auto +fields_base:: +find( + iterator from, + core::string_view name) const noexcept -> + iterator +{ + auto const last = end(); + while(from != last) + { + if(grammar::ci_is_equal( + name, from->name)) + break; + ++from; + } + return from; +} + +auto +fields_base:: +find_last( + iterator it, + field id) const noexcept -> + iterator +{ + auto const it0 = begin(); + for(;;) + { + if(it == it0) + return end(); + --it; + if(it->id == id) + return it; + } +} + +auto +fields_base:: +find_last( + iterator it, + core::string_view name) const noexcept -> + iterator +{ + auto const it0 = begin(); + for(;;) + { + if(it == it0) + return end(); + --it; + if(grammar::ci_is_equal( + it->name, name)) + return it; + } +} + +core::string_view +fields_base:: +value_or( + field id, + core::string_view s) const noexcept +{ + auto it = find(id); + if(it != end()) + return it->value; + return s; +} + +core::string_view +fields_base:: +value_or( + core::string_view name, + core::string_view s) const noexcept +{ + auto it = find(name); + if(it != end()) + return it->value; + return s; +} + +//------------------------------------------------ + +auto +fields_base:: +find_all( + field id) const noexcept -> + subrange +{ + return subrange( + &h_, find(id).i_); +} + +auto +fields_base:: +find_all( + core::string_view name) const noexcept -> + subrange +{ + return subrange( + &h_, find(name).i_); +} + +//------------------------------------------------ + +std::ostream& +operator<<( + std::ostream& os, + const fields_base& f) +{ + return os << f.buffer(); +} + //------------------------------------------------ // // Modifiers @@ -787,6 +1121,83 @@ set( rv->has_obs_fold); } +auto +fields_base:: +insert( + iterator before, + field id, + core::string_view value) + -> iterator +{ + system::error_code ec; + auto const it = insert(before, id, value, ec); + if(ec.failed()) + detail::throw_system_error(ec); + return it; +} + +auto +fields_base:: +insert( + iterator before, + field id, + core::string_view value, + system::error_code& ec) + -> iterator +{ + insert_impl( + id, + to_string(id), + value, + before.i_, ec); + return before; +} + +auto +fields_base:: +insert( + iterator before, + core::string_view name, + core::string_view value) + -> iterator +{ + system::error_code ec; + insert(before, name, value, ec); + if(ec.failed()) + detail::throw_system_error(ec); + return before; +} + +auto +fields_base:: +insert( + iterator before, + core::string_view name, + core::string_view value, + system::error_code& ec) + -> iterator +{ + insert_impl( + string_to_field(name), + name, + value, + before.i_, + ec); + return before; +} + +void +fields_base:: +set( + iterator it, + core::string_view value) +{ + system::error_code ec; + set(it, value, ec); + if(ec.failed()) + detail::throw_system_error(ec); +} + //------------------------------------------------ // // (implementation) @@ -800,7 +1211,7 @@ copy_impl( detail::header const& h) { BOOST_ASSERT( - h.kind == ph_->kind); + h.kind == h_.kind); auto const n = detail::header::bytes_needed( diff --git a/src/fields_view_base.cpp b/src/fields_view_base.cpp deleted file mode 100644 index 49a6d964..00000000 --- a/src/fields_view_base.cpp +++ /dev/null @@ -1,395 +0,0 @@ -// -// Copyright (c) 2021 Vinnie Falco (vinnie.falco@gmail.com) -// Copyright (c) 2025 Mohammad Nejati -// -// 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 -// - -#include -#include -#include -#include -#include -#include -#include - -namespace boost { -namespace http_proto { - -fields_view_base:: -value_type:: -value_type( - reference const& other) - : id(other.id) - , name(other.name) - , value(other.value) -{ -} - -//------------------------------------------------ - -auto -fields_view_base:: -iterator:: -operator*() const noexcept -> - reference -{ - BOOST_ASSERT(i_ < ph_->count); - auto tab = - ph_->tab(); - auto const& e = - tab[i_]; - auto const* p = - ph_->cbuf + ph_->prefix; - return { - (e.id == detail::header::unknown_field) - ? optional{} : e.id, - core::string_view( - p + e.np, e.nn), - core::string_view( - p + e.vp, e.vn) }; -} - -//------------------------------------------------ - -auto -fields_view_base:: -reverse_iterator:: -operator*() const noexcept -> - reference -{ - BOOST_ASSERT(i_ > 0); - auto tab = - ph_->tab(); - auto const& e = - tab[i_-1]; - auto const* p = - ph_->cbuf + ph_->prefix; - return { - (e.id == detail::header::unknown_field) - ? optional{} : e.id, - core::string_view( - p + e.np, e.nn), - core::string_view( - p + e.vp, e.vn) }; -} - -//------------------------------------------------ - -fields_view_base:: -subrange:: -iterator:: -iterator( - detail::header const* ph, - std::size_t i) noexcept - : ph_(ph) - , i_(i) -{ - BOOST_ASSERT(i <= ph_->count); -} - -fields_view_base:: -subrange:: -iterator:: -iterator( - detail::header const* ph) noexcept - : ph_(ph) - , i_(ph->count) -{ -} - -auto -fields_view_base:: -subrange:: -iterator:: -operator*() const noexcept -> - reference const -{ - auto tab = - ph_->tab(); - auto const& e = - tab[i_]; - auto const p = - ph_->cbuf + ph_->prefix; - return core::string_view( - p + e.vp, e.vn); -} - -auto -fields_view_base:: -subrange:: -iterator:: -operator++() noexcept -> - iterator& -{ - BOOST_ASSERT(i_ < ph_->count); - auto const* e = &ph_->tab()[i_]; - auto const id = e->id; - if(id != detail::header::unknown_field) - { - ++i_; - --e; - while(i_ != ph_->count) - { - if(e->id == id) - break; - ++i_; - --e; - } - return *this; - } - auto const p = - ph_->cbuf + ph_->prefix; - auto name = core::string_view( - p + e->np, e->nn); - ++i_; - --e; - while(i_ != ph_->count) - { - if(grammar::ci_is_equal( - name, core::string_view( - p + e->np, e->nn))) - break; - ++i_; - --e; - } - return *this; -} - -//------------------------------------------------ -// -// fields_view_base -// -//------------------------------------------------ - -core::string_view -fields_view_base:: -at( - field id) const -{ - auto const it = find(id); - if(it == end()) - BOOST_THROW_EXCEPTION( - std::out_of_range{ "field not found" }); - return it->value; -} - -core::string_view -fields_view_base:: -at( - core::string_view name) const -{ - auto const it = find(name); - if(it == end()) - BOOST_THROW_EXCEPTION( - std::out_of_range{ "field not found" }); - return it->value; -} - -bool -fields_view_base:: -exists( - field id) const noexcept -{ - return find(id) != end(); -} - -bool -fields_view_base:: -exists( - core::string_view name) const noexcept -{ - return find(name) != end(); -} - -std::size_t -fields_view_base:: -count(field id) const noexcept -{ - std::size_t n = 0; - for(auto v : *this) - if(v.id == id) - ++n; - return n; -} - -std::size_t -fields_view_base:: -count( - core::string_view name) const noexcept -{ - std::size_t n = 0; - for(auto v : *this) - if(grammar::ci_is_equal( - v.name, name)) - ++n; - return n; -} - -auto -fields_view_base:: -find(field id) const noexcept -> - iterator -{ - auto it = begin(); - auto const last = end(); - while(it != last) - { - if(it->id == id) - break; - ++it; - } - return it; -} - -auto -fields_view_base:: -find( - core::string_view name) const noexcept -> - iterator -{ - auto it = begin(); - auto const last = end(); - while(it != last) - { - if(grammar::ci_is_equal( - it->name, name)) - break; - ++it; - } - return it; -} - -auto -fields_view_base:: -find( - iterator from, - field id) const noexcept -> - iterator -{ - auto const last = end(); - while(from != last) - { - if(from->id == id) - break; - ++from; - } - return from; -} - -auto -fields_view_base:: -find( - iterator from, - core::string_view name) const noexcept -> - iterator -{ - auto const last = end(); - while(from != last) - { - if(grammar::ci_is_equal( - name, from->name)) - break; - ++from; - } - return from; -} - -auto -fields_view_base:: -find_last( - iterator it, - field id) const noexcept -> - iterator -{ - auto const it0 = begin(); - for(;;) - { - if(it == it0) - return end(); - --it; - if(it->id == id) - return it; - } -} - -auto -fields_view_base:: -find_last( - iterator it, - core::string_view name) const noexcept -> - iterator -{ - auto const it0 = begin(); - for(;;) - { - if(it == it0) - return end(); - --it; - if(grammar::ci_is_equal( - it->name, name)) - return it; - } -} - -core::string_view -fields_view_base:: -value_or( - field id, - core::string_view s) const noexcept -{ - auto it = find(id); - if(it != end()) - return it->value; - return s; -} - -core::string_view -fields_view_base:: -value_or( - core::string_view name, - core::string_view s) const noexcept -{ - auto it = find(name); - if(it != end()) - return it->value; - return s; -} - -//------------------------------------------------ - -auto -fields_view_base:: -find_all( - field id) const noexcept -> - subrange -{ - return subrange( - ph_, find(id).i_); -} - -auto -fields_view_base:: -find_all( - core::string_view name) const noexcept -> - subrange -{ - return subrange( - ph_, find(name).i_); -} - -//------------------------------------------------ - -std::ostream& -operator<<( - std::ostream& os, - const fields_view_base& f) -{ - return os << f.buffer(); -} - -} // http_proto -} // boost diff --git a/src/message_base.cpp b/src/message_base.cpp index 5f173fe1..7f5ace2d 100644 --- a/src/message_base.cpp +++ b/src/message_base.cpp @@ -73,16 +73,16 @@ void message_base:: set_keep_alive(bool value) { - if(ph_->md.connection.ec.failed()) + if(h_.md.connection.ec.failed()) { // throw? return false? return; } - if(ph_->md.connection.count == 0) + if(h_.md.connection.count == 0) { // no Connection field - switch(ph_->version) + switch(h_.version) { default: case http_proto::version::http_1_1: @@ -155,22 +155,22 @@ set_keep_alive(bool value) }; if(value) { - if(ph_->md.connection.close) + if(h_.md.connection.close) erase_token("close"); } else { - if(ph_->md.connection.keep_alive) + if(h_.md.connection.keep_alive) erase_token("keep-alive"); } - switch(ph_->version) + switch(h_.version) { default: case http_proto::version::http_1_1: if(! value) { // add one "close" token if needed - if(! ph_->md.connection.close) + if(! h_.md.connection.close) append(field::connection, "close"); } break; @@ -179,7 +179,7 @@ set_keep_alive(bool value) if(value) { // add one "keep-alive" token if needed - if(! ph_->md.connection.keep_alive) + if(! h_.md.connection.keep_alive) append(field::connection, "keep-alive"); } break; diff --git a/src/message_view_base.cpp b/src/message_view_base.cpp deleted file mode 100644 index 03c78ac1..00000000 --- a/src/message_view_base.cpp +++ /dev/null @@ -1,16 +0,0 @@ -// -// Copyright (c) 2021 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 -// - -#include - -namespace boost { -namespace http_proto { - -} // http_proto -} // boost diff --git a/src/parser.cpp b/src/parser.cpp index f2a56616..34ab4f12 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -11,6 +11,8 @@ #include #include #include +#include +#include #include #include @@ -538,7 +540,7 @@ class parser::impl parser_service& svc_; detail::workspace ws_; - detail::header h_; + static_request m_; std::uint64_t body_limit_; std::uint64_t body_total_; std::uint64_t payload_remain_; @@ -571,10 +573,11 @@ class parser::impl : ctx_(ctx) , svc_(ctx.get_service()) , ws_(svc_.space_needed) - , h_(detail::empty{ k }) + , m_(ws_.data(), ws_.size()) , state_(state::reset) , got_header_(false) { + m_.h_ = detail::header(detail::empty{ k }); } bool @@ -589,14 +592,25 @@ class parser::impl return state_ >= state::complete_in_place; } - detail::header const* - safe_get_header() const + static_request const& + safe_get_request() const { // headers must be received if(! got_header_) detail::throw_logic_error(); - return &h_; + return m_; + } + + static_response const& + safe_get_response() const + { + // headers must be received + if(! got_header_) + detail::throw_logic_error(); + + // TODO: use a union + return reinterpret_cast(m_); } bool @@ -710,12 +724,12 @@ class parser::impl BOOST_ASSERT( head_response == false || - h_.kind == detail::kind::response); + m_.h_.kind == detail::kind::response); - h_ = detail::header(detail::empty{h_.kind}); - h_.buf = reinterpret_cast(ws_.data()); - h_.cbuf = h_.buf; - h_.cap = ws_.size(); + m_.h_ = detail::header(detail::empty{m_.h_.kind}); + m_.h_.buf = reinterpret_cast(ws_.data()); + m_.h_.cbuf = m_.h_.buf; + m_.h_.cap = ws_.size(); state_ = state::header; style_ = style::in_place; @@ -760,7 +774,7 @@ class parser::impl case state::header: { BOOST_ASSERT( - h_.size < svc_.cfg.headers.max_size); + m_.h_.size < svc_.cfg.headers.max_size); std::size_t n = fb_.capacity() - fb_.size(); BOOST_ASSERT(n <= svc_.max_overread()); n = clamp(n, svc_.cfg.max_prepare); @@ -801,7 +815,7 @@ class parser::impl std::size_t n = cb0_.capacity(); n = clamp(n, svc_.cfg.max_prepare); - if(h_.md.payload == payload::size) + if(m_.payload() == payload::size) { if(n > payload_remain_) { @@ -815,7 +829,7 @@ class parser::impl else { BOOST_ASSERT( - h_.md.payload == payload::to_eof); + m_.payload() == payload::to_eof); // No more messages can be pipelined, so // limit the output buffer to the remaining // body limit plus one byte to detect @@ -837,7 +851,7 @@ class parser::impl std::size_t n = svc_.cfg.min_buffer; - if(h_.md.payload == payload::size) + if(m_.payload() == payload::size) { // Overreads are not allowed, or // else the caller will see extra @@ -847,7 +861,7 @@ class parser::impl else { BOOST_ASSERT( - h_.md.payload == payload::to_eof); + m_.payload() == payload::to_eof); // No more messages can be pipelined, so // limit the output buffer to the remaining // body limit plus one byte to detect @@ -1050,12 +1064,12 @@ class parser::impl case state::header: { - BOOST_ASSERT(h_.buf == static_cast< + BOOST_ASSERT(m_.h_.buf == static_cast< void const*>(ws_.data())); - BOOST_ASSERT(h_.cbuf == static_cast< + BOOST_ASSERT(m_.h_.cbuf == static_cast< void const*>(ws_.data())); - h_.parse(fb_.size(), svc_.cfg.headers, ec); + m_.h_.parse(fb_.size(), svc_.cfg.headers, ec); if(ec == condition::need_more_input) { @@ -1095,15 +1109,15 @@ class parser::impl got_header_ = true; // reserve headers + table - ws_.reserve_front(h_.size); - ws_.reserve_back(h_.table_space()); + ws_.reserve_front(m_.h_.size); + ws_.reserve_back(m_.h_.table_space()); // no payload - if(h_.md.payload == payload::none || + if(m_.payload() == payload::none || head_response_) { // octets of the next message - auto overread = fb_.size() - h_.size; + auto overread = fb_.size() - m_.h_.size; cb0_ = { ws_.data(), overread, overread }; ws_.reserve_front(overread); state_ = state::complete_in_place; @@ -1117,7 +1131,7 @@ class parser::impl case state::header_done: { // metadata error - if(h_.md.payload == payload::error) + if(m_.payload() == payload::error) { // VFALCO This needs looking at ec = BOOST_HTTP_PROTO_ERR( @@ -1131,7 +1145,7 @@ class parser::impl // this can include associated body octets for the // current message or octets of the next message in the // stream, e.g. pipelining is being used - auto const overread = fb_.size() - h_.size; + auto const overread = fb_.size() - m_.h_.size; BOOST_ASSERT(overread <= svc_.max_overread()); auto cap = fb_.capacity() + overread + @@ -1141,7 +1155,7 @@ class parser::impl // must be installed after them. auto const p = ws_.reserve_front(cap); - switch(h_.md.content_encoding.coding) + switch(m_.metadata().content_encoding.coding) { case content_coding::deflate: if(!svc_.cfg.apply_deflate_decoder) @@ -1188,17 +1202,17 @@ class parser::impl cb1_ = { p + n0 , n1 }; } - if(h_.md.payload == payload::size) + if(m_.payload() == payload::size) { if(!filter_ && - body_limit_ < h_.md.payload_size) + body_limit_ < m_.payload_size()) { ec = BOOST_HTTP_PROTO_ERR( error::body_too_large); state_ = state::reset; return; } - payload_remain_ = h_.md.payload_size; + payload_remain_ = m_.payload_size(); } state_ = state::body; @@ -1209,8 +1223,8 @@ class parser::impl { do_body: BOOST_ASSERT(state_ == state::body); - BOOST_ASSERT(h_.md.payload != payload::none); - BOOST_ASSERT(h_.md.payload != payload::error); + BOOST_ASSERT(m_.payload() != payload::none); + BOOST_ASSERT(m_.payload() != payload::error); auto set_state_to_complete = [&]() { @@ -1222,7 +1236,7 @@ class parser::impl state_ = state::complete; }; - if(h_.md.payload == payload::chunked) + if(m_.payload() == payload::chunked) { for(;;) { @@ -1404,7 +1418,7 @@ class parser::impl auto ret = cb0_.size(); if(!filter_) ret -= body_avail_; - if(h_.md.payload == payload::size) + if(m_.payload() == payload::size) return clamp(payload_remain_, ret); // payload::eof return ret; @@ -1412,7 +1426,7 @@ class parser::impl const bool is_complete = [&]() { - if(h_.md.payload == payload::size) + if(m_.payload() == payload::size) return payload_avail == payload_remain_; // payload::eof return got_eof_; @@ -1429,7 +1443,7 @@ class parser::impl { // plain body - if(h_.md.payload == payload::to_eof) + if(m_.payload() == payload::to_eof) { if(body_limit_remain() < payload_avail) { @@ -1510,7 +1524,7 @@ class parser::impl } } - if(h_.md.payload == payload::size && got_eof_) + if(m_.payload() == payload::size && got_eof_) { ec = BOOST_HTTP_PROTO_ERR( error::incomplete); @@ -1693,7 +1707,7 @@ class parser::impl is_plain() const noexcept { return ! filter_ && - h_.md.payload != payload::chunked; + m_.payload() != payload::chunked; } std::uint64_t @@ -1985,12 +1999,20 @@ start_impl(bool head_response) impl_->start(head_response); } -detail::header const* +static_request const& +parser:: +safe_get_request() const +{ + BOOST_ASSERT(impl_); + return impl_->safe_get_request(); +} + +static_response const& parser:: -safe_get_header() const +safe_get_response() const { BOOST_ASSERT(impl_); - return impl_->safe_get_header(); + return impl_->safe_get_response(); } detail::workspace& diff --git a/src/request.cpp b/src/request.cpp deleted file mode 100644 index 09e22987..00000000 --- a/src/request.cpp +++ /dev/null @@ -1,84 +0,0 @@ -// -// Copyright (c) 2021 Vinnie Falco (vinnie.falco@gmail.com) -// Copyright (c) 2024 Christian Mazakas -// Copyright (c) 2025 Mohammad Nejati -// -// 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 -// - -#include - -namespace boost { -namespace http_proto { - -request:: -request() noexcept - : fields_view_base( - &this->fields_base::h_) - , request_base() -{ -} - -request:: -request( - core::string_view s) - : fields_view_base( - &this->fields_base::h_) - , request_base(s) -{ -} - -request:: -request( - std::size_t cap, - std::size_t max_cap) - : request() -{ - reserve_bytes(cap); - set_max_capacity_in_bytes(max_cap); -} - -request:: -request( - request&& other) noexcept - : fields_view_base( - &this->fields_base::h_) - , request_base() -{ - swap(other); -} - -request:: -request( - request const& other) - : fields_view_base( - &this->fields_base::h_) - , request_base(*other.ph_) -{ -} - -request:: -request( - request_view const& other) - : fields_view_base( - &this->fields_base::h_) - , request_base(*other.ph_) -{ -} - -request& -request:: -operator=( - request&& other) noexcept -{ - request temp( - std::move(other)); - temp.swap(*this); - return *this; -} - -} // http_proto -} // boost diff --git a/src/request_parser.cpp b/src/request_parser.cpp index 65e9a194..2834b4ae 100644 --- a/src/request_parser.cpp +++ b/src/request_parser.cpp @@ -21,12 +21,11 @@ request_parser( { } -request_view +static_request const& request_parser:: get() const { - return request_view( - safe_get_header()); + return safe_get_request(); } } // http_proto diff --git a/src/response.cpp b/src/response.cpp deleted file mode 100644 index a3449641..00000000 --- a/src/response.cpp +++ /dev/null @@ -1,102 +0,0 @@ -// -// Copyright (c) 2021 Vinnie Falco (vinnie.falco@gmail.com) -// Copyright (c) 2024 Christian Mazakas -// Copyright (c) 2025 Mohammad Nejati -// -// 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 -// - -#include -#include - -#include - -namespace boost { -namespace http_proto { - -response:: -response() noexcept - : fields_view_base( - &this->fields_base::h_) - , response_base() -{ -} - -response:: -response( - core::string_view s) - : fields_view_base( - &this->fields_base::h_) - , response_base(s) -{ -} - -response:: -response( - std::size_t cap, - std::size_t max_cap) - : response() -{ - reserve_bytes(cap); - set_max_capacity_in_bytes(max_cap); -} - -response:: -response( - response&& other) noexcept - : response() -{ - swap(other); -} - -response:: -response( - response const& other) - : fields_view_base( - &this->fields_base::h_) - , response_base(*other.ph_) -{ -} - -response:: -response( - response_view const& other) - : fields_view_base( - &this->fields_base::h_) - , response_base(*other.ph_) -{ -} - -response& -response:: -operator=( - response&& other) noexcept -{ - response temp( - std::move(other)); - temp.swap(*this); - return *this; -} - -response:: -response( - http_proto::status sc) - : response( - sc, http_proto::version::http_1_1) -{ -} - -response:: -response( - http_proto::status sc, - http_proto::version v) - : response() -{ - set_start_line(sc, v); -} - -} // http_proto -} // boost diff --git a/src/response_parser.cpp b/src/response_parser.cpp index 85cc126f..c1baeefe 100644 --- a/src/response_parser.cpp +++ b/src/response_parser.cpp @@ -21,12 +21,11 @@ response_parser( { } -response_view +static_response const& response_parser:: get() const { - return response_view( - safe_get_header()); + return safe_get_response(); } } // http_proto diff --git a/src/rfc/combine_field_values.cpp b/src/rfc/combine_field_values.cpp index cf98e651..53c9d514 100644 --- a/src/rfc/combine_field_values.cpp +++ b/src/rfc/combine_field_values.cpp @@ -14,7 +14,7 @@ namespace http_proto { core::string_view combine_field_values( - fields_view_base::subrange const& vr, + fields_base::subrange const& vr, grammar::recycled_ptr& temp) { core::string_view result; diff --git a/src/serializer.cpp b/src/serializer.cpp index 0a45f146..179cddce 100644 --- a/src/serializer.cpp +++ b/src/serializer.cpp @@ -11,7 +11,7 @@ #include #include -#include +#include #include #include "src/detail/array_of_const_buffers.hpp" @@ -633,7 +633,7 @@ class serializer::impl void start_init( - message_view_base const& m) + message_base const& m) { // Precondition violation if(state_ != state::start) @@ -646,7 +646,7 @@ class serializer::impl // VFALCO what do we do with // metadata error code failures? - // m.ph_->md.maybe_throw(); + // m.h_.md.maybe_throw(); auto const& md = m.metadata(); needs_exp100_continue_ = md.expect.is_100_continue; @@ -701,7 +701,7 @@ class serializer::impl void start_empty( - message_view_base const& m) + message_base const& m) { start_init(m); style_ = style::empty; @@ -715,13 +715,13 @@ class serializer::impl if(!filter_) out_finish(); - prepped_.append({ m.ph_->cbuf, m.ph_->size }); + prepped_.append({ m.h_.cbuf, m.h_.size }); more_input_ = false; } void start_buffers( - message_view_base const& m, + message_base const& m, cbs_gen& cbs_gen) { // start_init() already called @@ -738,7 +738,7 @@ class serializer::impl batch_size + // buffers (is_chunked_ ? 2 : 0)); // chunk header + final chunk - prepped_.append({ m.ph_->cbuf, m.ph_->size }); + prepped_.append({ m.h_.cbuf, m.h_.size }); more_input_ = (batch_size != 0); if(is_chunked_) @@ -767,14 +767,14 @@ class serializer::impl out_init(); - prepped_.append({ m.ph_->cbuf, m.ph_->size }); + prepped_.append({ m.h_.cbuf, m.h_.size }); tmp_ = {}; more_input_ = true; } void start_source( - message_view_base const& m, + message_base const& m, source& source) { // start_init() already called @@ -794,12 +794,12 @@ class serializer::impl out_init(); - prepped_.append({ m.ph_->cbuf, m.ph_->size }); + prepped_.append({ m.h_.cbuf, m.h_.size }); more_input_ = true; } stream - start_stream(message_view_base const& m) + start_stream(message_base const& m) { start_init(m); style_ = style::stream; @@ -817,7 +817,7 @@ class serializer::impl out_init(); - prepped_.append({ m.ph_->cbuf, m.ph_->size }); + prepped_.append({ m.h_.cbuf, m.h_.size }); more_input_ = true; return stream{ this }; } @@ -961,7 +961,7 @@ reset() noexcept void serializer:: -start(message_view_base const& m) +start(message_base const& m) { BOOST_ASSERT(impl_); impl_->start_empty(m); @@ -970,7 +970,7 @@ start(message_view_base const& m) auto serializer:: start_stream( - message_view_base const& m) -> stream + message_base const& m) -> stream { BOOST_ASSERT(impl_); return impl_->start_stream(m); @@ -1013,7 +1013,7 @@ ws() void serializer:: -start_init(message_view_base const& m) +start_init(message_base const& m) { BOOST_ASSERT(impl_); impl_->start_init(m); @@ -1022,7 +1022,7 @@ start_init(message_view_base const& m) void serializer:: start_buffers( - message_view_base const& m, + message_base const& m, cbs_gen& cbs_gen) { BOOST_ASSERT(impl_); @@ -1032,7 +1032,7 @@ start_buffers( void serializer:: start_source( - message_view_base const& m, + message_base const& m, source& source) { BOOST_ASSERT(impl_); diff --git a/test/unit/Jamfile b/test/unit/Jamfile index cedad320..0fc028f6 100644 --- a/test/unit/Jamfile +++ b/test/unit/Jamfile @@ -35,28 +35,22 @@ local SOURCES = error.cpp field.cpp fields_base.cpp - fields_view_base.cpp - fields_view.cpp fields.cpp file_mode.cpp header_limits.cpp http_proto.cpp message_base.cpp - message_view_base.cpp metadata.cpp method.cpp parser.cpp request_parser.cpp - request_view.cpp request.cpp response_parser.cpp - response_view.cpp response.cpp sandbox.cpp serializer.cpp sink.cpp source.cpp - static_fields.cpp static_request.cpp static_response.cpp status.cpp diff --git a/test/unit/compression.cpp b/test/unit/compression.cpp index ba208c98..5dd75647 100644 --- a/test/unit/compression.cpp +++ b/test/unit/compression.cpp @@ -238,7 +238,7 @@ struct zlib_test static void serializer_source( - response_view res, + response const& res, serializer& sr, buffers::const_buffer body, buffers::string_buffer out) @@ -284,7 +284,7 @@ struct zlib_test static void serializer_stream( - response_view res, + response const& res, serializer& sr, buffers::const_buffer body, buffers::string_buffer out) @@ -322,7 +322,7 @@ struct zlib_test static void serializer_buffers( - response_view res, + response const& res, serializer& sr, buffers::const_buffer body, buffers::string_buffer out) @@ -354,7 +354,7 @@ struct zlib_test static void serializer_empty( - response_view res, + response const& res, serializer& sr, buffers::const_buffer body, buffers::string_buffer out) diff --git a/test/unit/fields.cpp b/test/unit/fields.cpp index de59faa2..f84df80c 100644 --- a/test/unit/fields.cpp +++ b/test/unit/fields.cpp @@ -12,7 +12,6 @@ #include #include -#include #include #include "test_helpers.hpp" @@ -110,33 +109,6 @@ struct fields_test } } - // fields(fields_view const&) - { - { - fields f1(cs1); - fields f2(static_cast< - fields_view>(f1)); - - BOOST_TEST_EQ( - f2.buffer(), cs1); - BOOST_TEST_NE( - f2.buffer().data(), - cs1.data()); - test_fields(f2, cs1); - } - - // default buffer - { - fields_view fv; - fields f(fv); - BOOST_TEST_EQ( - f.buffer(), "\r\n"); - BOOST_TEST_EQ( - f.buffer().data(), - fv.buffer().data()); - } - } - // operator=(fields&&) { { @@ -202,60 +174,6 @@ struct fields_test f2.buffer().data()); } } - - // operator=(fields_view) - { - { - fields f1(cs1); - fields f2; - f2 = static_cast< - fields_view>(f1); - test_fields(f1, cs1); - test_fields(f2, cs1); - BOOST_TEST_NE( - f1.buffer().data(), - f2.buffer().data()); - } - { - fields f1(cs1); - fields f2( - "x: 1\r\n" - "y: 2\r\n" - "z: 3\r\n" - "\r\n"); - f2 = static_cast< - fields_view>(f1); - test_fields(f1, cs1); - test_fields(f2, cs1); - BOOST_TEST_NE( - f1.buffer().data(), - f2.buffer().data()); - } - { - fields_view f1; - fields f2(cs1); - f2 = f1; - test_fields(f1, "\r\n"); - test_fields(f2, "\r\n"); - BOOST_TEST_EQ( - f1.buffer().data(), - f2.buffer().data()); - } - - // existing capacity - { - fields f1(cs1); - fields f2; - f2.reserve_bytes( - 2 * cs1.size() + 128); - f2 = static_cast< - fields_view>(f1); - test_fields(f2, cs1); - BOOST_TEST( - f1.buffer().data() != - f2.buffer().data()); - } - } } void diff --git a/test/unit/fields_base.cpp b/test/unit/fields_base.cpp index 0c9d2875..3bce305c 100644 --- a/test/unit/fields_base.cpp +++ b/test/unit/fields_base.cpp @@ -15,6 +15,8 @@ #include #include #include + +#include #include #include "test_helpers.hpp" @@ -1462,6 +1464,259 @@ struct fields_base_test } } + void + testIterators() + { + fields_base const& f = fields( + "x: 1\r\n" + "Accept: 2\r\n" + "z: 3\r\n" + "\r\n"); + + // iterator + // begin() + // end() + { + BOOST_STATIC_ASSERT(std::is_same< + fields_base::iterator, + fields_base::const_iterator>::value); + + BOOST_TEST( + fields_base::iterator() == + fields_base::iterator()); + + fields_base::iterator it = f.begin(); + BOOST_TEST(it == f.begin()); + BOOST_TEST(it != f.end()); + + BOOST_TEST(!it->id.has_value()); + BOOST_TEST_EQ(it->name, "x"); + BOOST_TEST_EQ(it->value, "1"); + + ++it; + BOOST_TEST_EQ(it->id, field::accept); + BOOST_TEST_EQ(it->name, "Accept"); + BOOST_TEST_EQ(it->value, "2"); + + { + auto it0 = it++; // post-increment + BOOST_TEST_EQ(it0->id, field::accept); + BOOST_TEST_EQ(it0->name, "Accept"); + BOOST_TEST_EQ(it0->value, "2"); + } + BOOST_TEST(!it->id.has_value()); + BOOST_TEST_EQ(it->name, "z"); + BOOST_TEST_EQ(it->value, "3"); + + ++it; + BOOST_TEST_EQ(it, f.end()); + + --it; + BOOST_TEST(!it->id.has_value()); + BOOST_TEST_EQ(it->name, "z"); + BOOST_TEST_EQ(it->value, "3"); + + { + auto it1 = it--; // post-decrement + BOOST_TEST(!it1->id.has_value()); + BOOST_TEST_EQ(it1->name, "z"); + BOOST_TEST_EQ(it1->value, "3"); + } + BOOST_TEST_EQ(it->id, field::accept); + BOOST_TEST_EQ(it->name, "Accept"); + BOOST_TEST_EQ(it->value, "2"); + + --it; + BOOST_TEST(!it->id.has_value()); + BOOST_TEST_EQ(it->name, "x"); + BOOST_TEST_EQ(it->value, "1"); + + BOOST_TEST_EQ(it, f.begin()); + } + + // reverse_iterator + // rbegin() + // rend() + { + BOOST_STATIC_ASSERT(std::is_same< + fields_base::reverse_iterator, + fields_base::const_reverse_iterator>::value); + + BOOST_TEST( + fields_base::reverse_iterator() == + fields_base::reverse_iterator()); + + fields_base::reverse_iterator it = f.rbegin(); + BOOST_TEST(it == f.rbegin()); + BOOST_TEST(it != f.rend()); + + BOOST_TEST(!it->id.has_value()); + BOOST_TEST_EQ(it->name, "z"); + BOOST_TEST_EQ(it->value, "3"); + + ++it; + BOOST_TEST_EQ(it->id, field::accept); + BOOST_TEST_EQ(it->name, "Accept"); + BOOST_TEST_EQ(it->value, "2"); + + { + auto it0 = it++; // post-increment + BOOST_TEST_EQ(it0->id, field::accept); + BOOST_TEST_EQ(it0->name, "Accept"); + BOOST_TEST_EQ(it0->value, "2"); + } + BOOST_TEST(!it->id.has_value()); + BOOST_TEST_EQ(it->name, "x"); + BOOST_TEST_EQ(it->value, "1"); + + ++it; + BOOST_TEST_EQ(it, f.rend()); + + --it; + BOOST_TEST(!it->id.has_value()); + BOOST_TEST_EQ(it->name, "x"); + BOOST_TEST_EQ(it->value, "1"); + + { + auto it0 = it--; // post-decrement + BOOST_TEST(!it0->id.has_value()); + BOOST_TEST_EQ(it0->name, "x"); + BOOST_TEST_EQ(it0->value, "1"); + } + BOOST_TEST_EQ(it->id, field::accept); + BOOST_TEST_EQ(it->name, "Accept"); + BOOST_TEST_EQ(it->value, "2"); + + --it; + BOOST_TEST(!it->id.has_value()); + BOOST_TEST_EQ(it->name, "z"); + BOOST_TEST_EQ(it->value, "3"); + + BOOST_TEST_EQ(it, f.rbegin()); + } + } + + void + testObservers() + { + fields_base const& f = + fields( + "Content-Length: 42\r\n" + "x: 1\r\n" + "y: 2\r\n" + "Set-Cookie: a\r\n" + "x: 3\r\n" + "z: 4\r\n" + "Set-Cookie: b\r\n" + "x: 5\r\n" + "p: 6\r\n" + "User-Agent: boost\r\n" + "\r\n"); + + // size() + + BOOST_TEST(f.size() == 10); + + // at(field) + // at(string_view) + + BOOST_TEST(f.at("x") == "1"); + BOOST_TEST(f.at(field::set_cookie) == "a"); + BOOST_TEST_THROWS( + f.at("accept"), + std::out_of_range); + BOOST_TEST_THROWS( + f.at(field::accept), + std::out_of_range); + + // exists(field) + // exists(string_view) + + BOOST_TEST(f.exists("x")); + BOOST_TEST(f.exists("X")); + BOOST_TEST(f.exists("user-agent")); + BOOST_TEST(! f.exists("a")); + BOOST_TEST(f.exists(field::user_agent)); + BOOST_TEST(! f.exists(field::range)); + + // count(field) + // count(string_view) + + BOOST_TEST(f.count("x") == 3); + BOOST_TEST(f.count("y") == 1); + BOOST_TEST(f.count("q") == 0); + BOOST_TEST(f.count(field::range) == 0); + BOOST_TEST(f.count(field::user_agent) == 1); + + // find(field) + // find(string_view) + { + BOOST_TEST(f.find("x")->name == "x"); + BOOST_TEST(f.find("accept") == f.end()); + BOOST_TEST(f.find(field::range) == f.end()); + BOOST_TEST(f.find(field::user_agent)->value == "boost"); + } + + // find(iterator, field) + // find(iterator, string_view) + { + auto const it = f.find("y"); + BOOST_TEST(it != f.end()); + BOOST_TEST(it->value == "2"); + + BOOST_TEST(f.find(it, "x")->value == "3"); + BOOST_TEST(f.find(it, "q") == f.end()); + BOOST_TEST(f.find(it, field::set_cookie)->value == "a"); + BOOST_TEST(f.find(it, field::range) == f.end()); + } + + // find_last(iterator, field) + // find_last(iterator, string_view) + { + auto const it = f.find_last(f.end(), "x"); + BOOST_TEST(it != f.end()); + BOOST_TEST(it->value == "5"); + + BOOST_TEST(f.find_last(it, "x")->value == "3"); + BOOST_TEST(f.find_last(it, "q") == f.end()); + BOOST_TEST(f.find_last(it, field::set_cookie)->value == "b"); + BOOST_TEST(f.find_last(it, field::range) == f.end()); + } + + // value_or(field, string_view) + // value_or(string_view, string_view) + { + BOOST_TEST(f.value_or( + field::set_cookie, "") == "a"); + BOOST_TEST(f.value_or( + field::set_cookie2, "Q") == "Q"); + + BOOST_TEST(f.value_or( + "set-cookie", "") == "a"); + BOOST_TEST(f.value_or( + "set-cookie2", "Q") == "Q"); + } + } + + void + testStream() + { + // operator<< + { + std::stringstream ss; + fields f; + f.set(field::content_length, "42"); + ss << f; + BOOST_TEST_EQ( + ss.str(), "Content-Length: 42\r\n\r\n"); + } + } + + void + testSubrange() + { + } + void run() { @@ -1471,6 +1726,10 @@ struct fields_base_test testErase(); testSet(); testExpect(); + testIterators(); + testObservers(); + testStream(); + testSubrange(); } }; diff --git a/test/unit/fields_view.cpp b/test/unit/fields_view.cpp deleted file mode 100644 index 87945ffe..00000000 --- a/test/unit/fields_view.cpp +++ /dev/null @@ -1,63 +0,0 @@ -// -// Copyright (c) 2021 Vinnie Falco (vinnie dot falco at gmail dot 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 -// - -// Test that header file is self-contained. -#include - -#include - -#include "test_helpers.hpp" - -#include - -namespace boost { -namespace http_proto { - -struct fields_view_test -{ - void - testSpecial() - { - // fields_view() - { - fields_view fv; - } - - // fields_view(fields_view const&) - { - { - fields_view f1; - fields_view f2(f1); - (void)f2; - } - } - - // operator=(fields_view const&) - { - { - fields_view f1; - fields_view f2; - f1 = f2; - } - } - } - - void - run() - { - testSpecial(); - } -}; - -TEST_SUITE( - fields_view_test, - "boost.http_proto.fields_view"); - -} // http_proto -} // boost diff --git a/test/unit/fields_view_base.cpp b/test/unit/fields_view_base.cpp deleted file mode 100644 index 0e4b1584..00000000 --- a/test/unit/fields_view_base.cpp +++ /dev/null @@ -1,276 +0,0 @@ -// -// Copyright (c) 2021 Vinnie Falco (vinnie dot falco at gmail dot 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 -// - -// Test that header file is self-contained. -#include -#include -#include -#include - -#include "test_helpers.hpp" - -namespace boost { -namespace http_proto { - -struct fields_view_base_test -{ - void - testIterators() - { - fields_view_base const& f = fields( - "x: 1\r\n" - "Accept: 2\r\n" - "z: 3\r\n" - "\r\n"); - - // iterator - // begin() - // end() - { - BOOST_STATIC_ASSERT(std::is_same< - fields_view_base::iterator, - fields_view_base::const_iterator>::value); - - BOOST_TEST( - fields_view_base::iterator() == - fields_view_base::iterator()); - - fields_view_base::iterator it = f.begin(); - BOOST_TEST(it == f.begin()); - BOOST_TEST(it != f.end()); - - BOOST_TEST(!it->id.has_value()); - BOOST_TEST_EQ(it->name, "x"); - BOOST_TEST_EQ(it->value, "1"); - - ++it; - BOOST_TEST_EQ(it->id, field::accept); - BOOST_TEST_EQ(it->name, "Accept"); - BOOST_TEST_EQ(it->value, "2"); - - { - auto it0 = it++; // post-increment - BOOST_TEST_EQ(it0->id, field::accept); - BOOST_TEST_EQ(it0->name, "Accept"); - BOOST_TEST_EQ(it0->value, "2"); - } - BOOST_TEST(!it->id.has_value()); - BOOST_TEST_EQ(it->name, "z"); - BOOST_TEST_EQ(it->value, "3"); - - ++it; - BOOST_TEST_EQ(it, f.end()); - - --it; - BOOST_TEST(!it->id.has_value()); - BOOST_TEST_EQ(it->name, "z"); - BOOST_TEST_EQ(it->value, "3"); - - { - auto it1 = it--; // post-decrement - BOOST_TEST(!it1->id.has_value()); - BOOST_TEST_EQ(it1->name, "z"); - BOOST_TEST_EQ(it1->value, "3"); - } - BOOST_TEST_EQ(it->id, field::accept); - BOOST_TEST_EQ(it->name, "Accept"); - BOOST_TEST_EQ(it->value, "2"); - - --it; - BOOST_TEST(!it->id.has_value()); - BOOST_TEST_EQ(it->name, "x"); - BOOST_TEST_EQ(it->value, "1"); - - BOOST_TEST_EQ(it, f.begin()); - } - - // reverse_iterator - // rbegin() - // rend() - { - BOOST_STATIC_ASSERT(std::is_same< - fields_view_base::reverse_iterator, - fields_view_base::const_reverse_iterator>::value); - - BOOST_TEST( - fields_view_base::reverse_iterator() == - fields_view_base::reverse_iterator()); - - fields_view_base::reverse_iterator it = f.rbegin(); - BOOST_TEST(it == f.rbegin()); - BOOST_TEST(it != f.rend()); - - BOOST_TEST(!it->id.has_value()); - BOOST_TEST_EQ(it->name, "z"); - BOOST_TEST_EQ(it->value, "3"); - - ++it; - BOOST_TEST_EQ(it->id, field::accept); - BOOST_TEST_EQ(it->name, "Accept"); - BOOST_TEST_EQ(it->value, "2"); - - { - auto it0 = it++; // post-increment - BOOST_TEST_EQ(it0->id, field::accept); - BOOST_TEST_EQ(it0->name, "Accept"); - BOOST_TEST_EQ(it0->value, "2"); - } - BOOST_TEST(!it->id.has_value()); - BOOST_TEST_EQ(it->name, "x"); - BOOST_TEST_EQ(it->value, "1"); - - ++it; - BOOST_TEST_EQ(it, f.rend()); - - --it; - BOOST_TEST(!it->id.has_value()); - BOOST_TEST_EQ(it->name, "x"); - BOOST_TEST_EQ(it->value, "1"); - - { - auto it0 = it--; // post-decrement - BOOST_TEST(!it0->id.has_value()); - BOOST_TEST_EQ(it0->name, "x"); - BOOST_TEST_EQ(it0->value, "1"); - } - BOOST_TEST_EQ(it->id, field::accept); - BOOST_TEST_EQ(it->name, "Accept"); - BOOST_TEST_EQ(it->value, "2"); - - --it; - BOOST_TEST(!it->id.has_value()); - BOOST_TEST_EQ(it->name, "z"); - BOOST_TEST_EQ(it->value, "3"); - - BOOST_TEST_EQ(it, f.rbegin()); - } - } - - void - testObservers() - { - fields_view_base const& f = - fields( - "Content-Length: 42\r\n" - "x: 1\r\n" - "y: 2\r\n" - "Set-Cookie: a\r\n" - "x: 3\r\n" - "z: 4\r\n" - "Set-Cookie: b\r\n" - "x: 5\r\n" - "p: 6\r\n" - "User-Agent: boost\r\n" - "\r\n"); - - // size() - - BOOST_TEST(f.size() == 10); - - // at(field) - // at(string_view) - - BOOST_TEST(f.at("x") == "1"); - BOOST_TEST(f.at(field::set_cookie) == "a"); - BOOST_TEST_THROWS( - f.at("accept"), - std::out_of_range); - BOOST_TEST_THROWS( - f.at(field::accept), - std::out_of_range); - - // exists(field) - // exists(string_view) - - BOOST_TEST(f.exists("x")); - BOOST_TEST(f.exists("X")); - BOOST_TEST(f.exists("user-agent")); - BOOST_TEST(! f.exists("a")); - BOOST_TEST(f.exists(field::user_agent)); - BOOST_TEST(! f.exists(field::range)); - - // count(field) - // count(string_view) - - BOOST_TEST(f.count("x") == 3); - BOOST_TEST(f.count("y") == 1); - BOOST_TEST(f.count("q") == 0); - BOOST_TEST(f.count(field::range) == 0); - BOOST_TEST(f.count(field::user_agent) == 1); - - // find(field) - // find(string_view) - { - BOOST_TEST(f.find("x")->name == "x"); - BOOST_TEST(f.find("accept") == f.end()); - BOOST_TEST(f.find(field::range) == f.end()); - BOOST_TEST(f.find(field::user_agent)->value == "boost"); - } - - // find(iterator, field) - // find(iterator, string_view) - { - auto const it = f.find("y"); - BOOST_TEST(it != f.end()); - BOOST_TEST(it->value == "2"); - - BOOST_TEST(f.find(it, "x")->value == "3"); - BOOST_TEST(f.find(it, "q") == f.end()); - BOOST_TEST(f.find(it, field::set_cookie)->value == "a"); - BOOST_TEST(f.find(it, field::range) == f.end()); - } - - // find_last(iterator, field) - // find_last(iterator, string_view) - { - auto const it = f.find_last(f.end(), "x"); - BOOST_TEST(it != f.end()); - BOOST_TEST(it->value == "5"); - - BOOST_TEST(f.find_last(it, "x")->value == "3"); - BOOST_TEST(f.find_last(it, "q") == f.end()); - BOOST_TEST(f.find_last(it, field::set_cookie)->value == "b"); - BOOST_TEST(f.find_last(it, field::range) == f.end()); - } - - // value_or(field, string_view) - // value_or(string_view, string_view) - { - BOOST_TEST(f.value_or( - field::set_cookie, "") == "a"); - BOOST_TEST(f.value_or( - field::set_cookie2, "Q") == "Q"); - - BOOST_TEST(f.value_or( - "set-cookie", "") == "a"); - BOOST_TEST(f.value_or( - "set-cookie2", "Q") == "Q"); - } - } - - void - testSubrange() - { - } - - void - run() - { - testIterators(); - testObservers(); - testSubrange(); - } -}; - -TEST_SUITE( - fields_view_base_test, - "boost.http_proto.fields_view_base"); - -} // http_proto -} // boost diff --git a/test/unit/message_view_base.cpp b/test/unit/message_view_base.cpp deleted file mode 100644 index 608653cd..00000000 --- a/test/unit/message_view_base.cpp +++ /dev/null @@ -1,11 +0,0 @@ -// -// Copyright (c) 2021 Vinnie Falco (vinnie dot falco at gmail dot 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 -// - -// Test that header file is self-contained. -#include diff --git a/test/unit/natvis.cpp b/test/unit/natvis.cpp index 590321d7..6cd93efd 100644 --- a/test/unit/natvis.cpp +++ b/test/unit/natvis.cpp @@ -8,11 +8,8 @@ // #include -#include #include -#include #include -#include #include "test_suite.hpp" @@ -32,8 +29,7 @@ struct natvis_test "Connection: keep-alive\r\n" "Server: localhost\r\n" "\r\n"); - request_view rv(req); - ignore_unused(rv); + ignore_unused(req); } { std::error_condition ec(std::errc::address_in_use); @@ -42,8 +38,7 @@ struct natvis_test "Connection: keep-alive\r\n" "Server: localhost\r\n" "\r\n"); - response_view rv(res); - ignore_unused(rv); + ignore_unused(res); } } }; diff --git a/test/unit/request.cpp b/test/unit/request.cpp index b4e3fe1e..3c008818 100644 --- a/test/unit/request.cpp +++ b/test/unit/request.cpp @@ -12,7 +12,6 @@ #include #include -#include #include @@ -112,6 +111,38 @@ struct request_test } } + // request(request const&) + { + { + // default + request_base const& r1 = request(); + request r2(r1); + check(r2, 0, + "GET / HTTP/1.1\r\n" + "\r\n"); + BOOST_TEST( + r2.method() == method::get); + BOOST_TEST( + r2.method_text() == "GET"); + BOOST_TEST( + r2.version() == version::http_1_1); + } + { + request_base const& r1 = request(cs); + request r2(r1); + check(r2, 2, cs); + BOOST_TEST( + r2.buffer().data() != + r1.buffer().data()); + BOOST_TEST( + r2.method() == method::post); + BOOST_TEST( + r2.method_text() == "POST"); + BOOST_TEST( + r2.version() == version::http_1_0); + } + } + // request(request&&) { { @@ -188,6 +219,27 @@ struct request_test } } + // operator=(request_base const&) + { + { + request r1(cs); + request_base const& r2 = request(); + r1 = r2; + check(r1, 0, + "GET / HTTP/1.1\r\n" + "\r\n"); + BOOST_TEST( + r1.buffer().data() != + r2.buffer().data()); + BOOST_TEST( + r1.method() == method::get); + BOOST_TEST( + r1.method_text() == "GET"); + BOOST_TEST( + r1.version() == version::http_1_1); + } + } + // operator=(fields&&) { { @@ -247,57 +299,6 @@ struct request_test } } - void - testViewConstructor() - { - { - request req; - BOOST_TEST_EQ( - req.buffer(), - "GET / HTTP/1.1\r\n\r\n"); - - request_view req_view(req); - request req2(req_view); - - BOOST_TEST_EQ( - req2.buffer(), - "GET / HTTP/1.1\r\n\r\n"); - - // default-constructed recycles the same string literal - BOOST_TEST_EQ( - req2.buffer().data(), - req.buffer().data()); - - BOOST_TEST_EQ( - req2.buffer().data(), - req_view.buffer().data()); - - } - - { - request req; - req.set_method("POST"); - BOOST_TEST_EQ( - req.buffer(), - "POST / HTTP/1.1\r\n\r\n"); - - request_view req_view(req); - request req2(req_view); - - BOOST_TEST_EQ( - req2.buffer(), - "POST / HTTP/1.1\r\n\r\n"); - - BOOST_TEST_NE( - req2.buffer().data(), - req.buffer().data()); - - BOOST_TEST_NE( - req2.buffer().data(), - req_view.buffer().data()); - } - } - void testObservers() { @@ -788,7 +789,6 @@ struct request_test { testHelpers(); testSpecial(); - testViewConstructor(); testObservers(); testModifiers(); testExpect(); diff --git a/test/unit/request_parser.cpp b/test/unit/request_parser.cpp index 68f520c0..db960496 100644 --- a/test/unit/request_parser.cpp +++ b/test/unit/request_parser.cpp @@ -99,8 +99,8 @@ struct request_parser_test BOOST_TEST( pr.got_header() ); if( expected.data() ) { - auto req_view = pr.get(); - BOOST_TEST_EQ(req_view.buffer(), expected); + auto const& req = pr.get(); + BOOST_TEST_EQ(req.buffer(), expected); } } } @@ -127,7 +127,7 @@ struct request_parser_test auto const f = [&](request_parser const& pr) { - auto const req = pr.get(); + auto const& req = pr.get(); BOOST_TEST(req.method() == m); BOOST_TEST(req.method_text() == to_string(m)); @@ -320,40 +320,40 @@ struct request_parser_test pr.start(); feed(pr, s); - auto const rv = pr.get(); + auto const& req = pr.get(); BOOST_TEST( - rv.method() == method::get); + req.method() == method::get); BOOST_TEST( - rv.method_text() == "GET"); - BOOST_TEST(rv.target() == "/"); - BOOST_TEST(rv.version() == + req.method_text() == "GET"); + BOOST_TEST(req.target() == "/"); + BOOST_TEST(req.version() == version::http_1_1); - BOOST_TEST(rv.buffer() == s); - BOOST_TEST(rv.size() == 7); + BOOST_TEST(req.buffer() == s); + BOOST_TEST(req.size() == 7); BOOST_TEST( - rv.exists(field::connection)); - BOOST_TEST(! rv.exists(field::age)); - BOOST_TEST(rv.exists("Connection")); - BOOST_TEST(rv.exists("CONNECTION")); - BOOST_TEST(! rv.exists("connector")); - BOOST_TEST(rv.count(field::accept) == 1); + req.exists(field::connection)); + BOOST_TEST(! req.exists(field::age)); + BOOST_TEST(req.exists("Connection")); + BOOST_TEST(req.exists("CONNECTION")); + BOOST_TEST(! req.exists("connector")); + BOOST_TEST(req.count(field::accept) == 1); BOOST_TEST( - rv.count(field::age) == 0); + req.count(field::age) == 0); BOOST_TEST( - rv.count("connection") == 1); - BOOST_TEST(rv.count("a") == 2); - BOOST_TEST(rv.find( + req.count("connection") == 1); + BOOST_TEST(req.count("a") == 2); + BOOST_TEST(req.find( field::connection)->id == field::connection); BOOST_TEST( - rv.find("a")->value == "1"); + req.find("a")->value == "1"); grammar::recycled_ptr temp; - BOOST_TEST(combine_field_values(rv.find_all( + BOOST_TEST(combine_field_values(req.find_all( field::user_agent), temp) == "x"); - BOOST_TEST(combine_field_values(rv.find_all( + BOOST_TEST(combine_field_values(req.find_all( "b"), temp) == "2"); - BOOST_TEST(combine_field_values(rv.find_all( + BOOST_TEST(combine_field_values(req.find_all( "a"), temp) == "1,3"); } diff --git a/test/unit/request_view.cpp b/test/unit/request_view.cpp deleted file mode 100644 index ab976ed1..00000000 --- a/test/unit/request_view.cpp +++ /dev/null @@ -1,54 +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 -// - -// Test that header file is self-contained. -#include - -#include "test_helpers.hpp" - -namespace boost { -namespace http_proto { - -class request_view_test -{ -public: - void - run() - { - // request_view() - { - request_view req; - } - - // request_view(request_view const&) - { - { - request_view req1; - request_view req2(req1); - } - } - - // operator=(request_view const&) - { - { - request_view req1; - request_view req2; - req1 = req2; - } - } - } -}; - -TEST_SUITE( - request_view_test, - "boost.http_proto.request_view"); - -} // http_proto -} // boost - diff --git a/test/unit/response.cpp b/test/unit/response.cpp index 790ed976..3128b090 100644 --- a/test/unit/response.cpp +++ b/test/unit/response.cpp @@ -11,7 +11,6 @@ // Test that header file is self-contained. #include -#include #include #include @@ -151,6 +150,30 @@ class response_test } } + // response(response_base const&) + { + { + response_base const& r1 = response(); + response r2 = response(r1); + check(r1, status::ok, 200, "OK", version::http_1_1); + check(r2, status::ok, 200, "OK", version::http_1_1); + BOOST_TEST( + r1.buffer().data() == r2.buffer().data()); + BOOST_TEST(r1.capacity_in_bytes() == 0); + BOOST_TEST(r2.capacity_in_bytes() == 0); + } + { + response_base const& r1 = response(status::not_found, version::http_1_0); + response r2 = response(r1); + check(r1, status::not_found, 404, "Not Found", version::http_1_0); + check(r2, status::not_found, 404, "Not Found", version::http_1_0); + BOOST_TEST( + r1.buffer().data() != r2.buffer().data()); + BOOST_TEST(r1.capacity_in_bytes() > 0); + BOOST_TEST(r2.capacity_in_bytes() > 0); + } + } + // operator=(response&&) { response r1; @@ -173,67 +196,16 @@ class response_test BOOST_TEST(r2.capacity_in_bytes() > 0); } - //---------------------------------------- - - // response(response_view const&) - { - core::string_view const s = - "HTTP/1.0 404 Not Found\r\n" - "Server: test\r\n" - "\r\n"; - response r(s); - response_view rv = r; - response res(rv); - check(res, status::not_found, 404, "Not Found", version::http_1_0); - BOOST_TEST_EQ(res.buffer(), s); - BOOST_TEST(res.buffer().data() != s.data()); - BOOST_TEST(res.begin()->id == field::server); - BOOST_TEST(res.begin()->name == "Server"); - BOOST_TEST(res.begin()->value == "test"); - } - - // operator=(response_view const&) - { - core::string_view const s = - "HTTP/1.1 101 Switching Protocols\r\n" - "Server: test\r\n" - "\r\n"; - response r(s); - response_view rv = r; - response res(status::not_found); - res = rv; - BOOST_TEST_EQ(res.buffer(), s); - BOOST_TEST(res.buffer().data() != s.data()); - check(res, status::switching_protocols, 101, "Switching Protocols", version::http_1_1); - BOOST_TEST(res.begin()->id == field::server); - BOOST_TEST(res.begin()->name == "Server"); - BOOST_TEST(res.begin()->value == "test"); - } - - //---------------------------------------- - - // operator response_view() + // operator=(response_base const&) { - { - response res; - response_view rv(res); - BOOST_TEST_EQ(rv.version(), version::http_1_1); - BOOST_TEST_EQ(rv.status(), status::ok); - BOOST_TEST_EQ(rv.status_int(), 200); - BOOST_TEST_EQ(rv.reason(), "OK"); - BOOST_TEST_EQ(rv.buffer(), "HTTP/1.1 200 OK\r\n\r\n"); - BOOST_TEST(rv.buffer().data() == res.buffer().data()); - } - { - response res(status::not_found, version::http_1_0); - response_view rv(res); - BOOST_TEST_EQ(rv.version(), version::http_1_0); - BOOST_TEST_EQ(rv.status(), status::not_found); - BOOST_TEST_EQ(rv.status_int(), 404); - BOOST_TEST_EQ(rv.reason(), "Not Found"); - BOOST_TEST_EQ(rv.buffer(), "HTTP/1.0 404 Not Found\r\n\r\n"); - BOOST_TEST(rv.buffer().data() == res.buffer().data()); - } + response r1; + response_base const& r2 = response(status::not_found, version::http_1_0); + r1 = r2; + check(r1, status::not_found, 404, "Not Found", version::http_1_0); + BOOST_TEST( + r1.buffer().data() != r2.buffer().data()); + BOOST_TEST(r1.capacity_in_bytes() > 0); + BOOST_TEST(r2.capacity_in_bytes() > 0); } } @@ -298,8 +270,7 @@ class response_test "Content-Length: 0\r\n" "\r\n"; response r(s); - response_view rv = r; - response res(rv); + response res(r); check(res, status::ok, 200, "OK", version::http_1_1); BOOST_TEST(res.size() == 2); auto it = res.begin(); diff --git a/test/unit/response_view.cpp b/test/unit/response_view.cpp deleted file mode 100644 index f578bf51..00000000 --- a/test/unit/response_view.cpp +++ /dev/null @@ -1,55 +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 -// - -// Test that header file is self-contained. -#include - -#include "test_suite.hpp" - -namespace boost { -namespace http_proto { - -class response_view_test -{ -public: - void - run() - { - // response_view() - { - response_view req; - } - - // response_view(response_view const&) - { - { - response_view res1; - response_view res2(res1); - (void)res2; - } - } - - // operator=(response_view const&) - { - { - response_view res1; - response_view res2; - res1 = res2; - } - } - } -}; - -TEST_SUITE( - response_view_test, - "boost.http_proto.response_view"); - -} // http_proto -} // boost - diff --git a/test/unit/static_fields.cpp b/test/unit/static_fields.cpp deleted file mode 100644 index 063dea2b..00000000 --- a/test/unit/static_fields.cpp +++ /dev/null @@ -1,249 +0,0 @@ -// -// Copyright (c) 2025 Mohammad Nejati -// -// 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 -// - -// Test that header file is self-contained. -#include - -#include -#include -#include - -#include "test_helpers.hpp" -#include "test_suite.hpp" - -#include -#include - -namespace boost { -namespace http_proto { - -struct static_fields_test -{ - template - void - modify( - core::string_view before, - void (*pf)(static_fields<256>&), - core::string_view after) - { - static_fields<256> f0(before); - static_fields<256> f1(after); - static_fields<256> f(f0); - (*pf)(f); - BOOST_TEST_EQ(f.buffer(), - f1.buffer()); - } - - //-------------------------------------------- - - void - testSpecial() - { - core::string_view const cs1 = - "Connection: close\r\n" - "Set-Cookie: 0\r\n" - "User-Agent: boost\r\n" - "Set-Cookie: 1\r\n" - "\r\n"; - - // static_fields(static_fields<256> const&) - { - { - static_fields<256> f1(cs1); - static_fields<256> f2(f1); - test_fields(f1, cs1); - test_fields(f2, cs1); - BOOST_TEST_NE( - f1.buffer().data(), - f2.buffer().data()); - } - } - - // static_fields(fields_view const&) - { - { - static_fields<256> f1(cs1); - static_fields<256> f2(static_cast< - fields_view>(f1)); - - BOOST_TEST_EQ( - f2.buffer(), cs1); - BOOST_TEST_NE( - f2.buffer().data(), - cs1.data()); - test_fields(f2, cs1); - } - - // default buffer - { - static_fields<256> f; - BOOST_TEST_EQ( - f.buffer(), "\r\n"); - } - } - - // operator=(static_fields<256> const&) - { - { - static_fields<256> f1(cs1); - static_fields<256> f2; - f2 = f1; - test_fields(f1, cs1); - test_fields(f2, cs1); - BOOST_TEST_NE( - f1.buffer().data(), - f2.buffer().data()); - } - { - static_fields<256> f1(cs1); - static_fields<256> f2( - "x: 1\r\n" - "y: 2\r\n" - "z: 3\r\n" - "\r\n"); - f2 = f1; - test_fields(f1, cs1); - test_fields(f2, cs1); - BOOST_TEST_NE( - f1.buffer().data(), - f2.buffer().data()); - } - { - static_fields<256> f1; - static_fields<256> f2(cs1); - f2 = f1; - test_fields(f1, "\r\n"); - test_fields(f2, "\r\n"); - BOOST_TEST_NE( - f1.buffer().data(), - f2.buffer().data()); - } - } - - // operator=(fields_view) - { - { - static_fields<256> f1(cs1); - static_fields<256> f2; - f2 = static_cast< - fields_view>(f1); - test_fields(f1, cs1); - test_fields(f2, cs1); - BOOST_TEST_NE( - f1.buffer().data(), - f2.buffer().data()); - } - { - static_fields<256> f1(cs1); - static_fields<256> f2( - "x: 1\r\n" - "y: 2\r\n" - "z: 3\r\n" - "\r\n"); - f2 = static_cast< - fields_view>(f1); - test_fields(f1, cs1); - test_fields(f2, cs1); - BOOST_TEST_NE( - f1.buffer().data(), - f2.buffer().data()); - } - { - fields_view f1; - static_fields<256> f2(cs1); - f2 = f1; - test_fields(f1, "\r\n"); - test_fields(f2, "\r\n"); - BOOST_TEST_NE( - f1.buffer().data(), - f2.buffer().data()); - } - - // existing capacity - { - static_fields<256> f1(cs1); - static_fields<512> f2; - f2.reserve_bytes( - 2 * cs1.size() + 128); - f2 = static_cast< - fields_view>(f1); - test_fields(f2, cs1); - BOOST_TEST_NE( - f1.buffer().data(), - f2.buffer().data()); - } - } - } - - void - testObservers() - { - core::string_view const cs = - "Connection: close\r\n" - "Set-Cookie: 0\r\n" - "User-Agent: boost\r\n" - "Set-Cookie: 1\r\n" - "\r\n"; - - // fields_view_base::string() - { - static_fields<256> f1(cs); - BOOST_TEST_EQ(f1.buffer(), cs); - } - - // fields_base::capacity_in_bytes() - { - { - static_fields<256> f; - BOOST_TEST_EQ( - f.capacity_in_bytes(), 256U); - } - { - static_fields<256> f; - f.reserve_bytes(100); - BOOST_TEST_EQ( - f.capacity_in_bytes(), 256U); - } - { - static_fields<256> f; - f.reserve_bytes(100); - f.shrink_to_fit(); - BOOST_TEST_EQ( - f.capacity_in_bytes(), 256U); - } - } - } - - void - testInitialSize() - { - { - static_fields<32> f{}; - BOOST_TEST_THROWS( - f.append(field::host, "www.google.com"), std::length_error); - BOOST_TEST_EQ( - f.max_capacity_in_bytes(), 32); - } - } - - void - run() - { - testSpecial(); - testObservers(); - testInitialSize(); - } -}; - -TEST_SUITE( - static_fields_test, - "boost.http_proto.static_fields"); - -} // http_proto -} // boost diff --git a/test/unit/static_request.cpp b/test/unit/static_request.cpp index aff76eb5..78a1f9ec 100644 --- a/test/unit/static_request.cpp +++ b/test/unit/static_request.cpp @@ -10,7 +10,7 @@ // Test that header file is self-contained. #include -#include +#include #include @@ -21,51 +21,19 @@ namespace http_proto { struct static_request_test { - template - static - void - check( - static_request& req, - std::size_t count, - core::string_view s) - { - req = static_request(s); - BOOST_TEST( - req.size() == count); - } - - void - testHelpers() - { - core::string_view const cs = - "POST /x HTTP/1.0\r\n" - "User-Agent: boost\r\n" - "\r\n"; - static_request<64> req(cs); - BOOST_TEST(req.method() == method::post); - BOOST_TEST(req.method_text() == "POST"); - BOOST_TEST(req.target() == "/x"); - BOOST_TEST(req.version() == version::http_1_0); - BOOST_TEST(req.buffer().data() != cs.data()); - BOOST_TEST(req.buffer() == cs); - } - void testSpecial() { - core::string_view const cs = "POST /x HTTP/1.0\r\n" "Content-Length: 42\r\n" "User-Agent: boost\r\n" "\r\n"; - // static_request() + // static_request(void* storage, std::size_t cap) { - static_request<64> req; - check(req, 0, - "GET / HTTP/1.1\r\n" - "\r\n"); + char buf[64]; + static_request req(buf, sizeof(buf)); BOOST_TEST( req.method() == method::get); BOOST_TEST( @@ -76,495 +44,55 @@ struct static_request_test req.version() == version::http_1_1); } - // static_request(static_request const&) - { - { - // default - static_request<64> r1; - static_request<64> r2(r1); - check(r2, 0, - "GET / HTTP/1.1\r\n" - "\r\n"); - BOOST_TEST( - r2.method() == method::get); - BOOST_TEST( - r2.method_text() == "GET"); - BOOST_TEST( - r2.version() == version::http_1_1); - } - { - static_request<128> r1(cs); - static_request<128> r2(r1); - check(r1, 2, cs); - check(r2, 2, cs); - BOOST_TEST( - r2.buffer().data() != - r1.buffer().data()); - BOOST_TEST( - r2.method() == method::post); - BOOST_TEST( - r2.method_text() == "POST"); - BOOST_TEST( - r2.version() == version::http_1_0); - } - } - - // operator=(static_request const&) - { - { - // default - static_request<128> r1; - static_request<128> r2(cs); - r1 = r2; - check(r1, 2, cs); - check(r2, 2, cs); - BOOST_TEST( - r2.buffer().data() != - r1.buffer().data()); - BOOST_TEST( - r1.method() == method::post); - BOOST_TEST( - r1.method_text() == "POST"); - BOOST_TEST( - r1.version() == version::http_1_0); - } - { - static_request<128> r1(cs); - static_request<128> r2; - r1 = r2; - check(r1, 0, - "GET / HTTP/1.1\r\n" - "\r\n"); - BOOST_TEST( - r1.buffer().data() != - r2.buffer().data()); - BOOST_TEST( - r1.method() == method::get); - BOOST_TEST( - r1.method_text() == "GET"); - BOOST_TEST( - r1.version() == version::http_1_1); - } - } - } - - void - testViewConstructor() - { - { - static_request<64> req; - BOOST_TEST_EQ( - req.buffer(), - "GET / HTTP/1.1\r\n\r\n"); - - request_view req_view(req); - static_request<64> req2(req_view); - - BOOST_TEST_EQ( - req2.buffer(), - "GET / HTTP/1.1\r\n\r\n"); - - BOOST_TEST_NE( - req2.buffer().data(), - req.buffer().data()); - } - + // static_request(static_request&&) { - static_request<64> req; - req.set_method("POST"); - BOOST_TEST_EQ( - req.buffer(), - "POST / HTTP/1.1\r\n\r\n"); - - request_view req_view(req); - static_request<64> req2(req_view); - - BOOST_TEST_EQ( - req2.buffer(), - "POST / HTTP/1.1\r\n\r\n"); - - BOOST_TEST_NE( - req2.buffer().data(), - req.buffer().data()); - - BOOST_TEST_NE( - req2.buffer().data(), - req_view.buffer().data()); - } - } - - void - testObservers() - { - } - - void - testModifiers() - { - // clear() - { - { - static_request<64> req; - BOOST_TEST(req.capacity_in_bytes() == 64); - req.clear(); - BOOST_TEST(req.capacity_in_bytes() == 64); - BOOST_TEST(req.buffer() == - "GET / HTTP/1.1\r\n\r\n"); - } - { - static_request<128> req( - "POST /x HTTP/1.1\r\n" - "User-Agent: boost\r\n" - "\r\n"); - auto const n = - req.capacity_in_bytes(); - BOOST_TEST(n > 0); - req.clear(); - BOOST_TEST(req.size() == 0); - BOOST_TEST( - req.capacity_in_bytes() == n); - BOOST_TEST( - req.method() == method::get); - BOOST_TEST( - req.method_text() == "GET"); - BOOST_TEST( - req.target() == "/"); - BOOST_TEST( - req.version() == version::http_1_1); - BOOST_TEST(req.buffer() == - "GET / HTTP/1.1\r\n\r\n"); - } - } - - // set_method(method) - { - { - static_request<64> req; - req.set_method(method::delete_); - BOOST_TEST( - req.method() == method::delete_); - BOOST_TEST( - req.method_text() == "DELETE"); - BOOST_TEST(req.buffer() == - "DELETE / HTTP/1.1\r\n\r\n"); - } - { - static_request<128> req( - "POST /x HTTP/1.1\r\n" - "User-Agent: boost\r\n" - "\r\n"); - req.set_method(method::delete_); - BOOST_TEST( - req.method() == method::delete_); - BOOST_TEST( - req.method_text() == "DELETE"); - BOOST_TEST(req.buffer() == - "DELETE /x HTTP/1.1\r\n" - "User-Agent: boost\r\n" - "\r\n"); - } - } - - // set_method(string_view) - { - { - static_request<64> req; - req.set_method("DELETE"); - BOOST_TEST( - req.method() == method::delete_); - BOOST_TEST( - req.method_text() == "DELETE"); - BOOST_TEST(req.buffer() == - "DELETE / HTTP/1.1\r\n\r\n"); - } - { - static_request<128> req( - "POST /abcdefghijklmnopqrstuvwxyz HTTP/1.1\r\n" - "User-Agent: boost\r\n" - "\r\n"); - req.set_method("DELETE"); - BOOST_TEST( - req.method() == method::delete_); - BOOST_TEST( - req.method_text() == "DELETE"); - BOOST_TEST(req.buffer() == - "DELETE /abcdefghijklmnopqrstuvwxyz HTTP/1.1\r\n" - "User-Agent: boost\r\n" - "\r\n"); - } - { - static_request<128> req( - "DELETE /abcdefghijklmnopqrstuvwxyz HTTP/1.1\r\n" - "User-Agent: boost\r\n" - "\r\n"); - req.set_method("PUT"); - BOOST_TEST( - req.method() == method::put); - BOOST_TEST( - req.method_text() == "PUT"); - BOOST_TEST(req.buffer() == - "PUT /abcdefghijklmnopqrstuvwxyz HTTP/1.1\r\n" - "User-Agent: boost\r\n" - "\r\n"); - } - { - static_request<128> req( - "SOMETHINGSUPERLONGHERE /abcdefghijklmnopqrstuvwxyz HTTP/1.1\r\n" - "User-Agent: boost\r\n" - "\r\n"); - req.set_method("PUT"); - BOOST_TEST( - req.method() == method::put); - BOOST_TEST( - req.method_text() == "PUT"); - BOOST_TEST_EQ(req.buffer(), - "PUT /abcdefghijklmnopqrstuvwxyz HTTP/1.1\r\n" - "User-Agent: boost\r\n" - "\r\n"); - } - { - static_request<128> req( - "SOMETHINGSUPERLONGHERE /abcdefghijklmnopqrstuvwxyz HTTP/1.1\r\n" - "User-Agent: boost\r\n" - "\r\n"); - req.set_method("SOMETHINGSUPERLONGHERE"); - BOOST_TEST( - req.method() == method::unknown); - BOOST_TEST( - req.method_text() == "SOMETHINGSUPERLONGHERE"); - BOOST_TEST(req.buffer() == - "SOMETHINGSUPERLONGHERE /abcdefghijklmnopqrstuvwxyz HTTP/1.1\r\n" - "User-Agent: boost\r\n" - "\r\n"); - } - } - - // set_target - { - { - static_request<128> req; - req.set_target("/index.htm"); - BOOST_TEST( - req.target() == "/index.htm"); - BOOST_TEST(req.buffer() == - "GET /index.htm HTTP/1.1\r\n\r\n"); - } - { - static_request<128> req( - "POST /x HTTP/1.1\r\n" - "User-Agent: boost\r\n" - "\r\n"); - req.set_target("/index.htm"); - BOOST_TEST(req.buffer() == - "POST /index.htm HTTP/1.1\r\n" - "User-Agent: boost\r\n" - "\r\n"); - } - { - // shrinks - static_request<128> req( - "SOMETHINGSUPERLONGHERE /abcdefghijklmnopqrstuvwxyz HTTP/1.1\r\n" - "User-Agent: boost\r\n" - "\r\n"); - req.set_target("/abc"); - BOOST_TEST_EQ( - req.target(), "/abc"); - BOOST_TEST_EQ(req.buffer(), - "SOMETHINGSUPERLONGHERE /abc HTTP/1.1\r\n" - "User-Agent: boost\r\n" - "\r\n"); - } - { - // same size - static_request<128> req( - "SOMETHINGSUPERLONGHERE /abcdefghijklmnopqrstuvwxyz HTTP/1.1\r\n" - "User-Agent: boost\r\n" - "\r\n"); - req.set_target("/zyxwvutsrqponmlkjihgfedcba"); - BOOST_TEST_EQ( - req.target(), "/zyxwvutsrqponmlkjihgfedcba"); - BOOST_TEST_EQ(req.buffer(), - "SOMETHINGSUPERLONGHERE /zyxwvutsrqponmlkjihgfedcba HTTP/1.1\r\n" - "User-Agent: boost\r\n" - "\r\n"); - } - { - // grows - static_request<128> req( - "SOMETHINGSUPERLONGHERE /abcdefghijklmnopqrstuvwxyz HTTP/1.1\r\n" - "User-Agent: boost\r\n" - "\r\n"); - req.set_target("/abcdefghijklmnopqrstuvwxyzzyxwvutsrqponmlkjihgfedcba"); - BOOST_TEST_EQ( - req.target(), "/abcdefghijklmnopqrstuvwxyzzyxwvutsrqponmlkjihgfedcba"); - BOOST_TEST_EQ(req.buffer(), - "SOMETHINGSUPERLONGHERE /abcdefghijklmnopqrstuvwxyzzyxwvutsrqponmlkjihgfedcba HTTP/1.1\r\n" - "User-Agent: boost\r\n" - "\r\n"); - } - } - - // set_version - { - { - static_request<128> req; - req.set_version(version::http_1_0); - BOOST_TEST( - req.version() == version::http_1_0); - BOOST_TEST(req.buffer() == - "GET / HTTP/1.0\r\n\r\n"); - } - { - static_request<128> req( - "POST /x HTTP/1.1\r\n" - "User-Agent: boost\r\n" - "\r\n"); - req.set_version(version::http_1_0); - BOOST_TEST( - req.version() == version::http_1_0); - BOOST_TEST(req.buffer() == - "POST /x HTTP/1.0\r\n" - "User-Agent: boost\r\n" - "\r\n"); - } - } - } - - void - testExpect() - { - { - static_request<64> req; - req.set_expect_100_continue(true); + char buf[64]; + static_request r1(buf, sizeof(buf)); + static_request r2(std::move(r1)); BOOST_TEST( - req.metadata().expect.is_100_continue); - - req.set_expect_100_continue(false); + r2.buffer().data() != r1.buffer().data()); BOOST_TEST( - !req.metadata().expect.is_100_continue); + r2.buffer().data() == buf); } - + // operator=(request_base const&) { - static_request<64> req; - req.set_expect_100_continue(false); + char buf1[128]; + static_request r1(buf1, sizeof(buf1)); + const request r2(cs); + r1 = r2; BOOST_TEST( - !req.metadata().expect.is_100_continue); - } - - { - static_request<64> req; - req.set_expect_100_continue(true); - BOOST_TEST( - req.metadata().expect.is_100_continue); - - req.set_expect_100_continue(true); + r1.buffer() == cs); BOOST_TEST( - req.metadata().expect.is_100_continue); + r1.buffer().data() != r2.buffer().data()); } + // operator=(static_request const&) { - static_request<64> req; - BOOST_TEST( - !req.metadata().expect.ec.failed()); - - req.set("Expect", "101-dalmations"); - BOOST_TEST( - req.metadata().expect.ec.failed()); - - req.set_expect_100_continue(true); - BOOST_TEST( - !req.metadata().expect.ec.failed()); - BOOST_TEST( - req.metadata().expect.is_100_continue); - } - - { - static_request<128> req; - req.append("Expect", "100-continue"); - req.append("Expect", "101-dalmations"); - - BOOST_TEST( - req.metadata().expect.ec.failed()); - BOOST_TEST_EQ( - req.count("Expect"), 2); - - req.set_expect_100_continue(true); - BOOST_TEST( - !req.metadata().expect.ec.failed()); - BOOST_TEST( - req.metadata().expect.is_100_continue); - BOOST_TEST_EQ( - req.count("Expect"), 1); - } - - { - static_request<256> req; - req.append("Expect", "100-continue"); - req.append("Content-Length", "1234"); - req.append("Expect", "100-continue"); - - BOOST_TEST( - req.metadata().expect.ec.failed()); - BOOST_TEST_EQ( - req.count("Expect"), 2); - - req.set_expect_100_continue(true); - BOOST_TEST( - !req.metadata().expect.ec.failed()); - BOOST_TEST( - req.metadata().expect.is_100_continue); - BOOST_TEST_EQ( - req.count("Expect"), 1); - } - - { - static_request<256> req; - req.append("Expect", "404-not-found"); - req.append("Content-Length", "1234"); - req.append("Expect", "101-dalmations"); - - BOOST_TEST( - req.metadata().expect.ec.failed()); - BOOST_TEST_EQ( - req.count("Expect"), 2); - - req.set_expect_100_continue(true); - BOOST_TEST( - !req.metadata().expect.ec.failed()); - BOOST_TEST( - req.metadata().expect.is_100_continue); - BOOST_TEST_EQ( - req.count("Expect"), 1); - } - - { - static_request<256> req; - req.append("Expect", "100-continue"); - req.append("Content-Length", "1234"); - req.append("Expect", "100-continue"); - - BOOST_TEST( - req.metadata().expect.ec.failed()); - BOOST_TEST_EQ( - req.count("Expect"), 2); - - req.set_expect_100_continue(false); + char buf1[128]; + static_request r1(buf1, sizeof(buf1)); + r1 = request(cs); + char buf2[128]; + static_request r2(buf2, sizeof(buf2)); + r2 = r1; BOOST_TEST( - !req.metadata().expect.ec.failed()); + r2.buffer() == cs); BOOST_TEST( - !req.metadata().expect.is_100_continue); - BOOST_TEST_EQ( - req.count("Expect"), 0); - BOOST_TEST_EQ( - req.count("Content-Length"), 1); + r2.buffer().data() != r1.buffer().data()); } } void - testInitialSize() + testCapacity() { - static_request<96> r; + char buf[96]; + static_request r(buf, sizeof(buf)); + + BOOST_TEST_EQ( + r.capacity_in_bytes(), 96); + BOOST_TEST_EQ( + r.max_capacity_in_bytes(), 96); + r.append("T", "*"); r.append("T", "*"); r.append("T", "*"); @@ -583,13 +111,8 @@ struct static_request_test void run() { - testHelpers(); testSpecial(); - testViewConstructor(); - testObservers(); - testModifiers(); - testExpect(); - testInitialSize(); + testCapacity(); } }; diff --git a/test/unit/static_response.cpp b/test/unit/static_response.cpp index d26c78cd..70b27573 100644 --- a/test/unit/static_response.cpp +++ b/test/unit/static_response.cpp @@ -10,11 +10,7 @@ // Test that header file is self-contained. #include -#include -#include - -#include -#include +#include #include "test_suite.hpp" @@ -24,253 +20,75 @@ namespace http_proto { class static_response_test { public: - - template - static - void - check( - static_response const& res, - status sc, - unsigned short si, - core::string_view rs, - version v) - { - BOOST_TEST_EQ(res.version(), v); - BOOST_TEST_EQ(res.status(), sc); - BOOST_TEST_EQ(res.status_int(), si); - BOOST_TEST_EQ(res.reason(), rs); - } - void testSpecial() { - // static_response(status, version) - { - { - static_response<64> res(status::ok); - check(res, status::ok, 200, "OK", version::http_1_1); - BOOST_TEST(res.capacity_in_bytes() == 64); - BOOST_TEST_EQ(res.buffer(), "HTTP/1.1 200 OK\r\n\r\n"); - } - - { - static_response<64> res(status::ok, version::http_1_0); - check(res, status::ok, 200, "OK", version::http_1_0); - BOOST_TEST(res.capacity_in_bytes() == 64); - BOOST_TEST_EQ(res.buffer(), "HTTP/1.0 200 OK\r\n\r\n"); - } - - { - static_response<64> res(status::not_found, version::http_1_0); - check(res, status::not_found, 404, "Not Found", version::http_1_0); - BOOST_TEST(res.capacity_in_bytes() == 64); - } - - // different buffer - { - static_response<64> r1(status::not_found); - static_response<64> r2(status::not_found); - BOOST_TEST(r1.buffer().data() != r2.buffer().data()); - BOOST_TEST(r1.capacity_in_bytes() == 64); - BOOST_TEST(r2.capacity_in_bytes() == 64); - } - } + core::string_view const cs = + "HTTP/1.1 101 Switching Protocols\r\n" + "Server: test\r\n" + "\r\n"; - // static_response() + // static_response(void* storage, std::size_t cap) { - { - static_response<64> res; - check(res, status::ok, 200, "OK", version::http_1_1); - BOOST_TEST(res.capacity_in_bytes() == 64); - } + char buf[64]; + static_response req(buf, sizeof(buf)); + BOOST_TEST( + req.status_int() == 200); + BOOST_TEST( + req.status() == status::ok); + BOOST_TEST( + req.version() == version::http_1_1); } - // static_response(static_response<64> const&) + // static_response(static_response&&) { - { - static_response<64> r1; - static_response<64> r2(r1); - check(r1, status::ok, 200, "OK", version::http_1_1); - check(r2, status::ok, 200, "OK", version::http_1_1); - BOOST_TEST_NE( - r1.buffer().data(), - r2.buffer().data()); - BOOST_TEST(r1.capacity_in_bytes() == 64); - BOOST_TEST(r2.capacity_in_bytes() == 64); - } - { - static_response<64> r1(status::not_found, version::http_1_0); - static_response<64> r2(r1); - check(r1, status::not_found, 404, "Not Found", version::http_1_0); - check(r2, status::not_found, 404, "Not Found", version::http_1_0); - BOOST_TEST( - r1.buffer().data() != r2.buffer().data()); - BOOST_TEST(r1.capacity_in_bytes() == 64); - BOOST_TEST(r2.capacity_in_bytes() == 64); - } + char buf[64]; + static_response r1(buf, sizeof(buf)); + static_response r2(std::move(r1)); + BOOST_TEST( + r2.buffer().data() != r1.buffer().data()); + BOOST_TEST( + r2.buffer().data() == buf); } - // operator=(static_response<64> const&) + // operator=(response_base const&) { - static_response<64> r1; - static_response<64> r2(status::not_found, version::http_1_0); + char buf1[128]; + static_response r1(buf1, sizeof(buf1)); + const response r2(cs); r1 = r2; - check(r1, status::not_found, 404, "Not Found", version::http_1_0); - check(r2, status::not_found, 404, "Not Found", version::http_1_0); + BOOST_TEST( + r1.buffer() == cs); BOOST_TEST( r1.buffer().data() != r2.buffer().data()); - BOOST_TEST(r1.capacity_in_bytes() == 64); - BOOST_TEST(r2.capacity_in_bytes() == 64); - } - - //---------------------------------------- - - // static_response(response_view const&) - { - core::string_view const s = - "HTTP/1.0 404 Not Found\r\n" - "Server: test\r\n" - "\r\n"; - static_response<64> r(s); - response_view rv = r; - static_response<64> res(rv); - check(res, status::not_found, 404, "Not Found", version::http_1_0); - BOOST_TEST_EQ(res.buffer(), s); - BOOST_TEST(res.buffer().data() != s.data()); - BOOST_TEST(res.begin()->id == field::server); - BOOST_TEST(res.begin()->name == "Server"); - BOOST_TEST(res.begin()->value == "test"); - } - - // operator=(response_view const&) - { - core::string_view const s = - "HTTP/1.1 101 Switching Protocols\r\n" - "Server: test\r\n" - "\r\n"; - static_response<128> r(s); - response_view rv = r; - static_response<128> res(status::not_found); - res = rv; - BOOST_TEST_EQ(res.buffer(), s); - BOOST_TEST(res.buffer().data() != s.data()); - check(res, status::switching_protocols, 101, "Switching Protocols", version::http_1_1); - BOOST_TEST(res.begin()->id == field::server); - BOOST_TEST(res.begin()->name == "Server"); - BOOST_TEST(res.begin()->value == "test"); - } - - //---------------------------------------- - - // operator response_view() - { - { - static_response<64> res; - response_view rv(res); - BOOST_TEST_EQ(rv.version(), version::http_1_1); - BOOST_TEST_EQ(rv.status(), status::ok); - BOOST_TEST_EQ(rv.status_int(), 200); - BOOST_TEST_EQ(rv.reason(), "OK"); - BOOST_TEST_EQ(rv.buffer(), "HTTP/1.1 200 OK\r\n\r\n"); - BOOST_TEST(rv.buffer().data() == res.buffer().data()); - } - { - static_response<64> res(status::not_found, version::http_1_0); - response_view rv(res); - BOOST_TEST_EQ(rv.version(), version::http_1_0); - BOOST_TEST_EQ(rv.status(), status::not_found); - BOOST_TEST_EQ(rv.status_int(), 404); - BOOST_TEST_EQ(rv.reason(), "Not Found"); - BOOST_TEST_EQ(rv.buffer(), "HTTP/1.0 404 Not Found\r\n\r\n"); - BOOST_TEST(rv.buffer().data() == res.buffer().data()); - } } - } - void - testModifiers() - { - // clear() + // operator=(static_response const&) { - { - static_response<64> res; - BOOST_TEST(res.capacity_in_bytes() == 64); - res.clear(); - BOOST_TEST(res.buffer() == "HTTP/1.1 200 OK\r\n\r\n"); - } - { - static_response<64> res(status::not_found, version::http_1_0); - BOOST_TEST(res.capacity_in_bytes() == 64); - res.clear(); - check(res, status::ok, 200, "OK", version::http_1_1); - BOOST_TEST(res.capacity_in_bytes() == 64); - } + char buf1[128]; + static_response r1(buf1, sizeof(buf1)); + r1 = response(cs); + char buf2[128]; + static_response r2(buf2, sizeof(buf2)); + r2 = r1; + BOOST_TEST( + r2.buffer() == cs); + BOOST_TEST( + r2.buffer().data() != r1.buffer().data()); } - // set_start_line() - { - { - static_response<64> res; - res.set_start_line(status::not_found); - check(res, status::not_found, 404, "Not Found", version::http_1_1); - } - { - static_response<64> res; - res.set_start_line(status::switching_protocols, version::http_1_0); - check(res, status::switching_protocols, 101, "Switching Protocols", version::http_1_0); - } - { - static_response<64> res; - res.set_start_line(199, "Huh", version::http_1_1); - check(res, status::unknown, 199, "Huh", version::http_1_1); - } - { - static_response<64> res; - res.set_start_line(199, "Huh", version::http_1_1); - check(res, status::unknown, 199, "Huh", version::http_1_1); - - res.set_start_line(199, "Huh", version::http_1_1); - check(res, status::unknown, 199, "Huh", version::http_1_1); - - res.set_start_line(199, "ab", version::http_1_1); - check(res, status::unknown, 199, "ab", version::http_1_1); - - res.set_start_line(199, "a", version::http_1_1); - check(res, status::unknown, 199, "a", version::http_1_1); - - res.set_start_line(199, "abcdefghijklmnopqrstuvwxyz", version::http_1_1); - check(res, status::unknown, 199, "abcdefghijklmnopqrstuvwxyz", version::http_1_1); - } - { - core::string_view s = - "HTTP/1.1 200 OK\r\n" - "Server: test\r\n" - "Content-Length: 0\r\n" - "\r\n"; - static_response<128> r(s); - response_view rv = r; - static_response<128> res(rv); - check(res, status::ok, 200, "OK", version::http_1_1); - BOOST_TEST(res.size() == 2); - auto it = res.begin(); - BOOST_TEST_EQ(it->id, field::server); - BOOST_TEST_EQ(it->name, "Server"); - BOOST_TEST_EQ(it->value, "test"); - ++it; - BOOST_TEST_EQ(it->id, field::content_length); - BOOST_TEST_EQ(it->name, "Content-Length"); - BOOST_TEST_EQ(it->value, "0"); - } - } } void - testInitialSize() + testCapacity() { - static_response<32> f; + char buf[32]; + static_response f(buf, sizeof(buf)); BOOST_TEST_THROWS( f.append(field::host, "www.google.com"), std::length_error); + BOOST_TEST_EQ( + f.capacity_in_bytes(), 32); BOOST_TEST_EQ( f.max_capacity_in_bytes(), 32); } @@ -279,8 +97,7 @@ class static_response_test run() { testSpecial(); - testModifiers(); - testInitialSize(); + testCapacity(); } }; diff --git a/test/unit/test_helpers.cpp b/test/unit/test_helpers.cpp index 1f2894f9..6b2e822c 100644 --- a/test/unit/test_helpers.cpp +++ b/test/unit/test_helpers.cpp @@ -17,7 +17,7 @@ namespace http_proto { void test_fields( - fields_view_base const& f, + fields_base const& f, core::string_view match) { fields r(match); diff --git a/test/unit/test_helpers.hpp b/test/unit/test_helpers.hpp index f7a99618..a4a9c7c5 100644 --- a/test/unit/test_helpers.hpp +++ b/test/unit/test_helpers.hpp @@ -52,7 +52,7 @@ test_to_string(Buffers const& bs) // Test that fields equals HTTP string void test_fields( - fields_view_base const& f, + fields_base const& f, core::string_view match); //------------------------------------------------