From 3f3ece88051a8e0ba678c5c6644733c26910098a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rimas=20Misevi=C4=8Dius?= Date: Thu, 5 Oct 2023 21:38:00 +0300 Subject: [PATCH] Add operator== and std::hash specialization for upa::url --- include/upa/url.h | 16 ++++++++++++++++ test/test-url.cpp | 18 ++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/include/upa/url.h b/include/upa/url.h index a7a0729..ef2c03a 100644 --- a/include/upa/url.h +++ b/include/upa/url.h @@ -626,6 +626,8 @@ class url { std::size_t path_segment_count_ = 0; detail::url_search_params_ptr search_params_ptr_; + friend bool operator==(const url& lhs, const url& rhs); + friend struct std::hash; friend detail::url_serializer; friend detail::url_setter; friend detail::url_parser; @@ -2927,6 +2929,11 @@ inline bool is_unc_path(const CharT* first, const CharT* last) // URL utilities (non-member functions) +/// @brief Lexicographically compares two URL's +inline bool operator==(const url& lhs, const url& rhs) { + return lhs.norm_url_ == rhs.norm_url_; +} + /// @brief Swaps the contents of two URLs /// /// Swaps the contents of the @a lhs and @a rhs URLs @@ -3002,6 +3009,15 @@ inline url url_from_file_path(StrT&& str) { } // namespace upa + +/// @brief std::hash specialization for upa::url class +template<> +struct std::hash { + std::size_t operator()(const upa::url& url) const noexcept { + return std::hash{}(url.norm_url_); + } +}; + // Includes that require the url class declaration #include "url_search_params-inl.h" diff --git a/test/test-url.cpp b/test/test-url.cpp index 1720521..d383ebf 100644 --- a/test/test-url.cpp +++ b/test/test-url.cpp @@ -6,6 +6,7 @@ #include "upa/url.h" #include "doctest-main.h" #include "test-utils.h" +#include std::string urls_to_str(const char* s1) { @@ -566,3 +567,20 @@ TEST_CASE("url_from_file_path") { CHECK_THROWS_AS(upa::url_from_file_path("\\\\.\\Volume{b75e2c83-0000-0000-0000-602f00000000}\\Test\\Foo.txt"), upa::url_error); } } + +// Test operator== and std::hash specialization + +TEST_CASE("operator== && std::hash") { + std::unordered_map map; + + map.emplace(upa::url{ "about:blank" }, 1); + map.emplace(upa::url{ "file:///path" }, 2); + map.emplace(upa::url{ "https://example.org/" }, 3); + + CHECK(map.at(upa::url{ "about:blank" }) == 1); + CHECK(map.at(upa::url{ "file:///path" }) == 2); + CHECK(map.at(upa::url{ "https://example.org/" }) == 3); + + CHECK(upa::url{ "about:blank" } == upa::url{ "about:blank" }); + CHECK_FALSE(upa::url{ "about:blank" } == upa::url{ "https://example.org/" }); +}