From 104b58feb18e1f9aff9aa1a5351ac57665e831f5 Mon Sep 17 00:00:00 2001 From: "Node.js GitHub Bot" Date: Tue, 25 Jul 2023 20:33:01 +0100 Subject: [PATCH] deps: update ada to 2.6.0 PR-URL: https://github.com/nodejs/node/pull/48896 Reviewed-By: Yagiz Nizipli Reviewed-By: Antoine du Hamel Reviewed-By: Luigi Pinca Reviewed-By: Jiawen Geng --- deps/ada/LICENSE-MIT | 2 +- deps/ada/ada.cpp | 219 ++++++++++++----------- deps/ada/ada.h | 405 ++++++++++++++++++++++++++++++++++++++----- deps/ada/ada_c.h | 4 + 4 files changed, 482 insertions(+), 148 deletions(-) diff --git a/deps/ada/LICENSE-MIT b/deps/ada/LICENSE-MIT index 9f3e50e0db7856..bd2abacfc1dd51 100644 --- a/deps/ada/LICENSE-MIT +++ b/deps/ada/LICENSE-MIT @@ -1,4 +1,4 @@ -Copyright 2023 Ada authors +Copyright 2023 Yagiz Nizipli and Daniel Lemire Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in diff --git a/deps/ada/ada.cpp b/deps/ada/ada.cpp index 855d5b9360392d..ce4e6302acbe87 100644 --- a/deps/ada/ada.cpp +++ b/deps/ada/ada.cpp @@ -1,4 +1,4 @@ -/* auto-generated on 2023-06-03 12:40:57 -0400. Do not edit! */ +/* auto-generated on 2023-07-23 15:03:22 -0400. Do not edit! */ /* begin file src/ada.cpp */ #include "ada.h" /* begin file src/checkers.cpp */ @@ -2829,8 +2829,6 @@ std::u32string map(std::u32string_view input) { break; case 2: return error; // disallowed - break; - // case 3 : default: // We have a mapping @@ -7750,7 +7748,7 @@ const char32_t composition_data[1883] = { namespace ada::idna { // See -// https://github.composition_count/uni-algo/uni-algo/blob/c612968c5ed3ace39bde4c894c24286c5f2c7fe2/include/uni_algo/impl/impl_norm.h#L467 +// https://github.com/uni-algo/uni-algo/blob/c612968c5ed3ace39bde4c894c24286c5f2c7fe2/include/uni_algo/impl/impl_norm.h#L467 constexpr char32_t hangul_sbase = 0xAC00; constexpr char32_t hangul_tbase = 0x11A7; constexpr char32_t hangul_vbase = 0x1161; @@ -9794,10 +9792,11 @@ ADA_POP_DISABLE_WARNINGS namespace ada::unicode { +constexpr uint64_t broadcast(uint8_t v) noexcept { + return 0x101010101010101ull * v; +} + constexpr bool to_lower_ascii(char* input, size_t length) noexcept { - auto broadcast = [](uint8_t v) -> uint64_t { - return 0x101010101010101ull * v; - }; uint64_t broadcast_80 = broadcast(0x80); uint64_t broadcast_Ap = broadcast(128 - 'A'); uint64_t broadcast_Zp = broadcast(128 - 'Z' - 1); @@ -9862,9 +9861,9 @@ ada_really_inline bool has_tabs_or_newline( _mm_cmpeq_epi8(word, mask3)); } if (i < user_input.size()) { - uint8_t buffer[16]{}; + alignas(16) uint8_t buffer[16]{}; memcpy(buffer, user_input.data() + i, user_input.size() - i); - __m128i word = _mm_loadu_si128((const __m128i*)buffer); + __m128i word = _mm_load_si128((const __m128i*)buffer); running = _mm_or_si128( _mm_or_si128(running, _mm_or_si128(_mm_cmpeq_epi8(word, mask1), _mm_cmpeq_epi8(word, mask2))), @@ -9878,9 +9877,6 @@ ada_really_inline bool has_tabs_or_newline( auto has_zero_byte = [](uint64_t v) { return ((v - 0x0101010101010101) & ~(v)&0x8080808080808080); }; - auto broadcast = [](uint8_t v) -> uint64_t { - return 0x101010101010101ull * v; - }; size_t i = 0; uint64_t mask1 = broadcast('\r'); uint64_t mask2 = broadcast('\n'); @@ -10542,8 +10538,8 @@ ada_really_inline bool shorten_path(std::string& path, ada::scheme::type type) noexcept { size_t first_delimiter = path.find_first_of('/', 1); - // Let path be url’s path. - // If url’s scheme is "file", path’s size is 1, and path[0] is a normalized + // Let path be url's path. + // If url's scheme is "file", path's size is 1, and path[0] is a normalized // Windows drive letter, then return. if (type == ada::scheme::type::FILE && first_delimiter == std::string_view::npos && !path.empty()) { @@ -10553,7 +10549,7 @@ ada_really_inline bool shorten_path(std::string& path, } } - // Remove path’s last item, if any. + // Remove path's last item, if any. size_t last_delimiter = path.rfind('/'); if (last_delimiter != std::string::npos) { path.erase(last_delimiter); @@ -10567,8 +10563,8 @@ ada_really_inline bool shorten_path(std::string_view& path, ada::scheme::type type) noexcept { size_t first_delimiter = path.find_first_of('/', 1); - // Let path be url’s path. - // If url’s scheme is "file", path’s size is 1, and path[0] is a normalized + // Let path be url's path. + // If url's scheme is "file", path's size is 1, and path[0] is a normalized // Windows drive letter, then return. if (type == ada::scheme::type::FILE && first_delimiter == std::string_view::npos && !path.empty()) { @@ -10578,7 +10574,7 @@ ada_really_inline bool shorten_path(std::string_view& path, } } - // Remove path’s last item, if any. + // Remove path's last item, if any. if (!path.empty()) { size_t slash_loc = path.rfind('/'); if (slash_loc != std::string_view::npos) { @@ -10991,7 +10987,7 @@ ada_really_inline void parse_prepared_path(std::string_view input, } // Otherwise, if path_buffer is not a single-dot path segment, then: else if (!unicode::is_single_dot_path_segment(path_buffer)) { - // If url’s scheme is "file", url’s path is empty, and path_buffer is a + // If url's scheme is "file", url's path is empty, and path_buffer is a // Windows drive letter, then replace the second code point in // path_buffer with U+003A (:). if (type == ada::scheme::type::FILE && path.empty() && @@ -11002,7 +10998,7 @@ ada_really_inline void parse_prepared_path(std::string_view input, path_buffer.remove_prefix(2); path.append(path_buffer); } else { - // Append path_buffer to url’s path. + // Append path_buffer to url's path. path += '/'; path.append(path_buffer); } @@ -11299,7 +11295,7 @@ bool url::parse_ipv6(std::string_view input) { uint16_t value = 0, length = 0; // While length is less than 4 and c is an ASCII hex digit, - // set value to value × 0x10 + c interpreted as hexadecimal number, and + // set value to value times 0x10 + c interpreted as hexadecimal number, and // increase pointer and length by 1. while (length < 4 && pointer != input.end() && unicode::is_ascii_hex_digit(*pointer)) { @@ -11370,7 +11366,7 @@ bool url::parse_ipv6(std::string_view input) { ada_log("parse_ipv6 if ipv4Piece is 0, validation error"); return is_valid = false; } - // Otherwise, set ipv4Piece to ipv4Piece × 10 + number. + // Otherwise, set ipv4Piece to ipv4Piece times 10 + number. else { ipv4_piece = *ipv4_piece * 10 + number; } @@ -11385,7 +11381,8 @@ bool url::parse_ipv6(std::string_view input) { pointer++; } - // Set address[pieceIndex] to address[pieceIndex] × 0x100 + ipv4Piece. + // Set address[pieceIndex] to address[pieceIndex] times 0x100 + + // ipv4Piece. // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int address[piece_index] = uint16_t(address[piece_index] * 0x100 + *ipv4_piece); @@ -11438,14 +11435,14 @@ bool url::parse_ipv6(std::string_view input) { // If compress is non-null, then: if (compress.has_value()) { - // Let swaps be pieceIndex − compress. + // Let swaps be pieceIndex - compress. int swaps = piece_index - *compress; // Set pieceIndex to 7. piece_index = 7; // While pieceIndex is not 0 and swaps is greater than 0, - // swap address[pieceIndex] with address[compress + swaps − 1], and then + // swap address[pieceIndex] with address[compress + swaps - 1], and then // decrease both pieceIndex and swaps by 1. while (piece_index != 0 && swaps > 0) { std::swap(address[piece_index], address[*compress + swaps - 1]); @@ -11476,7 +11473,7 @@ ada_really_inline bool url::parse_scheme(const std::string_view input) { **/ if (is_input_special) { // fast path!!! if (has_state_override) { - // If url’s scheme is not a special scheme and buffer is a special scheme, + // If url's scheme is not a special scheme and buffer is a special scheme, // then return. if (is_special() != is_input_special) { return true; @@ -11489,7 +11486,7 @@ ada_really_inline bool url::parse_scheme(const std::string_view input) { return true; } - // If url’s scheme is "file" and its host is an empty host, then return. + // If url's scheme is "file" and its host is an empty host, then return. // An empty host is the empty string. if (type == ada::scheme::type::FILE && host.has_value() && host.value().empty()) { @@ -11504,7 +11501,7 @@ ada_really_inline bool url::parse_scheme(const std::string_view input) { uint16_t urls_scheme_port = get_special_port(); if (urls_scheme_port) { - // If url’s port is url’s scheme’s default port, then set url’s port to + // If url's port is url's scheme's default port, then set url's port to // null. if (port.has_value() && *port == urls_scheme_port) { port = std::nullopt; @@ -11520,8 +11517,8 @@ ada_really_inline bool url::parse_scheme(const std::string_view input) { unicode::to_lower_ascii(_buffer.data(), _buffer.size()); if (has_state_override) { - // If url’s scheme is a special scheme and buffer is not a special scheme, - // then return. If url’s scheme is not a special scheme and buffer is a + // If url's scheme is a special scheme and buffer is not a special scheme, + // then return. If url's scheme is not a special scheme and buffer is a // special scheme, then return. if (is_special() != ada::scheme::is_special(_buffer)) { return true; @@ -11533,7 +11530,7 @@ ada_really_inline bool url::parse_scheme(const std::string_view input) { return true; } - // If url’s scheme is "file" and its host is an empty host, then return. + // If url's scheme is "file" and its host is an empty host, then return. // An empty host is the empty string. if (type == ada::scheme::type::FILE && host.has_value() && host.value().empty()) { @@ -11548,7 +11545,7 @@ ada_really_inline bool url::parse_scheme(const std::string_view input) { uint16_t urls_scheme_port = get_special_port(); if (urls_scheme_port) { - // If url’s port is url’s scheme’s default port, then set url’s port to + // If url's port is url's scheme's default port, then set url's port to // null. if (port.has_value() && *port == urls_scheme_port) { port = std::nullopt; @@ -11753,7 +11750,7 @@ namespace ada { auto result = ada::parse(path); if (result && (result->type == scheme::HTTP || result->type == scheme::HTTPS)) { - // If pathURL’s scheme is not "http" and not "https", then return a + // If pathURL's scheme is not "http" and not "https", then return a // new opaque origin. return ada::helpers::concat(result->get_protocol(), "//", result->get_host()); @@ -11774,9 +11771,9 @@ namespace ada { } [[nodiscard]] std::string url::get_host() const noexcept { - // If url’s host is null, then return the empty string. - // If url’s port is null, return url’s host, serialized. - // Return url’s host, serialized, followed by U+003A (:) and url’s port, + // If url's host is null, then return the empty string. + // If url's port is null, return url's host, serialized. + // Return url's host, serialized, followed by U+003A (:) and url's port, // serialized. if (!host.has_value()) { return ""; @@ -11796,8 +11793,8 @@ namespace ada { } [[nodiscard]] std::string url::get_search() const noexcept { - // If this’s URL’s query is either null or the empty string, then return the - // empty string. Return U+003F (?), followed by this’s URL’s query. + // If this's URL's query is either null or the empty string, then return the + // empty string. Return U+003F (?), followed by this's URL's query. return (!query.has_value() || (query.value().empty())) ? "" : "?" + query.value(); } @@ -11815,8 +11812,8 @@ namespace ada { } [[nodiscard]] std::string url::get_hash() const noexcept { - // If this’s URL’s fragment is either null or the empty string, then return - // the empty string. Return U+0023 (#), followed by this’s URL’s fragment. + // If this's URL's fragment is either null or the empty string, then return + // the empty string. Return U+0023 (#), followed by this's URL's fragment. return (!hash.has_value() || (hash.value().empty())) ? "" : "#" + hash.value(); } @@ -11871,7 +11868,7 @@ bool url::set_host_or_hostname(const std::string_view input) { } // If url is special and host_view is the empty string, validation error, // return failure. Otherwise, if state override is given, host_view is the - // empty string, and either url includes credentials or url’s port is + // empty string, and either url includes credentials or url's port is // non-null, return. else if (host_view.empty() && (is_special() || has_credentials() || port.has_value())) { @@ -11898,7 +11895,7 @@ bool url::set_host_or_hostname(const std::string_view input) { } if (new_host.empty()) { - // Set url’s host to the empty string. + // Set url's host to the empty string. host = ""; } else { // Let host be the result of host parsing buffer with url is not special. @@ -12108,7 +12105,7 @@ result_type parse_url(std::string_view user_input, // Most of the time, we just need user_input.size(). // In some instances, we may need a bit more. /////////////////////////// - // This is *very* important. This line should be removed + // This is *very* important. This line should *not* be removed // hastily. There are principled reasons why reserve is important // for performance. If you have a benchmark with small inputs, // it may not matter, but in other instances, it could. @@ -12203,13 +12200,13 @@ result_type parse_url(std::string_view user_input, } ada_log("SCHEME the scheme is ", url.get_protocol()); - // If url’s scheme is "file", then: + // If url's scheme is "file", then: if (url.type == ada::scheme::type::FILE) { // Set state to file state. state = ada::state::FILE; } - // Otherwise, if url is special, base is non-null, and base’s scheme - // is url’s scheme: Note: Doing base_url->scheme is unsafe if base_url + // Otherwise, if url is special, base is non-null, and base's scheme + // is url's scheme: Note: Doing base_url->scheme is unsafe if base_url // != nullptr is false. else if (url.is_special() && base_url != nullptr && base_url->type == url.type) { @@ -12228,7 +12225,7 @@ result_type parse_url(std::string_view user_input, state = ada::state::PATH_OR_AUTHORITY; input_position++; } - // Otherwise, set url’s path to the empty string and set state to + // Otherwise, set url's path to the empty string and set state to // opaque path state. else { state = ada::state::OPAQUE_PATH; @@ -12256,8 +12253,8 @@ result_type parse_url(std::string_view user_input, return url; } // Otherwise, if base has an opaque path and c is U+0023 (#), - // set url’s scheme to base’s scheme, url’s path to base’s path, url’s - // query to base’s query, and set state to fragment state. + // set url's scheme to base's scheme, url's path to base's path, url's + // query to base's query, and set state to fragment state. else if (base_url->has_opaque_path && fragment.has_value() && input_position == input_size) { ada_log("NO_SCHEME opaque base with fragment"); @@ -12274,7 +12271,7 @@ result_type parse_url(std::string_view user_input, url.update_unencoded_base_hash(*fragment); return url; } - // Otherwise, if base’s scheme is not "file", set state to relative + // Otherwise, if base's scheme is not "file", set state to relative // state and decrease pointer by 1. else if (base_url->type != ada::scheme::type::FILE) { ada_log("NO_SCHEME non-file relative path"); @@ -12447,7 +12444,7 @@ result_type parse_url(std::string_view user_input, ada_log("RELATIVE_SCHEME ", helpers::substring(url_data, input_position)); - // Set url’s scheme to base’s scheme. + // Set url's scheme to base's scheme. url.copy_scheme(*base_url); // If c is U+002F (/), then set state to relative slash state. @@ -12467,9 +12464,9 @@ result_type parse_url(std::string_view user_input, state = ada::state::RELATIVE_SLASH; } else { ada_log("RELATIVE_SCHEME otherwise"); - // Set url’s username to base’s username, url’s password to base’s - // password, url’s host to base’s host, url’s port to base’s port, - // url’s path to a clone of base’s path, and url’s query to base’s + // Set url's username to base's username, url's password to base's + // password, url's host to base's host, url's port to base's port, + // url's path to a clone of base's path, and url's query to base's // query. if constexpr (result_type_is_ada_url) { url.username = base_url->username; @@ -12495,7 +12492,7 @@ result_type parse_url(std::string_view user_input, url.has_opaque_path = base_url->has_opaque_path; - // If c is U+003F (?), then set url’s query to the empty string, and + // If c is U+003F (?), then set url's query to the empty string, and // state to query state. if ((input_position != input_size) && (url_data[input_position] == '?')) { @@ -12503,10 +12500,10 @@ result_type parse_url(std::string_view user_input, } // Otherwise, if c is not the EOF code point: else if (input_position != input_size) { - // Set url’s query to null. + // Set url's query to null. url.clear_search(); if constexpr (result_type_is_ada_url) { - // Shorten url’s path. + // Shorten url's path. helpers::shorten_path(url.path, url.type); } else { std::string_view path = url.get_pathname(); @@ -12539,10 +12536,10 @@ result_type parse_url(std::string_view user_input, state = ada::state::AUTHORITY; } // Otherwise, set - // - url’s username to base’s username, - // - url’s password to base’s password, - // - url’s host to base’s host, - // - url’s port to base’s port, + // - url's username to base's username, + // - url's password to base's password, + // - url's host to base's host, + // - url's port to base's port, // - state to path state, and then, decrease pointer by 1. else { if constexpr (result_type_is_ada_url) { @@ -12604,7 +12601,7 @@ result_type parse_url(std::string_view user_input, : ada::character_sets::QUERY_PERCENT_ENCODE; // Percent-encode after encoding, with encoding, buffer, and - // queryPercentEncodeSet, and append the result to url’s query. + // 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 "); @@ -12635,7 +12632,7 @@ result_type parse_url(std::string_view user_input, return url; } ada_log("HOST parsing results in ", url.get_hostname()); - // Set url’s host to host, buffer to the empty string, and state to + // Set url's host to host, buffer to the empty string, and state to // port state. state = ada::state::PORT; input_position++; @@ -12663,7 +12660,7 @@ result_type parse_url(std::string_view user_input, ada_log("HOST parsing results in ", url.get_hostname(), " href=", url.get_href()); - // Set url’s host to host, and state to path start state. + // Set url's host to host, and state to path start state. state = ada::state::PATH_START; } @@ -12672,7 +12669,7 @@ result_type parse_url(std::string_view user_input, case ada::state::OPAQUE_PATH: { ada_log("OPAQUE_PATH ", helpers::substring(url_data, input_position)); std::string_view view = helpers::substring(url_data, input_position); - // If c is U+003F (?), then set url’s query to the empty string and + // If c is U+003F (?), then set url's query to the empty string and // state to query state. size_t location = view.find('?'); if (location != std::string_view::npos) { @@ -12727,7 +12724,7 @@ result_type parse_url(std::string_view user_input, } } // Otherwise, if state override is not given and c is U+003F (?), - // set url’s query to the empty string and state to query state. + // set url's query to the empty string and state to query state. else if ((input_position != input_size) && (url_data[input_position] == '?')) { state = ada::state::QUERY; @@ -12781,12 +12778,12 @@ result_type parse_url(std::string_view user_input, input_position++; } else { ada_log("FILE_SLASH otherwise"); - // If base is non-null and base’s scheme is "file", then: + // If base is non-null and base's scheme is "file", then: // Note: it is unsafe to do base_url->scheme unless you know that // base_url_has_value() is true. if (base_url != nullptr && base_url->type == ada::scheme::type::FILE) { - // Set url’s host to base’s host. + // Set url's host to base's host. if constexpr (result_type_is_ada_url) { url.host = base_url->host; } else { @@ -12794,9 +12791,9 @@ result_type parse_url(std::string_view user_input, url.set_host(base_url->get_host()); } // If the code point substring from pointer to the end of input does - // not start with a Windows drive letter and base’s path[0] is a - // normalized Windows drive letter, then append base’s path[0] to - // url’s path. + // not start with a Windows drive letter and base's path[0] is a + // normalized Windows drive letter, then append base's path[0] to + // url's path. if (!base_url->get_pathname().empty()) { if (!checkers::is_windows_drive_letter( helpers::substring(url_data, input_position))) { @@ -12838,7 +12835,7 @@ result_type parse_url(std::string_view user_input, if (checkers::is_windows_drive_letter(file_host_buffer)) { state = ada::state::PATH; } else if (file_host_buffer.empty()) { - // Set url’s host to the empty string. + // Set url's host to the empty string. if constexpr (result_type_is_ada_url) { url.host = ""; } else { @@ -12879,7 +12876,7 @@ result_type parse_url(std::string_view user_input, url.set_protocol_as_file(); if constexpr (result_type_is_ada_url) { - // Set url’s host to the empty string. + // Set url's host to the empty string. url.host = ""; } else { url.update_base_hostname(""); @@ -12892,11 +12889,11 @@ result_type parse_url(std::string_view user_input, // Set state to file slash state. state = ada::state::FILE_SLASH; } - // Otherwise, if base is non-null and base’s scheme is "file": + // Otherwise, if base is non-null and base's scheme is "file": else if (base_url != nullptr && base_url->type == ada::scheme::type::FILE) { - // Set url’s host to base’s host, url’s path to a clone of base’s - // path, and url’s query to base’s query. + // Set url's host to base's host, url's path to a clone of base's + // path, and url's query to base's query. ada_log("FILE base non-null"); if constexpr (result_type_is_ada_url) { url.host = base_url->host; @@ -12911,17 +12908,17 @@ result_type parse_url(std::string_view user_input, } url.has_opaque_path = base_url->has_opaque_path; - // If c is U+003F (?), then set url’s query to the empty string and + // If c is U+003F (?), then set url's query to the empty string and // state to query state. if (input_position != input_size && url_data[input_position] == '?') { state = ada::state::QUERY; } // Otherwise, if c is not the EOF code point: else if (input_position != input_size) { - // Set url’s query to null. + // Set url's query to null. url.clear_search(); // If the code point substring from pointer to the end of input does - // not start with a Windows drive letter, then shorten url’s path. + // not start with a Windows drive letter, then shorten url's path. if (!checkers::is_windows_drive_letter(file_view)) { if constexpr (result_type_is_ada_url) { helpers::shorten_path(url.path, url.type); @@ -12934,7 +12931,7 @@ result_type parse_url(std::string_view user_input, } // Otherwise: else { - // Set url’s path to an empty list. + // Set url's path to an empty list. url.clear_pathname(); url.has_opaque_path = true; } @@ -13119,7 +13116,7 @@ template **/ if (is_input_special) { // fast path!!! if (has_state_override) { - // If url’s scheme is not a special scheme and buffer is a special scheme, + // If url's scheme is not a special scheme and buffer is a special scheme, // then return. if (is_special() != is_input_special) { return true; @@ -13132,7 +13129,7 @@ template return true; } - // If url’s scheme is "file" and its host is an empty host, then return. + // If url's scheme is "file" and its host is an empty host, then return. // An empty host is the empty string. if (type == ada::scheme::type::FILE && components.host_start == components.host_end) { @@ -13147,7 +13144,7 @@ template // This is uncommon. uint16_t urls_scheme_port = get_special_port(); - // If url’s port is url’s scheme’s default port, then set url’s port to + // If url's port is url's scheme's default port, then set url's port to // null. if (components.port == urls_scheme_port) { clear_port(); @@ -13161,8 +13158,8 @@ template unicode::to_lower_ascii(_buffer.data(), _buffer.size()); if (has_state_override) { - // If url’s scheme is a special scheme and buffer is not a special scheme, - // then return. If url’s scheme is not a special scheme and buffer is a + // If url's scheme is a special scheme and buffer is not a special scheme, + // then return. If url's scheme is not a special scheme and buffer is a // special scheme, then return. if (is_special() != ada::scheme::is_special(_buffer)) { return true; @@ -13175,7 +13172,7 @@ template return true; } - // If url’s scheme is "file" and its host is an empty host, then return. + // If url's scheme is "file" and its host is an empty host, then return. // An empty host is the empty string. if (type == ada::scheme::type::FILE && components.host_start == components.host_end) { @@ -13189,7 +13186,7 @@ template // This is uncommon. uint16_t urls_scheme_port = get_special_port(); - // If url’s port is url’s scheme’s default port, then set url’s port to + // If url's port is url's scheme's default port, then set url's port to // null. if (components.port == urls_scheme_port) { clear_port(); @@ -13638,7 +13635,7 @@ bool url_aggregator::set_host_or_hostname(const std::string_view input) { } // If url is special and host_view is the empty string, validation error, // return failure. Otherwise, if state override is given, host_view is the - // empty string, and either url includes credentials or url’s port is + // empty string, and either url includes credentials or url's port is // non-null, return. else if (host_view.empty() && (is_special() || has_credentials() || @@ -13674,7 +13671,7 @@ bool url_aggregator::set_host_or_hostname(const std::string_view input) { } if (new_host.empty()) { - // Set url’s host to the empty string. + // Set url's host to the empty string. clear_hostname(); } else { // Let host be the result of host parsing buffer with url is not special. @@ -13724,7 +13721,7 @@ bool url_aggregator::set_hostname(const std::string_view input) { if (!path.empty()) { auto out = ada::parse(path); if (out && (out->type == scheme::HTTP || out->type == scheme::HTTPS)) { - // If pathURL’s scheme is not "http" and not "https", then return a + // If pathURL's scheme is not "http" and not "https", then return a // new opaque origin. return helpers::concat(out->get_protocol(), "//", out->get_host()); } @@ -13764,8 +13761,8 @@ bool url_aggregator::set_hostname(const std::string_view input) { [[nodiscard]] std::string_view url_aggregator::get_hash() const noexcept { ada_log("url_aggregator::get_hash"); - // If this’s URL’s fragment is either null or the empty string, then return - // the empty string. Return U+0023 (#), followed by this’s URL’s fragment. + // If this's URL's fragment is either null or the empty string, then return + // the empty string. Return U+0023 (#), followed by this's URL's fragment. if (components.hash_start == url_components::omitted) { return ""; } @@ -13823,8 +13820,8 @@ bool url_aggregator::set_hostname(const std::string_view input) { [[nodiscard]] std::string_view url_aggregator::get_search() const noexcept { ada_log("url_aggregator::get_search"); - // If this’s URL’s query is either null or the empty string, then return the - // empty string. Return U+003F (?), followed by this’s URL’s query. + // If this's URL's query is either null or the empty string, then return the + // empty string. Return U+003F (?), followed by this's URL's query. if (components.search_start == url_components::omitted) { return ""; } @@ -14091,7 +14088,7 @@ bool url_aggregator::parse_ipv6(std::string_view input) { uint16_t value = 0, length = 0; // While length is less than 4 and c is an ASCII hex digit, - // set value to value × 0x10 + c interpreted as hexadecimal number, and + // set value to value times 0x10 + c interpreted as hexadecimal number, and // increase pointer and length by 1. while (length < 4 && pointer != input.end() && unicode::is_ascii_hex_digit(*pointer)) { @@ -14161,7 +14158,7 @@ bool url_aggregator::parse_ipv6(std::string_view input) { ada_log("parse_ipv6 if ipv4Piece is 0, validation error"); return is_valid = false; } - // Otherwise, set ipv4Piece to ipv4Piece × 10 + number. + // Otherwise, set ipv4Piece to ipv4Piece times 10 + number. else { ipv4_piece = *ipv4_piece * 10 + number; } @@ -14176,7 +14173,8 @@ bool url_aggregator::parse_ipv6(std::string_view input) { pointer++; } - // Set address[pieceIndex] to address[pieceIndex] × 0x100 + ipv4Piece. + // Set address[pieceIndex] to address[pieceIndex] times 0x100 + + // ipv4Piece. // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int address[piece_index] = uint16_t(address[piece_index] * 0x100 + *ipv4_piece); @@ -14229,14 +14227,14 @@ bool url_aggregator::parse_ipv6(std::string_view input) { // If compress is non-null, then: if (compress.has_value()) { - // Let swaps be pieceIndex − compress. + // Let swaps be pieceIndex - compress. int swaps = piece_index - *compress; // Set pieceIndex to 7. piece_index = 7; // While pieceIndex is not 0 and swaps is greater than 0, - // swap address[pieceIndex] with address[compress + swaps − 1], and then + // swap address[pieceIndex] with address[compress + swaps - 1], and then // decrease both pieceIndex and swaps by 1. while (piece_index != 0 && swaps > 0) { std::swap(address[piece_index], address[*compress + swaps - 1]); @@ -14777,7 +14775,7 @@ inline void url_aggregator::consume_prepared_path(std::string_view input) { } // Otherwise, if path_buffer is not a single-dot path segment, then: else if (!unicode::is_single_dot_path_segment(path_buffer)) { - // If url’s scheme is "file", url’s path is empty, and path_buffer is a + // If url's scheme is "file", url's path is empty, and path_buffer is a // Windows drive letter, then replace the second code point in // path_buffer with U+003A (:). if (type == ada::scheme::type::FILE && path.empty() && @@ -14788,7 +14786,7 @@ inline void url_aggregator::consume_prepared_path(std::string_view input) { path_buffer.remove_prefix(2); path.append(path_buffer); } else { - // Append path_buffer to url’s path. + // Append path_buffer to url's path. path += '/'; path.append(path_buffer); } @@ -15173,6 +15171,25 @@ const ada_url_components* ada_get_components(ada_url result) noexcept { } return reinterpret_cast(&r->get_components()); } + +ada_owned_string ada_idna_to_unicode(const char* input, size_t length) { + std::string out = ada::idna::to_unicode(std::string_view(input, length)); + ada_owned_string owned{}; + owned.length = out.length(); + owned.data = new char[owned.length]; + memcpy((void*)owned.data, out.data(), owned.length); + return owned; +} + +ada_owned_string ada_idna_to_ascii(const char* input, size_t length) { + std::string out = ada::idna::to_ascii(std::string_view(input, length)); + ada_owned_string owned{}; + owned.length = out.size(); + owned.data = new char[owned.length]; + memcpy((void*)owned.data, out.data(), owned.length); + return owned; +} + } // extern "C" /* end file src/ada_c.cpp */ /* end file src/ada.cpp */ diff --git a/deps/ada/ada.h b/deps/ada/ada.h index 4846b3172e6c64..3f1531944e96e7 100644 --- a/deps/ada/ada.h +++ b/deps/ada/ada.h @@ -1,4 +1,4 @@ -/* auto-generated on 2023-06-03 12:40:57 -0400. Do not edit! */ +/* auto-generated on 2023-07-23 15:03:22 -0400. Do not edit! */ /* begin file include/ada.h */ /** * @file ada.h @@ -120,7 +120,6 @@ namespace ada::idna { // this function. We also do not trim control characters. We also assume that // the input is not empty. We return "" on error. // -// Example: "www.öbb.at" -> "www.xn--bb-eka.at" // // This function may accept or even produce invalid domains. std::string to_ascii(std::string_view ut8_string); @@ -926,6 +925,72 @@ constexpr uint8_t PATH_PERCENT_ENCODE[32] = { // F8 F9 FA FB FC FD FE FF 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80}; +constexpr uint8_t WWW_FORM_URLENCODED_PERCENT_ENCODE[32] = { + // 00 01 02 03 04 05 06 07 + 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80, + // 08 09 0A 0B 0C 0D 0E 0F + 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80, + // 10 11 12 13 14 15 16 17 + 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80, + // 18 19 1A 1B 1C 1D 1E 1F + 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80, + // 20 21 22 23 24 25 26 27 + 0x00 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80, + // 28 29 2A 2B 2C 2D 2E 2F + 0x01 | 0x02 | 0x00 | 0x08 | 0x10 | 0x00 | 0x00 | 0x00, + // 30 31 32 33 34 35 36 37 + 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00, + // 38 39 3A 3B 3C 3D 3E 3F + 0x00 | 0x00 | 0x00 | 0x00 | 0x10 | 0x00 | 0x40 | 0x80, + // 40 41 42 43 44 45 46 47 + 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00, + // 48 49 4A 4B 4C 4D 4E 4F + 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00, + // 50 51 52 53 54 55 56 57 + 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00, + // 58 59 5A 5B 5C 5D 5E 5F + 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00, + // 60 61 62 63 64 65 66 67 + 0x01 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00, + // 68 69 6A 6B 6C 6D 6E 6F + 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00, + // 70 71 72 73 74 75 76 77 + 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00, + // 78 79 7A 7B 7C 7D 7E 7F + 0x00 | 0x00 | 0x00 | 0x08 | 0x00 | 0x20 | 0x40 | 0x80, + // 80 81 82 83 84 85 86 87 + 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80, + // 88 89 8A 8B 8C 8D 8E 8F + 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80, + // 90 91 92 93 94 95 96 97 + 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80, + // 98 99 9A 9B 9C 9D 9E 9F + 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80, + // A0 A1 A2 A3 A4 A5 A6 A7 + 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80, + // A8 A9 AA AB AC AD AE AF + 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80, + // B0 B1 B2 B3 B4 B5 B6 B7 + 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80, + // B8 B9 BA BB BC BD BE BF + 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80, + // C0 C1 C2 C3 C4 C5 C6 C7 + 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80, + // C8 C9 CA CB CC CD CE CF + 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80, + // D0 D1 D2 D3 D4 D5 D6 D7 + 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80, + // D8 D9 DA DB DC DD DE DF + 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80, + // E0 E1 E2 E3 E4 E5 E6 E7 + 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80, + // E8 E9 EA EB EC ED EE EF + 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80, + // F0 F1 F2 F3 F4 F5 F6 F7 + 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80, + // F8 F9 FA FB FC FD FE FF + 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80}; + ada_really_inline bool bit_at(const uint8_t a[], const uint8_t i) { return !!(a[i >> 3] & (1 << (i & 7))); } @@ -1375,7 +1440,7 @@ struct url_base { [[nodiscard]] ada_really_inline bool is_special() const noexcept; /** - * The origin getter steps are to return the serialization of this’s URL’s + * The origin getter steps are to return the serialization of this's URL's * origin. [HTML] * @return a newly allocated string. * @see https://url.spec.whatwg.org/#concept-url-origin @@ -4284,10 +4349,10 @@ namespace ada::unicode { * Given a domain, we need to identify its labels. * They are separated by label-separators: * - * U+002E ( . ) FULL STOP - * U+FF0E ( . ) FULLWIDTH FULL STOP - * U+3002 ( 。 ) IDEOGRAPHIC FULL STOP - * U+FF61 ( 。 ) HALFWIDTH IDEOGRAPHIC FULL STOP + * U+002E (.) FULL STOP + * U+FF0E FULLWIDTH FULL STOP + * U+3002 IDEOGRAPHIC FULL STOP + * U+FF61 HALFWIDTH IDEOGRAPHIC FULL STOP * * They are all mapped to U+002E. * @@ -4517,7 +4582,7 @@ struct url_aggregator : url_base { [[nodiscard]] bool has_valid_domain() const noexcept override; /** - * The origin getter steps are to return the serialization of this’s URL’s + * The origin getter steps are to return the serialization of this's URL's * origin. [HTML] * @return a newly allocated string. * @see https://url.spec.whatwg.org/#concept-url-origin @@ -4533,35 +4598,35 @@ struct url_aggregator : url_base { */ inline std::string_view get_href() const noexcept; /** - * The username getter steps are to return this’s URL’s username. + * The username getter steps are to return this's URL's username. * This function does not allocate memory. * @return a lightweight std::string_view. * @see https://url.spec.whatwg.org/#dom-url-username */ [[nodiscard]] std::string_view get_username() const noexcept; /** - * The password getter steps are to return this’s URL’s password. + * The password getter steps are to return this's URL's password. * This function does not allocate memory. * @return a lightweight std::string_view. * @see https://url.spec.whatwg.org/#dom-url-password */ [[nodiscard]] std::string_view get_password() const noexcept; /** - * Return this’s URL’s port, serialized. + * Return this's URL's port, serialized. * This function does not allocate memory. * @return a lightweight std::string_view. * @see https://url.spec.whatwg.org/#dom-url-port */ [[nodiscard]] std::string_view get_port() const noexcept; /** - * Return U+0023 (#), followed by this’s URL’s fragment. + * Return U+0023 (#), followed by this's URL's fragment. * This function does not allocate memory. * @return a lightweight std::string_view.. * @see https://url.spec.whatwg.org/#dom-url-hash */ [[nodiscard]] std::string_view get_hash() const noexcept; /** - * Return url’s host, serialized, followed by U+003A (:) and url’s port, + * Return url's host, serialized, followed by U+003A (:) and url's port, * serialized. * This function does not allocate memory. * When there is no host, this function returns the empty view. @@ -4570,7 +4635,7 @@ struct url_aggregator : url_base { */ [[nodiscard]] std::string_view get_host() const noexcept; /** - * Return this’s URL’s host, serialized. + * Return this's URL's host, serialized. * This function does not allocate memory. * When there is no host, this function returns the empty view. * @return a lightweight std::string_view. @@ -4579,7 +4644,7 @@ struct url_aggregator : url_base { [[nodiscard]] std::string_view get_hostname() const noexcept; /** * The pathname getter steps are to return the result of URL path serializing - * this’s URL. + * this's URL. * This function does not allocate memory. * @return a lightweight std::string_view. * @see https://url.spec.whatwg.org/#dom-url-pathname @@ -4593,14 +4658,14 @@ struct url_aggregator : url_base { */ ada_really_inline uint32_t get_pathname_length() const noexcept; /** - * Return U+003F (?), followed by this’s URL’s query. + * Return U+003F (?), followed by this's URL's query. * This function does not allocate memory. * @return a lightweight std::string_view. * @see https://url.spec.whatwg.org/#dom-url-search */ [[nodiscard]] std::string_view get_search() const noexcept; /** - * The protocol getter steps are to return this’s URL’s scheme, followed by + * The protocol getter steps are to return this's URL's scheme, followed by * U+003A (:). * This function does not allocate memory. * @return a lightweight std::string_view. @@ -4924,48 +4989,48 @@ struct url : url_base { /** * @private - * A URL’s username is an ASCII string identifying a username. It is initially + * A URL's username is an ASCII string identifying a username. It is initially * the empty string. */ std::string username{}; /** * @private - * A URL’s password is an ASCII string identifying a password. It is initially + * A URL's password is an ASCII string identifying a password. It is initially * the empty string. */ std::string password{}; /** * @private - * A URL’s host is null or a host. It is initially null. + * A URL's host is null or a host. It is initially null. */ std::optional host{}; /** * @private - * A URL’s port is either null or a 16-bit unsigned integer that identifies a + * A URL's port is either null or a 16-bit unsigned integer that identifies a * networking port. It is initially null. */ std::optional port{}; /** * @private - * A URL’s path is either an ASCII string or a list of zero or more ASCII + * A URL's path is either an ASCII string or a list of zero or more ASCII * strings, usually identifying a location. */ std::string path{}; /** * @private - * A URL’s query is either null or an ASCII string. It is initially null. + * A URL's query is either null or an ASCII string. It is initially null. */ std::optional query{}; /** * @private - * A URL’s fragment is either null or an ASCII string that can be used for - * further processing on the resource the URL’s other components identify. It + * A URL's fragment is either null or an ASCII string that can be used for + * further processing on the resource the URL's other components identify. It * is initially null. */ std::optional hash{}; @@ -4990,7 +5055,7 @@ struct url : url_base { [[nodiscard]] ada_really_inline std::string get_href() const noexcept; /** - * The origin getter steps are to return the serialization of this’s URL’s + * The origin getter steps are to return the serialization of this's URL's * origin. [HTML] * @return a newly allocated string. * @see https://url.spec.whatwg.org/#concept-url-origin @@ -4998,7 +5063,7 @@ struct url : url_base { [[nodiscard]] std::string get_origin() const noexcept override; /** - * The protocol getter steps are to return this’s URL’s scheme, followed by + * The protocol getter steps are to return this's URL's scheme, followed by * U+003A (:). * @return a newly allocated string. * @see https://url.spec.whatwg.org/#dom-url-protocol @@ -5006,7 +5071,7 @@ struct url : url_base { [[nodiscard]] std::string get_protocol() const noexcept; /** - * Return url’s host, serialized, followed by U+003A (:) and url’s port, + * Return url's host, serialized, followed by U+003A (:) and url's port, * serialized. * When there is no host, this function returns the empty string. * @return a newly allocated string. @@ -5015,7 +5080,7 @@ struct url : url_base { [[nodiscard]] std::string get_host() const noexcept; /** - * Return this’s URL’s host, serialized. + * Return this's URL's host, serialized. * When there is no host, this function returns the empty string. * @return a newly allocated string. * @see https://url.spec.whatwg.org/#dom-url-hostname @@ -5024,7 +5089,7 @@ struct url : url_base { /** * The pathname getter steps are to return the result of URL path serializing - * this’s URL. + * this's URL. * @return a newly allocated string. * @see https://url.spec.whatwg.org/#dom-url-pathname */ @@ -5039,14 +5104,14 @@ struct url : url_base { ada_really_inline size_t get_pathname_length() const noexcept; /** - * Return U+003F (?), followed by this’s URL’s query. + * Return U+003F (?), followed by this's URL's query. * @return a newly allocated string. * @see https://url.spec.whatwg.org/#dom-url-search */ [[nodiscard]] std::string get_search() const noexcept; /** - * The username getter steps are to return this’s URL’s username. + * The username getter steps are to return this's URL's username. * @return a constant reference to the underlying string. * @see https://url.spec.whatwg.org/#dom-url-username */ @@ -5112,21 +5177,21 @@ struct url : url_base { bool set_href(const std::string_view input); /** - * The password getter steps are to return this’s URL’s password. + * The password getter steps are to return this's URL's password. * @return a constant reference to the underlying string. * @see https://url.spec.whatwg.org/#dom-url-password */ [[nodiscard]] const std::string &get_password() const noexcept; /** - * Return this’s URL’s port, serialized. + * Return this's URL's port, serialized. * @return a newly constructed string representing the port. * @see https://url.spec.whatwg.org/#dom-url-port */ [[nodiscard]] std::string get_port() const noexcept; /** - * Return U+0023 (#), followed by this’s URL’s fragment. + * Return U+0023 (#), followed by this's URL's fragment. * @return a newly constructed string representing the hash. * @see https://url.spec.whatwg.org/#dom-url-hash */ @@ -5212,7 +5277,7 @@ struct url : url_base { [[nodiscard]] bool parse_opaque_host(std::string_view input); /** - * A URL’s scheme is an ASCII string that identifies the type of URL and can + * A URL's scheme is an ASCII string that identifies the type of URL and can * be used to dispatch a URL for further processing after parsing. It is * initially the empty string. We only set non_special_scheme when the scheme * is non-special, otherwise we avoid constructing string. @@ -5394,8 +5459,8 @@ size_t url::get_pathname_length() const noexcept { return path.size(); } out.host_end = out.host_start; if (!has_opaque_path && checkers::begins_with(path, "//")) { - // If url’s host is null, url does not have an opaque path, url’s path’s - // size is greater than 1, and url’s path[0] is the empty string, then + // If url's host is null, url does not have an opaque path, url's path's + // size is greater than 1, and url's path[0] is the empty string, then // append U+002F (/) followed by U+002E (.) to output. running_index = out.protocol_end + 2; } else { @@ -5509,8 +5574,8 @@ inline void url::copy_scheme(const ada::url &u) { output += ":" + get_port(); } } else if (!has_opaque_path && checkers::begins_with(path, "//")) { - // If url’s host is null, url does not have an opaque path, url’s path’s - // size is greater than 1, and url’s path[0] is the empty string, then + // If url's host is null, url does not have an opaque path, url's path's + // size is greater than 1, and url's path[0] is the empty string, then // append U+002F (/) followed by U+002E (.) to output. output += "/."; } @@ -5854,7 +5919,7 @@ inline void url_aggregator::update_base_pathname(const std::string_view input) { if (begins_with_dashdash && !has_opaque_path && !has_authority() && !has_dash_dot()) { - // If url’s host is null, url does not have an opaque path, url’s path’s + // If url's host is null, url does not have an opaque path, url's path's // size is greater than 1, then append U+002F (/) followed by U+002E (.) to // output. buffer.insert(components.pathname_start, "/."); @@ -6387,8 +6452,8 @@ inline bool url_aggregator::has_port() const noexcept { } inline bool url_aggregator::has_dash_dot() const noexcept { - // If url’s host is null, url does not have an opaque path, url’s path’s size - // is greater than 1, and url’s path[0] is the empty string, then append + // If url's host is null, url does not have an opaque path, url's path's size + // is greater than 1, and url's path[0] is the empty string, then append // U+002F (/) followed by U+002E (.) to output. ada_log("url_aggregator::has_dash_dot"); // Performance: instead of doing this potentially expensive check, we could @@ -6484,6 +6549,254 @@ inline std::ostream &operator<<(std::ostream &out, #endif // ADA_URL_AGGREGATOR_INL_H /* end file include/ada/url_aggregator-inl.h */ +/* begin file include/ada/url_search_params.h */ +/** + * @file url_search_params.h + * @brief Declaration for the URL Search Params + */ +#ifndef ADA_URL_SEARCH_PARAMS_H +#define ADA_URL_SEARCH_PARAMS_H + +#include +#include +#include +#include + +namespace ada { + +/** + * @see https://url.spec.whatwg.org/#interface-urlsearchparams + */ +struct url_search_params { + url_search_params() = default; + + /** + * @see + * https://github.com/web-platform-tests/wpt/blob/master/url/urlsearchparams-constructor.any.js + */ + url_search_params(const std::string_view input) { initialize(input); } + + url_search_params(const url_search_params &u) = default; + url_search_params(url_search_params &&u) noexcept = default; + url_search_params &operator=(url_search_params &&u) noexcept = default; + url_search_params &operator=(const url_search_params &u) = default; + ~url_search_params() = default; + + [[nodiscard]] inline size_t size() const noexcept; + + /** + * @see https://url.spec.whatwg.org/#dom-urlsearchparams-append + */ + inline void append(std::string_view key, std::string_view value); + + /** + * @see https://url.spec.whatwg.org/#dom-urlsearchparams-delete + */ + inline void remove(std::string_view key); + inline void remove(std::string_view key, std::string_view value); + + /** + * @see https://url.spec.whatwg.org/#dom-urlsearchparams-get + */ + inline std::optional get(std::string_view key); + + /** + * @see https://url.spec.whatwg.org/#dom-urlsearchparams-getall + */ + inline std::vector get_all(std::string_view key); + + /** + * @see https://url.spec.whatwg.org/#dom-urlsearchparams-has + */ + inline bool has(std::string_view key) noexcept; + + /** + * @see https://url.spec.whatwg.org/#dom-urlsearchparams-set + */ + inline void set(std::string_view key, std::string_view value); + + /** + * @see https://url.spec.whatwg.org/#dom-urlsearchparams-sort + */ + inline void sort(); + + /** + * @see https://url.spec.whatwg.org/#urlsearchparams-stringification-behavior + */ + inline std::string to_string(); + + private: + typedef std::pair key_value_pair; + std::vector params{}; + + /** + * @see https://url.spec.whatwg.org/#concept-urlencoded-parser + */ + void initialize(std::string_view init); +}; // url_search_params + +} // namespace ada +#endif +/* end file include/ada/url_search_params.h */ +/* begin file include/ada/url_search_params-inl.h */ +/** + * @file url_search_params-inl.h + * @brief Inline declarations for the URL Search Params + */ +#ifndef ADA_URL_SEARCH_PARAMS_INL_H +#define ADA_URL_SEARCH_PARAMS_INL_H + + +#include +#include +#include +#include +#include + +namespace ada { + +inline void url_search_params::initialize(std::string_view input) { + if (!input.empty() && input.front() == '?') { + input.remove_prefix(1); + } + + auto process_key_value = [&](const std::string_view current) { + auto equal = current.find('='); + + if (equal == std::string_view::npos) { + auto name = std::string(current); + std::replace(name.begin(), name.end(), '+', ' '); + params.emplace_back(unicode::percent_decode(name, name.find('%')), ""); + } else { + auto name = std::string(current.substr(0, equal)); + auto value = std::string(current.substr(equal + 1)); + + std::replace(name.begin(), name.end(), '+', ' '); + std::replace(value.begin(), value.end(), '+', ' '); + + params.emplace_back(unicode::percent_decode(name, name.find('%')), + unicode::percent_decode(value, value.find('%'))); + } + }; + + while (!input.empty()) { + auto ampersand_index = input.find('&'); + + if (ampersand_index == std::string_view::npos) { + if (!input.empty()) { + process_key_value(input); + } + break; + } else if (ampersand_index != 0) { + process_key_value(input.substr(0, ampersand_index)); + } + + input.remove_prefix(ampersand_index + 1); + } +} + +inline void url_search_params::append(const std::string_view key, + const std::string_view value) { + params.emplace_back(key, value); +} + +inline size_t url_search_params::size() const noexcept { return params.size(); } + +inline std::optional url_search_params::get( + const std::string_view key) { + auto entry = std::find_if(params.begin(), params.end(), + [&key](auto ¶m) { return param.first == key; }); + + if (entry == params.end()) { + return std::nullopt; + } + + return entry->second; +} + +inline std::vector url_search_params::get_all( + const std::string_view key) { + std::vector out{}; + + for (auto ¶m : params) { + if (param.first == key) { + out.emplace_back(param.second); + } + } + + return out; +} + +inline bool url_search_params::has(const std::string_view key) noexcept { + auto entry = std::find_if(params.begin(), params.end(), + [&key](auto ¶m) { return param.first == key; }); + return entry != params.end(); +} + +inline std::string url_search_params::to_string() { + auto character_set = ada::character_sets::WWW_FORM_URLENCODED_PERCENT_ENCODE; + std::string out{}; + for (size_t i = 0; i < params.size(); i++) { + auto key = ada::unicode::percent_encode(params[i].first, character_set); + auto value = ada::unicode::percent_encode(params[i].second, character_set); + + // Performance optimization: Move this inside percent_encode. + std::replace(key.begin(), key.end(), ' ', '+'); + std::replace(value.begin(), value.end(), ' ', '+'); + + if (i != 0) { + out += "&"; + } + out.append(key); + out += "="; + out.append(value); + } + return out; +} + +inline void url_search_params::set(const std::string_view key, + const std::string_view value) { + const auto find = [&key](auto ¶m) { return param.first == key; }; + + auto it = std::find_if(params.begin(), params.end(), find); + + if (it == params.end()) { + params.emplace_back(key, value); + } else { + it->second = value; + params.erase(std::remove_if(std::next(it), params.end(), find), + params.end()); + } +} + +inline void url_search_params::remove(const std::string_view key) { + params.erase( + std::remove_if(params.begin(), params.end(), + [&key](auto ¶m) { return param.first == key; }), + params.end()); +} + +inline void url_search_params::remove(const std::string_view key, + const std::string_view value) { + params.erase(std::remove_if(params.begin(), params.end(), + [&key, &value](auto ¶m) { + return param.first == key && + param.second == value; + }), + params.end()); +} + +inline void url_search_params::sort() { + std::stable_sort(params.begin(), params.end(), + [](const key_value_pair &lhs, const key_value_pair &rhs) { + return lhs.first < rhs.first; + }); +} + +} // namespace ada + +#endif // ADA_URL_SEARCH_PARAMS_INL_H +/* end file include/ada/url_search_params-inl.h */ // Public API /* begin file include/ada/ada_version.h */ @@ -6494,14 +6807,14 @@ inline std::ostream &operator<<(std::ostream &out, #ifndef ADA_ADA_VERSION_H #define ADA_ADA_VERSION_H -#define ADA_VERSION "2.5.1" +#define ADA_VERSION "2.6.0" namespace ada { enum { ADA_VERSION_MAJOR = 2, - ADA_VERSION_MINOR = 5, - ADA_VERSION_REVISION = 1, + ADA_VERSION_MINOR = 6, + ADA_VERSION_REVISION = 0, }; } // namespace ada diff --git a/deps/ada/ada_c.h b/deps/ada/ada_c.h index f8bcbdcd14d161..6e22584f612a75 100644 --- a/deps/ada/ada_c.h +++ b/deps/ada/ada_c.h @@ -97,4 +97,8 @@ bool ada_has_search(ada_url result); // returns a pointer to the internal url_aggregator::url_components const ada_url_components* ada_get_components(ada_url result); +// idna methods +ada_owned_string ada_idna_to_unicode(const char* input, size_t length); +ada_owned_string ada_idna_to_ascii(const char* input, size_t length); + #endif // ADA_C_H