From 7e492fa2516d4f754321443e64c798c517bc2481 Mon Sep 17 00:00:00 2001 From: Dima Panov Date: Wed, 18 Jan 2023 18:19:42 +0300 Subject: [PATCH] Try to fix Boost.URL (based on upstream MRs) --- .../patch-boost_url_detail_impl_normalize.ipp | 179 ++++++++++++++++++ .../files/patch-boost_url_url__view.hpp | 29 +++ .../files/patch-boost_url_url__view__base.hpp | 23 +++ .../files/patch-libs_url_test_unit_url.cpp | 21 ++ .../patch-libs_url_test_unit_url__view.cpp | 52 +++++ 5 files changed, 304 insertions(+) create mode 100644 devel/boost-libs/files/patch-boost_url_detail_impl_normalize.ipp create mode 100644 devel/boost-libs/files/patch-boost_url_url__view.hpp create mode 100644 devel/boost-libs/files/patch-boost_url_url__view__base.hpp create mode 100644 devel/boost-libs/files/patch-libs_url_test_unit_url.cpp create mode 100644 devel/boost-libs/files/patch-libs_url_test_unit_url__view.cpp diff --git a/devel/boost-libs/files/patch-boost_url_detail_impl_normalize.ipp b/devel/boost-libs/files/patch-boost_url_detail_impl_normalize.ipp new file mode 100644 index 0000000..34a56f8 --- /dev/null +++ b/devel/boost-libs/files/patch-boost_url_detail_impl_normalize.ipp @@ -0,0 +1,179 @@ +--- boost/url/detail/impl/normalize.ipp.orig 2022-12-08 01:02:49 UTC ++++ boost/url/detail/impl/normalize.ipp +@@ -650,11 +650,13 @@ normalized_path_digest( + while (!s.empty()); + } + ++// compare segments as if there were a normalized + int + segments_compare( + segments_encoded_view seg0, + segments_encoded_view seg1) noexcept + { ++ // calculate path size as if it were normalized + auto normalized_size = + [](segments_encoded_view seg) -> std::size_t + { +@@ -683,11 +685,14 @@ segments_compare( + n -= !seg.is_absolute(); + return n; + }; ++ ++ // find the normalized size for the comparison + std::size_t n0 = normalized_size(seg0); + std::size_t n1 = normalized_size(seg1); + std::size_t n00 = n0; + std::size_t n10 = n1; + ++ // consume the last char from a segment range + auto consume_last = + []( + std::size_t& n, +@@ -700,61 +705,87 @@ segments_compare( + { + if (cit != dseg.begin()) + { ++ // return last char from current segment + at_slash = false; + --cit; + --n; + return *cit; + } +- else ++ ++ if (!at_slash) + { +- if (!at_slash || dseg.empty()) ++ // current segment dseg is over and ++ // previous char was not a slash ++ // so we output one ++ at_slash = true; ++ --n; ++ return '/'; ++ } ++ ++ // current segment dseg is over and ++ // last char was already the slash ++ // between segments, so take the ++ // next final segment to consume ++ at_slash = false; ++ while (cit == dseg.begin()) ++ { ++ // take next segment ++ if (it != begin) ++ --it; ++ else ++ break; ++ if (**it == "..") + { +- at_slash = true; +- --n; +- return '/'; ++ // skip next if this is ".." ++ ++skip; + } +- at_slash = false; +- while (cit == dseg.begin()) ++ else if (**it != ".") + { +- if (it != begin) +- --it; +- else +- break; +- if (**it == "..") ++ if (skip) + { +- ++skip; ++ // discount skips ++ --skip; + } +- else if (**it != ".") ++ else + { +- if (skip) +- { +- --skip; +- } +- else +- { +- dseg = **it; +- cit = dseg.end(); +- } ++ // or update current seg ++ dseg = **it; ++ cit = dseg.end(); ++ break; + } + } +- --n; +- if (it == begin) +- { +- return "/.."[n]; +- } +- if (cit == dseg.begin()) +- { +- at_slash = true; +- return '/'; +- } +- else +- { +- --cit; +- return *cit; +- } + } ++ // consume from the new current ++ // segment ++ --n; ++ if (cit != dseg.begin()) ++ { ++ // in the general case, we consume ++ // one more character from the end ++ --cit; ++ return *cit; ++ } ++ ++ // nothing left to consume in the ++ // current and new segment ++ if (it == begin) ++ { ++ // if this is the first ++ // segment, the segments are ++ // over and there can only ++ // be repetitions of "../" to ++ // output ++ return "/.."[n % 3]; ++ } ++ // at other segments, we need ++ // a slash to transition to the ++ // next segment ++ at_slash = true; ++ return '/'; + }; + ++ // consume final segments from seg0 that ++ // should not influence the comparison + auto begin0 = seg0.begin(); + auto it0 = seg0.end(); + decode_view dseg0; +@@ -768,9 +799,11 @@ segments_compare( + bool at_slash0 = true; + while (n0 > n1) + { +- consume_last(n0, dseg0, begin0,it0, cit0, skip0, at_slash0); ++ consume_last(n0, dseg0, begin0, it0, cit0, skip0, at_slash0); + } + ++ // consume final segments from seg1 that ++ // should not influence the comparison + auto begin1 = seg1.begin(); + auto it1 = seg1.end(); + decode_view dseg1; +@@ -784,7 +817,7 @@ segments_compare( + bool at_slash1 = true; + while (n1 > n0) + { +- consume_last(n1, dseg1, begin1,it1, cit1, skip1, at_slash1); ++ consume_last(n1, dseg1, begin1, it1, cit1, skip1, at_slash1); + } + + int cmp = 0; diff --git a/devel/boost-libs/files/patch-boost_url_url__view.hpp b/devel/boost-libs/files/patch-boost_url_url__view.hpp new file mode 100644 index 0000000..9e06fd4 --- /dev/null +++ b/devel/boost-libs/files/patch-boost_url_url__view.hpp @@ -0,0 +1,29 @@ +--- boost/url/url_view.hpp.orig 2022-12-08 01:02:49 UTC ++++ boost/url/url_view.hpp +@@ -196,8 +196,25 @@ class BOOST_SYMBOL_VISIBLE url_view (public) + @ref parse_uri_reference. + */ + BOOST_URL_DECL +- explicit + url_view(string_view s); ++ ++ /// @copydoc url_view(string_view) ++ template< ++ class String ++#ifndef BOOST_URL_DOCS ++ , class = typename std::enable_if< ++ std::is_convertible< ++ String, ++ string_view ++ >::value>::type ++#endif ++ > ++ url_view( ++ String const& s) ++ : url_view( ++ string_view(s)) ++ { ++ } + + /** Constructor + diff --git a/devel/boost-libs/files/patch-boost_url_url__view__base.hpp b/devel/boost-libs/files/patch-boost_url_url__view__base.hpp new file mode 100644 index 0000000..3da8552 --- /dev/null +++ b/devel/boost-libs/files/patch-boost_url_url__view__base.hpp @@ -0,0 +1,23 @@ +--- boost/url/url_view_base.hpp.orig 2022-12-08 01:02:49 UTC ++++ boost/url/url_view_base.hpp +@@ -240,6 +240,20 @@ class BOOST_SYMBOL_VISIBLE (public) + data(), size()); + } + ++ /** Return the URL as a string_view ++ ++ @par Complexity ++ Constant. ++ ++ @par Exception Safety ++ Throws nothing. ++ ++ */ ++ operator string_view() const noexcept ++ { ++ return buffer(); ++ } ++ + /** Return a shared, persistent copy of the url + + This function returns a read-only copy of diff --git a/devel/boost-libs/files/patch-libs_url_test_unit_url.cpp b/devel/boost-libs/files/patch-libs_url_test_unit_url.cpp new file mode 100644 index 0000000..3a7a9aa --- /dev/null +++ b/devel/boost-libs/files/patch-libs_url_test_unit_url.cpp @@ -0,0 +1,21 @@ +--- libs/url/test/unit/url.cpp.orig 2022-12-08 01:02:49 UTC ++++ libs/url/test/unit/url.cpp +@@ -964,6 +964,8 @@ struct url_test + "http://cppalliance.org/g"); + check("http://cppalliance.org/a/b/../../../g", + "http://cppalliance.org/../g"); ++ check("http://cppalliance.org/a/b/../../../../g", ++ "http://cppalliance.org/../../g"); + check("http://cppalliance.org/..", + "http://cppalliance.org/.."); + check("http://cppalliance.org?%61=b", +@@ -1080,6 +1082,9 @@ struct url_test + check("http://cppalliance.org#frag", "http://cppalliance.org#glob", -1); + check("http://cppalliance.org#fra", "http://cppalliance.org#frag", -1); + check("http://cppalliance.org#frag", "http://cppalliance.org#fra", 1); ++ // issue 653 ++ check("http://httpbin.org/redirect/10", "http://httpbin.org/get", +1); ++ check("http://httpbin.org/redirect/10//10", "http://httpbin.org/11/../get", +1); + } + + // path inequality diff --git a/devel/boost-libs/files/patch-libs_url_test_unit_url__view.cpp b/devel/boost-libs/files/patch-libs_url_test_unit_url__view.cpp new file mode 100644 index 0000000..665489e --- /dev/null +++ b/devel/boost-libs/files/patch-libs_url_test_unit_url__view.cpp @@ -0,0 +1,52 @@ +--- libs/url/test/unit/url_view.cpp.orig 2022-12-08 01:02:49 UTC ++++ libs/url/test/unit/url_view.cpp +@@ -90,6 +90,24 @@ class url_view_test (public) + BOOST_TEST_THROWS(url_view("{}"), + std::exception); + } ++ ++ // url_view(string_view) no ambiguous ++ { ++ string_view s = ""; ++ BOOST_TEST_NO_THROW(url_view( s )); ++ } ++ ++ // implicit url_view(string_view) ++ { ++ auto const f = []( url_view ) {}; ++ f( "x" ); ++ } ++ ++ // implicit url_view(String) ++ { ++ auto const f = []( url_view ) {}; ++ f( "x" ); ++ } + } + + void +@@ -123,8 +141,8 @@ class url_view_test (public) + { + string_view s = "/index.htm"; + url_view u = parse_relative_ref(s).value(); +- BOOST_TEST_EQ(u.buffer(), s); +- BOOST_TEST_EQ(u.buffer().data(), s.data()); ++ BOOST_TEST_EQ(u, s); ++ BOOST_TEST_EQ(u.data(), s.data()); + } + + // persist() +@@ -145,6 +163,13 @@ class url_view_test (public) + // becomes invalid, but sp remains valid. + } + } ++ ++ // operator string_view() ++ { ++ auto const f = []( string_view ) {}; ++ f( url_view("x") ); ++ } ++ + } + + void -- 2.39.1