From 89f0030ac6b09ed202e6bba99eb438ec33b6f023 Mon Sep 17 00:00:00 2001 From: Mohammad Nejati Date: Mon, 28 Jul 2025 13:42:15 +0000 Subject: [PATCH 1/6] move detail rules to src --- include/boost/http_proto/rfc/detail/rules.hpp | 276 ------------------ include/boost/http_proto/rfc/detail/ws.hpp | 34 +++ .../boost/http_proto/rfc/impl/list_rule.hpp | 4 +- include/boost/http_proto/rfc/list_rule.hpp | 1 - src/detail/header.cpp | 2 +- src/fields_base.cpp | 1 - src/parser.cpp | 1 - src/rfc/detail/rules.cpp | 2 +- src/rfc/detail/rules.hpp | 252 +++++++++++++++- src/rfc/transfer_coding_rule.cpp | 2 +- test/unit/rfc/detail/rules.cpp | 2 +- 11 files changed, 284 insertions(+), 293 deletions(-) delete mode 100644 include/boost/http_proto/rfc/detail/rules.hpp create mode 100644 include/boost/http_proto/rfc/detail/ws.hpp diff --git a/include/boost/http_proto/rfc/detail/rules.hpp b/include/boost/http_proto/rfc/detail/rules.hpp deleted file mode 100644 index ff08337c..00000000 --- a/include/boost/http_proto/rfc/detail/rules.hpp +++ /dev/null @@ -1,276 +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 -// - -#ifndef BOOST_HTTP_PROTO_RFC_DETAIL_RULES_HPP -#define BOOST_HTTP_PROTO_RFC_DETAIL_RULES_HPP - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { -namespace http_proto { -namespace detail { - -//------------------------------------------------ - -// WS = SP / HTAB -struct ws_t -{ - constexpr - bool - operator()(char c) const noexcept - { - return c == ' ' || c == '\t'; - } -}; - -constexpr ws_t ws{}; - -//------------------------------------------------ - -/* Used with list_rule - - @par BNF - @code - ows-comma = OWS "," OWS - @endcode -*/ -struct ows_comma_ows_rule_t -{ - using value_type = void; - - auto - parse( - char const*& it, - char const* end) const noexcept -> - system::result - { - // OWS - it = grammar::find_if_not( - it, end, ws); - if(it == end) - return grammar::error::mismatch; - // "," - if(*it != ',') - return grammar::error::mismatch; - ++it; - // OWS - it = grammar::find_if_not( - it, end, ws); - return {}; - } -}; - -constexpr ows_comma_ows_rule_t ows_comma_ows_rule{}; - -//------------------------------------------------ - -// used for request-target -// -// target-char = -// -struct target_chars_t -{ - constexpr - bool - operator()(char c) const noexcept - { - return - (static_cast(c) >= 0x21) && - (static_cast(c) <= 0x7e); - } -}; - -constexpr target_chars_t target_chars{}; - -//------------------------------------------------ - -// WS-VCHAR = SP / HTAB / VCHAR -struct ws_vchars_t -{ - constexpr - bool - operator()(char ch) const noexcept - { - return ( - ch >= 0x20 && ch <= 0x7e) || - ch == 0x09; - } -}; - -constexpr ws_vchars_t ws_vchars{}; - -//------------------------------------------------ - -// OWS = *( SP / HTAB ) -inline -void -skip_ows( - char const*& it, - char const* end) noexcept -{ - while(it != end) - { - if(! ws(*it)) - break; - ++it; - } -} - -struct ows_rule_t -{ - using value_type = void; - - system::result - parse( - char const*& it, - char const* end) noexcept - { - skip_ows(it, end); - return system::error_code(); - } -}; - -constexpr ows_rule_t ows_rule{}; - -//------------------------------------------------ - -// CRLF = CR LF -struct crlf_rule_t -{ - using value_type = void; - - system::result - parse( - char const*& it, - char const* end) const noexcept; -}; - -constexpr crlf_rule_t crlf_rule{}; - -//------------------------------------------------ - -// HTTP-version = "HTTP/" DIGIT "." DIGIT -struct version_rule_t -{ - using value_type = unsigned char; - - system::result - parse( - char const*& it, - char const* end) const noexcept; -}; - -constexpr version_rule_t version_rule{}; - -//------------------------------------------------ - -// request-line = method SP request-target SP HTTP-version CRLF -constexpr auto -request_line_rule = - grammar::tuple_rule( - token_rule, - grammar::squelch( - grammar::delim_rule(' ') ), - grammar::token_rule( - grammar::lut_chars(target_chars) ), - grammar::squelch( - grammar::delim_rule(' ') ), - version_rule, - crlf_rule); - -//------------------------------------------------ - -// status-code = 3DIGIT -struct status_code_rule_t -{ - struct value_type - { - int v; - status st; - core::string_view s; - }; - - system::result - parse( - char const*& it, - char const* end) const noexcept; -}; - -constexpr status_code_rule_t status_code_rule{}; - -//------------------------------------------------ - -// status-code = *( HTAB / SP / VCHAR / obs-text ) -struct reason_phrase_rule_t -{ - using value_type = core::string_view; - - system::result - parse( - char const*& it, - char const* end) const noexcept; -}; - -constexpr reason_phrase_rule_t reason_phrase_rule{}; - -//------------------------------------------------ - -// status-line = HTTP-version SP status-code SP reason-phrase CRLF -constexpr auto -status_line_rule = - grammar::tuple_rule( - version_rule, - grammar::squelch( - grammar::delim_rule(' ') ), - status_code_rule, - grammar::squelch( - grammar::delim_rule(' ') ), - reason_phrase_rule, - crlf_rule); - -//------------------------------------------------ - -struct field_rule_t -{ - struct value_type - { - core::string_view name; - core::string_view value; - bool has_obs_fold = false; - }; - - system::result - parse( - char const*& it, - char const* end) const noexcept; -}; - -constexpr field_rule_t field_rule{}; - -/** Replace obs-fold with spaces -*/ -BOOST_HTTP_PROTO_DECL -void -remove_obs_fold( - char *start, - char const* end) noexcept; - -} // detail -} // http_proto -} // boost - -#endif diff --git a/include/boost/http_proto/rfc/detail/ws.hpp b/include/boost/http_proto/rfc/detail/ws.hpp new file mode 100644 index 00000000..20bcb04e --- /dev/null +++ b/include/boost/http_proto/rfc/detail/ws.hpp @@ -0,0 +1,34 @@ +// +// 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 +// + +#ifndef BOOST_HTTP_PROTO_RFC_DETAIL_WS_HPP +#define BOOST_HTTP_PROTO_RFC_DETAIL_WS_HPP + +namespace boost { +namespace http_proto { +namespace detail { + +// WS = SP / HTAB +struct ws_t +{ + constexpr + bool + operator()(char c) const noexcept + { + return c == ' ' || c == '\t'; + } +}; + +constexpr ws_t ws{}; + +} // detail +} // http_proto +} // boost + +#endif diff --git a/include/boost/http_proto/rfc/impl/list_rule.hpp b/include/boost/http_proto/rfc/impl/list_rule.hpp index f490cce2..ca18b490 100644 --- a/include/boost/http_proto/rfc/impl/list_rule.hpp +++ b/include/boost/http_proto/rfc/impl/list_rule.hpp @@ -10,10 +10,12 @@ #ifndef BOOST_HTTP_PROTO_RFC_IMPL_LIST_RULE_HPP #define BOOST_HTTP_PROTO_RFC_IMPL_LIST_RULE_HPP +#include + #include +#include #include #include -#include namespace boost { namespace http_proto { diff --git a/include/boost/http_proto/rfc/list_rule.hpp b/include/boost/http_proto/rfc/list_rule.hpp index 8565519b..5afa2de7 100644 --- a/include/boost/http_proto/rfc/list_rule.hpp +++ b/include/boost/http_proto/rfc/list_rule.hpp @@ -11,7 +11,6 @@ #define BOOST_HTTP_PROTO_RFC_LIST_RULE_HPP #include -#include #include #include diff --git a/src/detail/header.cpp b/src/detail/header.cpp index bb943faf..3da5d2bd 100644 --- a/src/detail/header.cpp +++ b/src/detail/header.cpp @@ -9,12 +9,12 @@ // #include "src/rfc/transfer_coding_rule.hpp" +#include "src/rfc/detail/rules.hpp" #include #include #include #include -#include #include #include #include diff --git a/src/fields_base.cpp b/src/fields_base.cpp index f97a25a3..cf1aecf8 100644 --- a/src/fields_base.cpp +++ b/src/fields_base.cpp @@ -15,7 +15,6 @@ #include #include #include -#include #include #include "src/detail/move_chars.hpp" diff --git a/src/parser.cpp b/src/parser.cpp index 6ec77e47..0203a6c3 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -11,7 +11,6 @@ #include #include #include -#include #include "src/detail/brotli_filter_base.hpp" #include "src/detail/zlib_filter_base.hpp" diff --git a/src/rfc/detail/rules.cpp b/src/rfc/detail/rules.cpp index cf0ef819..b7d8ce48 100644 --- a/src/rfc/detail/rules.cpp +++ b/src/rfc/detail/rules.cpp @@ -7,7 +7,7 @@ // Official repository: https://github.com/cppalliance/http_proto // -#include +#include "src/rfc/detail/rules.hpp" #include #include diff --git a/src/rfc/detail/rules.hpp b/src/rfc/detail/rules.hpp index 990ceabe..39125a9c 100644 --- a/src/rfc/detail/rules.hpp +++ b/src/rfc/detail/rules.hpp @@ -1,5 +1,6 @@ // // 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) @@ -10,15 +11,250 @@ #ifndef BOOST_HTTP_PROTO_SRC_RFC_DETAIL_RULES_HPP #define BOOST_HTTP_PROTO_SRC_RFC_DETAIL_RULES_HPP +#include +#include +#include +#include #include #include +#include +#include +#include +#include +#include -namespace boost +namespace boost { +namespace http_proto { +namespace detail { + +//------------------------------------------------ + +/* Used with list_rule + + @par BNF + @code + ows-comma = OWS "," OWS + @endcode +*/ +struct ows_comma_ows_rule_t +{ + using value_type = void; + + auto + parse( + char const*& it, + char const* end) const noexcept -> + system::result + { + // OWS + it = grammar::find_if_not( + it, end, ws); + if(it == end) + return grammar::error::mismatch; + // "," + if(*it != ',') + return grammar::error::mismatch; + ++it; + // OWS + it = grammar::find_if_not( + it, end, ws); + return {}; + } +}; + +constexpr ows_comma_ows_rule_t ows_comma_ows_rule{}; + +//------------------------------------------------ + +// used for request-target +// +// target-char = +// +struct target_chars_t +{ + constexpr + bool + operator()(char c) const noexcept + { + return + (static_cast(c) >= 0x21) && + (static_cast(c) <= 0x7e); + } +}; + +constexpr target_chars_t target_chars{}; + +//------------------------------------------------ + +// WS-VCHAR = SP / HTAB / VCHAR +struct ws_vchars_t +{ + constexpr + bool + operator()(char ch) const noexcept + { + return ( + ch >= 0x20 && ch <= 0x7e) || + ch == 0x09; + } +}; + +constexpr ws_vchars_t ws_vchars{}; + +//------------------------------------------------ + +// OWS = *( SP / HTAB ) +inline +void +skip_ows( + char const*& it, + char const* end) noexcept +{ + while(it != end) + { + if(! ws(*it)) + break; + ++it; + } +} + +struct ows_rule_t +{ + using value_type = void; + + system::result + parse( + char const*& it, + char const* end) noexcept + { + skip_ows(it, end); + return system::error_code(); + } +}; + +constexpr ows_rule_t ows_rule{}; + +//------------------------------------------------ + +// CRLF = CR LF +struct crlf_rule_t +{ + using value_type = void; + + system::result + parse( + char const*& it, + char const* end) const noexcept; +}; + +constexpr crlf_rule_t crlf_rule{}; + +//------------------------------------------------ + +// HTTP-version = "HTTP/" DIGIT "." DIGIT +struct version_rule_t +{ + using value_type = unsigned char; + + system::result + parse( + char const*& it, + char const* end) const noexcept; +}; + +constexpr version_rule_t version_rule{}; + +//------------------------------------------------ + +// request-line = method SP request-target SP HTTP-version CRLF +constexpr auto +request_line_rule = + grammar::tuple_rule( + token_rule, + grammar::squelch( + grammar::delim_rule(' ') ), + grammar::token_rule( + grammar::lut_chars(target_chars) ), + grammar::squelch( + grammar::delim_rule(' ') ), + version_rule, + crlf_rule); + +//------------------------------------------------ + +// status-code = 3DIGIT +struct status_code_rule_t { -namespace http_proto + struct value_type + { + int v; + status st; + core::string_view s; + }; + + system::result + parse( + char const*& it, + char const* end) const noexcept; +}; + +constexpr status_code_rule_t status_code_rule{}; + +//------------------------------------------------ + +// status-code = *( HTAB / SP / VCHAR / obs-text ) +struct reason_phrase_rule_t { -namespace detail + using value_type = core::string_view; + + system::result + parse( + char const*& it, + char const* end) const noexcept; +}; + +constexpr reason_phrase_rule_t reason_phrase_rule{}; + +//------------------------------------------------ + +// status-line = HTTP-version SP status-code SP reason-phrase CRLF +constexpr auto +status_line_rule = + grammar::tuple_rule( + version_rule, + grammar::squelch( + grammar::delim_rule(' ') ), + status_code_rule, + grammar::squelch( + grammar::delim_rule(' ') ), + reason_phrase_rule, + crlf_rule); + +//------------------------------------------------ + +struct field_rule_t { + struct value_type + { + core::string_view name; + core::string_view value; + bool has_obs_fold = false; + }; + + system::result + parse( + char const*& it, + char const* end) const noexcept; +}; + +constexpr field_rule_t field_rule{}; + +/** Replace obs-fold with spaces +*/ +void +remove_obs_fold( + char *start, + char const* end) noexcept; // header-field = field-name ":" OWS field-value OWS struct field_name_rule_t @@ -52,10 +288,8 @@ struct field_value_rule_t constexpr field_value_rule_t field_value_rule{}; -} // namespace detail -} // namespace http_proto -} // namespace boost - - +} // detail +} // http_proto +} // boost -#endif // BOOST_HTTP_PROTO_SRC_RFC_DETAIL_RULES_HPP +#endif diff --git a/src/rfc/transfer_coding_rule.cpp b/src/rfc/transfer_coding_rule.cpp index f4276203..36d7e747 100644 --- a/src/rfc/transfer_coding_rule.cpp +++ b/src/rfc/transfer_coding_rule.cpp @@ -10,7 +10,7 @@ #include "src/rfc/transfer_coding_rule.hpp" -#include +#include #include #include #include diff --git a/test/unit/rfc/detail/rules.cpp b/test/unit/rfc/detail/rules.cpp index 38f663f9..2993186e 100644 --- a/test/unit/rfc/detail/rules.cpp +++ b/test/unit/rfc/detail/rules.cpp @@ -8,7 +8,7 @@ // // Test that header file is self-contained. -#include +#include "../src/rfc/detail/rules.hpp" #include "test_rule.hpp" From 8cd6b797fcff45208d1689558fdfbe21ec5c216a Mon Sep 17 00:00:00 2001 From: Mohammad Nejati Date: Thu, 31 Jul 2025 06:21:30 +0000 Subject: [PATCH 2/6] unit tests for private interfaces are limited to static builds --- src/detail/header.cpp | 2 +- src/rfc/{ => detail}/transfer_coding_rule.cpp | 2 +- src/rfc/{ => detail}/transfer_coding_rule.hpp | 1 - test/unit/CMakeLists.txt | 1 + test/unit/Jamfile | 23 ++++++++++--------- test/unit/rfc/detail/rules.cpp | 6 ++++- .../rfc/{ => detail}/transfer_coding_rule.cpp | 6 ++++- 7 files changed, 25 insertions(+), 16 deletions(-) rename src/rfc/{ => detail}/transfer_coding_rule.cpp (98%) rename src/rfc/{ => detail}/transfer_coding_rule.hpp (98%) rename test/unit/rfc/{ => detail}/transfer_coding_rule.cpp (93%) diff --git a/src/detail/header.cpp b/src/detail/header.cpp index 3da5d2bd..4b71363d 100644 --- a/src/detail/header.cpp +++ b/src/detail/header.cpp @@ -8,8 +8,8 @@ // Official repository: https://github.com/cppalliance/http_proto // -#include "src/rfc/transfer_coding_rule.hpp" #include "src/rfc/detail/rules.hpp" +#include "src/rfc/detail/transfer_coding_rule.hpp" #include #include diff --git a/src/rfc/transfer_coding_rule.cpp b/src/rfc/detail/transfer_coding_rule.cpp similarity index 98% rename from src/rfc/transfer_coding_rule.cpp rename to src/rfc/detail/transfer_coding_rule.cpp index 36d7e747..7b608319 100644 --- a/src/rfc/transfer_coding_rule.cpp +++ b/src/rfc/detail/transfer_coding_rule.cpp @@ -8,7 +8,7 @@ // Official repository: https://github.com/cppalliance/http_proto // -#include "src/rfc/transfer_coding_rule.hpp" +#include "src/rfc/detail/transfer_coding_rule.hpp" #include #include diff --git a/src/rfc/transfer_coding_rule.hpp b/src/rfc/detail/transfer_coding_rule.hpp similarity index 98% rename from src/rfc/transfer_coding_rule.hpp rename to src/rfc/detail/transfer_coding_rule.hpp index f3960175..6912e83e 100644 --- a/src/rfc/transfer_coding_rule.hpp +++ b/src/rfc/detail/transfer_coding_rule.hpp @@ -75,7 +75,6 @@ struct transfer_coding_rule_t } extension; }; - BOOST_HTTP_PROTO_DECL auto parse( char const*& it, diff --git a/test/unit/CMakeLists.txt b/test/unit/CMakeLists.txt index 2847b837..f22e8135 100644 --- a/test/unit/CMakeLists.txt +++ b/test/unit/CMakeLists.txt @@ -25,6 +25,7 @@ source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} PREFIX "" FILES ${PFILES}) source_group("_extra" FILES ${EXTRAFILES}) add_executable(boost_http_proto_tests ${PFILES} ${EXTRAFILES}) target_include_directories(boost_http_proto_tests PRIVATE . ../../../url/extra/test_suite) +target_include_directories(boost_http_proto_tests PRIVATE . ../../) target_link_libraries( boost_http_proto_tests PRIVATE boost_http_proto diff --git a/test/unit/Jamfile b/test/unit/Jamfile index ad3d9c43..be6975c1 100644 --- a/test/unit/Jamfile +++ b/test/unit/Jamfile @@ -23,6 +23,7 @@ project ../../../url/extra/test_suite/test_suite.cpp ./test_helpers.cpp . + ../.. ../../../url/extra/test_suite extra on @@ -30,16 +31,15 @@ project ; local SOURCES = - compression.cpp() + compression.cpp error.cpp field.cpp - fields.cpp fields_base.cpp - fields_view.cpp fields_view_base.cpp - file.cpp + fields_view.cpp + fields.cpp file_base.cpp - file_body.cpp + file.cpp header_limits.cpp http_proto.cpp message_base.cpp @@ -47,12 +47,12 @@ local SOURCES = metadata.cpp method.cpp parser.cpp - request.cpp request_parser.cpp request_view.cpp - response.cpp + request.cpp response_parser.cpp response_view.cpp + response.cpp sandbox.cpp serializer.cpp sink.cpp @@ -65,26 +65,27 @@ local SOURCES = test_helpers.cpp version.cpp rfc/combine_field_values.cpp + rfc/detail/rules.cpp + rfc/detail/transfer_coding_rule.cpp rfc/list_rule.cpp rfc/parameter.cpp rfc/quoted_token_rule.cpp rfc/quoted_token_view.cpp rfc/token_rule.cpp - rfc/transfer_coding_rule.cpp - rfc/detail/rules.cpp ; for local f in $(SOURCES) { -# run $(f) : : : ; run $(f) : target-name $(f:B)_ ; } +# file tests + local FILE_TESTS = file_posix.cpp file_stdio.cpp file_win32.cpp -; + ; for local f in $(FILE_TESTS) { diff --git a/test/unit/rfc/detail/rules.cpp b/test/unit/rfc/detail/rules.cpp index 2993186e..1851ea51 100644 --- a/test/unit/rfc/detail/rules.cpp +++ b/test/unit/rfc/detail/rules.cpp @@ -8,10 +8,12 @@ // // Test that header file is self-contained. -#include "../src/rfc/detail/rules.hpp" +#include "src/rfc/detail/rules.hpp" #include "test_rule.hpp" +#if defined(BOOST_HTTP_PROTO_STATIC_LINK) + namespace boost { namespace http_proto { namespace detail { @@ -61,3 +63,5 @@ TEST_SUITE( } // detail } // http_proto } // boost + +#endif // defined(BOOST_HTTP_PROTO_STATIC_LINK) diff --git a/test/unit/rfc/transfer_coding_rule.cpp b/test/unit/rfc/detail/transfer_coding_rule.cpp similarity index 93% rename from test/unit/rfc/transfer_coding_rule.cpp rename to test/unit/rfc/detail/transfer_coding_rule.cpp index dc3d7f7c..9ec58e76 100644 --- a/test/unit/rfc/transfer_coding_rule.cpp +++ b/test/unit/rfc/detail/transfer_coding_rule.cpp @@ -9,7 +9,7 @@ // // Test that header file is self-contained. -#include "../../src/rfc/transfer_coding_rule.hpp" +#include "src/rfc/detail/transfer_coding_rule.hpp" #include "test_helpers.hpp" @@ -17,6 +17,8 @@ #include #include +#if defined(BOOST_HTTP_PROTO_STATIC_LINK) + namespace boost { namespace http_proto { namespace detail { @@ -83,3 +85,5 @@ TEST_SUITE( } // detail } // http_proto } // boost + +#endif // defined(BOOST_HTTP_PROTO_STATIC_LINK) From ded79e17bfdfec6c60b492ba1d84d677967cfe8a Mon Sep 17 00:00:00 2001 From: Mohammad Nejati Date: Fri, 1 Aug 2025 07:08:35 +0000 Subject: [PATCH 3/6] file_body is refactored into file_source and file_sink --- .github/workflows/ci.yml | 4 +- include/boost/http_proto.hpp | 5 +- include/boost/http_proto/file_sink.hpp | 50 ++++++ .../{file_body.hpp => file_source.hpp} | 31 ++-- src/file_sink.cpp | 43 +++++ src/{file_body.cpp => file_source.cpp} | 51 ++---- test/unit/Jamfile | 2 + test/unit/file_body.cpp | 31 ---- test/unit/file_sink.cpp | 109 +++++++++++++ test/unit/file_source.cpp | 150 ++++++++++++++++++ test/unit/file_test.hpp | 2 - 11 files changed, 387 insertions(+), 91 deletions(-) create mode 100644 include/boost/http_proto/file_sink.hpp rename include/boost/http_proto/{file_body.hpp => file_source.hpp} (63%) create mode 100644 src/file_sink.cpp rename src/{file_body.cpp => file_source.cpp} (53%) delete mode 100644 test/unit/file_body.cpp create mode 100644 test/unit/file_sink.cpp create mode 100644 test/unit/file_source.cpp diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 74576bb9..a948ff77 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -130,7 +130,7 @@ jobs: runs-on: "windows-2022" b2-toolset: "gcc" generator: "MinGW Makefiles" - is-latest: true + is-latest: false is-earliest: true name: "MinGW" build-type: "Release" @@ -143,7 +143,7 @@ jobs: runs-on: "windows-2022" b2-toolset: "gcc" generator: "MinGW Makefiles" - is-latest: true + is-latest: false is-earliest: true name: "MinGW (shared)" shared: true diff --git a/include/boost/http_proto.hpp b/include/boost/http_proto.hpp index 1b24bc02..f06c9d0d 100644 --- a/include/boost/http_proto.hpp +++ b/include/boost/http_proto.hpp @@ -19,10 +19,11 @@ #include #include #include -#include #include -#include +#include +#include #include +#include #include #include #include diff --git a/include/boost/http_proto/file_sink.hpp b/include/boost/http_proto/file_sink.hpp new file mode 100644 index 00000000..024cabaa --- /dev/null +++ b/include/boost/http_proto/file_sink.hpp @@ -0,0 +1,50 @@ +// +// Copyright (c) 2022 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_FILE_SINK_HPP +#define BOOST_HTTP_PROTO_FILE_SINK_HPP + +#include +#include +#include + +namespace boost { +namespace http_proto { + +class file_sink + : public sink +{ + file f_; + +public: + BOOST_HTTP_PROTO_DECL + explicit + file_sink(file&& f) noexcept; + + file_sink() = delete; + file_sink(file_sink const&) = delete; + + BOOST_HTTP_PROTO_DECL + file_sink(file_sink&&) noexcept; + + BOOST_HTTP_PROTO_DECL + ~file_sink(); + +private: + BOOST_HTTP_PROTO_DECL + results + on_write( + buffers::const_buffer, bool) override; +}; + +} // http_proto +} // boost + +#endif diff --git a/include/boost/http_proto/file_body.hpp b/include/boost/http_proto/file_source.hpp similarity index 63% rename from include/boost/http_proto/file_body.hpp rename to include/boost/http_proto/file_source.hpp index 7455cddf..447265d0 100644 --- a/include/boost/http_proto/file_body.hpp +++ b/include/boost/http_proto/file_source.hpp @@ -1,5 +1,6 @@ // // Copyright (c) 2022 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) @@ -7,53 +8,45 @@ // Official repository: https://github.com/cppalliance/http_proto // -#ifndef BOOST_HTTP_PROTO_FILE_BODY_HPP -#define BOOST_HTTP_PROTO_FILE_BODY_HPP +#ifndef BOOST_HTTP_PROTO_FILE_SOURCE_HPP +#define BOOST_HTTP_PROTO_FILE_SOURCE_HPP #include #include -#include #include #include namespace boost { namespace http_proto { -class BOOST_SYMBOL_VISIBLE - file_body - : public source, sink +class file_source + : public source { file f_; std::uint64_t n_; public: - file_body() = delete; - file_body( - file_body const&) = delete; + file_source() = delete; + file_source(file_source const&) = delete; BOOST_HTTP_PROTO_DECL - file_body( - file_body&&) noexcept; + file_source(file_source&&) noexcept; BOOST_HTTP_PROTO_DECL - ~file_body(); + ~file_source(); BOOST_HTTP_PROTO_DECL explicit - file_body( + file_source( file&& f, std::uint64_t size = std::uint64_t(-1)) noexcept; +private: BOOST_HTTP_PROTO_DECL - source::results + results on_read( buffers::mutable_buffer b) override; - - BOOST_HTTP_PROTO_DECL - sink::results - on_write( - buffers::const_buffer b, bool more) override; }; } // http_proto diff --git a/src/file_sink.cpp b/src/file_sink.cpp new file mode 100644 index 00000000..b6df9c2d --- /dev/null +++ b/src/file_sink.cpp @@ -0,0 +1,43 @@ +// +// Copyright (c) 2022 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 + +namespace boost { +namespace http_proto { + +file_sink:: +file_sink(file&& f) noexcept + : f_(std::move(f)) +{ +} + +file_sink:: +file_sink(file_sink&&) noexcept = default; + +file_sink:: +~file_sink() = default; + +auto +file_sink:: +on_write( + buffers::const_buffer b, + bool more) -> results +{ + results rv; + rv.bytes = f_.write( + b.data(), b.size(), rv.ec); + if(!more && !rv.ec) + f_.close(rv.ec); + return rv; +} + +} // http_proto +} // boost diff --git a/src/file_body.cpp b/src/file_source.cpp similarity index 53% rename from src/file_body.cpp rename to src/file_source.cpp index 9aec7d97..4f3dc89b 100644 --- a/src/file_body.cpp +++ b/src/file_source.cpp @@ -1,5 +1,6 @@ // // Copyright (c) 2022 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) @@ -7,21 +8,19 @@ // Official repository: https://github.com/cppalliance/http_proto // -#include -#include +#include namespace boost { namespace http_proto { -file_body:: -~file_body() = default; +file_source:: +~file_source() = default; -file_body:: -file_body( - file_body&&) noexcept = default; +file_source:: +file_source(file_source&&) noexcept = default; -file_body:: -file_body( +file_source:: +file_source( file&& f, std::uint64_t size) noexcept : f_(std::move(f)) @@ -30,12 +29,11 @@ file_body( } auto -file_body:: +file_source:: on_read( - buffers::mutable_buffer b) -> - source::results + buffers::mutable_buffer b) -> results { - source::results rv; + results rv; if(n_ > 0) { std::size_t n; @@ -46,33 +44,16 @@ on_read( n = f_.read( b.data(), n, rv.ec); rv.bytes = n; + if(n == 0 && b.size() != 0 && !rv.ec) + { + rv.finished = true; + return rv; + } n_ -= n; } rv.finished = n_ == 0; return rv; } -auto -file_body:: -on_write( - buffers::const_buffer b, bool) -> - sink::results -{ - sink::results rv; - if(n_ > 0) - { - std::size_t n; - if( n_ >= b.size()) - n = b.size(); - else - n = static_cast(n_); - n = f_.write( - b.data(), n, rv.ec); - rv.bytes = n; - n_ -= n; - } - return rv; -} - } // http_proto } // boost diff --git a/test/unit/Jamfile b/test/unit/Jamfile index be6975c1..fb64fb2c 100644 --- a/test/unit/Jamfile +++ b/test/unit/Jamfile @@ -83,6 +83,8 @@ for local f in $(SOURCES) local FILE_TESTS = file_posix.cpp + file_sink.cpp + file_source.cpp file_stdio.cpp file_win32.cpp ; diff --git a/test/unit/file_body.cpp b/test/unit/file_body.cpp deleted file mode 100644 index 6b7b877f..00000000 --- a/test/unit/file_body.cpp +++ /dev/null @@ -1,31 +0,0 @@ -// -// Copyright (c) 2022 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 "test_suite.hpp" - -namespace boost { -namespace http_proto { - -struct file_body_test -{ - void - run() - { - } -}; - -TEST_SUITE( - file_body_test, - "boost.http_proto.file_body"); - -} // http_proto -} // boost diff --git a/test/unit/file_sink.cpp b/test/unit/file_sink.cpp new file mode 100644 index 00000000..f900e9fa --- /dev/null +++ b/test/unit/file_sink.cpp @@ -0,0 +1,109 @@ +// +// Copyright (c) 2022 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 "test_suite.hpp" + +namespace boost { +namespace http_proto { + +struct file_sink_test +{ + class temp_path + { + std::string path_; + + public: + temp_path() + // filesystem::path::string() fails on older + // versions of mingw when rtti is off + : path_(filesystem::unique_path().string()) + { + } + + operator char const*() const noexcept + { + return path_.c_str(); + } + + ~temp_path() + { + filesystem::remove(path_); + } + }; + + std::string + read_file(temp_path const& path) + { + std::ifstream ifs(path); + std::ostringstream buf; + buf << ifs.rdbuf(); + return buf.str(); + } + + void + testReportErros() + { + // passing a closed file + { + file f; + file_sink fsink(std::move(f)); + buffers::const_buffer cb("123", 3); + auto rs = fsink.write(cb, true); + BOOST_TEST_EQ(rs.bytes, 0); + BOOST_TEST(rs.ec.failed()); + } + } + + void + testWrite() + { + temp_path path; + file f; + system::error_code ec; + f.open(path, file_mode::write, ec); + BOOST_TEST(!ec); + BOOST_TEST(f.is_open()); + file_sink fsink(std::move(f)); + std::array bufs{ + "Hello", + ", ", + "World!", + {} }; // empty + for(auto s : bufs) + { + buffers::const_buffer cb(s.data(), s.size()); + auto rs = fsink.write(cb, s.size() != 0); + BOOST_TEST_EQ(rs.bytes, cb.size()); + BOOST_TEST(!rs.ec); + } + BOOST_TEST_EQ( + read_file(path), + "Hello, World!"); + } + + void + run() + { + testReportErros(); + testWrite(); + } +}; + +TEST_SUITE( + file_sink_test, + "boost.http_proto.file_sink"); + +} // http_proto +} // boost diff --git a/test/unit/file_source.cpp b/test/unit/file_source.cpp new file mode 100644 index 00000000..ee0b4259 --- /dev/null +++ b/test/unit/file_source.cpp @@ -0,0 +1,150 @@ +// +// Copyright (c) 2022 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 + +#include "test_suite.hpp" + +namespace boost { +namespace http_proto { + +struct file_source_test +{ + class temp_path + { + std::string path_; + + public: + temp_path() + // filesystem::path::string() fails on older + // versions of mingw when rtti is off + : path_(filesystem::unique_path().string()) + { + } + + operator char const*() const noexcept + { + return path_.c_str(); + } + + ~temp_path() + { + filesystem::remove(path_); + } + }; + + void + write_file( + temp_path const& path, + core::string_view content) + { + std::ofstream ofs(path); + ofs << content; + } + + void + testReportErros() + { + // passing a closed file + { + file f; + file_source fsource(std::move(f)); + char buf[16] = {}; + auto rs = fsource.read( + buffers::mutable_buffer(buf, 16)); + BOOST_TEST_EQ(rs.bytes, 0); + BOOST_TEST(rs.ec.failed()); + BOOST_TEST(!rs.finished); + } + } + + void + testRead() + { + temp_path path; + write_file(path, "Hello, World!"); + file f; + system::error_code ec; + f.open(path, file_mode::read, ec); + BOOST_TEST(!ec); + BOOST_TEST(f.is_open()); + file_source fsource(std::move(f)); + char buf[16] = {}; + auto read = [&](std::size_t n, bool more) -> + core::string_view + { + auto rs = fsource.read( + buffers::prefix( + buffers::make_buffer(buf), n)); + BOOST_TEST_EQ(rs.finished, !more); + BOOST_TEST(!rs.ec); + return { buf, rs.bytes }; + }; + BOOST_TEST_EQ(read(6, true), "Hello,"); + BOOST_TEST_EQ(read(1, true), " "); + BOOST_TEST_EQ(read(6, true), "World!"); + BOOST_TEST_EQ(read(1, false), ""); + } + + void + testBoundedRead() + { + temp_path path; + write_file(path, "Hello, World!"); + file f; + system::error_code ec; + f.open(path, file_mode::read, ec); + file_source fsource( + std::move(f), + 6); // Bounded to 6 bytes + + { + char buf[5] = {}; + auto rs = fsource.read(buffers::make_buffer(buf)); + BOOST_TEST_EQ(rs.bytes, 5); + BOOST_TEST(!rs.ec); + BOOST_TEST(!rs.finished); + BOOST_TEST_EQ( + core::string_view(buf, 5), + "Hello"); + } + + { + char buf[5] = {}; + auto rs = fsource.read(buffers::make_buffer(buf)); + BOOST_TEST_EQ(rs.bytes, 1); + BOOST_TEST(!rs.ec); + BOOST_TEST(rs.finished); + BOOST_TEST_EQ( + core::string_view(buf, 1), + ","); + } + } + + void + run() + { + testReportErros(); + testRead(); + testBoundedRead(); + } +}; + +TEST_SUITE( + file_source_test, + "boost.http_proto.file_source"); + +} // http_proto +} // boost diff --git a/test/unit/file_test.hpp b/test/unit/file_test.hpp index a6dde41b..caf213ba 100644 --- a/test/unit/file_test.hpp +++ b/test/unit/file_test.hpp @@ -37,8 +37,6 @@ template void test_file() { - BOOST_STATIC_ASSERT( - is_file::value); BOOST_STATIC_ASSERT( ! std::is_copy_constructible::value); BOOST_STATIC_ASSERT( From 90e9a05b0f912a8c203f797179f2504785b020be Mon Sep 17 00:00:00 2001 From: Mohammad Nejati Date: Sat, 2 Aug 2025 10:05:29 +0000 Subject: [PATCH 4/6] file_stdio uses _wfopen_s when _WIN32 is defined --- src/file_stdio.cpp | 20 ++++++++++---------- test/unit/file_stdio.cpp | 20 +------------------- test/unit/file_win32.cpp | 15 --------------- 3 files changed, 11 insertions(+), 44 deletions(-) diff --git a/src/file_stdio.cpp b/src/file_stdio.cpp index 2bf3f2eb..f6b86faa 100644 --- a/src/file_stdio.cpp +++ b/src/file_stdio.cpp @@ -85,7 +85,7 @@ open(char const* path, file_mode mode, f_ = nullptr; } ec = {}; -#if defined(BOOST_MSVC) || defined(_MSVC_STL_VERSION) +#ifdef _WIN32 boost::winapi::WCHAR_ const* s; detail::win32_unicode_path unicode_path(path, ec); if (ec) @@ -97,7 +97,7 @@ open(char const* path, file_mode mode, { default: case file_mode::read: - #if defined(BOOST_MSVC) || defined(_MSVC_STL_VERSION) + #ifdef _WIN32 s = L"rb"; #else s = "rb"; @@ -105,7 +105,7 @@ open(char const* path, file_mode mode, break; case file_mode::scan: - #if defined(BOOST_MSVC) || defined(_MSVC_STL_VERSION) + #ifdef _WIN32 s = L"rbS"; #else s = "rb"; @@ -113,7 +113,7 @@ open(char const* path, file_mode mode, break; case file_mode::write: - #if defined(BOOST_MSVC) || defined(_MSVC_STL_VERSION) + #ifdef _WIN32 s = L"wb+"; #else s = "wb+"; @@ -122,7 +122,7 @@ open(char const* path, file_mode mode, case file_mode::write_new: { -#if defined(BOOST_MSVC) || defined(_MSVC_STL_VERSION) +#ifdef _WIN32 # if (defined(BOOST_MSVC) && BOOST_MSVC >= 1910) || (defined(_MSVC_STL_VERSION) && _MSVC_STL_VERSION >= 141) s = L"wbx"; # else @@ -151,7 +151,7 @@ open(char const* path, file_mode mode, } case file_mode::write_existing: - #if defined(BOOST_MSVC) || defined(_MSVC_STL_VERSION) + #ifdef _WIN32 s = L"rb+"; #else s = "rb+"; @@ -159,7 +159,7 @@ open(char const* path, file_mode mode, break; case file_mode::append: - #if defined(BOOST_MSVC) || defined(_MSVC_STL_VERSION) + #ifdef _WIN32 s = L"ab"; #else s = "ab"; @@ -168,7 +168,7 @@ open(char const* path, file_mode mode, case file_mode::append_existing: { -#if defined(BOOST_MSVC) || defined(_MSVC_STL_VERSION) +#ifdef _WIN32 std::FILE* f0; auto const ev = ::_wfopen_s(&f0, unicode_path.c_str(), L"rb+"); @@ -189,7 +189,7 @@ open(char const* path, file_mode mode, } #endif std::fclose(f0); - #if defined(BOOST_MSVC) || defined(_MSVC_STL_VERSION) + #ifdef _WIN32 s = L"ab"; #else s = "ab"; @@ -198,7 +198,7 @@ open(char const* path, file_mode mode, } } -#if defined(BOOST_MSVC) || defined(_MSVC_STL_VERSION) +#ifdef _WIN32 auto const ev = ::_wfopen_s( &f_, unicode_path.c_str(), s); if(ev) diff --git a/test/unit/file_stdio.cpp b/test/unit/file_stdio.cpp index 6c773bb5..549ede8a 100644 --- a/test/unit/file_stdio.cpp +++ b/test/unit/file_stdio.cpp @@ -10,22 +10,6 @@ // Test that header file is self-contained. #include -#include - -#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) || \ - defined(__CYGWIN__) -#define BOOST_HTTP_PROTO_IS_WIN -#endif - -#if defined(BOOST_NO_RTTI) && defined(BOOST_HTTP_PROTO_IS_WIN) && \ - defined(BOOST_GCC) - -#include - -BOOST_PRAGMA_MESSAGE("skipping file_stdio_ tests for this configuration") - -#else - #include "file_test.hpp" #include "test_suite.hpp" @@ -38,7 +22,7 @@ class file_stdio_test void run() { -#ifdef BOOST_MSVC +#ifdef _WIN32 test_file(); #else test_file(); @@ -51,5 +35,3 @@ TEST_SUITE( "boost.http_proto.file_stdio"); } // http_proto } // boost - -#endif diff --git a/test/unit/file_win32.cpp b/test/unit/file_win32.cpp index a5740c2d..69fcac3e 100644 --- a/test/unit/file_win32.cpp +++ b/test/unit/file_win32.cpp @@ -10,20 +10,6 @@ // Test that header file is self-contained. #include -#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) || \ - defined(__CYGWIN__) -#define BOOST_HTTP_PROTO_IS_WIN -#endif - -#if defined(BOOST_NO_RTTI) && defined(BOOST_HTTP_PROTO_IS_WIN) && \ - defined(BOOST_GCC) - -#include - -BOOST_PRAGMA_MESSAGE("skipping file_win32_ tests for this configuration") - -#else - #if BOOST_HTTP_PROTO_USE_WIN32_FILE #include "file_test.hpp" @@ -50,4 +36,3 @@ TEST_SUITE( } // boost #endif // BOOST_HTTP_PROTO_USE_WIN32_FILE -#endif From bb96ea09d0f3f3a953e25d180d764dbaed97064b Mon Sep 17 00:00:00 2001 From: Mohammad Nejati Date: Sun, 3 Aug 2025 05:39:05 +0000 Subject: [PATCH 5/6] move implementations of file type to detail --- include/boost/http_proto.hpp | 5 +- .../boost/http_proto/detail/file_posix.hpp | 116 +++++++++++ .../boost/http_proto/detail/file_stdio.hpp | 92 +++++++++ .../boost/http_proto/detail/file_win32.hpp | 108 ++++++++++ include/boost/http_proto/file.hpp | 191 +++++++++++++++-- .../{file_base.hpp => file_mode.hpp} | 74 +------ include/boost/http_proto/file_posix.hpp | 193 ------------------ include/boost/http_proto/file_stdio.hpp | 170 --------------- include/boost/http_proto/file_win32.hpp | 189 ----------------- src/{ => detail}/file_posix.cpp | 6 +- src/{ => detail}/file_stdio.cpp | 8 +- src/{ => detail}/file_win32.cpp | 10 +- test/unit/Jamfile | 8 +- test/unit/{ => detail}/file_posix.cpp | 4 +- test/unit/{ => detail}/file_stdio.cpp | 5 +- test/unit/{ => detail}/file_test.hpp | 2 +- test/unit/{ => detail}/file_win32.cpp | 4 +- test/unit/{file_base.cpp => file_mode.cpp} | 2 +- 18 files changed, 525 insertions(+), 662 deletions(-) create mode 100644 include/boost/http_proto/detail/file_posix.hpp create mode 100644 include/boost/http_proto/detail/file_stdio.hpp create mode 100644 include/boost/http_proto/detail/file_win32.hpp rename include/boost/http_proto/{file_base.hpp => file_mode.hpp} (55%) delete mode 100644 include/boost/http_proto/file_posix.hpp delete mode 100644 include/boost/http_proto/file_stdio.hpp delete mode 100644 include/boost/http_proto/file_win32.hpp rename src/{ => detail}/file_posix.cpp (98%) rename src/{ => detail}/file_stdio.cpp (97%) rename src/{ => detail}/file_win32.cpp (98%) rename test/unit/{ => detail}/file_posix.cpp (89%) rename test/unit/{ => detail}/file_stdio.cpp (89%) rename test/unit/{ => detail}/file_test.hpp (99%) rename test/unit/{ => detail}/file_win32.cpp (89%) rename test/unit/{file_base.cpp => file_mode.cpp} (89%) diff --git a/include/boost/http_proto.hpp b/include/boost/http_proto.hpp index f06c9d0d..70595ead 100644 --- a/include/boost/http_proto.hpp +++ b/include/boost/http_proto.hpp @@ -18,12 +18,9 @@ #include #include #include -#include -#include +#include #include #include -#include -#include #include #include #include diff --git a/include/boost/http_proto/detail/file_posix.hpp b/include/boost/http_proto/detail/file_posix.hpp new file mode 100644 index 00000000..c2f669a7 --- /dev/null +++ b/include/boost/http_proto/detail/file_posix.hpp @@ -0,0 +1,116 @@ +// +// Copyright (c) 2022 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_DETAIL_FILE_POSIX_HPP +#define BOOST_HTTP_PROTO_DETAIL_FILE_POSIX_HPP + +#include + +#if ! defined(BOOST_HTTP_PROTO_NO_POSIX_FILE) +# if ! defined(__APPLE__) && ! defined(__linux__) +# define BOOST_HTTP_PROTO_NO_POSIX_FILE +# endif +#endif + +#if ! defined(BOOST_HTTP_PROTO_USE_POSIX_FILE) +# if ! defined(BOOST_HTTP_PROTO_NO_POSIX_FILE) +# define BOOST_HTTP_PROTO_USE_POSIX_FILE 1 +# else +# define BOOST_HTTP_PROTO_USE_POSIX_FILE 0 +# endif +#endif + +#if BOOST_HTTP_PROTO_USE_POSIX_FILE + +#include +#include +#include +#include + +namespace boost { +namespace http_proto { +namespace detail { + +// Implementation of File for POSIX systems. +class file_posix +{ + int fd_ = -1; + + BOOST_HTTP_PROTO_DECL + static + int + native_close(int& fd); + +public: + using native_handle_type = int; + + BOOST_HTTP_PROTO_DECL + ~file_posix(); + + file_posix() = default; + + BOOST_HTTP_PROTO_DECL + file_posix(file_posix&& other) noexcept; + + BOOST_HTTP_PROTO_DECL + file_posix& + operator=(file_posix&& other) noexcept; + + native_handle_type + native_handle() const + { + return fd_; + } + + BOOST_HTTP_PROTO_DECL + void + native_handle(native_handle_type fd); + + bool + is_open() const + { + return fd_ != -1; + } + + BOOST_HTTP_PROTO_DECL + void + close(system::error_code& ec); + + BOOST_HTTP_PROTO_DECL + void + open(char const* path, file_mode mode, system::error_code& ec); + + BOOST_HTTP_PROTO_DECL + std::uint64_t + size(system::error_code& ec) const; + + BOOST_HTTP_PROTO_DECL + std::uint64_t + pos(system::error_code& ec) const; + + BOOST_HTTP_PROTO_DECL + void + seek(std::uint64_t offset, system::error_code& ec); + + BOOST_HTTP_PROTO_DECL + std::size_t + read(void* buffer, std::size_t n, system::error_code& ec); + + BOOST_HTTP_PROTO_DECL + std::size_t + write(void const* buffer, std::size_t n, system::error_code& ec); +}; + +} // detail +} // http_proto +} // boost + +#endif + +#endif diff --git a/include/boost/http_proto/detail/file_stdio.hpp b/include/boost/http_proto/detail/file_stdio.hpp new file mode 100644 index 00000000..e6121dc9 --- /dev/null +++ b/include/boost/http_proto/detail/file_stdio.hpp @@ -0,0 +1,92 @@ +// +// Copyright (c) 2022 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_DETAIL_FILE_STDIO_HPP +#define BOOST_HTTP_PROTO_DETAIL_FILE_STDIO_HPP + +#include +#include +#include +#include +#include + +namespace boost { +namespace http_proto { +namespace detail { + +// Implementation of File which uses cstdio. +class file_stdio +{ + std::FILE* f_ = nullptr; + +public: + using native_handle_type = std::FILE*; + + BOOST_HTTP_PROTO_DECL + ~file_stdio(); + + file_stdio() = default; + + BOOST_HTTP_PROTO_DECL + file_stdio(file_stdio&& other) noexcept; + + BOOST_HTTP_PROTO_DECL + file_stdio& + operator=(file_stdio&& other) noexcept; + + std::FILE* + native_handle() const + { + return f_; + } + + BOOST_HTTP_PROTO_DECL + void + native_handle(std::FILE* f); + + bool + is_open() const + { + return f_ != nullptr; + } + + BOOST_HTTP_PROTO_DECL + void + close(system::error_code& ec); + + BOOST_HTTP_PROTO_DECL + void + open(char const* path, file_mode mode, system::error_code& ec); + + BOOST_HTTP_PROTO_DECL + std::uint64_t + size(system::error_code& ec) const; + + BOOST_HTTP_PROTO_DECL + std::uint64_t + pos(system::error_code& ec) const; + + BOOST_HTTP_PROTO_DECL + void + seek(std::uint64_t offset, system::error_code& ec); + + BOOST_HTTP_PROTO_DECL + std::size_t + read(void* buffer, std::size_t n, system::error_code& ec); + + BOOST_HTTP_PROTO_DECL + std::size_t + write(void const* buffer, std::size_t n, system::error_code& ec); +}; + +} // detail +} // http_proto +} // boost + +#endif diff --git a/include/boost/http_proto/detail/file_win32.hpp b/include/boost/http_proto/detail/file_win32.hpp new file mode 100644 index 00000000..42145d62 --- /dev/null +++ b/include/boost/http_proto/detail/file_win32.hpp @@ -0,0 +1,108 @@ +// +// Copyright (c) 2022 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_DETAIL_FILE_WIN32_HPP +#define BOOST_HTTP_PROTO_DETAIL_FILE_WIN32_HPP + +#include + +#if ! defined(BOOST_HTTP_PROTO_USE_WIN32_FILE) +# ifdef _WIN32 +# define BOOST_HTTP_PROTO_USE_WIN32_FILE 1 +# else +# define BOOST_HTTP_PROTO_USE_WIN32_FILE 0 +# endif +#endif + +#if BOOST_HTTP_PROTO_USE_WIN32_FILE + +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace http_proto { +namespace detail { + +// Implementation of File for Win32. +class file_win32 +{ + boost::winapi::HANDLE_ h_ = + boost::winapi::INVALID_HANDLE_VALUE_; + +public: + using native_handle_type = boost::winapi::HANDLE_; + + BOOST_HTTP_PROTO_DECL + ~file_win32(); + + file_win32() = default; + + BOOST_HTTP_PROTO_DECL + file_win32(file_win32&& other) noexcept; + + BOOST_HTTP_PROTO_DECL + file_win32& + operator=(file_win32&& other) noexcept; + + native_handle_type + native_handle() + { + return h_; + } + + BOOST_HTTP_PROTO_DECL + void + native_handle(native_handle_type h); + + bool + is_open() const + { + return h_ != boost::winapi::INVALID_HANDLE_VALUE_; + } + + BOOST_HTTP_PROTO_DECL + void + close(system::error_code& ec); + + BOOST_HTTP_PROTO_DECL + void + open(char const* path, file_mode mode, system::error_code& ec); + + BOOST_HTTP_PROTO_DECL + std::uint64_t + size(system::error_code& ec) const; + + BOOST_HTTP_PROTO_DECL + std::uint64_t + pos(system::error_code& ec) const; + + BOOST_HTTP_PROTO_DECL + void + seek(std::uint64_t offset, system::error_code& ec); + + BOOST_HTTP_PROTO_DECL + std::size_t + read(void* buffer, std::size_t n, system::error_code& ec); + + BOOST_HTTP_PROTO_DECL + std::size_t + write(void const* buffer, std::size_t n, system::error_code& ec); +}; + +} // detail +} // http_proto +} // boost + +#endif + +#endif diff --git a/include/boost/http_proto/file.hpp b/include/boost/http_proto/file.hpp index 5078608b..981105ff 100644 --- a/include/boost/http_proto/file.hpp +++ b/include/boost/http_proto/file.hpp @@ -1,5 +1,6 @@ // // Copyright (c) 2022 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) @@ -11,33 +12,193 @@ #define BOOST_HTTP_PROTO_FILE_HPP #include -#include -#include -#include -#include +#include +#include +#include +#include namespace boost { namespace http_proto { -/** An implementation of File. +/** A file stream. - This alias is set to the best available implementation - of File given the platform and build settings. + This class is intended for use with + @ref file_sink and @ref file_source. + + @par Example + @code + file f; + system::error_code ec; + + f.open("example.zip", file_mode::write_new, ec); + if(ec.failed()) + throw system::system_error(ec); + parser.set_body(std::move(file)); + @endcode */ -#if BOOST_HTTP_PROTO_DOCS -struct file : file_stdio +class file { -}; -#else #if BOOST_HTTP_PROTO_USE_WIN32_FILE -using file = file_win32; + using impl_type = detail::file_win32; #elif BOOST_HTTP_PROTO_USE_POSIX_FILE -using file = file_posix; + using impl_type = detail::file_posix; #else -using file = file_stdio; -#endif + using impl_type = detail::file_stdio; #endif + impl_type impl_; + +public: + /** The type of the underlying file handle. + + This is platform-specific. + */ + using native_handle_type = + impl_type::native_handle_type; + + /** Constructor + + There is no open file initially. + */ + file() = default; + + /** Constructor + + The moved-from object behaves as if default constructed. + */ + file(file&& other) noexcept = default; + + /** Assignment + + The moved-from object behaves as if default constructed. + */ + file& + operator=( + file&& other) noexcept = default; + + /** Returns the native handle associated with the file. + */ + native_handle_type + native_handle() + { + return impl_.native_handle(); + } + + /** Set the native handle associated with the file. + + If the file is open it is first closed. + + @param fd The native file handle to assign. + */ + void + native_handle(native_handle_type h) + { + impl_.native_handle(h); + } + + /** Returns `true` if the file is open + */ + bool + is_open() const + { + return impl_.is_open(); + } + + /** Close the file if open + + @param ec Set to the error, if any occurred. + */ + void + close(system::error_code& ec) + { + impl_.close(ec); + } + + /** Open a file at the given path with the specified mode + + @param path The utf-8 encoded path to the file + + @param mode The file mode to use + + @param ec Set to the error, if any occurred + */ + void + open(char const* path, file_mode mode, system::error_code& ec) + { + impl_.open(path, mode, ec); + } + + /** Return the size of the open file + + @param ec Set to the error, if any occurred + + @return The size in bytes + */ + std::uint64_t + size(system::error_code& ec) const + { + return impl_.size(ec); + } + + /** Return the current position in the open file + + @param ec Set to the error, if any occurred + + @return The offset in bytes from the beginning of the file + */ + std::uint64_t + pos(system::error_code& ec) const + { + return impl_.pos(ec); + } + + /** Adjust the current position in the open file + + @param offset The offset in bytes from the beginning of the file + + @param ec Set to the error, if any occurred + */ + void + seek(std::uint64_t offset, system::error_code& ec) + { + return impl_.seek(offset, ec); + } + + /** Read from the open file + + @param buffer The buffer for storing the result of the read + + @param n The number of bytes to read + + @param ec Set to the error, if any occurred + */ + std::size_t + read(void* buffer, std::size_t n, system::error_code& ec) + { + return impl_.read(buffer, n, ec); + } + + /** Write to the open file + + @param buffer The buffer holding the data to write + + @param n The number of bytes to write + + @param ec Set to the error, if any occurred + */ + std::size_t + write(void const* buffer, std::size_t n, system::error_code& ec) + { + return impl_.write(buffer, n, ec); + } + + /** Destructor + + If the file is open it is first closed. + */ + ~file() = default; +}; + } // http_proto } // boost diff --git a/include/boost/http_proto/file_base.hpp b/include/boost/http_proto/file_mode.hpp similarity index 55% rename from include/boost/http_proto/file_base.hpp rename to include/boost/http_proto/file_mode.hpp index 9deae285..3350c300 100644 --- a/include/boost/http_proto/file_base.hpp +++ b/include/boost/http_proto/file_mode.hpp @@ -1,5 +1,6 @@ // // Copyright (c) 2022 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) @@ -7,14 +8,8 @@ // Official repository: https://github.com/cppalliance/http_proto // -#ifndef BOOST_HTTP_PROTO_FILE_BASE_HPP -#define BOOST_HTTP_PROTO_FILE_BASE_HPP - -#include -#include -#include -#include -#include +#ifndef BOOST_HTTP_PROTO_FILE_MODE_HPP +#define BOOST_HTTP_PROTO_FILE_MODE_HPP namespace boost { namespace http_proto { @@ -96,69 +91,6 @@ enum class file_mode append_existing }; -/** Determine if `T` meets the requirements of File. - - Metafunctions are used to perform compile time checking of template - types. This type will be `std::true_type` if `T` meets the requirements, - else the type will be `std::false_type`. - - @par Example - - Use with `static_assert`: - - @code - template - void f(File& file) - { - static_assert(is_file::value, - "File type requirements not met"); - ... - @endcode - - Use with `std::enable_if` (SFINAE): - - @code - template - typename std::enable_if::value>::type - f(File& file); - @endcode -*/ -#if BOOST_HTTP_PROTO_DOCS -template -struct is_file : std::integral_constant{}; -#else -template -struct is_file : std::false_type {}; - -template -struct is_file() = std::declval().is_open(), - std::declval().close(std::declval()), - std::declval().open( - std::declval(), - std::declval(), - std::declval()), - std::declval() = std::declval().size( - std::declval()), - std::declval() = std::declval().pos( - std::declval()), - std::declval().seek( - std::declval(), - std::declval()), - std::declval() = std::declval().read( - std::declval(), - std::declval(), - std::declval()), - std::declval() = std::declval().write( - std::declval(), - std::declval(), - std::declval()) - )>> : std::integral_constant::value && - std::is_destructible::value - > {}; -#endif - } // http_proto } // boost diff --git a/include/boost/http_proto/file_posix.hpp b/include/boost/http_proto/file_posix.hpp deleted file mode 100644 index 80e9a9a7..00000000 --- a/include/boost/http_proto/file_posix.hpp +++ /dev/null @@ -1,193 +0,0 @@ -// -// Copyright (c) 2022 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_FILE_POSIX_HPP -#define BOOST_HTTP_PROTO_FILE_POSIX_HPP - -#include - -#if ! defined(BOOST_HTTP_PROTO_NO_POSIX_FILE) -# if ! defined(__APPLE__) && ! defined(__linux__) -# define BOOST_HTTP_PROTO_NO_POSIX_FILE -# endif -#endif - -#if ! defined(BOOST_HTTP_PROTO_USE_POSIX_FILE) -# if ! defined(BOOST_HTTP_PROTO_NO_POSIX_FILE) -# define BOOST_HTTP_PROTO_USE_POSIX_FILE 1 -# else -# define BOOST_HTTP_PROTO_USE_POSIX_FILE 0 -# endif -#endif - -#if BOOST_HTTP_PROTO_USE_POSIX_FILE - -#include -#include -#include -#include - -namespace boost { -namespace http_proto { - -/** An implementation of File for POSIX systems. - - This class implements a File using POSIX interfaces. -*/ -class file_posix -{ - int fd_ = -1; - - BOOST_HTTP_PROTO_DECL - static - int - native_close(int& fd); - -public: - /** The type of the underlying file handle. - - This is platform-specific. - */ - using native_handle_type = int; - - /** Destructor - - If the file is open it is first closed. - */ - BOOST_HTTP_PROTO_DECL - ~file_posix(); - - /** Constructor - - There is no open file initially. - */ - file_posix() = default; - - /** Constructor - - The moved-from object behaves as if default constructed. - */ - BOOST_HTTP_PROTO_DECL - file_posix( - file_posix&& other) noexcept; - - /** Assignment - - The moved-from object behaves as if default constructed. - */ - BOOST_HTTP_PROTO_DECL - file_posix& - operator=( - file_posix&& other) noexcept; - - /// Returns the native handle associated with the file. - native_handle_type - native_handle() const - { - return fd_; - } - - /** Set the native handle associated with the file. - - If the file is open it is first closed. - - @param fd The native file handle to assign. - */ - BOOST_HTTP_PROTO_DECL - void - native_handle(native_handle_type fd); - - /// Returns `true` if the file is open - bool - is_open() const - { - return fd_ != -1; - } - - /** Close the file if open - - @param ec Set to the error, if any occurred. - */ - BOOST_HTTP_PROTO_DECL - void - close(system::error_code& ec); - - /** Open a file at the given path with the specified mode - - @param path The utf-8 encoded path to the file - - @param mode The file mode to use - - @param ec Set to the error, if any occurred - */ - BOOST_HTTP_PROTO_DECL - void - open(char const* path, file_mode mode, system::error_code& ec); - - /** Return the size of the open file - - @param ec Set to the error, if any occurred - - @return The size in bytes - */ - BOOST_HTTP_PROTO_DECL - std::uint64_t - size(system::error_code& ec) const; - - /** Return the current position in the open file - - @param ec Set to the error, if any occurred - - @return The offset in bytes from the beginning of the file - */ - BOOST_HTTP_PROTO_DECL - std::uint64_t - pos(system::error_code& ec) const; - - /** Adjust the current position in the open file - - @param offset The offset in bytes from the beginning of the file - - @param ec Set to the error, if any occurred - */ - BOOST_HTTP_PROTO_DECL - void - seek(std::uint64_t offset, system::error_code& ec); - - /** Read from the open file - - @param buffer The buffer for storing the result of the read - - @param n The number of bytes to read - - @param ec Set to the error, if any occurred - */ - BOOST_HTTP_PROTO_DECL - std::size_t - read(void* buffer, std::size_t n, system::error_code& ec) const; - - /** Write to the open file - - @param buffer The buffer holding the data to write - - @param n The number of bytes to write - - @param ec Set to the error, if any occurred - */ - BOOST_HTTP_PROTO_DECL - std::size_t - write(void const* buffer, std::size_t n, system::error_code& ec); -}; - -} // http_proto -} // boost - -#endif - -#endif diff --git a/include/boost/http_proto/file_stdio.hpp b/include/boost/http_proto/file_stdio.hpp deleted file mode 100644 index 17fb2e7b..00000000 --- a/include/boost/http_proto/file_stdio.hpp +++ /dev/null @@ -1,170 +0,0 @@ -// -// Copyright (c) 2022 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_FILE_STDIO_HPP -#define BOOST_HTTP_PROTO_FILE_STDIO_HPP - -#include -#include -#include -#include -#include - -namespace boost { -namespace http_proto { - -/** An implementation of File which uses cstdio. - - This class implements a file using the interfaces present - in the C++ Standard Library, in ``. -*/ -class file_stdio -{ - std::FILE* f_ = nullptr; - -public: - /** The type of the underlying file handle. - - This is platform-specific. - */ - using native_handle_type = std::FILE*; - - /** Destructor - - If the file is open it is first closed. - */ - BOOST_HTTP_PROTO_DECL - ~file_stdio(); - - /** Constructor - - There is no open file initially. - */ - file_stdio() = default; - - /** Constructor - - The moved-from object behaves as if default constructed. - */ - BOOST_HTTP_PROTO_DECL - file_stdio( - file_stdio&& other) noexcept; - - /** Assignment - - The moved-from object behaves as if default constructed. - */ - BOOST_HTTP_PROTO_DECL - file_stdio& - operator=( - file_stdio&& other) noexcept; - - /// Returns the native handle associated with the file. - std::FILE* - native_handle() const - { - return f_; - } - - /** Set the native handle associated with the file. - - If the file is open it is first closed. - - @param f The native file handle to assign. - */ - BOOST_HTTP_PROTO_DECL - void - native_handle(std::FILE* f); - - /// Returns `true` if the file is open - bool - is_open() const - { - return f_ != nullptr; - } - - /** Close the file if open - - @param ec Set to the error, if any occurred. - */ - BOOST_HTTP_PROTO_DECL - void - close(system::error_code& ec); - - /** Open a file at the given path with the specified mode - - @param path The utf-8 encoded path to the file - - @param mode The file mode to use - - @param ec Set to the error, if any occurred - */ - BOOST_HTTP_PROTO_DECL - void - open(char const* path, file_mode mode, system::error_code& ec); - - /** Return the size of the open file - - @param ec Set to the error, if any occurred - - @return The size in bytes - */ - BOOST_HTTP_PROTO_DECL - std::uint64_t - size(system::error_code& ec) const; - - /** Return the current position in the open file - - @param ec Set to the error, if any occurred - - @return The offset in bytes from the beginning of the file - */ - BOOST_HTTP_PROTO_DECL - std::uint64_t - pos(system::error_code& ec) const; - - /** Adjust the current position in the open file - - @param offset The offset in bytes from the beginning of the file - - @param ec Set to the error, if any occurred - */ - BOOST_HTTP_PROTO_DECL - void - seek(std::uint64_t offset, system::error_code& ec); - - /** Read from the open file - - @param buffer The buffer for storing the result of the read - - @param n The number of bytes to read - - @param ec Set to the error, if any occurred - */ - BOOST_HTTP_PROTO_DECL - std::size_t - read(void* buffer, std::size_t n, system::error_code& ec) const; - - /** Write to the open file - - @param buffer The buffer holding the data to write - - @param n The number of bytes to write - - @param ec Set to the error, if any occurred - */ - BOOST_HTTP_PROTO_DECL - std::size_t - write(void const* buffer, std::size_t n, system::error_code& ec); -}; - -} // http_proto -} // boost - -#endif diff --git a/include/boost/http_proto/file_win32.hpp b/include/boost/http_proto/file_win32.hpp deleted file mode 100644 index e29c3b7a..00000000 --- a/include/boost/http_proto/file_win32.hpp +++ /dev/null @@ -1,189 +0,0 @@ -// -// Copyright (c) 2022 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_FILE_WIN32_HPP -#define BOOST_HTTP_PROTO_FILE_WIN32_HPP - -#include - -#if ! defined(BOOST_HTTP_PROTO_USE_WIN32_FILE) -# ifdef _WIN32 -# define BOOST_HTTP_PROTO_USE_WIN32_FILE 1 -# else -# define BOOST_HTTP_PROTO_USE_WIN32_FILE 0 -# endif -#endif - -#if BOOST_HTTP_PROTO_USE_WIN32_FILE - -#include -#include -#include -#include -#include -#include - -namespace boost { -namespace http_proto { - -/** An implementation of File for Win32. - - This class implements a File using Win32 native interfaces. -*/ -class file_win32 -{ - boost::winapi::HANDLE_ h_ = - boost::winapi::INVALID_HANDLE_VALUE_; - -public: - /** The type of the underlying file handle. - - This is platform-specific. - */ -#if BOOST_HTTP_PROTO_DOXYGEN - using native_handle_type = HANDLE; -#else - using native_handle_type = boost::winapi::HANDLE_; -#endif - - /** Destructor - - If the file is open it is first closed. - */ - BOOST_HTTP_PROTO_DECL - ~file_win32(); - - /** Constructor - - There is no open file initially. - */ - file_win32() = default; - - /** Constructor - - The moved-from object behaves as if default constructed. - */ - BOOST_HTTP_PROTO_DECL - file_win32( - file_win32&& other) noexcept; - - /** Assignment - - The moved-from object behaves as if default constructed. - */ - BOOST_HTTP_PROTO_DECL - file_win32& - operator=( - file_win32&& other) noexcept; - - /// Returns the native handle associated with the file. - native_handle_type - native_handle() - { - return h_; - } - - /** Set the native handle associated with the file. - - If the file is open it is first closed. - - @param h The native file handle to assign. - */ - BOOST_HTTP_PROTO_DECL - void - native_handle(native_handle_type h); - - /// Returns `true` if the file is open - bool - is_open() const - { - return h_ != boost::winapi::INVALID_HANDLE_VALUE_; - } - - /** Close the file if open - - @param ec Set to the error, if any occurred. - */ - BOOST_HTTP_PROTO_DECL - void - close(system::error_code& ec); - - /** Open a file at the given path with the specified mode - - @param path The utf-8 encoded path to the file - - @param mode The file mode to use - - @param ec Set to the error, if any occurred - */ - BOOST_HTTP_PROTO_DECL - void - open(char const* path, file_mode mode, system::error_code& ec); - - /** Return the size of the open file - - @param ec Set to the error, if any occurred - - @return The size in bytes - */ - BOOST_HTTP_PROTO_DECL - std::uint64_t - size(system::error_code& ec) const; - - /** Return the current position in the open file - - @param ec Set to the error, if any occurred - - @return The offset in bytes from the beginning of the file - */ - BOOST_HTTP_PROTO_DECL - std::uint64_t - pos(system::error_code& ec); - - /** Adjust the current position in the open file - - @param offset The offset in bytes from the beginning of the file - - @param ec Set to the error, if any occurred - */ - BOOST_HTTP_PROTO_DECL - void - seek(std::uint64_t offset, system::error_code& ec); - - /** Read from the open file - - @param buffer The buffer for storing the result of the read - - @param n The number of bytes to read - - @param ec Set to the error, if any occurred - */ - BOOST_HTTP_PROTO_DECL - std::size_t - read(void* buffer, std::size_t n, system::error_code& ec); - - /** Write to the open file - - @param buffer The buffer holding the data to write - - @param n The number of bytes to write - - @param ec Set to the error, if any occurred - */ - BOOST_HTTP_PROTO_DECL - std::size_t - write(void const* buffer, std::size_t n, system::error_code& ec); -}; - -} // http_proto -} // boost - -#endif - -#endif diff --git a/src/file_posix.cpp b/src/detail/file_posix.cpp similarity index 98% rename from src/file_posix.cpp rename to src/detail/file_posix.cpp index 115a0f36..cc1f14f5 100644 --- a/src/file_posix.cpp +++ b/src/detail/file_posix.cpp @@ -7,7 +7,7 @@ // Official repository: https://github.com/cppalliance/http_proto // -#include +#include #if BOOST_HTTP_PROTO_USE_POSIX_FILE @@ -36,6 +36,7 @@ namespace boost { namespace http_proto { +namespace detail { int file_posix:: @@ -274,7 +275,7 @@ seek(std::uint64_t offset, std::size_t file_posix:: read(void* buffer, std::size_t n, - system::error_code& ec) const + system::error_code& ec) { if(fd_ == -1) { @@ -350,6 +351,7 @@ write(void const* buffer, std::size_t n, return nwritten; } +} // detail } // http_proto } // boost diff --git a/src/file_stdio.cpp b/src/detail/file_stdio.cpp similarity index 97% rename from src/file_stdio.cpp rename to src/detail/file_stdio.cpp index f6b86faa..a2fa3717 100644 --- a/src/file_stdio.cpp +++ b/src/detail/file_stdio.cpp @@ -7,9 +7,9 @@ // Official repository: https://github.com/cppalliance/http_proto // -#include +#include "src/detail/win32_unicode_path.hpp" +#include #include -#include "detail/win32_unicode_path.hpp" #include #include #include @@ -17,6 +17,7 @@ namespace boost { namespace http_proto { +namespace detail { file_stdio:: ~file_stdio() @@ -312,7 +313,7 @@ seek(std::uint64_t offset, std::size_t file_stdio:: read(void* buffer, std::size_t n, - system::error_code& ec) const + system::error_code& ec) { if(! f_) { @@ -351,5 +352,6 @@ write(void const* buffer, std::size_t n, return nwritten; } +} // detail } // http_proto } // boost diff --git a/src/file_win32.cpp b/src/detail/file_win32.cpp similarity index 98% rename from src/file_win32.cpp rename to src/detail/file_win32.cpp index 10701181..e5203fc1 100644 --- a/src/file_win32.cpp +++ b/src/detail/file_win32.cpp @@ -7,11 +7,11 @@ // Official repository: https://github.com/cppalliance/http_proto // -#include +#include #if BOOST_HTTP_PROTO_USE_WIN32_FILE -#include "detail/win32_unicode_path.hpp" +#include "src/detail/win32_unicode_path.hpp" #include #include #include @@ -22,7 +22,6 @@ namespace boost { namespace http_proto { - namespace detail { // VFALCO Can't seem to get boost/detail/winapi to work with @@ -51,8 +50,6 @@ set_file_pointer_ex( return 1; } -} // detail - file_win32:: ~file_win32() { @@ -250,7 +247,7 @@ size( std::uint64_t file_win32:: pos( - system::error_code& ec) + system::error_code& ec) const { if(h_ == winapi::INVALID_HANDLE_VALUE_) { @@ -381,6 +378,7 @@ write(void const* buffer, std::size_t n, return nwritten; } +} // detail } // http_proto } // boost diff --git a/test/unit/Jamfile b/test/unit/Jamfile index fb64fb2c..0f033129 100644 --- a/test/unit/Jamfile +++ b/test/unit/Jamfile @@ -38,7 +38,7 @@ local SOURCES = fields_view_base.cpp fields_view.cpp fields.cpp - file_base.cpp + file_mode.cpp file.cpp header_limits.cpp http_proto.cpp @@ -82,11 +82,11 @@ for local f in $(SOURCES) # file tests local FILE_TESTS = - file_posix.cpp file_sink.cpp file_source.cpp - file_stdio.cpp - file_win32.cpp + detail/file_posix.cpp + detail/file_stdio.cpp + detail/file_win32.cpp ; for local f in $(FILE_TESTS) diff --git a/test/unit/file_posix.cpp b/test/unit/detail/file_posix.cpp similarity index 89% rename from test/unit/file_posix.cpp rename to test/unit/detail/file_posix.cpp index 5c82b7b4..d77adfa0 100644 --- a/test/unit/file_posix.cpp +++ b/test/unit/detail/file_posix.cpp @@ -8,7 +8,7 @@ // // Test that header file is self-contained. -#include +#include #if BOOST_HTTP_PROTO_USE_POSIX_FILE @@ -17,6 +17,7 @@ namespace boost { namespace http_proto { +namespace detail { class file_posix_test { @@ -32,6 +33,7 @@ TEST_SUITE( file_posix_test, "boost.http_proto.file_posix"); +} // detail } // http_proto } // boost diff --git a/test/unit/file_stdio.cpp b/test/unit/detail/file_stdio.cpp similarity index 89% rename from test/unit/file_stdio.cpp rename to test/unit/detail/file_stdio.cpp index 549ede8a..fdf00819 100644 --- a/test/unit/file_stdio.cpp +++ b/test/unit/detail/file_stdio.cpp @@ -8,13 +8,14 @@ // // Test that header file is self-contained. -#include +#include #include "file_test.hpp" #include "test_suite.hpp" namespace boost { namespace http_proto { +namespace detail { class file_stdio_test { @@ -33,5 +34,7 @@ class file_stdio_test TEST_SUITE( file_stdio_test, "boost.http_proto.file_stdio"); + +} // detail } // http_proto } // boost diff --git a/test/unit/file_test.hpp b/test/unit/detail/file_test.hpp similarity index 99% rename from test/unit/file_test.hpp rename to test/unit/detail/file_test.hpp index caf213ba..b4abb646 100644 --- a/test/unit/file_test.hpp +++ b/test/unit/detail/file_test.hpp @@ -10,7 +10,7 @@ #ifndef BOOST_HTTP_PROTO_FILE_TEST_HPP #define BOOST_HTTP_PROTO_FILE_TEST_HPP -#include +#include #include #include #include diff --git a/test/unit/file_win32.cpp b/test/unit/detail/file_win32.cpp similarity index 89% rename from test/unit/file_win32.cpp rename to test/unit/detail/file_win32.cpp index 69fcac3e..c8ff2469 100644 --- a/test/unit/file_win32.cpp +++ b/test/unit/detail/file_win32.cpp @@ -8,7 +8,7 @@ // // Test that header file is self-contained. -#include +#include #if BOOST_HTTP_PROTO_USE_WIN32_FILE @@ -17,6 +17,7 @@ namespace boost { namespace http_proto { +namespace detail { class file_win32_test { @@ -32,6 +33,7 @@ TEST_SUITE( file_win32_test, "boost.http_proto.file_win32"); +} // detail } // http_proto } // boost diff --git a/test/unit/file_base.cpp b/test/unit/file_mode.cpp similarity index 89% rename from test/unit/file_base.cpp rename to test/unit/file_mode.cpp index bdb485dd..5ff75fa6 100644 --- a/test/unit/file_base.cpp +++ b/test/unit/file_mode.cpp @@ -8,4 +8,4 @@ // // Test that header file is self-contained. -#include +#include From a29e2af953d50d02c9850ad9a1daa36915b4a062 Mon Sep 17 00:00:00 2001 From: Mohammad Nejati Date: Sun, 3 Aug 2025 06:41:17 +0000 Subject: [PATCH 6/6] use file_posix on FreeBSD and NetBSD --- include/boost/http_proto/detail/file_posix.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/http_proto/detail/file_posix.hpp b/include/boost/http_proto/detail/file_posix.hpp index c2f669a7..caba34f8 100644 --- a/include/boost/http_proto/detail/file_posix.hpp +++ b/include/boost/http_proto/detail/file_posix.hpp @@ -13,7 +13,7 @@ #include #if ! defined(BOOST_HTTP_PROTO_NO_POSIX_FILE) -# if ! defined(__APPLE__) && ! defined(__linux__) +# if ! defined(__APPLE__) && ! defined(__linux__) && ! defined(__FreeBSD__) && ! defined(__NetBSD__) # define BOOST_HTTP_PROTO_NO_POSIX_FILE # endif #endif