Skip to content

Commit

Permalink
perf: improve ada::can_parse (#674)
Browse files Browse the repository at this point in the history
* create copy of parse function, but commenting possible unnecessary code for a can_parse verification

* comment unused variable

* run linter

* Refactor and create parse_url_impl with store_values parameter

* format files

* use constexpr

* remove duplicated if statement
  • Loading branch information
CarlosEduR committed Jun 18, 2024
1 parent 9cd08da commit 46ece6b
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 48 deletions.
17 changes: 12 additions & 5 deletions include/ada/parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 <optional>
#include <string_view>

#include "ada/encoding_type.h"
#include "ada/expected.h"
#include "ada/state.h"

/**
* @private
*/
Expand All @@ -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
Expand All @@ -41,6 +40,14 @@ extern template url_aggregator parse_url<url_aggregator>(
extern template url parse_url<url>(std::string_view user_input,
const url* base_url);

template <typename result_type = ada::url_aggregator, bool store_values = true>
result_type parse_url_impl(std::string_view user_input,
const result_type* base_url = nullptr);

extern template url_aggregator parse_url_impl<url_aggregator>(
std::string_view user_input, const url_aggregator* base_url);
extern template url parse_url_impl<url>(std::string_view user_input,
const url* base_url);
} // namespace ada::parser

#endif // ADA_PARSER_H
19 changes: 12 additions & 7 deletions include/ada/url.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@
#ifndef ADA_URL_H
#define ADA_URL_H

#include <algorithm>
#include <charconv>
#include <iostream>
#include <optional>
#include <string>
#include <string_view>

#include "ada/checkers.h"
#include "ada/common_defs.h"
#include "ada/log.h"
Expand All @@ -14,13 +21,6 @@
#include "ada/url_base.h"
#include "ada/url_components.h"

#include <algorithm>
#include <charconv>
#include <iostream>
#include <optional>
#include <string>
#include <string_view>

namespace ada {

/**
Expand Down Expand Up @@ -295,6 +295,11 @@ struct url : url_base {
friend void ada::helpers::strip_trailing_spaces_from_opaque_path<ada::url>(
ada::url &url) noexcept;

friend ada::url ada::parser::parse_url_impl<ada::url, true>(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);
Expand Down
11 changes: 8 additions & 3 deletions include/ada/url_aggregator.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
#ifndef ADA_URL_AGGREGATOR_H
#define ADA_URL_AGGREGATOR_H

#include <string>
#include <string_view>

#include "ada/common_defs.h"
#include "ada/url_base.h"
#include "ada/url_components.h"

#include <string>
#include <string_view>

namespace ada {

/**
Expand Down Expand Up @@ -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<ada::url_aggregator, false>(
std::string_view, const ada::url_aggregator *);

std::string buffer{};
url_components components{};
Expand Down
1 change: 1 addition & 0 deletions src/checkers.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "ada/checkers.h"

#include <algorithm>

namespace ada::checkers {
Expand Down
19 changes: 13 additions & 6 deletions src/implementation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ namespace ada {
template <class result_type>
ada_warn_unused tl::expected<result_type, ada::errors> parse(
std::string_view input, const result_type* base_url) {
result_type u = ada::parser::parse_url<result_type>(input, base_url);
result_type u =
ada::parser::parse_url_impl<result_type, true>(input, base_url);
if (!u.is_valid) {
return tl::unexpected(errors::generic_error);
}
Expand Down Expand Up @@ -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<ada::url_aggregator> base;
ada::url_aggregator base_aggregator;
ada::url_aggregator* base_pointer = nullptr;

if (base_input != nullptr) {
base = ada::parse<url_aggregator>(*base_input);
if (!base) {
base_aggregator = ada::parser::parse_url_impl<ada::url_aggregator, false>(
*base_input, nullptr);
if (!base_aggregator.is_valid) {
return false;
}
base_pointer = &base.value();
base_pointer = &base_aggregator;
}
return ada::parse<url_aggregator>(input, base_pointer).has_value();

ada::url_aggregator result =
ada::parser::parse_url_impl<ada::url_aggregator, false>(input,
base_pointer);
return result.is_valid;
}

ada_warn_unused std::string to_string(ada::encoding_type type) {
Expand Down
70 changes: 43 additions & 27 deletions src/parser.cpp
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
#include "ada/parser.h"

#include <limits>

#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 <limits>

namespace ada::parser {

template <class result_type>
result_type parse_url(std::string_view user_input,
const result_type* base_url) {
template <class result_type, bool store_values>
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 {
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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 <class result_type>
result_type parse_url(std::string_view user_input,
const result_type* base_url) {
return parse_url_impl<result_type, true>(user_input, base_url);
}

template url parse_url<url>(std::string_view user_input,
const url* base_url = nullptr);
template url_aggregator parse_url<url_aggregator>(
std::string_view user_input, const url_aggregator* base_url = nullptr);

} // namespace ada::parser

0 comments on commit 46ece6b

Please sign in to comment.