Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perf: improve ada::can_parse #674

Merged
merged 8 commits into from
Jun 18, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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>(
anonrig marked this conversation as resolved.
Show resolved Hide resolved
*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
72 changes: 45 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,
anonrig marked this conversation as resolved.
Show resolved Hide resolved
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,24 @@ 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 constexpr (store_values) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this if statement seems like a duplicate. there is already an if statement that checks for store values couple of lines ahove

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True, updated!

if (fragment.has_value()) {
url.update_unencoded_base_hash(*fragment);
}
}
}
return url;
}
Expand Down Expand Up @@ -702,11 +708,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 +914,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
Loading