diff --git a/include/upa/url.h b/include/upa/url.h index af1cfc7..55bb3c2 100644 --- a/include/upa/url.h +++ b/include/upa/url.h @@ -213,7 +213,7 @@ class url { /// @param[in] pbase pointer to base URL, may be `nullptr` /// @return true if given @a str_url can be parsed against @a *pbase template = 0> - static bool can_parse(T&& str_url, const url* pbase = nullptr) { + [[nodiscard]] static bool can_parse(T&& str_url, const url* pbase = nullptr) { upa::url url; return url.for_can_parse(std::forward(str_url), pbase) == validation_errc::ok; } @@ -227,7 +227,7 @@ class url { /// @param[in] base base URL /// @return true if given @a str_url can be parsed against base URL template = 0> - static bool can_parse(T&& str_url, const url& base) { + [[nodiscard]] static bool can_parse(T&& str_url, const url& base) { return can_parse(std::forward(str_url), &base); } @@ -241,7 +241,7 @@ class url { /// @param[in] str_base base URL string /// @return true if given @a str_url can be parsed against @a str_base URL string template = 0, enable_if_str_arg_t = 0> - static bool can_parse(T&& str_url, TB&& str_base) { + [[nodiscard]] static bool can_parse(T&& str_url, TB&& str_base) { upa::url base; return base.for_can_parse(std::forward(str_base), nullptr) == validation_errc::ok && @@ -387,9 +387,9 @@ class url { /// More info: https://url.spec.whatwg.org/#dom-url-href /// /// @return serialized URL - string_view href() const; + [[nodiscard]] string_view href() const; /// Equivalent to @link href() const @endlink - string_view get_href() const { return href(); } + [[nodiscard]] string_view get_href() const { return href(); } /// @brief The origin getter /// @@ -399,109 +399,109 @@ class url { /// origin (null). /// /// @return ASCII serialized URL's origin - std::string origin() const; + [[nodiscard]] std::string origin() const; /// @brief The protocol getter /// /// More info: https://url.spec.whatwg.org/#dom-url-protocol /// /// @return URL's scheme, followed by U+003A (:) - string_view protocol() const; + [[nodiscard]] string_view protocol() const; /// Equivalent to @link protocol() const @endlink - string_view get_protocol() const { return protocol(); } + [[nodiscard]] string_view get_protocol() const { return protocol(); } /// @brief The username getter /// /// More info: https://url.spec.whatwg.org/#dom-url-username /// /// @return URL’s username - string_view username() const; + [[nodiscard]] string_view username() const; /// Equivalent to @link username() const @endlink - string_view get_username() const { return username(); } + [[nodiscard]] string_view get_username() const { return username(); } /// @brief The password getter /// /// More info: https://url.spec.whatwg.org/#dom-url-password /// /// @return URL’s password - string_view password() const; + [[nodiscard]] string_view password() const; /// Equivalent to @link password() const @endlink - string_view get_password() const { return password(); } + [[nodiscard]] string_view get_password() const { return password(); } /// @brief The host getter /// /// More info: https://url.spec.whatwg.org/#dom-url-host /// /// @return URL’s host, serialized, followed by U+003A (:) and URL’s port, serialized - string_view host() const; + [[nodiscard]] string_view host() const; /// Equivalent to @link host() const @endlink - string_view get_host() const { return host(); } + [[nodiscard]] string_view get_host() const { return host(); } /// @brief The hostname getter /// /// More info: https://url.spec.whatwg.org/#dom-url-hostname /// /// @return URL’s host, serialized - string_view hostname() const; + [[nodiscard]] string_view hostname() const; /// Equivalent to @link hostname() const @endlink - string_view get_hostname() const { return hostname(); } + [[nodiscard]] string_view get_hostname() const { return hostname(); } /// @brief The host_type getter /// /// @return URL’s host type as HostType enumeration value - HostType host_type() const noexcept; + [[nodiscard]] HostType host_type() const noexcept; /// @brief The port getter /// /// More info: https://url.spec.whatwg.org/#dom-url-port /// /// @return URL’s port, serialized, if URL’s port is not null, otherwise empty string - string_view port() const; + [[nodiscard]] string_view port() const; /// Equivalent to @link port() const @endlink - string_view get_port() const { return port(); } + [[nodiscard]] string_view get_port() const { return port(); } /// @return URL’s port, converted to `int` value, if URL’s port is not null, /// otherwise `-1` - int port_int() const; + [[nodiscard]] int port_int() const; /// @return URL’s port, converted to `int` value, if URL’s port is not null, /// otherwise default port, if URL's scheme has default port, /// otherwise `-1` - int real_port_int() const; + [[nodiscard]] int real_port_int() const; /// @brief The path getter /// /// @return URL's path, serialized, followed by U+003F (?) and URL’s query - string_view path() const; + [[nodiscard]] string_view path() const; /// Equivalent to @link path() const @endlink - string_view get_path() const { return path(); } + [[nodiscard]] string_view get_path() const { return path(); } /// @brief The pathname getter /// /// More info: https://url.spec.whatwg.org/#dom-url-pathname /// /// @return URL’s path, serialized - string_view pathname() const; + [[nodiscard]] string_view pathname() const; /// Equivalent to @link pathname() const @endlink - string_view get_pathname() const { return pathname(); } + [[nodiscard]] string_view get_pathname() const { return pathname(); } /// @brief The search getter /// /// More info: https://url.spec.whatwg.org/#dom-url-search /// /// @return empty string or U+003F (?), followed by URL’s query - string_view search() const; + [[nodiscard]] string_view search() const; /// Equivalent to @link search() const @endlink - string_view get_search() const { return search(); } + [[nodiscard]] string_view get_search() const { return search(); } /// @brief The hash getter /// /// More info: https://url.spec.whatwg.org/#dom-url-hash /// /// @return empty string or U+0023 (#), followed by URL’s fragment - string_view hash() const; + [[nodiscard]] string_view hash() const; /// Equivalent to @link hash() const @endlink - string_view get_hash() const { return hash(); } + [[nodiscard]] string_view get_hash() const { return hash(); } /// @brief The searchParams getter /// @@ -517,7 +517,7 @@ class url { /// /// @return the move constructed copy of this’s query object (url_search_params class) /// @see search_params()& - url_search_params search_params()&&; + [[nodiscard]] url_search_params search_params()&&; /// @brief URL serializer /// @@ -526,21 +526,21 @@ class url { /// /// @param[in] exclude_fragment exclude fragment when serializing /// @return serialized URL as string_view - string_view serialize(bool exclude_fragment = false) const; + [[nodiscard]] string_view serialize(bool exclude_fragment = false) const; // Get url info /// @brief Checks whether the URL is empty /// /// @return `true` if URL is empty, `false` otherwise - bool empty() const noexcept; + [[nodiscard]] bool empty() const noexcept; /// @brief Returns whether the URL is valid /// /// URL is valid if it is not empty, and contains a successfully parsed URL. /// /// @return `true` if URL is valid, `false` otherwise - bool is_valid() const noexcept; + [[nodiscard]] bool is_valid() const noexcept; /// @brief Gets URL's part (URL record member) as string /// @@ -558,13 +558,13 @@ class url { /// /// @param[in] t URL's part /// @return URL's part string; it is empty if part is empty or null - string_view get_part_view(PartType t) const; + [[nodiscard]] string_view get_part_view(PartType t) const; /// @brief Checks whether the URL's part (URL record member) is empty or null /// /// @param[in] t URL's part /// @return `true` if URL's part @a t is empty or null, `false` otherwise - bool is_empty(PartType t) const; + [[nodiscard]] bool is_empty(PartType t) const; /// @brief Checks whether the URL's part (URL record member) is null /// @@ -577,27 +577,27 @@ class url { /// /// @param[in] t URL's part /// @return `true` if URL's part @a t is null, `false` otherwise - bool is_null(PartType t) const noexcept; + [[nodiscard]] bool is_null(PartType t) const noexcept; /// @return `true` if URL's scheme is special ("ftp", "file", "http", "https", "ws", or "wss"), /// `false` otherwise; see: https://url.spec.whatwg.org/#special-scheme - bool is_special_scheme() const noexcept; + [[nodiscard]] bool is_special_scheme() const noexcept; /// @return `true` if URL's scheme is "file", `false` otherwise - bool is_file_scheme() const noexcept; + [[nodiscard]] bool is_file_scheme() const noexcept; /// @return `true` if URL's scheme is "http" or "https", `false` otherwise - bool is_http_scheme() const noexcept; + [[nodiscard]] bool is_http_scheme() const noexcept; /// @return `true` if URL includes credentials (username, password), `false` otherwise - bool has_credentials() const; + [[nodiscard]] bool has_credentials() const; /// see: https://url.spec.whatwg.org/#url-opaque-path /// @return `true` if URL's path is a URL path segment, `false` otherwise - bool has_opaque_path() const noexcept; + [[nodiscard]] bool has_opaque_path() const noexcept; /// @return serialized URL as `std::string` - std::string to_string() const; + [[nodiscard]] std::string to_string() const; private: struct alignas(32) scheme_info { @@ -3061,12 +3061,12 @@ inline bool has_dot_dot_segment(const CharT* first, const CharT* last, IsSlash i /// /// @param[in] lhs,rhs URLs to compare /// @param[in] exclude_fragments exclude fragments when comparing -inline bool equals(const url& lhs, const url& rhs, bool exclude_fragments = false) { +[[nodiscard]] inline bool equals(const url& lhs, const url& rhs, bool exclude_fragments = false) { return lhs.serialize(exclude_fragments) == rhs.serialize(exclude_fragments); } /// @brief Lexicographically compares two URL's -inline bool operator==(const url& lhs, const url& rhs) noexcept { +[[nodiscard]] inline bool operator==(const url& lhs, const url& rhs) noexcept { return lhs.norm_url_ == rhs.norm_url_; } @@ -3116,7 +3116,7 @@ enum class file_path_format { /// [GetFullPathName](https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfullpathnamew), /// [std::filesystem::canonical](https://en.cppreference.com/w/cpp/filesystem/canonical) template = 0> -inline url url_from_file_path(StrT&& str, file_path_format format = file_path_format::native) { +[[nodiscard]] inline url url_from_file_path(StrT&& str, file_path_format format = file_path_format::native) { using CharT = str_arg_char_t; const auto inp = make_str_arg(std::forward(str)); const auto* first = inp.begin(); @@ -3197,7 +3197,7 @@ inline url url_from_file_path(StrT&& str, file_path_format format = file_path_fo /// @param[in] format file path format, one of upa::file_path_format::posix, /// upa::file_path_format::windows, upa::file_path_format::native /// @return OS path -inline std::string path_from_file_url(const url& file_url, file_path_format format = file_path_format::native) { +[[nodiscard]] inline std::string path_from_file_url(const url& file_url, file_path_format format = file_path_format::native) { if (!file_url.is_file_scheme()) throw url_error(validation_errc::not_file_url, "Not a file URL"); @@ -3280,7 +3280,7 @@ namespace std { /// @brief std::hash specialization for upa::url class template<> struct hash { - std::size_t operator()(const upa::url& url) const noexcept { + [[nodiscard]] std::size_t operator()(const upa::url& url) const noexcept { return std::hash{}(url.norm_url_); } }; @@ -3288,6 +3288,6 @@ struct hash { } // namespace std // Includes that require the url class declaration -#include "url_search_params-inl.h" +#include "url_search_params-inl.h" // IWYU pragma: export #endif // UPA_URL_H diff --git a/include/upa/url_host.h b/include/upa/url_host.h index 20a7191..3c0e05e 100644 --- a/include/upa/url_host.h +++ b/include/upa/url_host.h @@ -102,14 +102,14 @@ class url_host { /// Host type getter /// /// @return host type, the one of: Domain, IPv4, IPv6 - HostType type() const { + [[nodiscard]] HostType type() const { return type_; } /// Hostname stringifier /// /// @return host serialized to string - std::string to_string() const { + [[nodiscard]] std::string to_string() const { return host_str_; } diff --git a/include/upa/url_percent_encode.h b/include/upa/url_percent_encode.h index 4d7de0c..e8a4ca4 100644 --- a/include/upa/url_percent_encode.h +++ b/include/upa/url_percent_encode.h @@ -84,7 +84,7 @@ class code_point_set { /// @brief test code point set contains code point @a c /// @param[in] c code point to test template - constexpr bool operator[](CharT c) const { + [[nodiscard]] constexpr bool operator[](CharT c) const { const auto uc = util::to_unsigned(c); return is_8bit(uc) && (arr_[uc >> 3] & (1u << (uc & 0x07))) != 0; } @@ -232,7 +232,7 @@ class code_points_multiset { /// @param[in] c code point to test /// @param[in] cps code point set template - constexpr bool char_in_set(CharT c, CP_SET cps) const { + [[nodiscard]] constexpr bool char_in_set(CharT c, CP_SET cps) const { const auto uc = util::to_unsigned(c); return is_8bit(uc) && (arr_[uc] & cps); } @@ -511,7 +511,7 @@ inline void append_percent_decoded(StrT&& str, std::string& output) { /// @param[in] str string input /// @return percent decoded string template = 0> -inline std::string percent_decode(StrT&& str) { +[[nodiscard]] inline std::string percent_decode(StrT&& str) { std::string out; detail::append_percent_decoded(std::forward(str), out); return out; @@ -529,7 +529,7 @@ inline std::string percent_decode(StrT&& str) { /// must not be percent encoded /// @return percent encoded string template = 0> -inline std::string percent_encode(StrT&& str, const code_point_set& no_encode_set) { +[[nodiscard]] inline std::string percent_encode(StrT&& str, const code_point_set& no_encode_set) { const auto inp = make_str_arg(std::forward(str)); std::string out; @@ -548,7 +548,7 @@ inline std::string percent_encode(StrT&& str, const code_point_set& no_encode_se /// @param[in] str string input /// @return percent encoded string template = 0> -inline std::string encode_url_component(StrT&& str) { +[[nodiscard]] inline std::string encode_url_component(StrT&& str) { return percent_encode(std::forward(str), component_no_encode_set); } diff --git a/include/upa/url_result.h b/include/upa/url_result.h index 43b5edf..f69fbc6 100644 --- a/include/upa/url_result.h +++ b/include/upa/url_result.h @@ -89,7 +89,7 @@ enum class validation_errc { /// @brief Check validation error code indicates success /// @return `true` if validation error code is validation_errc::ok, `false` otherwise -constexpr bool success(validation_errc res) noexcept { +[[nodiscard]] constexpr bool success(validation_errc res) noexcept { return res == validation_errc::ok; } @@ -107,7 +107,7 @@ class url_error : public std::runtime_error { {} /// @return validation error code - validation_errc result() const noexcept { + [[nodiscard]] validation_errc result() const noexcept { return res_; } private: @@ -127,7 +127,7 @@ struct result_value { : result(res) {} result_value(R res, T val) noexcept : value(val), result(res) {} - operator R() const noexcept { + [[nodiscard]] operator R() const noexcept { return result; } }; diff --git a/include/upa/url_search_params.h b/include/upa/url_search_params.h index 2f1e43b..5e40f82 100644 --- a/include/upa/url_search_params.h +++ b/include/upa/url_search_params.h @@ -248,7 +248,7 @@ class url_search_params /// @param[in] name /// @return pair value, or `nullptr` template - const std::string* get(const TN& name) const; + [[nodiscard]] const std::string* get(const TN& name) const; /// Return the values of all name-value pairs whose name is @a name. /// @@ -257,7 +257,7 @@ class url_search_params /// @param[in] name /// @return list of values as `std::string` template - std::list get_all(const TN& name) const; + [[nodiscard]] std::list get_all(const TN& name) const; /// Tests if list contains a name-value pair whose name is @a name. /// @@ -266,7 +266,7 @@ class url_search_params /// @param[in] name /// @return `true`, if list contains such pair, `false` otherwise template - bool has(const TN& name) const; + [[nodiscard]] bool has(const TN& name) const; /// Tests if list contains a name-value pair whose name is @a name and value is @a value. /// @@ -276,7 +276,7 @@ class url_search_params /// @param[in] value /// @return `true`, if list contains such pair, `false` otherwise template - bool has(const TN& name, const TV& value) const; + [[nodiscard]] bool has(const TN& name, const TV& value) const; /// Sets search parameter value /// @@ -305,43 +305,43 @@ class url_search_params /// More info: https://url.spec.whatwg.org/#urlsearchparams-stringification-behavior /// /// @return serialized name-value pairs - std::string to_string() const; + [[nodiscard]] std::string to_string() const; // Iterators /// @return an iterator to the beginning of name-value list - const_iterator begin() const noexcept { return params_.begin(); } + [[nodiscard]] const_iterator begin() const noexcept { return params_.begin(); } /// @return an iterator to the beginning of name-value list - const_iterator cbegin() const noexcept { return params_.cbegin(); } + [[nodiscard]] const_iterator cbegin() const noexcept { return params_.cbegin(); } /// @return an iterator to the end of name-value list - const_iterator end() const noexcept { return params_.end(); } + [[nodiscard]] const_iterator end() const noexcept { return params_.end(); } /// @return an iterator to the end of name-value list - const_iterator cend() const noexcept { return params_.cend(); } + [[nodiscard]] const_iterator cend() const noexcept { return params_.cend(); } /// @return a reverse iterator to the beginning of name-value list - const_reverse_iterator rbegin() const noexcept { return params_.rbegin(); } + [[nodiscard]] const_reverse_iterator rbegin() const noexcept { return params_.rbegin(); } /// @return a reverse iterator to the beginning of name-value list - const_reverse_iterator crbegin() const noexcept { return params_.crbegin(); } + [[nodiscard]] const_reverse_iterator crbegin() const noexcept { return params_.crbegin(); } /// @return a reverse iterator to the end of name-value list - const_reverse_iterator rend() const noexcept { return params_.rend(); } + [[nodiscard]] const_reverse_iterator rend() const noexcept { return params_.rend(); } /// @return a reverse iterator to the end of name-value list - const_reverse_iterator crend() const noexcept { return params_.crend(); } + [[nodiscard]] const_reverse_iterator crend() const noexcept { return params_.crend(); } // Capacity /// Checks whether the name-value list is empty /// /// @return `true` if the container is empty, `false` otherwise - bool empty() const noexcept { return params_.empty(); } + [[nodiscard]] bool empty() const noexcept { return params_.empty(); } /// @return the number of elements in the name-value list - size_type size() const noexcept { return params_.size(); } + [[nodiscard]] size_type size() const noexcept { return params_.size(); } // Utils @@ -351,7 +351,7 @@ class url_search_params /// then skips first code point in @a query /// @param[in] query string to parse template = 0> - static name_value_list do_parse(bool rem_qmark, StrT&& query); + [[nodiscard]] static name_value_list do_parse(bool rem_qmark, StrT&& query); /// Percent encodes the @a value using application/x-www-form-urlencoded percent-encode set, /// and replacing 0x20 (SP) with U+002B (+). Appends result to the @a encoded string. diff --git a/test/test-url.cpp b/test/test-url.cpp index f769054..6b3d5c9 100644 --- a/test/test-url.cpp +++ b/test/test-url.cpp @@ -9,6 +9,9 @@ #include +template +void discard(T&&) {} + std::string urls_to_str(const char* s1) { return s1; } @@ -633,17 +636,17 @@ TEST_CASE("url_from_file_path") { CHECK(upa::url_from_file_path("/\\", upa::file_path_format::posix).href() == "file:///%5C"); CHECK(upa::url_from_file_path("/..\\", upa::file_path_format::posix).href() == "file:///..%5C"); // empty path - CHECK_THROWS_AS(upa::url_from_file_path("", upa::file_path_format::posix), upa::url_error); + CHECK_THROWS_AS(discard(upa::url_from_file_path("", upa::file_path_format::posix)), upa::url_error); // non absolute path - CHECK_THROWS_AS(upa::url_from_file_path("path", upa::file_path_format::posix), upa::url_error); - CHECK_THROWS_AS(upa::url_from_file_path("C:\\path", upa::file_path_format::posix), upa::url_error); - CHECK_THROWS_AS(upa::url_from_file_path("C:/path", upa::file_path_format::posix), upa::url_error); - CHECK_THROWS_AS(upa::url_from_file_path("\\\\h\\p", upa::file_path_format::posix), upa::url_error); + CHECK_THROWS_AS(discard(upa::url_from_file_path("path", upa::file_path_format::posix)), upa::url_error); + CHECK_THROWS_AS(discard(upa::url_from_file_path("C:\\path", upa::file_path_format::posix)), upa::url_error); + CHECK_THROWS_AS(discard(upa::url_from_file_path("C:/path", upa::file_path_format::posix)), upa::url_error); + CHECK_THROWS_AS(discard(upa::url_from_file_path("\\\\h\\p", upa::file_path_format::posix)), upa::url_error); // ".." segments - CHECK_THROWS_AS(upa::url_from_file_path("/..", upa::file_path_format::posix), upa::url_error); - CHECK_THROWS_AS(upa::url_from_file_path("/../", upa::file_path_format::posix), upa::url_error); + CHECK_THROWS_AS(discard(upa::url_from_file_path("/..", upa::file_path_format::posix)), upa::url_error); + CHECK_THROWS_AS(discard(upa::url_from_file_path("/../", upa::file_path_format::posix)), upa::url_error); // null character - CHECK_THROWS_AS(upa::url_from_file_path(std::string{ "/p\0", 3 }, upa::file_path_format::posix), upa::url_error); + CHECK_THROWS_AS(discard(upa::url_from_file_path(std::string{ "/p\0", 3 }, upa::file_path_format::posix)), upa::url_error); } SUBCASE("Windows path") { // https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file @@ -679,45 +682,45 @@ TEST_CASE("url_from_file_path") { CHECK(upa::url_from_file_path("//?/unc/h/very_long_path", upa::file_path_format::windows).href() == "file://h/very_long_path"); CHECK(upa::url_from_file_path("//./unc/h/just_path", upa::file_path_format::windows).href() == "file://h/just_path"); // empty path - CHECK_THROWS_AS(upa::url_from_file_path("", upa::file_path_format::windows), upa::url_error); + CHECK_THROWS_AS(discard(upa::url_from_file_path("", upa::file_path_format::windows)), upa::url_error); // non absolute path - CHECK_THROWS_AS(upa::url_from_file_path("\\", upa::file_path_format::windows), upa::url_error); - CHECK_THROWS_AS(upa::url_from_file_path("C:path", upa::file_path_format::windows), upa::url_error); - CHECK_THROWS_AS(upa::url_from_file_path("path", upa::file_path_format::windows), upa::url_error); - CHECK_THROWS_AS(upa::url_from_file_path("/", upa::file_path_format::windows), upa::url_error); - CHECK_THROWS_AS(upa::url_from_file_path("C|\\path", upa::file_path_format::windows), upa::url_error); - CHECK_THROWS_AS(upa::url_from_file_path("C|/path", upa::file_path_format::windows), upa::url_error); + CHECK_THROWS_AS(discard(upa::url_from_file_path("\\", upa::file_path_format::windows)), upa::url_error); + CHECK_THROWS_AS(discard(upa::url_from_file_path("C:path", upa::file_path_format::windows)), upa::url_error); + CHECK_THROWS_AS(discard(upa::url_from_file_path("path", upa::file_path_format::windows)), upa::url_error); + CHECK_THROWS_AS(discard(upa::url_from_file_path("/", upa::file_path_format::windows)), upa::url_error); + CHECK_THROWS_AS(discard(upa::url_from_file_path("C|\\path", upa::file_path_format::windows)), upa::url_error); + CHECK_THROWS_AS(discard(upa::url_from_file_path("C|/path", upa::file_path_format::windows)), upa::url_error); // invalid UNC - CHECK_THROWS_AS(upa::url_from_file_path("\\\\", upa::file_path_format::windows), upa::url_error); - CHECK_THROWS_AS(upa::url_from_file_path("\\\\h\\\\", upa::file_path_format::windows), upa::url_error); - CHECK_THROWS_AS(upa::url_from_file_path("\\\\h\\.", upa::file_path_format::windows), upa::url_error); - CHECK_THROWS_AS(upa::url_from_file_path("\\\\h\\..", upa::file_path_format::windows), upa::url_error); - CHECK_THROWS_AS(upa::url_from_file_path(std::string{ '\\', '\\', 'h', '\\', 'a', '\0', 'b' }, - upa::file_path_format::windows), upa::url_error); - CHECK_THROWS_AS(upa::url_from_file_path("\\\\C:\\path", upa::file_path_format::windows), upa::url_error); - CHECK_THROWS_AS(upa::url_from_file_path("\\\\C|\\path", upa::file_path_format::windows), upa::url_error); - CHECK_THROWS_AS(upa::url_from_file_path("\\\\?\\UNC\\?\\name", upa::file_path_format::windows), upa::url_error); - CHECK_THROWS_AS(upa::url_from_file_path("\\\\?\\UNC\\.\\name", upa::file_path_format::windows), upa::url_error); - CHECK_THROWS_AS(upa::url_from_file_path("\\\\?\\UNC\\h\\.", upa::file_path_format::windows), upa::url_error); - CHECK_THROWS_AS(upa::url_from_file_path("\\\\?\\UNC\\h\\..", upa::file_path_format::windows), upa::url_error); + CHECK_THROWS_AS(discard(upa::url_from_file_path("\\\\", upa::file_path_format::windows)), upa::url_error); + CHECK_THROWS_AS(discard(upa::url_from_file_path("\\\\h\\\\", upa::file_path_format::windows)), upa::url_error); + CHECK_THROWS_AS(discard(upa::url_from_file_path("\\\\h\\.", upa::file_path_format::windows)), upa::url_error); + CHECK_THROWS_AS(discard(upa::url_from_file_path("\\\\h\\..", upa::file_path_format::windows)), upa::url_error); + CHECK_THROWS_AS(discard(upa::url_from_file_path(std::string{ '\\', '\\', 'h', '\\', 'a', '\0', 'b' }, + upa::file_path_format::windows)), upa::url_error); + CHECK_THROWS_AS(discard(upa::url_from_file_path("\\\\C:\\path", upa::file_path_format::windows)), upa::url_error); + CHECK_THROWS_AS(discard(upa::url_from_file_path("\\\\C|\\path", upa::file_path_format::windows)), upa::url_error); + CHECK_THROWS_AS(discard(upa::url_from_file_path("\\\\?\\UNC\\?\\name", upa::file_path_format::windows)), upa::url_error); + CHECK_THROWS_AS(discard(upa::url_from_file_path("\\\\?\\UNC\\.\\name", upa::file_path_format::windows)), upa::url_error); + CHECK_THROWS_AS(discard(upa::url_from_file_path("\\\\?\\UNC\\h\\.", upa::file_path_format::windows)), upa::url_error); + CHECK_THROWS_AS(discard(upa::url_from_file_path("\\\\?\\UNC\\h\\..", upa::file_path_format::windows)), upa::url_error); // UNC: invalid hostname - CHECK_THROWS_AS(upa::url_from_file_path("\\\\a b\\path", upa::file_path_format::windows), upa::url_error); - CHECK_THROWS_AS(upa::url_from_file_path("\\\\a?b\\path", upa::file_path_format::windows), upa::url_error); - CHECK_THROWS_AS(upa::url_from_file_path("\\\\a#b\\path", upa::file_path_format::windows), upa::url_error); + CHECK_THROWS_AS(discard(upa::url_from_file_path("\\\\a b\\path", upa::file_path_format::windows)), upa::url_error); + CHECK_THROWS_AS(discard(upa::url_from_file_path("\\\\a?b\\path", upa::file_path_format::windows)), upa::url_error); + CHECK_THROWS_AS(discard(upa::url_from_file_path("\\\\a#b\\path", upa::file_path_format::windows)), upa::url_error); // unsupported pathes - CHECK_THROWS_AS(upa::url_from_file_path("\\\\?\\Volume{b75e2c83-0000-0000-0000-602f00000000}\\Test\\Foo.txt", - upa::file_path_format::windows), upa::url_error); - CHECK_THROWS_AS(upa::url_from_file_path("\\\\.\\Volume{b75e2c83-0000-0000-0000-602f00000000}\\Test\\Foo.txt", - upa::file_path_format::windows), upa::url_error); + CHECK_THROWS_AS(discard(upa::url_from_file_path("\\\\?\\Volume{b75e2c83-0000-0000-0000-602f00000000}\\Test\\Foo.txt", + upa::file_path_format::windows)), upa::url_error); + CHECK_THROWS_AS(discard(upa::url_from_file_path("\\\\.\\Volume{b75e2c83-0000-0000-0000-602f00000000}\\Test\\Foo.txt", + upa::file_path_format::windows)), upa::url_error); // ".." segments - CHECK_THROWS_AS(upa::url_from_file_path("C:\\..", upa::file_path_format::windows), upa::url_error); - CHECK_THROWS_AS(upa::url_from_file_path("C:\\..\\", upa::file_path_format::windows), upa::url_error); - CHECK_THROWS_AS(upa::url_from_file_path("C:/..", upa::file_path_format::windows), upa::url_error); - CHECK_THROWS_AS(upa::url_from_file_path("C:/../", upa::file_path_format::windows), upa::url_error); - CHECK_THROWS_AS(upa::url_from_file_path("\\h\\sn\\..", upa::file_path_format::windows), upa::url_error); - CHECK_THROWS_AS(upa::url_from_file_path("\\h\\sn\\../", upa::file_path_format::windows), upa::url_error); + CHECK_THROWS_AS(discard(upa::url_from_file_path("C:\\..", upa::file_path_format::windows)), upa::url_error); + CHECK_THROWS_AS(discard(upa::url_from_file_path("C:\\..\\", upa::file_path_format::windows)), upa::url_error); + CHECK_THROWS_AS(discard(upa::url_from_file_path("C:/..", upa::file_path_format::windows)), upa::url_error); + CHECK_THROWS_AS(discard(upa::url_from_file_path("C:/../", upa::file_path_format::windows)), upa::url_error); + CHECK_THROWS_AS(discard(upa::url_from_file_path("\\h\\sn\\..", upa::file_path_format::windows)), upa::url_error); + CHECK_THROWS_AS(discard(upa::url_from_file_path("\\h\\sn\\../", upa::file_path_format::windows)), upa::url_error); // null character - CHECK_THROWS_AS(upa::url_from_file_path(std::string{ "C:\\p\0", 5 }, upa::file_path_format::windows), upa::url_error); + CHECK_THROWS_AS(discard(upa::url_from_file_path(std::string{ "C:\\p\0", 5 }, upa::file_path_format::windows)), upa::url_error); } SUBCASE("Native path") { #ifdef _WIN32