From 8c8b6fc615d654986fcc415dc42e3ad0d4536dee Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Mon, 20 Jan 2025 15:35:57 -0500 Subject: [PATCH] cleaner --- include/ada/implementation.h | 6 +- include/ada/parser.h | 15 ++-- include/ada/url_aggregator.h | 6 +- include/ada/url_pattern-inl.h | 70 +++++++---------- include/ada/url_pattern.h | 32 ++++---- include/ada/url_pattern_helpers-inl.h | 98 +++++++++--------------- include/ada/url_pattern_helpers.h | 14 ++-- include/ada/url_pattern_regex.h | 52 +++++++------ src/implementation.cpp | 18 ++++- src/parser.cpp | 105 ++++++++++++-------------- src/url_pattern.cpp | 34 ++++----- src/url_pattern_helpers.cpp | 31 ++++---- tests/wpt_urlpattern_tests.cpp | 22 +++--- 13 files changed, 229 insertions(+), 274 deletions(-) diff --git a/include/ada/implementation.h b/include/ada/implementation.h index 0aed06f93..ae3ef2080 100644 --- a/include/ada/implementation.h +++ b/include/ada/implementation.h @@ -58,9 +58,9 @@ bool can_parse(std::string_view input, * use ada::url_pattern_regex::std_regex_provider * @return url_pattern instance */ -template - requires url_pattern_regex::derived_from_provider -ada_warn_unused tl::expected, errors> +template +ada_warn_unused tl::expected, errors> parse_url_pattern(std::variant input, const std::string_view* base_url = nullptr, const url_pattern_options* options = nullptr, diff --git a/include/ada/parser.h b/include/ada/parser.h index 733636932..02b7dadf1 100644 --- a/include/ada/parser.h +++ b/include/ada/parser.h @@ -17,8 +17,7 @@ namespace ada { struct url_aggregator; struct url; -template - requires url_pattern_regex::derived_from_provider +template class url_pattern; struct url_pattern_options; struct url_pattern_init; @@ -54,13 +53,11 @@ extern template url_aggregator parse_url_impl( extern template url parse_url_impl(std::string_view user_input, const url* base_url); -template - requires url_pattern_regex::derived_from_provider -tl::expected, errors> -parse_url_pattern_impl(std::variant input, - const std::string_view* base_url, - const url_pattern_options* options, - regex_provider&& provider); +template +tl::expected, errors> parse_url_pattern_impl( + std::variant input, + const std::string_view* base_url, const url_pattern_options* options, + regex_provider&& provider); } // namespace ada::parser diff --git a/include/ada/url_aggregator.h b/include/ada/url_aggregator.h index 8a768e8af..053e577fa 100644 --- a/include/ada/url_aggregator.h +++ b/include/ada/url_aggregator.h @@ -222,10 +222,8 @@ struct url_aggregator : url_base { friend url_aggregator parser::parse_url_impl( std::string_view, const url_aggregator *); // url_pattern methods - template - requires url_pattern_regex::derived_from_provider - friend tl::expected, errors> + template + friend tl::expected, errors> parse_url_pattern_impl(std::variant input, const std::string_view *base_url, const url_pattern_options *options); diff --git a/include/ada/url_pattern-inl.h b/include/ada/url_pattern-inl.h index 23fb7dbf3..981ae8134 100644 --- a/include/ada/url_pattern-inl.h +++ b/include/ada/url_pattern-inl.h @@ -24,10 +24,8 @@ inline bool url_pattern_component_result::operator==( return input == other.input && groups == other.groups; } -template - requires url_pattern_regex::derived_from_provider -std::string url_pattern_component::to_string() - const { +template +std::string url_pattern_component::to_string() const { #ifdef ADA_HAS_FORMAT return std::format(R"({{"pattern": "{}", "has_regexp_groups": {}}})", pattern, has_regexp_groups ? "true" : "false" //, @@ -37,11 +35,10 @@ std::string url_pattern_component::to_string() #endif } -template - requires url_pattern_regex::derived_from_provider -url_pattern_component_result url_pattern_component:: - create_component_match_result(std::string_view input, - const std::smatch& exec_result) { +template +url_pattern_component_result +url_pattern_component::create_component_match_result( + std::string_view input, const std::smatch& exec_result) { // Let result be a new URLPatternComponentResult. // Set result["input"] to input. // Let groups be a record. @@ -75,9 +72,8 @@ url_pattern_component_result url_pattern_component:: return result; } -template - requires url_pattern_regex::derived_from_provider -std::string url_pattern::to_string() const { +template +std::string url_pattern::to_string() const { #ifdef ADA_HAS_FORMAT return std::format( R"({{"protocol_component": "{}", "username_component": {}, "password_component": {}, "hostname_component": {}, "port_component": {}, "pathname_component": {}, "search_component": {}, "hash_component": {}, "ignore_case": {}}})", @@ -91,70 +87,60 @@ std::string url_pattern::to_string() const { #endif } -template - requires url_pattern_regex::derived_from_provider -std::string_view url_pattern::get_protocol() const +template +std::string_view url_pattern::get_protocol() const ada_lifetime_bound { // Return this's associated URL pattern's protocol component's pattern string. return protocol_component.pattern; } -template - requires url_pattern_regex::derived_from_provider -std::string_view url_pattern::get_username() const +template +std::string_view url_pattern::get_username() const ada_lifetime_bound { // Return this's associated URL pattern's username component's pattern string. return username_component.pattern; } -template - requires url_pattern_regex::derived_from_provider -std::string_view url_pattern::get_password() const +template +std::string_view url_pattern::get_password() const ada_lifetime_bound { // Return this's associated URL pattern's password component's pattern string. return password_component.pattern; } -template - requires url_pattern_regex::derived_from_provider -std::string_view url_pattern::get_hostname() const +template +std::string_view url_pattern::get_hostname() const ada_lifetime_bound { // Return this's associated URL pattern's hostname component's pattern string. return hostname_component.pattern; } -template - requires url_pattern_regex::derived_from_provider -std::string_view url_pattern::get_port() const +template +std::string_view url_pattern::get_port() const ada_lifetime_bound { // Return this's associated URL pattern's port component's pattern string. return port_component.pattern; } -template - requires url_pattern_regex::derived_from_provider -std::string_view url_pattern::get_pathname() const +template +std::string_view url_pattern::get_pathname() const ada_lifetime_bound { // Return this's associated URL pattern's pathname component's pattern string. return pathname_component.pattern; } -template - requires url_pattern_regex::derived_from_provider -std::string_view url_pattern::get_search() const +template +std::string_view url_pattern::get_search() const ada_lifetime_bound { // Return this's associated URL pattern's search component's pattern string. return search_component.pattern; } -template - requires url_pattern_regex::derived_from_provider -std::string_view url_pattern::get_hash() const +template +std::string_view url_pattern::get_hash() const ada_lifetime_bound { // Return this's associated URL pattern's hash component's pattern string. return hash_component.pattern; } -template - requires url_pattern_regex::derived_from_provider -bool url_pattern::ignore_case() const { +template +bool url_pattern::ignore_case() const { return ignore_case_; } -template - requires url_pattern_regex::derived_from_provider -bool url_pattern::has_regexp_groups() const { +template +bool url_pattern::has_regexp_groups() const { // If this's associated URL pattern's has regexp groups, then return true. return protocol_component.has_regexp_groups || username_component.has_regexp_groups || diff --git a/include/ada/url_pattern.h b/include/ada/url_pattern.h index 105e393a5..fb6f19ee7 100644 --- a/include/ada/url_pattern.h +++ b/include/ada/url_pattern.h @@ -207,15 +207,15 @@ struct url_pattern_component_result { #endif // ADA_TESTING }; -template - requires url_pattern_regex::derived_from_provider +template class url_pattern_component { public: url_pattern_component() = default; // This function explicitly takes a std::string because it is moved. // To avoid unnecessary copy, move each value while calling the constructor. - url_pattern_component(std::string&& new_pattern, regex_type&& new_regexp, + url_pattern_component(std::string&& new_pattern, + regex_provider::regex_type&& new_regexp, std::vector&& new_group_name_list, bool new_has_regexp_groups) : regexp(std::move(new_regexp)), @@ -236,7 +236,7 @@ class url_pattern_component { std::string to_string() const; - regex_type regexp{}; + regex_provider::regex_type regexp{}; std::string pattern{}; std::vector group_name_list{}; bool has_regexp_groups = false; @@ -270,13 +270,11 @@ struct url_pattern_options { // defined in https://wicg.github.io/urlpattern. // More information about the URL Pattern syntax can be found at // https://developer.mozilla.org/en-US/docs/Web/API/URL_Pattern_API -template - requires url_pattern_regex::derived_from_provider +template class url_pattern { public: - explicit url_pattern( - url_pattern_regex::provider&& new_regex_provider) - : regex_provider_(std::move(new_regex_provider)) {} + explicit url_pattern(regex_provider&& new_regex_provider) + : regex_provider_(new_regex_provider) {} /** * @see https://urlpattern.spec.whatwg.org/#dom-urlpattern-exec @@ -322,14 +320,14 @@ class url_pattern { [[nodiscard]] std::string to_string() const; - url_pattern_component protocol_component{}; - url_pattern_component username_component{}; - url_pattern_component password_component{}; - url_pattern_component hostname_component{}; - url_pattern_component port_component{}; - url_pattern_component pathname_component{}; - url_pattern_component search_component{}; - url_pattern_component hash_component{}; + url_pattern_component protocol_component{}; + url_pattern_component username_component{}; + url_pattern_component password_component{}; + url_pattern_component hostname_component{}; + url_pattern_component port_component{}; + url_pattern_component pathname_component{}; + url_pattern_component search_component{}; + url_pattern_component hash_component{}; bool ignore_case_ = false; regex_provider regex_provider_; diff --git a/include/ada/url_pattern_helpers-inl.h b/include/ada/url_pattern_helpers-inl.h index 6a5cfe479..3e0b3a07b 100644 --- a/include/ada/url_pattern_helpers-inl.h +++ b/include/ada/url_pattern_helpers-inl.h @@ -39,26 +39,23 @@ inline std::string to_string(token_type type) { } } -template - requires url_pattern_regex::derived_from_provider -void constructor_string_parser::rewind() { +template +void constructor_string_parser::rewind() { // Set parser’s token index to parser’s component start. token_index = component_start; // Set parser’s token increment to 0. token_increment = 0; } -template - requires url_pattern_regex::derived_from_provider -bool constructor_string_parser::is_hash_prefix() { +template +bool constructor_string_parser::is_hash_prefix() { // Return the result of running is a non-special pattern char given parser, // parser’s token index and "#". return is_non_special_pattern_char(token_index, "#"); } -template - requires url_pattern_regex::derived_from_provider -bool constructor_string_parser::is_search_prefix() { +template +bool constructor_string_parser::is_search_prefix() { // If result of running is a non-special pattern char given parser, parser’s // token index and "?" is true, then return true. if (is_non_special_pattern_char(token_index, "?")) { @@ -90,10 +87,9 @@ bool constructor_string_parser::is_search_prefix() { previous_token->type == token_type::ASTERISK); } -template - requires url_pattern_regex::derived_from_provider -bool constructor_string_parser:: - is_non_special_pattern_char(size_t index, std::string_view value) { +template +bool constructor_string_parser::is_non_special_pattern_char( + size_t index, std::string_view value) { // Let token be the result of running get a safe token given parser and index. auto token = get_safe_token(index); ADA_ASSERT_TRUE(token); @@ -113,10 +109,8 @@ bool constructor_string_parser:: token->type == token_type::INVALID_CHAR; } -template - requires url_pattern_regex::derived_from_provider -const Token* -constructor_string_parser::get_safe_token( +template +const Token* constructor_string_parser::get_safe_token( size_t index) { // If index is less than parser’s token list's size, then return parser’s // token list[index]. @@ -135,28 +129,22 @@ constructor_string_parser::get_safe_token( return &token_list.back(); } -template - requires url_pattern_regex::derived_from_provider -bool constructor_string_parser::is_group_open() - const { +template +bool constructor_string_parser::is_group_open() const { // If parser’s token list[parser’s token index]'s type is "open", then return // true. return token_list[token_index].type == token_type::OPEN; } -template - requires url_pattern_regex::derived_from_provider -bool constructor_string_parser::is_group_close() - const { +template +bool constructor_string_parser::is_group_close() const { // If parser’s token list[parser’s token index]'s type is "close", then return // true. return token_list[token_index].type == token_type::CLOSE; } -template - requires url_pattern_regex::derived_from_provider -bool constructor_string_parser::next_is_authority_slashes() { +template +bool constructor_string_parser::next_is_authority_slashes() { // If the result of running is a non-special pattern char given parser, // parser’s token index + 1, and "/" is false, then return false. if (!is_non_special_pattern_char(token_index + 1, "/")) { @@ -170,19 +158,16 @@ bool constructor_string_parser - requires url_pattern_regex::derived_from_provider -bool constructor_string_parser::is_protocol_suffix() { +template +bool constructor_string_parser::is_protocol_suffix() { // Return the result of running is a non-special pattern char given parser, // parser’s token index, and ":". return is_non_special_pattern_char(token_index, ":"); } -template - requires url_pattern_regex::derived_from_provider -void constructor_string_parser::change_state( - State new_state, size_t skip) { +template +void constructor_string_parser::change_state(State new_state, + size_t skip) { // If parser’s state is not "init", not "authority", and not "done", then set // parser’s result[parser’s state] to the result of running make a component // string given parser. @@ -280,10 +265,8 @@ void constructor_string_parser::change_state( token_increment = 0; } -template - requires url_pattern_regex::derived_from_provider -std::string -constructor_string_parser::make_component_string() { +template +std::string constructor_string_parser::make_component_string() { // Assert: parser’s token index is less than parser’s token list's size. ADA_ASSERT_TRUE(token_index < token_list.size()); @@ -302,52 +285,43 @@ constructor_string_parser::make_component_string() { end_index - component_start_input_index); } -template - requires url_pattern_regex::derived_from_provider -bool constructor_string_parser::is_an_identity_terminator() { +template +bool constructor_string_parser::is_an_identity_terminator() { // Return the result of running is a non-special pattern char given parser, // parser’s token index, and "@". return is_non_special_pattern_char(token_index, "@"); } -template - requires url_pattern_regex::derived_from_provider -bool constructor_string_parser::is_pathname_start() { +template +bool constructor_string_parser::is_pathname_start() { // Return the result of running is a non-special pattern char given parser, // parser’s token index, and "/". return is_non_special_pattern_char(token_index, "/"); } -template - requires url_pattern_regex::derived_from_provider -bool constructor_string_parser::is_password_prefix() { +template +bool constructor_string_parser::is_password_prefix() { // Return the result of running is a non-special pattern char given parser, // parser’s token index, and ":". return is_non_special_pattern_char(token_index, ":"); } -template - requires url_pattern_regex::derived_from_provider -bool constructor_string_parser::is_an_ipv6_open() { +template +bool constructor_string_parser::is_an_ipv6_open() { // Return the result of running is a non-special pattern char given parser, // parser’s token index, and "[". return is_non_special_pattern_char(token_index, "["); } -template - requires url_pattern_regex::derived_from_provider -bool constructor_string_parser::is_an_ipv6_close() { +template +bool constructor_string_parser::is_an_ipv6_close() { // Return the result of running is a non-special pattern char given parser, // parser’s token index, and "]". return is_non_special_pattern_char(token_index, "]"); } -template - requires url_pattern_regex::derived_from_provider -bool constructor_string_parser::is_port_prefix() { +template +bool constructor_string_parser::is_port_prefix() { // Return the result of running is a non-special pattern char given parser, // parser’s token index, and ":". return is_non_special_pattern_char(token_index, ":"); diff --git a/include/ada/url_pattern_helpers.h b/include/ada/url_pattern_helpers.h index 6865d2332..d62c0e612 100644 --- a/include/ada/url_pattern_helpers.h +++ b/include/ada/url_pattern_helpers.h @@ -139,8 +139,7 @@ class Tokenizer { }; // @see https://urlpattern.spec.whatwg.org/#constructor-string-parser -template - requires url_pattern_regex::derived_from_provider +template struct constructor_string_parser { explicit constructor_string_parser(std::string_view new_input, std::vector&& new_token_list) @@ -156,7 +155,8 @@ struct constructor_string_parser { bool is_search_prefix(); // @see https://urlpattern.spec.whatwg.org/#parse-a-constructor-string - static tl::expected parse(std::string_view input); + static tl::expected parse(std::string_view input, + regex_provider provider); // @see https://urlpattern.spec.whatwg.org/#constructor-string-parser-state enum class State { @@ -187,7 +187,8 @@ struct constructor_string_parser { // @see // https://urlpattern.spec.whatwg.org/#compute-protocol-matches-a-special-scheme-flag - std::optional compute_protocol_matches_special_scheme_flag(); + std::optional compute_protocol_matches_special_scheme_flag( + regex_provider provider); // @see https://urlpattern.spec.whatwg.org/#next-is-authority-slashes bool next_is_authority_slashes(); @@ -323,10 +324,9 @@ bool is_ipv6_address(std::string_view input) noexcept; // @see // https://urlpattern.spec.whatwg.org/#protocol-component-matches-a-special-scheme -template - requires url_pattern_regex::derived_from_provider +template bool protocol_component_matches_special_scheme( - ada::url_pattern_component& input); + ada::url_pattern_component& input); // @see https://urlpattern.spec.whatwg.org/#convert-a-modifier-to-a-string std::string convert_modifier_to_string(url_pattern_part_modifier modifier); diff --git a/include/ada/url_pattern_regex.h b/include/ada/url_pattern_regex.h index 550c27372..4d2ca0820 100644 --- a/include/ada/url_pattern_regex.h +++ b/include/ada/url_pattern_regex.h @@ -10,33 +10,43 @@ namespace ada::url_pattern_regex { -template -class provider { - public: - using regex_type = T; - - virtual ~provider() = default; - virtual std::optional create_instance(std::string_view pattern, - bool ignore_case) = 0; - virtual std::optional> regex_search( - std::string_view input, const regex_type& pattern) = 0; - virtual bool regex_match(std::string_view input, - const regex_type& pattern) = 0; +template +concept regex_concept = requires(T t, std::string_view pattern, + bool ignore_case, std::string_view input) { + // Ensure the class has a type alias 'regex_type' + typename T::regex_type; + + // Function to create a regex instance + { + T::create_instance(pattern, ignore_case) + } -> std::same_as>; + + // Function to perform regex search + { + t.regex_search(input, std::declval()) + } -> std::same_as>>; + + // Function to match regex pattern + { + t.regex_match(input, std::declval()) + } -> std::same_as; + + // Copy constructor + { T(std::declval()) } -> std::same_as; + + // Move constructor + { T(std::declval()) } -> std::same_as; }; -template -concept derived_from_provider = - std::is_base_of_v, derived_class>; - -class std_regex_provider : public provider { +class std_regex_provider { public: std_regex_provider() = default; using regex_type = std::regex; - std::optional create_instance(std::string_view pattern, - bool ignore_case) override; + static std::optional create_instance(std::string_view pattern, + bool ignore_case); std::optional> regex_search( - std::string_view input, const regex_type& pattern) override; - bool regex_match(std::string_view input, const regex_type& pattern) override; + std::string_view input, const regex_type& pattern); + bool regex_match(std::string_view input, const regex_type& pattern); }; } // namespace ada::url_pattern_regex diff --git a/src/implementation.cpp b/src/implementation.cpp index 876bc1ba0..c6bfc45d1 100644 --- a/src/implementation.cpp +++ b/src/implementation.cpp @@ -79,16 +79,26 @@ ada_warn_unused std::string to_string(ada::encoding_type type) { } } -template - requires url_pattern_regex::derived_from_provider -ada_warn_unused tl::expected, errors> +template +ada_warn_unused tl::expected, errors> parse_url_pattern(std::variant input, const std::string_view* base_url, const url_pattern_options* options, std::optional provider) { - return parser::parse_url_pattern_impl( + return parser::parse_url_pattern_impl( std::move(input), base_url, options, provider.value_or(url_pattern_regex::std_regex_provider())); } +template ada_warn_unused + tl::expected, errors> + parse_url_pattern( + std::variant input, + const std::string_view* base_url, const url_pattern_options* options, + std::optional provider); + +template result> +url_pattern::exec( + const url_pattern_input& input, std::string_view* base_url); + } // namespace ada diff --git a/src/parser.cpp b/src/parser.cpp index e699b2536..6ad6298f1 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -898,21 +898,20 @@ result_type parse_url_impl(std::string_view user_input, return url; } -template - requires url_pattern_regex::derived_from_provider -tl::expected, errors> -parse_url_pattern_impl(std::variant input, - const std::string_view* base_url, - const url_pattern_options* options, - regex_provider&& provider) { +template +tl::expected, errors> parse_url_pattern_impl( + std::variant input, + const std::string_view* base_url, const url_pattern_options* options, + regex_provider&& provider) { // Let init be null. url_pattern_init init; // If input is a scalar value string then: if (std::holds_alternative(input)) { // Set init to the result of running parse a constructor string given input. - auto parse_result = url_pattern_helpers::constructor_string_parser< - regex_provider, regex_type>::parse(std::get(input)); + auto parse_result = + url_pattern_helpers::constructor_string_parser::parse( + std::get(input), provider); if (!parse_result) { ada_log("constructor_string_parser::parse failed"); return tl::unexpected(parse_result.error()); @@ -987,16 +986,15 @@ parse_url_pattern_impl(std::variant input, } // Let urlPattern be a new URL pattern. - auto url_pattern_ = url_pattern(std::move(provider)); + url_pattern url_pattern_(std::move(provider)); // Set urlPattern’s protocol component to the result of compiling a component // given processedInit["protocol"], canonicalize a protocol, and default // options. - auto protocol_component = - url_pattern_component::compile( - processed_init->protocol.value(), - url_pattern_helpers::canonicalize_protocol, - url_pattern_compile_component_options::DEFAULT); + auto protocol_component = url_pattern_component::compile( + processed_init->protocol.value(), + url_pattern_helpers::canonicalize_protocol, + url_pattern_compile_component_options::DEFAULT, provider); if (!protocol_component) { ada_log("url_pattern_component::compile failed for protocol ", processed_init->protocol.value()); @@ -1007,11 +1005,10 @@ parse_url_pattern_impl(std::variant input, // Set urlPattern’s username component to the result of compiling a component // given processedInit["username"], canonicalize a username, and default // options. - auto username_component = - url_pattern_component::compile( - processed_init->username.value(), - url_pattern_helpers::canonicalize_username, - url_pattern_compile_component_options::DEFAULT); + auto username_component = url_pattern_component::compile( + processed_init->username.value(), + url_pattern_helpers::canonicalize_username, + url_pattern_compile_component_options::DEFAULT, provider); if (!username_component) { ada_log("url_pattern_component::compile failed for username ", processed_init->username.value()); @@ -1022,11 +1019,10 @@ parse_url_pattern_impl(std::variant input, // Set urlPattern’s password component to the result of compiling a component // given processedInit["password"], canonicalize a password, and default // options. - auto password_component = - url_pattern_component::compile( - processed_init->password.value(), - url_pattern_helpers::canonicalize_password, - url_pattern_compile_component_options::DEFAULT); + auto password_component = url_pattern_component::compile( + processed_init->password.value(), + url_pattern_helpers::canonicalize_password, + url_pattern_compile_component_options::DEFAULT, provider); if (!password_component) { ada_log("url_pattern_component::compile failed for password ", processed_init->password.value()); @@ -1045,11 +1041,10 @@ parse_url_pattern_impl(std::variant input, // then set urlPattern’s hostname component to the result of compiling a // component given processedInit["hostname"], canonicalize an IPv6 hostname, // and hostname options. - auto hostname_component = - url_pattern_component::compile( - processed_init->hostname.value(), - url_pattern_helpers::canonicalize_ipv6_hostname, - url_pattern_compile_component_options::DEFAULT); + auto hostname_component = url_pattern_component::compile( + processed_init->hostname.value(), + url_pattern_helpers::canonicalize_ipv6_hostname, + url_pattern_compile_component_options::DEFAULT, provider); if (!hostname_component) { ada_log("url_pattern_component::compile failed for ipv6 hostname ", processed_init->hostname.value()); @@ -1060,11 +1055,10 @@ parse_url_pattern_impl(std::variant input, // Otherwise, set urlPattern’s hostname component to the result of compiling // a component given processedInit["hostname"], canonicalize a hostname, and // hostname options. - auto hostname_component = - url_pattern_component::compile( - processed_init->hostname.value(), - url_pattern_helpers::canonicalize_hostname, - url_pattern_compile_component_options::HOSTNAME); + auto hostname_component = url_pattern_component::compile( + processed_init->hostname.value(), + url_pattern_helpers::canonicalize_hostname, + url_pattern_compile_component_options::HOSTNAME, provider); if (!hostname_component) { ada_log("url_pattern_component::compile failed for hostname ", processed_init->hostname.value()); @@ -1075,10 +1069,9 @@ parse_url_pattern_impl(std::variant input, // Set urlPattern’s port component to the result of compiling a component // given processedInit["port"], canonicalize a port, and default options. - auto port_component = - url_pattern_component::compile( - processed_init->port.value(), url_pattern_helpers::canonicalize_port, - url_pattern_compile_component_options::DEFAULT); + auto port_component = url_pattern_component::compile( + processed_init->port.value(), url_pattern_helpers::canonicalize_port, + url_pattern_compile_component_options::DEFAULT, provider); if (!port_component) { ada_log("url_pattern_component::compile failed for port ", processed_init->port.value()); @@ -1096,8 +1089,8 @@ parse_url_pattern_impl(std::variant input, // TODO: Optimization opportunity: Simplify this if statement. // If the result of running protocol component matches a special scheme given // urlPattern’s protocol component is true, then: - if (url_pattern_helpers::protocol_component_matches_special_scheme( - url_pattern_.protocol_component)) { + if (url_pattern_helpers::protocol_component_matches_special_scheme< + regex_provider>(url_pattern_.protocol_component)) { // Let pathCompileOptions be copy of the pathname options with the ignore // case property set to options["ignoreCase"]. auto path_compile_options = url_pattern_compile_component_options::PATHNAME; @@ -1108,10 +1101,10 @@ parse_url_pattern_impl(std::variant input, // Set urlPattern’s pathname component to the result of compiling a // component given processedInit["pathname"], canonicalize a pathname, and // pathCompileOptions. - auto pathname_component = - url_pattern_component::compile( - processed_init->pathname.value(), - url_pattern_helpers::canonicalize_pathname, path_compile_options); + auto pathname_component = url_pattern_component::compile( + processed_init->pathname.value(), + url_pattern_helpers::canonicalize_pathname, path_compile_options, + provider); if (!pathname_component) { ada_log("url_pattern_component::compile failed for pathname ", processed_init->pathname.value()); @@ -1122,10 +1115,10 @@ parse_url_pattern_impl(std::variant input, // Otherwise set urlPattern’s pathname component to the result of compiling // a component given processedInit["pathname"], canonicalize an opaque // pathname, and compileOptions. - auto pathname_component = - url_pattern_component::compile( - processed_init->pathname.value(), - url_pattern_helpers::canonicalize_opaque_pathname, compile_options); + auto pathname_component = url_pattern_component::compile( + processed_init->pathname.value(), + url_pattern_helpers::canonicalize_opaque_pathname, compile_options, + provider); if (!pathname_component) { ada_log("url_pattern_component::compile failed for opaque pathname ", processed_init->pathname.value()); @@ -1136,10 +1129,9 @@ parse_url_pattern_impl(std::variant input, // Set urlPattern’s search component to the result of compiling a component // given processedInit["search"], canonicalize a search, and compileOptions. - auto search_component = - url_pattern_component::compile( - processed_init->search.value(), - url_pattern_helpers::canonicalize_search, compile_options); + auto search_component = url_pattern_component::compile( + processed_init->search.value(), url_pattern_helpers::canonicalize_search, + compile_options, provider); if (!search_component) { ada_log("url_pattern_component::compile failed for search ", processed_init->search.value()); @@ -1149,10 +1141,9 @@ parse_url_pattern_impl(std::variant input, // Set urlPattern’s hash component to the result of compiling a component // given processedInit["hash"], canonicalize a hash, and compileOptions. - auto hash_component = - url_pattern_component::compile( - processed_init->hash.value(), url_pattern_helpers::canonicalize_hash, - compile_options); + auto hash_component = url_pattern_component::compile( + processed_init->hash.value(), url_pattern_helpers::canonicalize_hash, + compile_options, provider); if (!hash_component) { ada_log("url_pattern_component::compile failed for hash ", processed_init->hash.value()); diff --git a/src/url_pattern.cpp b/src/url_pattern.cpp index 25ddbb58c..34c26f2ff 100644 --- a/src/url_pattern.cpp +++ b/src/url_pattern.cpp @@ -450,11 +450,10 @@ std::string url_pattern_init::to_string() const { return answer; } -template - requires url_pattern_regex::derived_from_provider +template template -tl::expected, errors> -url_pattern_component::compile( +tl::expected, errors> +url_pattern_component::compile( std::string_view input, F& encoding_callback, url_pattern_compile_component_options& options, const regex_provider& provider) { @@ -485,7 +484,7 @@ url_pattern_component::compile( // Let regular expression be RegExpCreate(regular expression string, // flags). If this throws an exception, catch it, and throw a // TypeError. - auto regular_expression = + std::optional regular_expression = provider.create_instance(regular_expression_string, options.ignore_case); if (!regular_expression) { @@ -502,25 +501,22 @@ url_pattern_component::compile( // Return a new component whose pattern string is pattern string, regular // expression is regular expression, group name list is name list, and has // regexp groups is has regexp groups. - return url_pattern_component( - std::move(pattern_string), std::move(regular_expression), + return url_pattern_component( + std::move(pattern_string), std::move(*regular_expression), std::move(name_list), has_regexp_groups); } -template - requires url_pattern_regex::derived_from_provider -result> -url_pattern::exec(const url_pattern_input& input, - std::string_view* base_url) { +template +result> url_pattern::exec( + const url_pattern_input& input, std::string_view* base_url) { // Return the result of match given this's associated URL pattern, input, and // baseURL if given. return match(input, base_url); } -template - requires url_pattern_regex::derived_from_provider -result url_pattern::test( - const url_pattern_input& input, std::string_view* base_url) { +template +result url_pattern::test(const url_pattern_input& input, + std::string_view* base_url) { // TODO: Optimization opportunity. Rather than returning `url_pattern_result` // Implement a fast path just like `can_parse()` in ada_url. // Let result be the result of match given this's associated URL pattern, @@ -532,10 +528,8 @@ result url_pattern::test( return tl::unexpected(errors::type_error); } -template - requires url_pattern_regex::derived_from_provider -result> -url_pattern::match( +template +result> url_pattern::match( const url_pattern_input& input, std::string_view* base_url_string) { std::string protocol{}; std::string username{}; diff --git a/src/url_pattern_helpers.cpp b/src/url_pattern_helpers.cpp index 37dac8938..d025ac98f 100644 --- a/src/url_pattern_helpers.cpp +++ b/src/url_pattern_helpers.cpp @@ -189,10 +189,9 @@ std::string generate_segment_wildcard_regexp( ada_log("generate_segment_wildcard_regexp result: ", result); return result; } -template - requires url_pattern_regex::derived_from_provider +template bool protocol_component_matches_special_scheme( - url_pattern_component& component) { + url_pattern_component& component) { auto regex = component.regexp; // TODO: Use provider.regex_match return std::regex_match("http", regex) || std::regex_match("https", regex) || @@ -200,11 +199,9 @@ bool protocol_component_matches_special_scheme( std::regex_match("ftp", regex); } -template - requires url_pattern_regex::derived_from_provider -inline std::optional constructor_string_parser< - regex_provider, - regex_type>::compute_protocol_matches_special_scheme_flag() { +template +inline std::optional constructor_string_parser:: + compute_protocol_matches_special_scheme_flag(regex_provider provider) { ada_log( "constructor_string_parser::compute_protocol_matches_special_scheme_" "flag"); @@ -213,10 +210,9 @@ inline std::optional constructor_string_parser< auto protocol_string = make_component_string(); // Let protocol component be the result of compiling a component given // protocol string, canonicalize a protocol, and default options. - auto protocol_component = - url_pattern_component::compile( - protocol_string, canonicalize_protocol, - url_pattern_compile_component_options::DEFAULT); + auto protocol_component = url_pattern_component::compile( + protocol_string, canonicalize_protocol, + url_pattern_compile_component_options::DEFAULT, provider); if (!protocol_component) { ada_log("url_pattern_component::compile failed for protocol_string ", protocol_string); @@ -476,11 +472,10 @@ tl::expected canonicalize_hash(std::string_view input) { return tl::unexpected(errors::type_error); } -template - requires url_pattern_regex::derived_from_provider +template tl::expected -constructor_string_parser::parse( - std::string_view input) { +constructor_string_parser::parse(std::string_view input, + regex_provider provider) { ada_log("constructor_string_parser::parse input=", input); // Let parser be a new constructor string parser whose input is input and // token list is the result of running tokenize given input and "lenient". @@ -573,8 +568,8 @@ constructor_string_parser::parse( if (parser.is_protocol_suffix()) { // Run compute protocol matches a special scheme flag given parser. if (const auto error = - parser.template compute_protocol_matches_special_scheme_flag< - regex_type>()) { + parser.compute_protocol_matches_special_scheme_flag( + provider)) { ada_log("compute_protocol_matches_special_scheme_flag failed"); return tl::unexpected(*error); } diff --git a/tests/wpt_urlpattern_tests.cpp b/tests/wpt_urlpattern_tests.cpp index ffa19e950..231dba595 100644 --- a/tests/wpt_urlpattern_tests.cpp +++ b/tests/wpt_urlpattern_tests.cpp @@ -30,19 +30,19 @@ TEST(wpt_urlpattern_tests, parse_pattern_string_basic_tests) { TEST(wpt_urlpattern_tests, compile_basic_tests) { auto provider = ada::url_pattern_regex::std_regex_provider(); - auto protocol_component = ada::url_pattern_component< - ada::url_pattern_regex::std_regex_provider, - std::regex>::compile("*", ada::url_pattern_helpers::canonicalize_protocol, - ada::url_pattern_compile_component_options::DEFAULT, - provider); + auto protocol_component = + ada::url_pattern_component:: + compile("*", ada::url_pattern_helpers::canonicalize_protocol, + ada::url_pattern_compile_component_options::DEFAULT, + provider); ASSERT_TRUE(protocol_component); } TEST(wpt_urlpattern_tests, basic_tests) { auto init = ada::url_pattern_init{}; init.pathname = "/books"; - auto url = ada::parse_url_pattern(init); + auto url = + ada::parse_url_pattern(init); ASSERT_TRUE(url); ASSERT_EQ(url->get_protocol(), "*"); ASSERT_EQ(url->get_hostname(), "*"); @@ -59,8 +59,8 @@ TEST(wpt_urlpattern_tests, basic_tests) { // Tests are taken from WPT // https://github.com/web-platform-tests/wpt/blob/0c1d19546fd4873bb9f4147f0bbf868e7b4f91b7/urlpattern/resources/urlpattern-hasregexpgroups-tests.js TEST(wpt_urlpattern_tests, has_regexp_groups) { - auto create_init = [](std::string_view component, std::string value) - -> ada::url_pattern_init { + auto create_init = [](std::string_view component, + std::string value) -> ada::url_pattern_init { if (component == "protocol") return {.protocol = value}; if (component == "username") return {.username = value}; if (component == "password") return {.password = value}; @@ -228,7 +228,9 @@ parse_pattern_field(ondemand::array& patterns) { return std::tuple(*init_str, base_url, options); } -tl::expected, ada::errors> parse_pattern( +tl::expected, + ada::errors> +parse_pattern( std::variant& init_variant, std::optional& base_url, std::optional& options) {