From b81a2775cb0f1905febf46bf7caa4aa1e2424968 Mon Sep 17 00:00:00 2001 From: csk Date: Tue, 24 Jul 2018 14:24:26 +0200 Subject: [PATCH 1/4] Use character-by-character comparison for comparison operators This follows the proposal in section [uri.header-synopsis.equality-comparison]. Otherwise the type would do expensive allocation due to normalization of the URIs when used in containers or algorithms. The operator functions have been made friend functions of the uri class to take advantage of comparing the underlying string_view instead of re-implementing the behavior based on iterators. --- include/network/uri/uri.hpp | 99 ++++++++++++++++++------------------ src/uri.cpp | 11 ++-- test/uri_comparison_test.cpp | 2 +- 3 files changed, 55 insertions(+), 57 deletions(-) diff --git a/include/network/uri/uri.hpp b/include/network/uri/uri.hpp index 66fb752d..c43161dc 100644 --- a/include/network/uri/uri.hpp +++ b/include/network/uri/uri.hpp @@ -590,6 +590,56 @@ class uri { return detail::decode(first, last, out); } + /** + * \brief Equality operator for the \c uri. + */ + friend bool operator==(const uri &lhs, const uri &rhs) noexcept; + + /** + * \brief Equality operator for the \c uri. + */ + friend bool operator==(const uri &lhs, const char *rhs) noexcept; + + /** + * \brief Equality operator for the \c uri. + */ + friend inline bool operator==(const char *lhs, const uri &rhs) noexcept { + return rhs == lhs; + } + + /** + * \brief Inequality operator for the \c uri. + */ + friend inline bool operator!=(const uri &lhs, const uri &rhs) noexcept { + return !(lhs == rhs); + } + + /** + * \brief Less-than operator for the \c uri. + */ + friend bool operator<(const uri &lhs, const uri &rhs) noexcept; + + /** + * \brief Greater-than operator for the \c uri. + */ + friend inline bool operator>(const uri &lhs, const uri &rhs) noexcept { + return rhs < lhs; + } + + /** + * \brief Less-than-or-equal-to operator for the \c uri. + */ + friend inline bool operator<=(const uri &lhs, const uri &rhs) noexcept { + return !(rhs < lhs); + } + + /** + * \brief Greater-than-or-equal-to operator for the \c uri. + */ + friend inline bool operator>=(const uri &lhs, const uri &rhs) noexcept { + return !(lhs < rhs); + } + private: bool initialize(const string_type &uri); @@ -629,55 +679,6 @@ inline uri make_uri(const Source &source, std::error_code &ec) { */ void swap(uri &lhs, uri &rhs) noexcept; -/** -* \brief Equality operator for the \c uri. -*/ -bool operator==(const uri &lhs, const uri &rhs) noexcept; - -/** - * \brief Equality operator for the \c uri. - */ -bool operator==(const uri &lhs, const char *rhs) noexcept; - -/** - * \brief Equality operator for the \c uri. - */ -inline bool operator==(const char *lhs, const uri &rhs) noexcept { - return rhs == lhs; -} - -/** - * \brief Inequality operator for the \c uri. - */ -inline bool operator!=(const uri &lhs, const uri &rhs) noexcept { - return !(lhs == rhs); -} - -/** - * \brief Less-than operator for the \c uri. - */ -bool operator<(const uri &lhs, const uri &rhs) noexcept; - -/** - * \brief Greater-than operator for the \c uri. - */ -inline bool operator>(const uri &lhs, const uri &rhs) noexcept { - return rhs < lhs; -} - -/** - * \brief Less-than-or-equal-to operator for the \c uri. - */ -inline bool operator<=(const uri &lhs, const uri &rhs) noexcept { - return !(rhs < lhs); -} - -/** - * \brief Greater-than-or-equal-to operator for the \c uri. - */ -inline bool operator>=(const uri &lhs, const uri &rhs) noexcept { - return !(lhs < rhs); -} } // namespace network #if !defined(DOXYGEN_SHOULD_SKIP_THIS) diff --git a/src/uri.cpp b/src/uri.cpp index a1fa79f7..dc312ebe 100644 --- a/src/uri.cpp +++ b/src/uri.cpp @@ -685,18 +685,15 @@ bool uri::initialize(const string_type &uri) { void swap(uri &lhs, uri &rhs) noexcept { lhs.swap(rhs); } bool operator==(const uri &lhs, const uri &rhs) noexcept { - return lhs.compare(rhs, uri_comparison_level::syntax_based) == 0; + return lhs.uri_view_ == rhs.uri_view_; } bool operator==(const uri &lhs, const char *rhs) noexcept { - if (std::strlen(rhs) != - std::size_t(std::distance(std::begin(lhs), std::end(lhs)))) { - return false; - } - return std::equal(std::begin(lhs), std::end(lhs), rhs); + return lhs.uri_view_ == rhs; } bool operator<(const uri &lhs, const uri &rhs) noexcept { - return lhs.compare(rhs, uri_comparison_level::syntax_based) < 0; + return lhs.uri_view_ < rhs.uri_view_; } + } // namespace network diff --git a/test/uri_comparison_test.cpp b/test/uri_comparison_test.cpp index 67ca4363..198a1f5b 100644 --- a/test/uri_comparison_test.cpp +++ b/test/uri_comparison_test.cpp @@ -70,7 +70,7 @@ TEST(uri_comparison_test, inequality_test) { TEST(uri_comparison_test, less_than_test) { // lhs is lexicographically less than rhs network::uri lhs("http://www.example.com/"); - network::uri rhs("http://www.example.org/"); + network::uri rhs("http://www.example.com/path"); ASSERT_LT(lhs, rhs); } From 8078b10b4b01f754d550ea5a269185effdca0997 Mon Sep 17 00:00:00 2001 From: csk Date: Wed, 25 Jul 2018 10:27:26 +0200 Subject: [PATCH 2/4] fixup! Use character-by-character comparison for comparison operators --- src/uri.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/uri.cpp b/src/uri.cpp index dc312ebe..dea1e098 100644 --- a/src/uri.cpp +++ b/src/uri.cpp @@ -689,7 +689,7 @@ bool operator==(const uri &lhs, const uri &rhs) noexcept { } bool operator==(const uri &lhs, const char *rhs) noexcept { - return lhs.uri_view_ == rhs; + return lhs.uri_view_ == string_view{rhs}; } bool operator<(const uri &lhs, const uri &rhs) noexcept { From c0de1e3b1be0467b874ee92a299b8d0a173d2b5e Mon Sep 17 00:00:00 2001 From: csk Date: Wed, 25 Jul 2018 12:52:33 +0200 Subject: [PATCH 3/4] fixup! Use character-by-character comparison for comparison operators --- include/network/uri/uri.hpp | 105 +++++++++++++++++++----------------- src/uri.cpp | 10 ++-- 2 files changed, 62 insertions(+), 53 deletions(-) diff --git a/include/network/uri/uri.hpp b/include/network/uri/uri.hpp index c43161dc..4698139d 100644 --- a/include/network/uri/uri.hpp +++ b/include/network/uri/uri.hpp @@ -416,6 +416,12 @@ class uri { */ std::u32string u32string() const; + /** + * \brief Returns the URI as a string_view object. + * \returns A URI string view. + */ + string_view view() const noexcept; + /** * \brief Checks if the uri object is empty, i.e. it has no parts. * \returns \c true if there are no parts, \c false otherwise. @@ -590,56 +596,6 @@ class uri { return detail::decode(first, last, out); } - /** - * \brief Equality operator for the \c uri. - */ - friend bool operator==(const uri &lhs, const uri &rhs) noexcept; - - /** - * \brief Equality operator for the \c uri. - */ - friend bool operator==(const uri &lhs, const char *rhs) noexcept; - - /** - * \brief Equality operator for the \c uri. - */ - friend inline bool operator==(const char *lhs, const uri &rhs) noexcept { - return rhs == lhs; - } - - /** - * \brief Inequality operator for the \c uri. - */ - friend inline bool operator!=(const uri &lhs, const uri &rhs) noexcept { - return !(lhs == rhs); - } - - /** - * \brief Less-than operator for the \c uri. - */ - friend bool operator<(const uri &lhs, const uri &rhs) noexcept; - - /** - * \brief Greater-than operator for the \c uri. - */ - friend inline bool operator>(const uri &lhs, const uri &rhs) noexcept { - return rhs < lhs; - } - - /** - * \brief Less-than-or-equal-to operator for the \c uri. - */ - friend inline bool operator<=(const uri &lhs, const uri &rhs) noexcept { - return !(rhs < lhs); - } - - /** - * \brief Greater-than-or-equal-to operator for the \c uri. - */ - friend inline bool operator>=(const uri &lhs, const uri &rhs) noexcept { - return !(lhs < rhs); - } - private: bool initialize(const string_type &uri); @@ -679,6 +635,55 @@ inline uri make_uri(const Source &source, std::error_code &ec) { */ void swap(uri &lhs, uri &rhs) noexcept; +/** +* \brief Equality operator for the \c uri. +*/ +bool operator==(const uri &lhs, const uri &rhs) noexcept; + +/** + * \brief Equality operator for the \c uri. + */ +bool operator==(const uri &lhs, const char *rhs) noexcept; + +/** + * \brief Equality operator for the \c uri. + */ +inline bool operator==(const char *lhs, const uri &rhs) noexcept { + return rhs == lhs; +} + +/** + * \brief Inequality operator for the \c uri. + */ +inline bool operator!=(const uri &lhs, const uri &rhs) noexcept { + return !(lhs == rhs); +} + +/** + * \brief Less-than operator for the \c uri. + */ +bool operator<(const uri &lhs, const uri &rhs) noexcept; + +/** + * \brief Greater-than operator for the \c uri. + */ +inline bool operator>(const uri &lhs, const uri &rhs) noexcept { + return rhs < lhs; +} + +/** + * \brief Less-than-or-equal-to operator for the \c uri. + */ +inline bool operator<=(const uri &lhs, const uri &rhs) noexcept { + return !(rhs < lhs); +} + +/** + * \brief Greater-than-or-equal-to operator for the \c uri. + */ +inline bool operator>=(const uri &lhs, const uri &rhs) noexcept { + return !(lhs < rhs); +} } // namespace network #if !defined(DOXYGEN_SHOULD_SKIP_THIS) diff --git a/src/uri.cpp b/src/uri.cpp index dea1e098..5950f345 100644 --- a/src/uri.cpp +++ b/src/uri.cpp @@ -446,6 +446,10 @@ std::u32string uri::u32string() const { return std::u32string(std::begin(*this), std::end(*this)); } +uri::string_view uri::view() const noexcept { + return uri_view_; +} + bool uri::empty() const noexcept { return uri_.empty(); } bool uri::is_absolute() const noexcept { return has_scheme(); } @@ -685,15 +689,15 @@ bool uri::initialize(const string_type &uri) { void swap(uri &lhs, uri &rhs) noexcept { lhs.swap(rhs); } bool operator==(const uri &lhs, const uri &rhs) noexcept { - return lhs.uri_view_ == rhs.uri_view_; + return lhs.view() == rhs.view(); } bool operator==(const uri &lhs, const char *rhs) noexcept { - return lhs.uri_view_ == string_view{rhs}; + return lhs.view() == string_view{rhs}; } bool operator<(const uri &lhs, const uri &rhs) noexcept { - return lhs.uri_view_ < rhs.uri_view_; + return lhs.view() < rhs.view(); } } // namespace network From 1a55ecf3dae88070d4e3045a3b00252e1d6364bb Mon Sep 17 00:00:00 2001 From: csk Date: Wed, 25 Jul 2018 12:57:21 +0200 Subject: [PATCH 4/4] fixup! Use character-by-character comparison for comparison operators --- test/uri_comparison_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/uri_comparison_test.cpp b/test/uri_comparison_test.cpp index 198a1f5b..67ca4363 100644 --- a/test/uri_comparison_test.cpp +++ b/test/uri_comparison_test.cpp @@ -70,7 +70,7 @@ TEST(uri_comparison_test, inequality_test) { TEST(uri_comparison_test, less_than_test) { // lhs is lexicographically less than rhs network::uri lhs("http://www.example.com/"); - network::uri rhs("http://www.example.com/path"); + network::uri rhs("http://www.example.org/"); ASSERT_LT(lhs, rhs); }