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

reduce string allocations in urlpattern #881

Merged
merged 1 commit into from
Feb 15, 2025
Merged
Show file tree
Hide file tree
Changes from all 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
4 changes: 2 additions & 2 deletions include/ada/parser-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ tl::expected<url_pattern<regex_provider>, errors> parse_url_pattern_impl(

// Let processedInit be the result of process a URLPatternInit given init,
// "pattern", null, null, null, null, null, null, null, and null.
// TODO: Make "pattern" an enum to avoid creating a string everytime.
auto processed_init = url_pattern_init::process(init, "pattern");
auto processed_init =
url_pattern_init::process(init, url_pattern_init::process_type::pattern);
if (!processed_init) {
ada_log("url_pattern_init::process failed for init and 'pattern'");
return tl::unexpected(processed_init.error());
Expand Down
4 changes: 2 additions & 2 deletions include/ada/url_pattern-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -244,8 +244,8 @@ result<std::optional<url_pattern_result>> url_pattern<regex_provider>::match(
// "url", protocol, username, password, hostname, port, pathname, search,
// and hash.
auto apply_result = url_pattern_init::process(
std::get<url_pattern_init>(input), "url", protocol, username, password,
hostname, port, pathname, search, hash);
std::get<url_pattern_init>(input), url_pattern_init::process_type::url,
protocol, username, password, hostname, port, pathname, search, hash);

// If this throws an exception, catch it, and return null.
if (!apply_result.has_value()) {
Expand Down
6 changes: 3 additions & 3 deletions include/ada/url_pattern_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ tl::expected<std::vector<token>, errors> tokenize(std::string_view input,

// @see https://urlpattern.spec.whatwg.org/#process-a-base-url-string
std::string process_base_url_string(std::string_view input,
std::string_view type);
url_pattern_init::process_type type);

// @see https://urlpattern.spec.whatwg.org/#escape-a-pattern-string
std::string escape_pattern_string(std::string_view input);
Expand All @@ -304,8 +304,8 @@ std::string escape_pattern_string(std::string_view input);
std::string escape_regexp_string(std::string_view input);

// @see https://urlpattern.spec.whatwg.org/#is-an-absolute-pathname
constexpr bool is_absolute_pathname(std::string_view input,
std::string_view type) noexcept;
constexpr bool is_absolute_pathname(
std::string_view input, url_pattern_init::process_type type) noexcept;

// @see https://urlpattern.spec.whatwg.org/#parse-a-pattern-string
template <url_pattern_encoding_callback F>
Expand Down
23 changes: 14 additions & 9 deletions include/ada/url_pattern_init.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,15 @@ concept url_pattern_encoding_callback = requires(F f, std::string_view sv) {
// API is defined as part of the URLPattern specification.
// All provided strings must be valid UTF-8.
struct url_pattern_init {
enum class process_type : uint8_t {
url,
pattern,
};

// All strings must be valid UTF-8.
// @see https://urlpattern.spec.whatwg.org/#process-a-urlpatterninit
static tl::expected<url_pattern_init, errors> process(
url_pattern_init init, std::string_view type,
url_pattern_init init, process_type type,
std::optional<std::string_view> protocol = std::nullopt,
std::optional<std::string_view> username = std::nullopt,
std::optional<std::string_view> password = std::nullopt,
Expand All @@ -49,35 +54,35 @@ struct url_pattern_init {

// @see https://urlpattern.spec.whatwg.org/#process-protocol-for-init
static tl::expected<std::string, errors> process_protocol(
std::string_view value, std::string_view type);
std::string_view value, process_type type);

// @see https://urlpattern.spec.whatwg.org/#process-username-for-init
static tl::expected<std::string, errors> process_username(
std::string_view value, std::string_view type);
std::string_view value, process_type type);

// @see https://urlpattern.spec.whatwg.org/#process-password-for-init
static tl::expected<std::string, errors> process_password(
std::string_view value, std::string_view type);
std::string_view value, process_type type);

// @see https://urlpattern.spec.whatwg.org/#process-hostname-for-init
static tl::expected<std::string, errors> process_hostname(
std::string_view value, std::string_view type);
std::string_view value, process_type type);

// @see https://urlpattern.spec.whatwg.org/#process-port-for-init
static tl::expected<std::string, errors> process_port(
std::string_view port, std::string_view protocol, std::string_view type);
std::string_view port, std::string_view protocol, process_type type);

// @see https://urlpattern.spec.whatwg.org/#process-pathname-for-init
static tl::expected<std::string, errors> process_pathname(
std::string_view value, std::string_view protocol, std::string_view type);
std::string_view value, std::string_view protocol, process_type type);

// @see https://urlpattern.spec.whatwg.org/#process-search-for-init
static tl::expected<std::string, errors> process_search(
std::string_view value, std::string_view type);
std::string_view value, process_type type);

