From 3842cb1778d7c1e0c57fc6000792021735ae53ef Mon Sep 17 00:00:00 2001 From: Yagiz Nizipli Date: Thu, 11 Jul 2024 15:04:17 -0400 Subject: [PATCH] chore: update ada to v2.9.0 (#68) --- deps/ada.cpp | 410 ++++++++++++++++++++++++++++----------------------- deps/ada.h | 276 +++++++++++++++++++++++++--------- deps/ada_c.h | 2 + 3 files changed, 438 insertions(+), 250 deletions(-) diff --git a/deps/ada.cpp b/deps/ada.cpp index a7be606..72512a0 100644 --- a/deps/ada.cpp +++ b/deps/ada.cpp @@ -1,7 +1,8 @@ -/* auto-generated on 2024-03-07 13:23:39 -0500. Do not edit! */ +/* auto-generated on 2024-07-06 17:38:56 -0400. Do not edit! */ /* begin file src/ada.cpp */ #include "ada.h" /* begin file src/checkers.cpp */ + #include namespace ada::checkers { @@ -65,8 +66,7 @@ static constexpr std::array path_signature_table = std::array result{}; for (size_t i = 0; i < 256; i++) { if (i <= 0x20 || i == 0x22 || i == 0x23 || i == 0x3c || i == 0x3e || - i == 0x3f || i == 0x60 || i == 0x7b || i == 0x7b || i == 0x7d || - i > 0x7e) { + i == 0x3f || i == 0x60 || i == 0x7b || i == 0x7d || i > 0x7e) { result[i] = 1; } else if (i == 0x25) { result[i] = 8; @@ -9795,6 +9795,10 @@ ADA_POP_DISABLE_WARNINGS namespace ada::unicode { +constexpr bool is_tabs_or_newline(char c) noexcept { + return c == '\r' || c == '\n' || c == '\t'; +} + constexpr uint64_t broadcast(uint8_t v) noexcept { return 0x101010101010101ull * v; } @@ -9829,53 +9833,54 @@ ada_really_inline bool has_tabs_or_newline( std::string_view user_input) noexcept { // first check for short strings in which case we do it naively. if (user_input.size() < 16) { // slow path - for (size_t i = 0; i < user_input.size(); i++) { - if (user_input[i] == '\r' || user_input[i] == '\n' || - user_input[i] == '\t') { - return true; - } - } - return false; + return std::any_of(user_input.begin(), user_input.end(), + is_tabs_or_newline); } // fast path for long strings (expected to be common) size_t i = 0; - const uint8x16_t mask1 = vmovq_n_u8('\r'); - const uint8x16_t mask2 = vmovq_n_u8('\n'); - const uint8x16_t mask3 = vmovq_n_u8('\t'); + /** + * The fastest way to check for `\t` (==9), '\n'(== 10) and `\r` (==13) relies + * on table lookup instruction. We notice that these are all unique numbers + * between 0..15. Let's prepare a special register, where we put '\t' in the + * 9th position, '\n' - 10th and '\r' - 13th. Then we shuffle this register by + * input register. If the input had `\t` in position X then this shuffled + * register will also have '\t' in that position. Comparing input with this + * shuffled register will mark us all interesting characters in the input. + * + * credit for algorithmic idea: @aqrit, credit for description: + * @DenisYaroshevskiy + */ + static uint8_t rnt_array[16] = {1, 0, 0, 0, 0, 0, 0, 0, + 0, 9, 10, 0, 0, 13, 0, 0}; + const uint8x16_t rnt = vld1q_u8(rnt_array); + // m['0xd', '0xa', '0x9'] uint8x16_t running{0}; for (; i + 15 < user_input.size(); i += 16) { uint8x16_t word = vld1q_u8((const uint8_t*)user_input.data() + i); - running = vorrq_u8(vorrq_u8(running, vorrq_u8(vceqq_u8(word, mask1), - vceqq_u8(word, mask2))), - vceqq_u8(word, mask3)); + + running = vorrq_u8(running, vceqq_u8(vqtbl1q_u8(rnt, word), word)); } if (i < user_input.size()) { uint8x16_t word = vld1q_u8((const uint8_t*)user_input.data() + user_input.length() - 16); - running = vorrq_u8(vorrq_u8(running, vorrq_u8(vceqq_u8(word, mask1), - vceqq_u8(word, mask2))), - vceqq_u8(word, mask3)); + running = vorrq_u8(running, vceqq_u8(vqtbl1q_u8(rnt, word), word)); } - return vmaxvq_u8(running) != 0; + return vmaxvq_u32(vreinterpretq_u32_u8(running)) != 0; } #elif ADA_SSE2 ada_really_inline bool has_tabs_or_newline( std::string_view user_input) noexcept { // first check for short strings in which case we do it naively. if (user_input.size() < 16) { // slow path - for (size_t i = 0; i < user_input.size(); i++) { - if (user_input[i] == '\r' || user_input[i] == '\n' || - user_input[i] == '\t') { - return true; - } - } - return false; + return std::any_of(user_input.begin(), user_input.end(), + is_tabs_or_newline); } // fast path for long strings (expected to be common) size_t i = 0; const __m128i mask1 = _mm_set1_epi8('\r'); const __m128i mask2 = _mm_set1_epi8('\n'); const __m128i mask3 = _mm_set1_epi8('\t'); + // If we supported SSSE3, we could use the algorithm that we use for NEON. __m128i running{0}; for (; i + 15 < user_input.size(); i += 16) { __m128i word = _mm_loadu_si128((const __m128i*)(user_input.data() + i)); @@ -9898,7 +9903,7 @@ ada_really_inline bool has_tabs_or_newline( ada_really_inline bool has_tabs_or_newline( std::string_view user_input) noexcept { auto has_zero_byte = [](uint64_t v) { - return ((v - 0x0101010101010101) & ~(v)&0x8080808080808080); + return ((v - 0x0101010101010101) & ~(v) & 0x8080808080808080); }; size_t i = 0; uint64_t mask1 = broadcast('\r'); @@ -10028,15 +10033,8 @@ contains_forbidden_domain_code_point_or_upper(const char* input, constexpr static std::array is_alnum_plus_table = []() constexpr { std::array result{}; for (size_t c = 0; c < 256; c++) { - if (c >= '0' && c <= '9') { - result[c] = true; - } else if (c >= 'a' && c <= 'z') { - result[c] = true; - } else if (c >= 'A' && c <= 'Z') { - result[c] = true; - } else if (c == '+' || c == '-' || c == '.') { - result[c] = true; - } + result[c] = (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || + (c >= 'A' && c <= 'Z') || c == '+' || c == '-' || c == '.'; } return result; }(); @@ -10260,10 +10258,6 @@ std::string percent_encode(const std::string_view input, return out; } -std::string to_unicode(std::string_view input) { - return ada::idna::to_unicode(input); -} - } // namespace ada::unicode /* end file src/unicode.cpp */ /* begin file src/serializers.cpp */ @@ -10356,7 +10350,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); } @@ -10392,16 +10387,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) { @@ -10659,7 +10660,7 @@ ada_really_inline size_t find_next_host_delimiter_special( uint8x16_t lowpart = vqtbl1q_u8(low_mask, vandq_u8(word, fmask)); uint8x16_t highpart = vqtbl1q_u8(high_mask, vshrq_n_u8(word, 4)); uint8x16_t classify = vandq_u8(lowpart, highpart); - if (vmaxvq_u8(classify) != 0) { + if (vmaxvq_u32(vreinterpretq_u32_u8(classify)) != 0) { uint8x16_t is_zero = vceqq_u8(classify, zero); uint16_t is_non_zero = ~to_bitmask(is_zero); return i + trailing_zeroes(is_non_zero); @@ -10672,7 +10673,7 @@ ada_really_inline size_t find_next_host_delimiter_special( uint8x16_t lowpart = vqtbl1q_u8(low_mask, vandq_u8(word, fmask)); uint8x16_t highpart = vqtbl1q_u8(high_mask, vshrq_n_u8(word, 4)); uint8x16_t classify = vandq_u8(lowpart, highpart); - if (vmaxvq_u8(classify) != 0) { + if (vmaxvq_u32(vreinterpretq_u32_u8(classify)) != 0) { uint8x16_t is_zero = vceqq_u8(classify, zero); uint16_t is_non_zero = ~to_bitmask(is_zero); return view.length() - 16 + trailing_zeroes(is_non_zero); @@ -10797,7 +10798,7 @@ ada_really_inline size_t find_next_host_delimiter(std::string_view view, uint8x16_t lowpart = vqtbl1q_u8(low_mask, vandq_u8(word, fmask)); uint8x16_t highpart = vqtbl1q_u8(high_mask, vshrq_n_u8(word, 4)); uint8x16_t classify = vandq_u8(lowpart, highpart); - if (vmaxvq_u8(classify) != 0) { + if (vmaxvq_u32(vreinterpretq_u32_u8(classify)) != 0) { uint8x16_t is_zero = vceqq_u8(classify, zero); uint16_t is_non_zero = ~to_bitmask(is_zero); return i + trailing_zeroes(is_non_zero); @@ -10810,7 +10811,7 @@ ada_really_inline size_t find_next_host_delimiter(std::string_view view, uint8x16_t lowpart = vqtbl1q_u8(low_mask, vandq_u8(word, fmask)); uint8x16_t highpart = vqtbl1q_u8(high_mask, vshrq_n_u8(word, 4)); uint8x16_t classify = vandq_u8(lowpart, highpart); - if (vmaxvq_u8(classify) != 0) { + if (vmaxvq_u32(vreinterpretq_u32_u8(classify)) != 0) { uint8x16_t is_zero = vceqq_u8(classify, zero); uint16_t is_non_zero = ~to_bitmask(is_zero); return view.length() - 16 + trailing_zeroes(is_non_zero); @@ -11164,7 +11165,7 @@ ada_really_inline void strip_trailing_spaces_from_opaque_path( static constexpr std::array authority_delimiter_special = []() constexpr { std::array result{}; - for (int i : {'@', '/', '\\', '?'}) { + for (uint8_t i : {'@', '/', '\\', '?'}) { result[i] = 1; } return result; @@ -11185,7 +11186,7 @@ find_authority_delimiter_special(std::string_view view) noexcept { // @ / ? static constexpr std::array authority_delimiter = []() constexpr { std::array result{}; - for (int i : {'@', '/', '?'}) { + for (uint8_t i : {'@', '/', '?'}) { result[i] = 1; } return result; @@ -11255,7 +11256,7 @@ bool url::parse_ipv4(std::string_view input) { segment_result = 0; input.remove_prefix(2); } else { - std::from_chars_result r; + std::from_chars_result r{}; if (is_hex) { r = std::from_chars(input.data() + 2, input.data() + input.size(), segment_result, 16); @@ -11585,7 +11586,7 @@ ada_really_inline bool url::parse_scheme(const std::string_view input) { } } } else { // slow path - std::string _buffer = std::string(input); + std::string _buffer(input); // Next function is only valid if the input is ASCII and returns false // otherwise, but it seems that we always have ascii content so we do not // need to check the return value. @@ -11809,7 +11810,6 @@ ada_really_inline void url::parse_path(std::string_view input) { * Includes all the getters of `ada::url` */ -#include #include namespace ada { @@ -12058,7 +12058,6 @@ void url::set_hash(const std::string_view input) { helpers::remove_ascii_tab_or_newline(new_value); hash = unicode::percent_encode(new_value, ada::character_sets::FRAGMENT_PERCENT_ENCODE); - return; } void url::set_search(const std::string_view input) { @@ -12136,14 +12135,14 @@ bool url::set_href(const std::string_view input) { /* end file src/url-setters.cpp */ /* begin file src/parser.cpp */ -#include #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 { @@ -12178,7 +12177,7 @@ result_type parse_url(std::string_view user_input, if (!url.is_valid) { return url; } - if constexpr (result_type_is_ada_url_aggregator) { + if constexpr (result_type_is_ada_url_aggregator && store_values) { // Most of the time, we just need user_input.size(). // In some instances, we may need a bit more. /////////////////////////// @@ -12195,9 +12194,6 @@ result_type parse_url(std::string_view user_input, helpers::leading_zeroes(uint32_t(1 | user_input.size()))) + 1; url.reserve(reserve_capacity); - // - // - // } std::string tmp_buffer; std::string_view internal_input; @@ -12420,32 +12416,36 @@ result_type parse_url(std::string_view user_input, password_token_seen = password_token_location != std::string_view::npos; - if (!password_token_seen) { - if constexpr (result_type_is_ada_url) { - url.username += unicode::percent_encode( - authority_view, character_sets::USERINFO_PERCENT_ENCODE); - } else { - url.append_base_username(unicode::percent_encode( - authority_view, character_sets::USERINFO_PERCENT_ENCODE)); - } - } else { - if constexpr (result_type_is_ada_url) { - url.username += unicode::percent_encode( - authority_view.substr(0, password_token_location), - character_sets::USERINFO_PERCENT_ENCODE); - url.password += unicode::percent_encode( - authority_view.substr(password_token_location + 1), - character_sets::USERINFO_PERCENT_ENCODE); + if constexpr (store_values) { + if (!password_token_seen) { + if constexpr (result_type_is_ada_url) { + url.username += unicode::percent_encode( + authority_view, + character_sets::USERINFO_PERCENT_ENCODE); + } else { + url.append_base_username(unicode::percent_encode( + authority_view, + character_sets::USERINFO_PERCENT_ENCODE)); + } } else { - url.append_base_username(unicode::percent_encode( - authority_view.substr(0, password_token_location), - character_sets::USERINFO_PERCENT_ENCODE)); - url.append_base_password(unicode::percent_encode( - authority_view.substr(password_token_location + 1), - character_sets::USERINFO_PERCENT_ENCODE)); + if constexpr (result_type_is_ada_url) { + url.username += unicode::percent_encode( + authority_view.substr(0, password_token_location), + character_sets::USERINFO_PERCENT_ENCODE); + url.password += unicode::percent_encode( + authority_view.substr(password_token_location + 1), + character_sets::USERINFO_PERCENT_ENCODE); + } else { + url.append_base_username(unicode::percent_encode( + authority_view.substr(0, password_token_location), + character_sets::USERINFO_PERCENT_ENCODE)); + url.append_base_password(unicode::percent_encode( + authority_view.substr(password_token_location + 1), + character_sets::USERINFO_PERCENT_ENCODE)); + } } } - } else { + } else if constexpr (store_values) { if constexpr (result_type_is_ada_url) { url.password += unicode::percent_encode( authority_view, character_sets::USERINFO_PERCENT_ENCODE); @@ -12472,8 +12472,10 @@ result_type parse_url(std::string_view user_input, break; } if (end_of_authority == input_size) { - if (fragment.has_value()) { - url.update_unencoded_base_hash(*fragment); + if constexpr (store_values) { + if (fragment.has_value()) { + url.update_unencoded_base_hash(*fragment); + } } return url; } @@ -12670,19 +12672,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; } @@ -12785,9 +12790,11 @@ result_type parse_url(std::string_view user_input, // Optimization: Avoiding going into PATH state improves the // performance of urls ending with /. if (input_position == input_size) { - url.update_base_pathname("/"); - if (fragment.has_value()) { - url.update_unencoded_base_hash(*fragment); + if constexpr (store_values) { + url.update_base_pathname("/"); + if (fragment.has_value()) { + url.update_unencoded_base_hash(*fragment); + } } return url; } @@ -12833,11 +12840,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; } @@ -13031,17 +13040,29 @@ result_type parse_url(std::string_view user_input, ada::unreachable(); } } - if (fragment.has_value()) { - url.update_unencoded_base_hash(*fragment); + if constexpr (store_values) { + if (fragment.has_value()) { + url.update_unencoded_base_hash(*fragment); + } } 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 /* end file src/parser.cpp */ /* begin file src/url_components.cpp */ @@ -13121,7 +13142,6 @@ namespace ada { if (hash_start < index) { return false; } - index = hash_start; } return true; @@ -13227,7 +13247,7 @@ template } } } else { // slow path - std::string _buffer = std::string(input); + std::string _buffer(input); // Next function is only valid if the input is ASCII and returns false // otherwise, but it seems that we always have ascii content so we do not // need to check the return value. @@ -13479,7 +13499,7 @@ bool url_aggregator::set_pathname(const std::string_view input) { } clear_pathname(); parse_path(input); - if (checkers::begins_with(input, "//") && !has_authority() && + if (checkers::begins_with(get_pathname(), "//") && !has_authority() && !has_dash_dot()) { buffer.insert(components.pathname_start, "/."); components.pathname_start += 2; @@ -13683,7 +13703,7 @@ bool url_aggregator::set_host_or_hostname(const std::string_view input) { return false; } - std::string previous_host = std::string(get_hostname()); + std::string previous_host(get_hostname()); uint32_t previous_port = components.port; size_t host_end_pos = input.find('#'); @@ -13863,7 +13883,7 @@ bool url_aggregator::set_hostname(const std::string_view input) { // if we have an empty host, then the space between components.host_end and // components.pathname_start may be occupied by /. if (start == components.host_end) { - return std::string_view(); + return {}; } return helpers::substring(buffer, start, components.pathname_start); } @@ -13887,7 +13907,7 @@ bool url_aggregator::set_hostname(const std::string_view input) { components.pathname_start, " buffer.size() = ", buffer.size(), " components.search_start = ", components.search_start, " components.hash_start = ", components.hash_start); - uint32_t ending_index = uint32_t(buffer.size()); + auto ending_index = uint32_t(buffer.size()); if (components.search_start != url_components::omitted) { ending_index = components.search_start; } else if (components.hash_start != url_components::omitted) { @@ -13903,7 +13923,7 @@ bool url_aggregator::set_hostname(const std::string_view input) { if (components.search_start == url_components::omitted) { return ""; } - uint32_t ending_index = uint32_t(buffer.size()); + auto ending_index = uint32_t(buffer.size()); if (components.hash_start != url_components::omitted) { ending_index = components.hash_start; } @@ -14041,7 +14061,7 @@ bool url_aggregator::parse_ipv4(std::string_view input, bool in_place) { segment_result = 0; input.remove_prefix(2); } else { - std::from_chars_result r; + std::from_chars_result r{}; if (is_hex) { ada_log("parse_ipv4 trying to parse hex number"); r = std::from_chars(input.data() + 2, input.data() + input.size(), @@ -14983,13 +15003,12 @@ bool ada_can_parse(const char* input, size_t length) noexcept { bool ada_can_parse_with_base(const char* input, size_t input_length, const char* base, size_t base_length) noexcept { - auto base_view = std::string_view(base, base_length); + std::string_view base_view(base, base_length); return ada::can_parse(std::string_view(input, input_length), &base_view); } void ada_free(ada_url result) noexcept { - ada::result* r = - (ada::result*)result; + auto* r = (ada::result*)result; delete r; } @@ -15006,7 +15025,7 @@ bool ada_is_valid(ada_url result) noexcept { // caller must free the result with ada_free_owned_string ada_owned_string ada_get_origin(ada_url result) noexcept { ada::result& r = get_instance(result); - ada_owned_string owned; + ada_owned_string owned{}; if (!r) { owned.data = nullptr; owned.length = 0; @@ -15021,14 +15040,12 @@ ada_owned_string ada_get_origin(ada_url result) noexcept { void ada_free_owned_string(ada_owned_string owned) noexcept { delete[] owned.data; - owned.data = nullptr; - owned.length = 0; } ada_string ada_get_href(ada_url result) noexcept { ada::result& r = get_instance(result); if (!r) { - return ada_string_create(NULL, 0); + return ada_string_create(nullptr, 0); } std::string_view out = r->get_href(); return ada_string_create(out.data(), out.length()); @@ -15037,7 +15054,7 @@ ada_string ada_get_href(ada_url result) noexcept { ada_string ada_get_username(ada_url result) noexcept { ada::result& r = get_instance(result); if (!r) { - return ada_string_create(NULL, 0); + return ada_string_create(nullptr, 0); } std::string_view out = r->get_username(); return ada_string_create(out.data(), out.length()); @@ -15046,7 +15063,7 @@ ada_string ada_get_username(ada_url result) noexcept { ada_string ada_get_password(ada_url result) noexcept { ada::result& r = get_instance(result); if (!r) { - return ada_string_create(NULL, 0); + return ada_string_create(nullptr, 0); } std::string_view out = r->get_password(); return ada_string_create(out.data(), out.length()); @@ -15055,7 +15072,7 @@ ada_string ada_get_password(ada_url result) noexcept { ada_string ada_get_port(ada_url result) noexcept { ada::result& r = get_instance(result); if (!r) { - return ada_string_create(NULL, 0); + return ada_string_create(nullptr, 0); } std::string_view out = r->get_port(); return ada_string_create(out.data(), out.length()); @@ -15064,7 +15081,7 @@ ada_string ada_get_port(ada_url result) noexcept { ada_string ada_get_hash(ada_url result) noexcept { ada::result& r = get_instance(result); if (!r) { - return ada_string_create(NULL, 0); + return ada_string_create(nullptr, 0); } std::string_view out = r->get_hash(); return ada_string_create(out.data(), out.length()); @@ -15073,7 +15090,7 @@ ada_string ada_get_hash(ada_url result) noexcept { ada_string ada_get_host(ada_url result) noexcept { ada::result& r = get_instance(result); if (!r) { - return ada_string_create(NULL, 0); + return ada_string_create(nullptr, 0); } std::string_view out = r->get_host(); return ada_string_create(out.data(), out.length()); @@ -15082,7 +15099,7 @@ ada_string ada_get_host(ada_url result) noexcept { ada_string ada_get_hostname(ada_url result) noexcept { ada::result& r = get_instance(result); if (!r) { - return ada_string_create(NULL, 0); + return ada_string_create(nullptr, 0); } std::string_view out = r->get_hostname(); return ada_string_create(out.data(), out.length()); @@ -15091,7 +15108,7 @@ ada_string ada_get_hostname(ada_url result) noexcept { ada_string ada_get_pathname(ada_url result) noexcept { ada::result& r = get_instance(result); if (!r) { - return ada_string_create(NULL, 0); + return ada_string_create(nullptr, 0); } std::string_view out = r->get_pathname(); return ada_string_create(out.data(), out.length()); @@ -15100,7 +15117,7 @@ ada_string ada_get_pathname(ada_url result) noexcept { ada_string ada_get_search(ada_url result) noexcept { ada::result& r = get_instance(result); if (!r) { - return ada_string_create(NULL, 0); + return ada_string_create(nullptr, 0); } std::string_view out = r->get_search(); return ada_string_create(out.data(), out.length()); @@ -15109,7 +15126,7 @@ ada_string ada_get_search(ada_url result) noexcept { ada_string ada_get_protocol(ada_url result) noexcept { ada::result& r = get_instance(result); if (!r) { - return ada_string_create(NULL, 0); + return ada_string_create(nullptr, 0); } std::string_view out = r->get_protocol(); return ada_string_create(out.data(), out.length()); @@ -15368,15 +15385,14 @@ ada_url_search_params ada_parse_search_params(const char* input, } void ada_free_search_params(ada_url_search_params result) { - ada::result* r = - (ada::result*)result; + auto* r = (ada::result*)result; delete r; } ada_owned_string ada_search_params_to_string(ada_url_search_params result) { ada::result& r = *(ada::result*)result; - if (!r) return ada_owned_string{NULL, 0}; + if (!r) return ada_owned_string{nullptr, 0}; std::string out = r->to_string(); ada_owned_string owned{}; owned.length = out.size(); @@ -15388,14 +15404,27 @@ ada_owned_string ada_search_params_to_string(ada_url_search_params result) { size_t ada_search_params_size(ada_url_search_params result) { ada::result& r = *(ada::result*)result; - if (!r) return 0; + if (!r) { + return 0; + } return r->size(); } void ada_search_params_sort(ada_url_search_params result) { ada::result& r = *(ada::result*)result; - if (r) r->sort(); + if (r) { + r->sort(); + } +} + +void ada_search_params_reset(ada_url_search_params result, const char* input, + size_t length) { + ada::result& r = + *(ada::result*)result; + if (r) { + r->reset(std::string_view(input, length)); + } } void ada_search_params_append(ada_url_search_params result, const char* key, @@ -15444,7 +15473,9 @@ bool ada_search_params_has(ada_url_search_params result, const char* key, size_t key_length) { ada::result& r = *(ada::result*)result; - if (!r) return false; + if (!r) { + return false; + } return r->has(std::string_view(key, key_length)); } @@ -15453,7 +15484,9 @@ bool ada_search_params_has_value(ada_url_search_params result, const char* key, size_t value_length) { ada::result& r = *(ada::result*)result; - if (!r) return false; + if (!r) { + return false; + } return r->has(std::string_view(key, key_length), std::string_view(value, value_length)); } @@ -15462,9 +15495,13 @@ ada_string ada_search_params_get(ada_url_search_params result, const char* key, size_t key_length) { ada::result& r = *(ada::result*)result; - if (!r) return ada_string_create(NULL, 0); + if (!r) { + return ada_string_create(nullptr, 0); + } auto found = r->get(std::string_view(key, key_length)); - if (!found.has_value()) return ada_string_create(NULL, 0); + if (!found.has_value()) { + return ada_string_create(nullptr, 0); + } return ada_string_create(found->data(), found->length()); } @@ -15514,90 +15551,96 @@ ada_url_search_params_entries_iter ada_search_params_get_entries( } void ada_free_strings(ada_strings result) { - ada::result>* r = - (ada::result>*)result; + auto* r = (ada::result>*)result; delete r; } size_t ada_strings_size(ada_strings result) { - ada::result>* r = - (ada::result>*)result; - if (!r) return 0; + auto* r = (ada::result>*)result; + if (!r) { + return 0; + } return (*r)->size(); } ada_string ada_strings_get(ada_strings result, size_t index) { - ada::result>* r = - (ada::result>*)result; - if (!r) return ada_string_create(NULL, 0); + auto* r = (ada::result>*)result; + if (!r) { + return ada_string_create(nullptr, 0); + } std::string_view view = (*r)->at(index); return ada_string_create(view.data(), view.length()); } void ada_free_search_params_keys_iter(ada_url_search_params_keys_iter result) { - ada::result* r = - (ada::result*)result; + auto* r = (ada::result*)result; delete r; } ada_string ada_search_params_keys_iter_next( ada_url_search_params_keys_iter result) { - ada::result* r = - (ada::result*)result; - if (!r) return ada_string_create(NULL, 0); + auto* r = (ada::result*)result; + if (!r) { + return ada_string_create(nullptr, 0); + } auto next = (*r)->next(); - if (!next.has_value()) return ada_string_create(NULL, 0); + if (!next.has_value()) { + return ada_string_create(nullptr, 0); + } return ada_string_create(next->data(), next->length()); } bool ada_search_params_keys_iter_has_next( ada_url_search_params_keys_iter result) { - ada::result* r = - (ada::result*)result; - if (!r) return false; + auto* r = (ada::result*)result; + if (!r) { + return false; + } return (*r)->has_next(); } void ada_free_search_params_values_iter( ada_url_search_params_values_iter result) { - ada::result* r = - (ada::result*)result; + auto* r = (ada::result*)result; delete r; } ada_string ada_search_params_values_iter_next( ada_url_search_params_values_iter result) { - ada::result* r = - (ada::result*)result; - if (!r) return ada_string_create(NULL, 0); + auto* r = (ada::result*)result; + if (!r) { + return ada_string_create(nullptr, 0); + } auto next = (*r)->next(); - if (!next.has_value()) return ada_string_create(NULL, 0); + if (!next.has_value()) { + return ada_string_create(nullptr, 0); + } return ada_string_create(next->data(), next->length()); } bool ada_search_params_values_iter_has_next( ada_url_search_params_values_iter result) { - ada::result* r = - (ada::result*)result; - if (!r) return false; + auto* r = (ada::result*)result; + if (!r) { + return false; + } return (*r)->has_next(); } void ada_free_search_params_entries_iter( ada_url_search_params_entries_iter result) { - ada::result* r = - (ada::result*)result; + auto* r = (ada::result*)result; delete r; } ada_string_pair ada_search_params_entries_iter_next( ada_url_search_params_entries_iter result) { - ada::result* r = - (ada::result*)result; - if (!r) return {ada_string_create(NULL, 0), ada_string_create(NULL, 0)}; + auto* r = (ada::result*)result; + if (!r) return {ada_string_create(nullptr, 0), ada_string_create(nullptr, 0)}; auto next = (*r)->next(); - if (!next.has_value()) - return {ada_string_create(NULL, 0), ada_string_create(NULL, 0)}; + if (!next.has_value()) { + return {ada_string_create(nullptr, 0), ada_string_create(nullptr, 0)}; + } return ada_string_pair{ ada_string_create(next->first.data(), next->first.length()), ada_string_create(next->second.data(), next->second.length())}; @@ -15605,9 +15648,10 @@ ada_string_pair ada_search_params_entries_iter_next( bool ada_search_params_entries_iter_has_next( ada_url_search_params_entries_iter result) { - ada::result* r = - (ada::result*)result; - if (!r) return false; + auto* r = (ada::result*)result; + if (!r) { + return false; + } return (*r)->has_next(); } diff --git a/deps/ada.h b/deps/ada.h index 721ac73..00ccd80 100644 --- a/deps/ada.h +++ b/deps/ada.h @@ -1,4 +1,4 @@ -/* auto-generated on 2024-03-07 13:23:39 -0500. Do not edit! */ +/* auto-generated on 2024-07-06 17:38:56 -0400. Do not edit! */ /* begin file include/ada.h */ /** * @file ada.h @@ -461,9 +461,11 @@ namespace ada { #ifdef ADA_VISUAL_STUDIO #define ADA_ASSUME(COND) __assume(COND) #else -#define ADA_ASSUME(COND) \ - do { \ - if (!(COND)) __builtin_unreachable(); \ +#define ADA_ASSUME(COND) \ + do { \ + if (!(COND)) { \ + __builtin_unreachable(); \ + } \ } while (0) #endif @@ -948,15 +950,15 @@ constexpr uint8_t WWW_FORM_URLENCODED_PERCENT_ENCODE[32] = { // 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, + 0x00 | 0x00 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80, // 40 41 42 43 44 45 46 47 - 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00, + 0x01 | 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, + 0x00 | 0x00 | 0x00 | 0x08 | 0x00 | 0x20 | 0x40 | 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 @@ -964,7 +966,7 @@ constexpr uint8_t WWW_FORM_URLENCODED_PERCENT_ENCODE[32] = { // 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, + 0x00 | 0x00 | 0x00 | 0x08 | 0x10 | 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 @@ -1072,7 +1074,7 @@ ada_really_inline bool begins_with(std::string_view view, } // namespace ada::checkers -#endif // ADA_CHECKERS_H +#endif // ADA_CHECKERS_INL_H /* end file include/ada/checkers-inl.h */ /* begin file include/ada/log.h */ /** @@ -1212,25 +1214,104 @@ namespace ada { * @see https://url.spec.whatwg.org/#url-parsing */ enum class state { + /** + * @see https://url.spec.whatwg.org/#authority-state + */ AUTHORITY, + + /** + * @see https://url.spec.whatwg.org/#scheme-start-state + */ SCHEME_START, + + /** + * @see https://url.spec.whatwg.org/#scheme-state + */ SCHEME, + + /** + * @see https://url.spec.whatwg.org/#host-state + */ HOST, + + /** + * @see https://url.spec.whatwg.org/#no-scheme-state + */ NO_SCHEME, + + /** + * @see https://url.spec.whatwg.org/#fragment-state + */ FRAGMENT, + + /** + * @see https://url.spec.whatwg.org/#relative-state + */ RELATIVE_SCHEME, + + /** + * @see https://url.spec.whatwg.org/#relative-slash-state + */ RELATIVE_SLASH, + + /** + * @see https://url.spec.whatwg.org/#file-state + */ FILE, + + /** + * @see https://url.spec.whatwg.org/#file-host-state + */ FILE_HOST, + + /** + * @see https://url.spec.whatwg.org/#file-slash-state + */ FILE_SLASH, + + /** + * @see https://url.spec.whatwg.org/#path-or-authority-state + */ PATH_OR_AUTHORITY, + + /** + * @see https://url.spec.whatwg.org/#special-authority-ignore-slashes-state + */ SPECIAL_AUTHORITY_IGNORE_SLASHES, + + /** + * @see https://url.spec.whatwg.org/#special-authority-slashes-state + */ SPECIAL_AUTHORITY_SLASHES, + + /** + * @see https://url.spec.whatwg.org/#special-relative-or-authority-state + */ SPECIAL_RELATIVE_OR_AUTHORITY, + + /** + * @see https://url.spec.whatwg.org/#query-state + */ QUERY, + + /** + * @see https://url.spec.whatwg.org/#path-state + */ PATH, + + /** + * @see https://url.spec.whatwg.org/#path-start-state + */ PATH_START, + + /** + * @see https://url.spec.whatwg.org/#cannot-be-a-base-url-path-state + */ OPAQUE_PATH, + + /** + * @see https://url.spec.whatwg.org/#port-state + */ PORT, }; @@ -1774,6 +1855,9 @@ inline int fast_digit_count(uint32_t x) noexcept { #ifndef ADA_PARSER_H #define ADA_PARSER_H +#include +#include + /* begin file include/ada/expected.h */ /** * @file expected.h @@ -2751,8 +2835,9 @@ struct expected_operations_base : expected_storage_base { // This class manages conditionally having a trivial copy constructor // This specialization is for when T and E are trivially copy constructible template :: - value &&TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(E)::value> + bool = is_void_or::value && + TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(E)::value> struct expected_copy_base : expected_operations_base { using expected_operations_base::expected_operations_base; }; @@ -2784,8 +2869,9 @@ struct expected_copy_base : expected_operations_base { // move constructible #ifndef TL_EXPECTED_GCC49 template >::value - &&std::is_trivially_move_constructible::value> + bool = + is_void_or>::value && + std::is_trivially_move_constructible::value> struct expected_move_base : expected_copy_base { using expected_copy_base::expected_copy_base; }; @@ -2814,14 +2900,16 @@ struct expected_move_base : expected_copy_base { }; // This class manages conditionally having a trivial copy assignment operator -template >::value - &&TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(E)::value - &&TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(E)::value - &&TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(E)::value> +template < + class T, class E, + bool = + is_void_or< + T, conjunction>::value && + TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(E)::value && + TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(E)::value && + TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(E)::value> struct expected_copy_assign_base : expected_move_base { using expected_move_base::expected_move_base; }; @@ -2848,14 +2936,15 @@ struct expected_copy_assign_base : expected_move_base { // to make do with a non-trivial move assignment operator even if T is trivially // move assignable #ifndef TL_EXPECTED_GCC49 -template , - std::is_trivially_move_constructible, - std::is_trivially_move_assignable>>:: - value &&std::is_trivially_destructible::value - &&std::is_trivially_move_constructible::value - &&std::is_trivially_move_assignable::value> +template < + class T, class E, + bool = is_void_or< + T, conjunction, + std::is_trivially_move_constructible, + std::is_trivially_move_assignable>>::value && + std::is_trivially_destructible::value && + std::is_trivially_move_constructible::value && + std::is_trivially_move_assignable::value> struct expected_move_assign_base : expected_copy_assign_base { using expected_copy_assign_base::expected_copy_assign_base; }; @@ -2877,10 +2966,10 @@ struct expected_move_assign_base expected_move_assign_base &operator=(const expected_move_assign_base &rhs) = default; - expected_move_assign_base & - operator=(expected_move_assign_base &&rhs) noexcept( - std::is_nothrow_move_constructible::value - &&std::is_nothrow_move_assignable::value) { + expected_move_assign_base &operator=( + expected_move_assign_base + &&rhs) noexcept(std::is_nothrow_move_constructible::value && + std::is_nothrow_move_assignable::value) { this->assign(std::move(rhs)); return *this; } @@ -3769,11 +3858,10 @@ class expected : private detail::expected_move_assign_base, detail::is_swappable::value && (std::is_nothrow_move_constructible::value || std::is_nothrow_move_constructible::value)> - swap(expected &rhs) noexcept( - std::is_nothrow_move_constructible::value - &&detail::is_nothrow_swappable::value - &&std::is_nothrow_move_constructible::value - &&detail::is_nothrow_swappable::value) { + swap(expected &rhs) noexcept(std::is_nothrow_move_constructible::value && + detail::is_nothrow_swappable::value && + std::is_nothrow_move_constructible::value && + detail::is_nothrow_swappable::value) { if (has_value() && rhs.has_value()) { swap_where_both_have_value(rhs, typename std::is_void::type{}); } else if (!has_value() && rhs.has_value()) { @@ -4292,9 +4380,6 @@ void swap(expected &lhs, #endif /* end file include/ada/expected.h */ -#include -#include - /** * @private */ @@ -4308,9 +4393,11 @@ struct url; * @brief Includes the definitions for supported parsers */ namespace ada::parser { - /** - * Parses a url. + * 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 + * parameter that can be used to resolve relative URLs. If the base_url is + * provided, the user_input is resolved against the base_url. */ template result_type parse_url(std::string_view user_input, @@ -4321,6 +4408,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 @@ -4349,6 +4444,30 @@ constexpr std::string_view is_special_list[] = {"http", " ", "https", "ws", constexpr uint16_t special_ports[] = {80, 0, 443, 80, 21, 443, 0, 0}; } // namespace details +/**** + * @private + * In is_special, get_scheme_type, and get_special_port, we + * use a standard hashing technique to find the index of the scheme in + * the is_special_list. The hashing technique is based on the size of + * the scheme and the first character of the scheme. It ensures that we + * do at most one string comparison per call. If the protocol is + * predictible (e.g., it is always "http"), we can get a better average + * performance by using a simpler approach where we loop and compare + * scheme with all possible protocols starting with the most likely + * protocol. Doing multiple comparisons may have a poor worst case + * performance, however. In this instance, we choose a potentially + * slightly lower best-case performance for a better worst-case + * performance. We can revisit this choice at any time. + * + * Reference: + * Schmidt, Douglas C. "Gperf: A perfect hash function generator." + * More C++ gems 17 (2000). + * + * Reference: https://en.wikipedia.org/wiki/Perfect_hash_function + * + * Reference: https://github.com/ada-url/ada/issues/617 + ****/ + ada_really_inline constexpr bool is_special(std::string_view scheme) { if (scheme.empty()) { return false; @@ -4501,12 +4620,6 @@ namespace ada::unicode { bool to_ascii(std::optional& out, std::string_view plain, size_t first_percent); -/** - * @private - * @see https://www.unicode.org/reports/tr46/#ToUnicode - */ -std::string to_unicode(std::string_view input); - /** * @private * Checks if the input has tab or newline characters. @@ -4683,10 +4796,10 @@ constexpr bool to_lower_ascii(char* input, size_t length) noexcept; #ifndef ADA_URL_AGGREGATOR_H #define ADA_URL_AGGREGATOR_H - #include #include + namespace ada { /** @@ -4880,6 +4993,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{}; @@ -5115,7 +5233,6 @@ ada_really_inline constexpr bool verify_dns_length( #ifndef ADA_URL_H #define ADA_URL_H - #include #include #include @@ -5123,6 +5240,7 @@ ada_really_inline constexpr bool verify_dns_length( #include #include + namespace ada { /** @@ -5397,6 +5515,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); @@ -5642,7 +5765,7 @@ inline std::ostream &operator<<(std::ostream &out, const ada::url &u) { if (query.has_value()) { out.search_start = uint32_t(running_index); running_index += get_search().size(); - if (get_search().size() == 0) { + if (get_search().empty()) { running_index++; } } @@ -6113,7 +6236,7 @@ inline void url_aggregator::append_base_pathname(const std::string_view input) { ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer)); #if ADA_DEVELOPMENT_CHECKS // computing the expected password. - std::string path_expected = std::string(get_pathname()); + std::string path_expected(get_pathname()); path_expected.append(input); #endif // ADA_DEVELOPMENT_CHECKS uint32_t ending_index = uint32_t(buffer.size()); @@ -6183,7 +6306,7 @@ inline void url_aggregator::append_base_username(const std::string_view input) { ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer)); #if ADA_DEVELOPMENT_CHECKS // computing the expected password. - std::string username_expected = std::string(get_username()); + std::string username_expected(get_username()); username_expected.append(input); #endif // ADA_DEVELOPMENT_CHECKS add_authority_slashes_if_needed(); @@ -6213,7 +6336,7 @@ inline void url_aggregator::append_base_username(const std::string_view input) { components.hash_start += difference; } #if ADA_DEVELOPMENT_CHECKS - std::string username_after = std::string(get_username()); + std::string username_after(get_username()); ADA_ASSERT_EQUAL( username_expected, username_after, "append_base_username problem after inserting " + std::string(input)); @@ -6339,7 +6462,7 @@ inline void url_aggregator::append_base_password(const std::string_view input) { components.hash_start += difference; } #if ADA_DEVELOPMENT_CHECKS - std::string password_after = std::string(get_password()); + std::string password_after(get_password()); ADA_ASSERT_EQUAL( password_expected, password_after, "append_base_password problem after inserting " + std::string(input)); @@ -6826,7 +6949,7 @@ struct url_search_params { /** * @see https://url.spec.whatwg.org/#urlsearchparams-stringification-behavior */ - inline std::string to_string(); + inline std::string to_string() const; /** * Returns a simple JS-style iterator over all of the keys in this @@ -6864,6 +6987,14 @@ struct url_search_params { inline auto back() const { return params.back(); } inline auto operator[](size_t index) const { return params[index]; } + /** + * @private + * Used to reset the search params to a new input. + * Used primarily for C API. + * @param input + */ + void reset(std::string_view input); + private: typedef std::pair key_value_pair; std::vector params{}; @@ -6934,6 +7065,11 @@ namespace ada { template url_search_params url_search_params_iter::EMPTY; +inline void url_search_params::reset(std::string_view input) { + params.clear(); + initialize(input); +} + inline void url_search_params::initialize(std::string_view input) { if (!input.empty() && input.front() == '?') { input.remove_prefix(1); @@ -6943,12 +7079,12 @@ inline void url_search_params::initialize(std::string_view input) { auto equal = current.find('='); if (equal == std::string_view::npos) { - auto name = std::string(current); + std::string name(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::string name(current.substr(0, equal)); + std::string value(current.substr(equal + 1)); std::replace(name.begin(), name.end(), '+', ' '); std::replace(value.begin(), value.end(), '+', ' '); @@ -7021,7 +7157,7 @@ inline bool url_search_params::has(std::string_view key, return entry != params.end(); } -inline std::string url_search_params::to_string() { +inline std::string url_search_params::to_string() const { auto character_set = ada::character_sets::WWW_FORM_URLENCODED_PERCENT_ENCODE; std::string out{}; for (size_t i = 0; i < params.size(); i++) { @@ -7106,20 +7242,26 @@ inline bool url_search_params_iter::has_next() { template <> inline std::optional url_search_params_keys_iter::next() { - if (!has_next()) return std::nullopt; + if (!has_next()) { + return std::nullopt; + } return params.params[pos++].first; } template <> inline std::optional url_search_params_values_iter::next() { - if (!has_next()) return std::nullopt; + if (!has_next()) { + return std::nullopt; + } return params.params[pos++].second; } template <> inline std::optional url_search_params_entries_iter::next() { - if (!has_next()) return std::nullopt; + if (!has_next()) { + return std::nullopt; + } return params.params[pos++]; } @@ -7137,14 +7279,14 @@ url_search_params_entries_iter::next() { #ifndef ADA_ADA_VERSION_H #define ADA_ADA_VERSION_H -#define ADA_VERSION "2.7.7" +#define ADA_VERSION "2.9.0" namespace ada { enum { ADA_VERSION_MAJOR = 2, - ADA_VERSION_MINOR = 7, - ADA_VERSION_REVISION = 7, + ADA_VERSION_MINOR = 9, + ADA_VERSION_REVISION = 0, }; } // namespace ada diff --git a/deps/ada_c.h b/deps/ada_c.h index 173e27b..44e945c 100644 --- a/deps/ada_c.h +++ b/deps/ada_c.h @@ -151,6 +151,8 @@ ada_string ada_search_params_get(ada_url_search_params result, const char* key, size_t key_length); ada_strings ada_search_params_get_all(ada_url_search_params result, const char* key, size_t key_length); +void ada_search_params_reset(ada_url_search_params result, const char* input, + size_t length); ada_url_search_params_keys_iter ada_search_params_get_keys( ada_url_search_params result); ada_url_search_params_values_iter ada_search_params_get_values(