diff --git a/include/ada/parser.h b/include/ada/parser.h index c539867e3..5bb148c89 100644 --- a/include/ada/parser.h +++ b/include/ada/parser.h @@ -5,13 +5,13 @@ #ifndef ADA_PARSER_H #define ADA_PARSER_H -#include "ada/state.h" -#include "ada/encoding_type.h" -#include "ada/expected.h" - #include #include +#include "ada/encoding_type.h" +#include "ada/expected.h" +#include "ada/state.h" + /** * @private */ @@ -25,7 +25,6 @@ struct url; * @brief Includes the definitions for supported parsers */ namespace ada::parser { - /** * Parses a url. The parameter user_input is the input to be parsed: * it should be a valid UTF-8 string. The parameter base_url is an optional @@ -41,6 +40,14 @@ extern template url_aggregator parse_url( extern template url parse_url(std::string_view user_input, const url* base_url); +template +result_type parse_url_impl(std::string_view user_input, + const result_type* base_url = nullptr); + +extern template url_aggregator parse_url_impl( + std::string_view user_input, const url_aggregator* base_url); +extern template url parse_url_impl(std::string_view user_input, + const url* base_url); } // namespace ada::parser #endif // ADA_PARSER_H diff --git a/include/ada/url.h b/include/ada/url.h index c30fca242..1418d9bb7 100644 --- a/include/ada/url.h +++ b/include/ada/url.h @@ -5,6 +5,13 @@ #ifndef ADA_URL_H #define ADA_URL_H +#include +#include +#include +#include +#include +#include + #include "ada/checkers.h" #include "ada/common_defs.h" #include "ada/log.h" @@ -14,13 +21,6 @@ #include "ada/url_base.h" #include "ada/url_components.h" -#include -#include -#include -#include -#include -#include - namespace ada { /** @@ -295,6 +295,11 @@ struct url : url_base { friend void ada::helpers::strip_trailing_spaces_from_opaque_path( ada::url &url) noexcept; + friend ada::url ada::parser::parse_url_impl(std::string_view, + const ada::url *); + friend ada::url_aggregator ada::parser::parse_url_impl< + ada::url_aggregator, true>(std::string_view, const ada::url_aggregator *); + inline void update_unencoded_base_hash(std::string_view input); inline void update_base_hostname(std::string_view input); inline void update_base_search(std::string_view input); diff --git a/include/ada/url_aggregator.h b/include/ada/url_aggregator.h index 2c269a3c3..b24c2db75 100644 --- a/include/ada/url_aggregator.h +++ b/include/ada/url_aggregator.h @@ -5,13 +5,13 @@ #ifndef ADA_URL_AGGREGATOR_H #define ADA_URL_AGGREGATOR_H +#include +#include + #include "ada/common_defs.h" #include "ada/url_base.h" #include "ada/url_components.h" -#include -#include - namespace ada { /** @@ -205,6 +205,11 @@ struct url_aggregator : url_base { std::string_view, const ada::url_aggregator *); friend void ada::helpers::strip_trailing_spaces_from_opaque_path< ada::url_aggregator>(ada::url_aggregator &url) noexcept; + friend ada::url_aggregator ada::parser::parse_url_impl< + ada::url_aggregator, true>(std::string_view, const ada::url_aggregator *); + friend ada::url_aggregator + ada::parser::parse_url_impl( + std::string_view, const ada::url_aggregator *); std::string buffer{}; url_components components{}; diff --git a/src/checkers.cpp b/src/checkers.cpp index 01176e9fe..46d43f618 100644 --- a/src/checkers.cpp +++ b/src/checkers.cpp @@ -1,4 +1,5 @@ #include "ada/checkers.h" + #include namespace ada::checkers { diff --git a/src/implementation.cpp b/src/implementation.cpp index e5ad039cd..fef682e51 100644 --- a/src/implementation.cpp +++ b/src/implementation.cpp @@ -11,7 +11,8 @@ namespace ada { template ada_warn_unused tl::expected parse( std::string_view input, const result_type* base_url) { - result_type u = ada::parser::parse_url(input, base_url); + result_type u = + ada::parser::parse_url_impl(input, base_url); if (!u.is_valid) { return tl::unexpected(errors::generic_error); } @@ -47,16 +48,22 @@ std::string href_from_file(std::string_view input) { } bool can_parse(std::string_view input, const std::string_view* base_input) { - ada::result base; + ada::url_aggregator base_aggregator; ada::url_aggregator* base_pointer = nullptr; + if (base_input != nullptr) { - base = ada::parse(*base_input); - if (!base) { + base_aggregator = ada::parser::parse_url_impl( + *base_input, nullptr); + if (!base_aggregator.is_valid) { return false; } - base_pointer = &base.value(); + base_pointer = &base_aggregator; } - return ada::parse(input, base_pointer).has_value(); + + ada::url_aggregator result = + ada::parser::parse_url_impl(input, + base_pointer); + return result.is_valid; } ada_warn_unused std::string to_string(ada::encoding_type type) { diff --git a/src/parser.cpp b/src/parser.cpp index a3a6b3586..15c5cd2b3 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -1,18 +1,19 @@ +#include "ada/parser.h" + +#include + #include "ada.h" -#include "ada/common_defs.h" #include "ada/character_sets-inl.h" +#include "ada/common_defs.h" +#include "ada/log.h" #include "ada/unicode.h" #include "ada/url-inl.h" -#include "ada/log.h" -#include "ada/parser.h" - -#include namespace ada::parser { -template -result_type parse_url(std::string_view user_input, - const result_type* base_url) { +template +result_type parse_url_impl(std::string_view user_input, + const result_type* base_url) { // We can specialize the implementation per type. // Important: result_type_is_ada_url is evaluated at *compile time*. This // means that doing if constexpr(result_type_is_ada_url) { something } else { @@ -539,19 +540,22 @@ result_type parse_url(std::string_view user_input, } case ada::state::QUERY: { ada_log("QUERY ", helpers::substring(url_data, input_position)); - // Let queryPercentEncodeSet be the special-query percent-encode set if - // url is special; otherwise the query percent-encode set. - const uint8_t* query_percent_encode_set = - url.is_special() ? ada::character_sets::SPECIAL_QUERY_PERCENT_ENCODE - : ada::character_sets::QUERY_PERCENT_ENCODE; - - // Percent-encode after encoding, with encoding, buffer, and - // queryPercentEncodeSet, and append the result to url's query. - url.update_base_search(helpers::substring(url_data, input_position), - query_percent_encode_set); - ada_log("QUERY update_base_search completed "); - if (fragment.has_value()) { - url.update_unencoded_base_hash(*fragment); + if constexpr (store_values) { + // Let queryPercentEncodeSet be the special-query percent-encode set + // if url is special; otherwise the query percent-encode set. + const uint8_t* query_percent_encode_set = + url.is_special() + ? ada::character_sets::SPECIAL_QUERY_PERCENT_ENCODE + : ada::character_sets::QUERY_PERCENT_ENCODE; + + // Percent-encode after encoding, with encoding, buffer, and + // queryPercentEncodeSet, and append the result to url's query. + url.update_base_search(helpers::substring(url_data, input_position), + query_percent_encode_set); + ada_log("QUERY update_base_search completed "); + if (fragment.has_value()) { + url.update_unencoded_base_hash(*fragment); + } } return url; } @@ -702,11 +706,13 @@ result_type parse_url(std::string_view user_input, } else { input_position = input_size + 1; } - if constexpr (result_type_is_ada_url) { - helpers::parse_prepared_path(view, url.type, url.path); - } else { - url.consume_prepared_path(view); - ADA_ASSERT_TRUE(url.validate()); + if constexpr (store_values) { + if constexpr (result_type_is_ada_url) { + helpers::parse_prepared_path(view, url.type, url.path); + } else { + url.consume_prepared_path(view); + ADA_ASSERT_TRUE(url.validate()); + } } break; } @@ -906,9 +912,19 @@ result_type parse_url(std::string_view user_input, return url; } +template url parse_url_impl(std::string_view user_input, + const url* base_url = nullptr); +template url_aggregator parse_url_impl( + std::string_view user_input, const url_aggregator* base_url = nullptr); + +template +result_type parse_url(std::string_view user_input, + const result_type* base_url) { + return parse_url_impl(user_input, base_url); +} + template url parse_url(std::string_view user_input, const url* base_url = nullptr); template url_aggregator parse_url( std::string_view user_input, const url_aggregator* base_url = nullptr); - } // namespace ada::parser