// @see https://urlpattern.spec.whatwg.org/#process-hash-for-init
static tl::expected<std::string, errors> process_hash(std::string_view value,
std::string_view type);
process_type type);

#if ADA_TESTING
friend void PrintTo(const url_pattern_init& init, std::ostream* os) {
Expand Down
42 changes: 21 additions & 21 deletions src/url_pattern.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
namespace ada {

tl::expected<url_pattern_init, errors> url_pattern_init::process(
url_pattern_init init, std::string_view type,
url_pattern_init init, url_pattern_init::process_type type,
std::optional<std::string_view> protocol,
std::optional<std::string_view> username,
std::optional<std::string_view> password,
Expand Down Expand Up @@ -69,8 +69,8 @@ tl::expected<url_pattern_init, errors> url_pattern_init::process(
// If type is not "pattern" and init contains none of "protocol",
// "hostname", "port" and "username", then set result["username"] to the
// result of processing a base URL string given baseURL’s username and type.
if (type != "pattern" && !init.protocol && !init.hostname && !init.port &&
!init.username) {
if (type != process_type::pattern && !init.protocol && !init.hostname &&
!init.port && !init.username) {
result.username = url_pattern_helpers::process_base_url_string(
base_url->get_username(), type);
}
Expand All @@ -80,8 +80,8 @@ tl::expected<url_pattern_init, errors> url_pattern_init::process(
// "hostname", "port", "username" and "password", then set
// result["password"] to the result of processing a base URL string given
// baseURL’s password and type.
if (type != "pattern" && !init.protocol && !init.hostname && !init.port &&
!init.username && !init.password) {
if (type != process_type::pattern && !init.protocol && !init.hostname &&
!init.port && !init.username && !init.password) {
result.password = url_pattern_helpers::process_base_url_string(
base_url->get_password(), type);
}
Expand Down Expand Up @@ -255,56 +255,56 @@ tl::expected<url_pattern_init, errors> url_pattern_init::process(
}

tl::expected<std::string, errors> url_pattern_init::process_protocol(
std::string_view value, std::string_view type) {
std::string_view value, process_type type) {
ada_log("process_protocol=", value, " [", type, "]");
// Let strippedValue be the given value with a single trailing U+003A (:)
// removed, if any.
if (value.ends_with(":")) {
value.remove_suffix(1);
}
// If type is "pattern" then return strippedValue.
if (type == "pattern") {
if (type == process_type::pattern) {
return std::string(value);
}
// Return the result of running canonicalize a protocol given strippedValue.
return url_pattern_helpers::canonicalize_protocol(value);
}

tl::expected<std::string, errors> url_pattern_init::process_username(
std::string_view value, std::string_view type) {
std::string_view value, process_type type) {
// If type is "pattern" then return value.
if (type == "pattern") {
if (type == process_type::pattern) {
return std::string(value);
}
// Return the result of running canonicalize a username given value.
return url_pattern_helpers::canonicalize_username(value);
}

tl::expected<std::string, errors> url_pattern_init::process_password(
std::string_view value, std::string_view type) {
std::string_view value, process_type type) {
// If type is "pattern" then return value.
if (type == "pattern") {
if (type == process_type::pattern) {
return std::string(value);
}
// Return the result of running canonicalize a password given value.
return url_pattern_helpers::canonicalize_password(value);
}

tl::expected<std::string, errors> url_pattern_init::process_hostname(
std::string_view value, std::string_view type) {
std::string_view value, process_type type) {
ada_log("process_hostname value=", value, " type=", type);
// If type is "pattern" then return value.
if (type == "pattern") {
if (type == process_type::pattern) {
return std::string(value);
}
// Return the result of running canonicalize a hostname given value.
return url_pattern_helpers::canonicalize_hostname(value);
}

tl::expected<std::string, errors> url_pattern_init::process_port(
std::string_view port, std::string_view protocol, std::string_view type) {
std::string_view port, std::string_view protocol, process_type type) {
// If type is "pattern" then return portValue.
if (type == "pattern") {
if (type == process_type::pattern) {
return std::string(port);
}
// Return the result of running canonicalize a port given portValue and
Expand All @@ -313,9 +313,9 @@ tl::expected<std::string, errors> url_pattern_init::process_port(
}

tl::expected<std::string, errors> url_pattern_init::process_pathname(
std::string_view value, std::string_view protocol, std::string_view type) {
std::string_view value, std::string_view protocol, process_type type) {
// If type is "pattern" then return pathnameValue.
if (type == "pattern") {
if (type == process_type::pattern) {
return std::string(value);
}

Expand All @@ -331,31 +331,31 @@ tl::expected<std::string, errors> url_pattern_init::process_pathname(
}

tl::expected<std::string, errors> url_pattern_init::process_search(
std::string_view value, std::string_view type) {
std::string_view value, process_type type) {
// Let strippedValue be the given value with a single leading U+003F (?)
// removed, if any.
if (value.starts_with("?")) {
value.remove_prefix(1);
}
ADA_ASSERT_TRUE(!value.starts_with("?"));
// If type is "pattern" then return strippedValue.
if (type == "pattern") {
if (type == process_type::pattern) {
return std::string(value);
}
// Return the result of running canonicalize a search given strippedValue.
return url_pattern_helpers::canonicalize_search(value);
}

tl::expected<std::string, errors> url_pattern_init::process_hash(
std::string_view value, std::string_view type) {
std::string_view value, process_type type) {
// Let strippedValue be the given value with a single leading U+0023 (#)
// removed, if any.
if (value.starts_with("#")) {
value.remove_prefix(1);
}
ADA_ASSERT_TRUE(!value.starts_with("#"));
// If type is "pattern" then return strippedValue.
if (type == "pattern") {
if (type == process_type::pattern) {
return std::string(value);
}
// Return the result of running canonicalize a hash given strippedValue.
Expand Down
12 changes: 6 additions & 6 deletions src/url_pattern_helpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -803,25 +803,25 @@ std::string escape_regexp_string(std::string_view input) {
}

std::string process_base_url_string(std::string_view input,
std::string_view type) {
url_pattern_init::process_type type) {
// If type is not "pattern" return input.
if (type != "pattern") {
if (type != url_pattern_init::process_type::pattern) {
return std::string(input);
}
// Return the result of escaping a pattern string given input.
return escape_pattern_string(input);
}

constexpr bool is_absolute_pathname(std::string_view input,
std::string_view type) noexcept {
constexpr bool is_absolute_pathname(
std::string_view input, url_pattern_init::process_type type) noexcept {
// If input is the empty string, then return false.
if (input.empty()) [[unlikely]] {
return false;
}
// If input[0] is U+002F (/), then return true.
if (input.starts_with("/")) return true;
// If type is "url", then return false.
if (type == "url") return false;
if (type == url_pattern_init::process_type::url) return false;
// If input’s code point length is less than 2, then return false.
if (input.size() < 2) return false;
// If input[0] is U+005C (\) and input[1] is U+002F (/), then return true.
Expand Down Expand Up @@ -1014,4 +1014,4 @@ std::string generate_pattern_string(
// Return result.
return result;
}
} // namespace ada::url_pattern_helpers
} // namespace ada::url_pattern_helpers
Loading