From a1c2d1b78b02cd993d616846f515ffb0c078655e Mon Sep 17 00:00:00 2001 From: Nathan Walker Date: Tue, 9 Jul 2024 20:37:22 -0700 Subject: [PATCH] feat: Ada 2.9 --- test-app/runtime/src/main/cpp/ada/ada.cpp | 497 ++++---- test-app/runtime/src/main/cpp/ada/ada.h | 1393 ++++++++++++--------- 2 files changed, 1065 insertions(+), 825 deletions(-) diff --git a/test-app/runtime/src/main/cpp/ada/ada.cpp b/test-app/runtime/src/main/cpp/ada/ada.cpp index 449046ff4..8237277f7 100644 --- a/test-app/runtime/src/main/cpp/ada/ada.cpp +++ b/test-app/runtime/src/main/cpp/ada/ada.cpp @@ -1,7 +1,8 @@ -/* auto-generated on 2023-11-19 13:35:02 -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 { @@ -62,24 +63,24 @@ ada_really_inline ada_constexpr bool is_ipv4(std::string_view view) noexcept { // encoding. static constexpr std::array path_signature_table = []() constexpr { - 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) { - result[i] = 1; - } else if (i == 0x25) { - result[i] = 8; - } else if (i == 0x2e) { - result[i] = 4; - } else if (i == 0x5c) { - result[i] = 2; - } else { - result[i] = 0; - } - } - return result; - }(); + 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 == 0x7d || i > 0x7e) { + result[i] = 1; + } else if (i == 0x25) { + result[i] = 8; + } else if (i == 0x2e) { + result[i] = 4; + } else if (i == 0x5c) { + result[i] = 2; + } else { + result[i] = 0; + } + } + return result; +} +(); ada_really_inline constexpr uint8_t path_signature( std::string_view input) noexcept { @@ -9795,6 +9796,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 +9834,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 +9904,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 +10034,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 +10259,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 +10351,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 +10388,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 +10661,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 +10674,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 +10799,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 +10812,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 +11166,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 +11187,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; @@ -11221,7 +11223,7 @@ ada_warn_unused std::string to_string(ada::state state) { namespace ada { bool url::parse_opaque_host(std::string_view input) { - ada_log("parse_opaque_host ", input, "[", input.size(), " bytes]"); + ada_log("parse_opaque_host ", input, " [", input.size(), " bytes]"); if (std::any_of(input.begin(), input.end(), ada::unicode::is_forbidden_host_code_point)) { return is_valid = false; @@ -11235,7 +11237,7 @@ bool url::parse_opaque_host(std::string_view input) { } bool url::parse_ipv4(std::string_view input) { - ada_log("parse_ipv4 ", input, "[", input.size(), " bytes]"); + ada_log("parse_ipv4 ", input, " [", input.size(), " bytes]"); if (input.back() == '.') { input.remove_suffix(1); } @@ -11255,7 +11257,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); @@ -11277,7 +11279,7 @@ bool url::parse_ipv4(std::string_view input) { // We have the last value. // At this stage, ipv4 contains digit_count*8 bits. // So we have 32-digit_count*8 bits left. - if (segment_result > (uint64_t(1) << (32 - digit_count * 8))) { + if (segment_result >= (uint64_t(1) << (32 - digit_count * 8))) { return is_valid = false; } ipv4 <<= (32 - digit_count * 8); @@ -11310,7 +11312,7 @@ bool url::parse_ipv4(std::string_view input) { } bool url::parse_ipv6(std::string_view input) { - ada_log("parse_ipv6 ", input, "[", input.size(), " bytes]"); + ada_log("parse_ipv6 ", input, " [", input.size(), " bytes]"); if (input.empty()) { return is_valid = false; @@ -11585,7 +11587,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. @@ -11634,7 +11636,7 @@ ada_really_inline bool url::parse_scheme(const std::string_view input) { } ada_really_inline bool url::parse_host(std::string_view input) { - ada_log("parse_host ", input, "[", input.size(), " bytes]"); + ada_log("parse_host ", input, " [", input.size(), " bytes]"); if (input.empty()) { return is_valid = false; } // technically unnecessary. @@ -11686,6 +11688,8 @@ ada_really_inline bool url::parse_host(std::string_view input) { ada_log("parse_host to_ascii returns false"); return is_valid = false; } + ada_log("parse_host to_ascii succeeded ", *host, " [", host->size(), + " bytes]"); if (std::any_of(host.value().begin(), host.value().end(), ada::unicode::is_forbidden_domain_code_point)) { @@ -11696,7 +11700,7 @@ ada_really_inline bool url::parse_host(std::string_view input) { // If asciiDomain ends in a number, then return the result of IPv4 parsing // asciiDomain. if (checkers::is_ipv4(host.value())) { - ada_log("parse_host got ipv4", *host); + ada_log("parse_host got ipv4 ", *host); return parse_ipv4(host.value()); } @@ -11807,7 +11811,6 @@ ada_really_inline void url::parse_path(std::string_view input) { * Includes all the getters of `ada::url` */ -#include #include namespace ada { @@ -12056,7 +12059,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) { @@ -12134,14 +12136,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 { @@ -12176,7 +12178,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. /////////////////////////// @@ -12193,9 +12195,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; @@ -12418,32 +12417,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); @@ -12470,8 +12473,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; } @@ -12668,19 +12673,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; } @@ -12783,9 +12791,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; } @@ -12831,11 +12841,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; } @@ -13029,17 +13041,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 */ @@ -13119,7 +13143,6 @@ namespace ada { if (hash_start < index) { return false; } - index = hash_start; } return true; @@ -13225,7 +13248,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. @@ -13477,7 +13500,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; @@ -13571,7 +13594,7 @@ void url_aggregator::set_hash(const std::string_view input) { bool url_aggregator::set_href(const std::string_view input) { ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer)); - ada_log("url_aggregator::set_href ", input, "[", input.size(), " bytes]"); + ada_log("url_aggregator::set_href ", input, " [", input.size(), " bytes]"); ada::result out = ada::parse(input); ada_log("url_aggregator::set_href, success :", out.has_value()); @@ -13585,7 +13608,8 @@ bool url_aggregator::set_href(const std::string_view input) { } ada_really_inline bool url_aggregator::parse_host(std::string_view input) { - ada_log("url_aggregator:parse_host ", input, "[", input.size(), " bytes]"); + ada_log("url_aggregator:parse_host \"", input, "\" [", input.size(), + " bytes]"); ADA_ASSERT_TRUE(validate()); ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer)); if (input.empty()) { @@ -13635,7 +13659,7 @@ ada_really_inline bool url_aggregator::parse_host(std::string_view input) { update_base_hostname(input); if (checkers::is_ipv4(get_hostname())) { ada_log("parse_host fast path ipv4"); - return parse_ipv4(get_hostname()); + return parse_ipv4(get_hostname(), true); } ada_log("parse_host fast path ", get_hostname()); return true; @@ -13651,6 +13675,8 @@ ada_really_inline bool url_aggregator::parse_host(std::string_view input) { ada_log("parse_host to_ascii returns false"); return is_valid = false; } + ada_log("parse_host to_ascii succeeded ", *host, " [", host->size(), + " bytes]"); if (std::any_of(host.value().begin(), host.value().end(), ada::unicode::is_forbidden_domain_code_point)) { @@ -13660,8 +13686,8 @@ ada_really_inline bool url_aggregator::parse_host(std::string_view input) { // If asciiDomain ends in a number, then return the result of IPv4 parsing // asciiDomain. if (checkers::is_ipv4(host.value())) { - ada_log("parse_host got ipv4", *host); - return parse_ipv4(host.value()); + ada_log("parse_host got ipv4 ", *host); + return parse_ipv4(host.value(), false); } update_base_hostname(host.value()); @@ -13678,7 +13704,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('#'); @@ -13858,7 +13884,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); } @@ -13882,7 +13908,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) { @@ -13898,7 +13924,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; } @@ -13914,7 +13940,7 @@ bool url_aggregator::set_hostname(const std::string_view input) { } [[nodiscard]] std::string ada::url_aggregator::to_string() const { - ada_log("url_aggregator::to_string buffer:", buffer, "[", buffer.size(), + ada_log("url_aggregator::to_string buffer:", buffer, " [", buffer.size(), " bytes]"); if (!is_valid) { return "null"; @@ -14013,8 +14039,8 @@ bool url_aggregator::set_hostname(const std::string_view input) { return checkers::verify_dns_length(get_hostname()); } -bool url_aggregator::parse_ipv4(std::string_view input) { - ada_log("parse_ipv4 ", input, "[", input.size(), +bool url_aggregator::parse_ipv4(std::string_view input, bool in_place) { + ada_log("parse_ipv4 ", input, " [", input.size(), " bytes], overlaps with buffer: ", helpers::overlaps(input, buffer) ? "yes" : "no"); ADA_ASSERT_TRUE(validate()); @@ -14036,29 +14062,34 @@ bool url_aggregator::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) { + ada_log("parse_ipv4 trying to parse hex number"); r = std::from_chars(input.data() + 2, input.data() + input.size(), segment_result, 16); } else if ((input.length() >= 2) && input[0] == '0' && checkers::is_digit(input[1])) { + ada_log("parse_ipv4 trying to parse octal number"); r = std::from_chars(input.data() + 1, input.data() + input.size(), segment_result, 8); } else { + ada_log("parse_ipv4 trying to parse decimal number"); pure_decimal_count++; r = std::from_chars(input.data(), input.data() + input.size(), segment_result, 10); } if (r.ec != std::errc()) { + ada_log("parse_ipv4 parsing failed"); return is_valid = false; } + ada_log("parse_ipv4 parsed ", segment_result); input.remove_prefix(r.ptr - input.data()); } if (input.empty()) { // We have the last value. // At this stage, ipv4 contains digit_count*8 bits. // So we have 32-digit_count*8 bits left. - if (segment_result > (uint64_t(1) << (32 - digit_count * 8))) { + if (segment_result >= (uint64_t(1) << (32 - digit_count * 8))) { return is_valid = false; } ipv4 <<= (32 - digit_count * 8); @@ -14076,6 +14107,7 @@ bool url_aggregator::parse_ipv4(std::string_view input) { } } if ((digit_count != 4) || (!input.empty())) { + ada_log("parse_ipv4 found invalid (more than 4 numbers or empty) "); return is_valid = false; } final: @@ -14083,10 +14115,14 @@ bool url_aggregator::parse_ipv4(std::string_view input) { " host: ", get_host()); // We could also check r.ptr to see where the parsing ended. - if (pure_decimal_count == 4 && !trailing_dot) { + if (in_place && pure_decimal_count == 4 && !trailing_dot) { + ada_log( + "url_aggregator::parse_ipv4 completed and was already correct in the " + "buffer"); // The original input was already all decimal and we validated it. So we // don't need to do anything. } else { + ada_log("url_aggregator::parse_ipv4 completed and we need to update it"); // Optimization opportunity: Get rid of unnecessary string return in ipv4 // serializer. // TODO: This is likely a bug because it goes back update_base_hostname, not @@ -14100,8 +14136,11 @@ bool url_aggregator::parse_ipv4(std::string_view input) { } bool url_aggregator::parse_ipv6(std::string_view input) { + // TODO: Implement in_place optimization: we know that input points + // in the buffer, so we can just check whether the buffer is already + // well formatted. // TODO: Find a way to merge parse_ipv6 with url.cpp implementation. - ada_log("parse_ipv6 ", input, "[", input.size(), " bytes]"); + ada_log("parse_ipv6 ", input, " [", input.size(), " bytes]"); ADA_ASSERT_TRUE(validate()); ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer)); if (input.empty()) { @@ -14335,7 +14374,7 @@ bool url_aggregator::parse_ipv6(std::string_view input) { } bool url_aggregator::parse_opaque_host(std::string_view input) { - ada_log("parse_opaque_host ", input, "[", input.size(), " bytes]"); + ada_log("parse_opaque_host ", input, " [", input.size(), " bytes]"); ADA_ASSERT_TRUE(validate()); ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer)); if (std::any_of(input.begin(), input.end(), @@ -14965,13 +15004,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; } @@ -14988,7 +15026,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; @@ -15003,14 +15041,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()); @@ -15019,7 +15055,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()); @@ -15028,7 +15064,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()); @@ -15037,7 +15073,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()); @@ -15046,7 +15082,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()); @@ -15055,7 +15091,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()); @@ -15064,7 +15100,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()); @@ -15073,7 +15109,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()); @@ -15082,7 +15118,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()); @@ -15091,7 +15127,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()); @@ -15350,15 +15386,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(); @@ -15370,14 +15405,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, @@ -15426,7 +15474,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)); } @@ -15435,7 +15485,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)); } @@ -15444,9 +15496,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()); } @@ -15496,90 +15552,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())}; @@ -15587,9 +15649,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/test-app/runtime/src/main/cpp/ada/ada.h b/test-app/runtime/src/main/cpp/ada/ada.h index a4aa39d17..a42ed6efe 100644 --- a/test-app/runtime/src/main/cpp/ada/ada.h +++ b/test-app/runtime/src/main/cpp/ada/ada.h @@ -1,4 +1,4 @@ -/* auto-generated on 2023-11-19 13:35:02 -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 @@ -482,6 +484,9 @@ namespace ada { #include /** + * These functions are not part of our public API and may + * change at any time. + * @private * @namespace ada::character_sets * @brief Includes the definitions for unicode character sets. */ @@ -492,6 +497,11 @@ ada_really_inline bool bit_at(const uint8_t a[], uint8_t i); #endif // ADA_CHARACTER_SETS_H /* end file include/ada/character_sets.h */ +/** + * These functions are not part of our public API and may + * change at any time. + * @private + */ namespace ada::character_sets { constexpr char hex[1024] = @@ -936,19 +946,19 @@ constexpr uint8_t WWW_FORM_URLENCODED_PERCENT_ENCODE[32] = { // 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, + 0x01 | 0x02 | 0x00 | 0x08 | 0x10 | 0x00 | 0x00 | 0x80, // 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 @@ -956,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 @@ -1006,10 +1016,9 @@ ada_really_inline bool bit_at(const uint8_t a[], const uint8_t i) { #ifndef ADA_CHECKERS_INL_H #define ADA_CHECKERS_INL_H - #include -#include #include +#include namespace ada::checkers { @@ -1064,7 +1073,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 */ /** @@ -1195,7 +1204,6 @@ ada_warn_unused std::string to_string(encoding_type type); #ifndef ADA_STATE_H #define ADA_STATE_H - #include namespace ada { @@ -1204,25 +1212,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, }; @@ -1251,7 +1338,6 @@ ada_warn_unused std::string to_string(ada::state s); #ifndef ADA_URL_COMPONENTS_H #define ADA_URL_COMPONENTS_H - #include #include @@ -1269,10 +1355,10 @@ struct url_components { constexpr static uint32_t omitted = uint32_t(-1); url_components() = default; - url_components(const url_components &u) = default; - url_components(url_components &&u) noexcept = default; - url_components &operator=(url_components &&u) noexcept = default; - url_components &operator=(const url_components &u) = default; + url_components(const url_components& u) = default; + url_components(url_components&& u) noexcept = default; + url_components& operator=(url_components&& u) noexcept = default; + url_components& operator=(const url_components& u) = default; ~url_components() = default; /* @@ -1332,7 +1418,6 @@ struct url_components { #ifndef ADA_SCHEME_H #define ADA_SCHEME_H - #include #include #include @@ -1536,10 +1621,13 @@ struct url_base { #endif /* end file include/ada/url_base.h */ -#include #include +#include /** + * These functions are not part of our public API and may + * change at any time. + * * @private * @namespace ada::helpers * @brief Includes the definitions for helper functions @@ -1702,6 +1790,7 @@ inline void inner_concat(std::string& buffer, T t, Args... args) { } /** + * @private * Concatenate the arguments and return a string. * @returns a string */ @@ -1713,6 +1802,7 @@ std::string concat(Args... args) { } /** + * @private * @return Number of leading zeroes. */ inline int leading_zeroes(uint32_t input_num) noexcept { @@ -1726,6 +1816,7 @@ inline int leading_zeroes(uint32_t input_num) noexcept { } /** + * @private * Counts the number of decimal digits necessary to represent x. * faster than std::to_string(x).size(). * @return digit count @@ -1760,6 +1851,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 @@ -1914,25 +2008,25 @@ class unexpected { static_assert(!std::is_same::value, "E must not be void"); unexpected() = delete; - constexpr explicit unexpected(const E &e) : m_val(e) {} + constexpr explicit unexpected(const E& e) : m_val(e) {} - constexpr explicit unexpected(E &&e) : m_val(std::move(e)) {} + constexpr explicit unexpected(E&& e) : m_val(std::move(e)) {} template ::value>::type * = nullptr> - constexpr explicit unexpected(Args &&...args) + E, Args&&...>::value>::type* = nullptr> + constexpr explicit unexpected(Args&&... args) : m_val(std::forward(args)...) {} template < class U, class... Args, typename std::enable_if &, Args &&...>::value>::type * = nullptr> - constexpr explicit unexpected(std::initializer_list l, Args &&...args) + E, std::initializer_list&, Args&&...>::value>::type* = nullptr> + constexpr explicit unexpected(std::initializer_list l, Args&&... args) : m_val(l, std::forward(args)...) {} - constexpr const E &value() const & { return m_val; } - TL_EXPECTED_11_CONSTEXPR E &value() & { return m_val; } - TL_EXPECTED_11_CONSTEXPR E &&value() && { return std::move(m_val); } - constexpr const E &&value() const && { return std::move(m_val); } + constexpr const E& value() const& { return m_val; } + TL_EXPECTED_11_CONSTEXPR E& value() & { return m_val; } + TL_EXPECTED_11_CONSTEXPR E&& value() && { return std::move(m_val); } + constexpr const E&& value() const&& { return std::move(m_val); } private: E m_val; @@ -1944,32 +2038,32 @@ unexpected(E) -> unexpected; #endif template -constexpr bool operator==(const unexpected &lhs, const unexpected &rhs) { +constexpr bool operator==(const unexpected& lhs, const unexpected& rhs) { return lhs.value() == rhs.value(); } template -constexpr bool operator!=(const unexpected &lhs, const unexpected &rhs) { +constexpr bool operator!=(const unexpected& lhs, const unexpected& rhs) { return lhs.value() != rhs.value(); } template -constexpr bool operator<(const unexpected &lhs, const unexpected &rhs) { +constexpr bool operator<(const unexpected& lhs, const unexpected& rhs) { return lhs.value() < rhs.value(); } template -constexpr bool operator<=(const unexpected &lhs, const unexpected &rhs) { +constexpr bool operator<=(const unexpected& lhs, const unexpected& rhs) { return lhs.value() <= rhs.value(); } template -constexpr bool operator>(const unexpected &lhs, const unexpected &rhs) { +constexpr bool operator>(const unexpected& lhs, const unexpected& rhs) { return lhs.value() > rhs.value(); } template -constexpr bool operator>=(const unexpected &lhs, const unexpected &rhs) { +constexpr bool operator>=(const unexpected& lhs, const unexpected& rhs) { return lhs.value() >= rhs.value(); } template -unexpected::type> make_unexpected(E &&e) { +unexpected::type> make_unexpected(E&& e) { return unexpected::type>(std::forward(e)); } @@ -1980,7 +2074,7 @@ static constexpr unexpect_t unexpect{}; namespace detail { template -[[noreturn]] TL_EXPECTED_11_CONSTEXPR void throw_exception(E &&e) { +[[noreturn]] TL_EXPECTED_11_CONSTEXPR void throw_exception(E&& e) { #ifdef TL_EXPECTED_EXCEPTIONS_ENABLED throw std::forward(e); #else @@ -2030,7 +2124,7 @@ template struct is_pointer_to_non_const_member_func : std::true_type {}; template -struct is_pointer_to_non_const_member_func +struct is_pointer_to_non_const_member_func : std::true_type {}; template struct is_pointer_to_non_const_member_func @@ -2039,16 +2133,16 @@ template struct is_pointer_to_non_const_member_func : std::true_type {}; template -struct is_pointer_to_non_const_member_func +struct is_pointer_to_non_const_member_func : std::true_type {}; template -struct is_pointer_to_non_const_member_func +struct is_pointer_to_non_const_member_func : std::true_type {}; template struct is_const_or_const_ref : std::false_type {}; template -struct is_const_or_const_ref : std::true_type {}; +struct is_const_or_const_ref : std::true_type {}; template struct is_const_or_const_ref : std::true_type {}; #endif @@ -2062,7 +2156,7 @@ template < is_const_or_const_ref::value)>, #endif typename = enable_if_t>::value>, int = 0> -constexpr auto invoke(Fn &&f, Args &&...args) noexcept( +constexpr auto invoke(Fn&& f, Args&&... args) noexcept( noexcept(std::mem_fn(f)(std::forward(args)...))) -> decltype(std::mem_fn(f)(std::forward(args)...)) { return std::mem_fn(f)(std::forward(args)...); @@ -2070,7 +2164,7 @@ constexpr auto invoke(Fn &&f, Args &&...args) noexcept( template >::value>> -constexpr auto invoke(Fn &&f, Args &&...args) noexcept( +constexpr auto invoke(Fn&& f, Args&&... args) noexcept( noexcept(std::forward(f)(std::forward(args)...))) -> decltype(std::forward(f)(std::forward(args)...)) { return std::forward(f)(std::forward(args)...); @@ -2110,7 +2204,7 @@ namespace swap_adl_tests { struct tag {}; template -tag swap(T &, T &); +tag swap(T&, T&); template tag swap(T (&a)[N], T (&b)[N]); @@ -2119,14 +2213,14 @@ tag swap(T (&a)[N], T (&b)[N]); template std::false_type can_swap(...) noexcept(false); template (), std::declval()))> -std::true_type can_swap(int) noexcept(noexcept(swap(std::declval(), - std::declval()))); + class = decltype(swap(std::declval(), std::declval()))> +std::true_type can_swap(int) noexcept(noexcept(swap(std::declval(), + std::declval()))); template std::false_type uses_std(...); template -std::is_same(), std::declval())), tag> +std::is_same(), std::declval())), tag> uses_std(int); template @@ -2157,8 +2251,8 @@ struct is_swappable : std::integral_constant< bool, decltype(detail::swap_adl_tests::can_swap(0))::value && - (!decltype(detail::swap_adl_tests::uses_std( - 0))::value || + (!decltype( + detail::swap_adl_tests::uses_std(0))::value || is_swappable::value)> {}; template @@ -2166,10 +2260,12 @@ struct is_nothrow_swappable : std::integral_constant< bool, is_swappable::value && - ((decltype(detail::swap_adl_tests::uses_std(0))::value && - detail::swap_adl_tests::is_std_swap_noexcept::value) || - (!decltype(detail::swap_adl_tests::uses_std(0))::value && - detail::swap_adl_tests::is_adl_swap_noexcept::value))> {}; + ((decltype(detail::swap_adl_tests::uses_std(0))::value&& + detail::swap_adl_tests::is_std_swap_noexcept::value) || + (!decltype(detail::swap_adl_tests::uses_std(0))::value&& + detail::swap_adl_tests::is_adl_swap_noexcept::value))> { +}; #endif #endif @@ -2183,7 +2279,7 @@ using is_expected = is_expected_impl>; template using expected_enable_forward_value = detail::enable_if_t< - std::is_constructible::value && + std::is_constructible::value && !std::is_same, in_place_t>::value && !std::is_same, detail::decay_t>::value && !std::is_same, detail::decay_t>::value>; @@ -2192,14 +2288,14 @@ template using expected_enable_from_other = detail::enable_if_t< std::is_constructible::value && std::is_constructible::value && - !std::is_constructible &>::value && - !std::is_constructible &&>::value && - !std::is_constructible &>::value && - !std::is_constructible &&>::value && - !std::is_convertible &, T>::value && - !std::is_convertible &&, T>::value && - !std::is_convertible &, T>::value && - !std::is_convertible &&, T>::value>; + !std::is_constructible&>::value && + !std::is_constructible&&>::value && + !std::is_constructible&>::value && + !std::is_constructible&&>::value && + !std::is_convertible&, T>::value && + !std::is_convertible&&, T>::value && + !std::is_convertible&, T>::value && + !std::is_convertible&&, T>::value>; template using is_void_or = conditional_t::value, std::true_type, U>; @@ -2237,29 +2333,29 @@ struct expected_storage_base { constexpr expected_storage_base(no_init_t) : m_no_init(), m_has_val(false) {} template ::value> * = + detail::enable_if_t::value>* = nullptr> - constexpr expected_storage_base(in_place_t, Args &&...args) + constexpr expected_storage_base(in_place_t, Args&&... args) : m_val(std::forward(args)...), m_has_val(true) {} template &, Args &&...>::value> * = nullptr> + T, std::initializer_list&, Args&&...>::value>* = nullptr> constexpr expected_storage_base(in_place_t, std::initializer_list il, - Args &&...args) + Args&&... args) : m_val(il, std::forward(args)...), m_has_val(true) {} template ::value> * = + detail::enable_if_t::value>* = nullptr> - constexpr explicit expected_storage_base(unexpect_t, Args &&...args) + constexpr explicit expected_storage_base(unexpect_t, Args&&... args) : m_unexpect(std::forward(args)...), m_has_val(false) {} template &, Args &&...>::value> * = nullptr> + E, std::initializer_list&, Args&&...>::value>* = nullptr> constexpr explicit expected_storage_base(unexpect_t, std::initializer_list il, - Args &&...args) + Args&&... args) : m_unexpect(il, std::forward(args)...), m_has_val(false) {} ~expected_storage_base() { @@ -2285,29 +2381,29 @@ struct expected_storage_base { constexpr expected_storage_base(no_init_t) : m_no_init(), m_has_val(false) {} template ::value> * = + detail::enable_if_t::value>* = nullptr> - constexpr expected_storage_base(in_place_t, Args &&...args) + constexpr expected_storage_base(in_place_t, Args&&... args) : m_val(std::forward(args)...), m_has_val(true) {} template &, Args &&...>::value> * = nullptr> + T, std::initializer_list&, Args&&...>::value>* = nullptr> constexpr expected_storage_base(in_place_t, std::initializer_list il, - Args &&...args) + Args&&... args) : m_val(il, std::forward(args)...), m_has_val(true) {} template ::value> * = + detail::enable_if_t::value>* = nullptr> - constexpr explicit expected_storage_base(unexpect_t, Args &&...args) + constexpr explicit expected_storage_base(unexpect_t, Args&&... args) : m_unexpect(std::forward(args)...), m_has_val(false) {} template &, Args &&...>::value> * = nullptr> + E, std::initializer_list&, Args&&...>::value>* = nullptr> constexpr explicit expected_storage_base(unexpect_t, std::initializer_list il, - Args &&...args) + Args&&... args) : m_unexpect(il, std::forward(args)...), m_has_val(false) {} ~expected_storage_base() = default; @@ -2327,29 +2423,29 @@ struct expected_storage_base { : m_no_init(), m_has_val(false) {} template ::value> * = + detail::enable_if_t::value>* = nullptr> - constexpr expected_storage_base(in_place_t, Args &&...args) + constexpr expected_storage_base(in_place_t, Args&&... args) : m_val(std::forward(args)...), m_has_val(true) {} template &, Args &&...>::value> * = nullptr> + T, std::initializer_list&, Args&&...>::value>* = nullptr> constexpr expected_storage_base(in_place_t, std::initializer_list il, - Args &&...args) + Args&&... args) : m_val(il, std::forward(args)...), m_has_val(true) {} template ::value> * = + detail::enable_if_t::value>* = nullptr> - constexpr explicit expected_storage_base(unexpect_t, Args &&...args) + constexpr explicit expected_storage_base(unexpect_t, Args&&... args) : m_unexpect(std::forward(args)...), m_has_val(false) {} template &, Args &&...>::value> * = nullptr> + E, std::initializer_list&, Args&&...>::value>* = nullptr> constexpr explicit expected_storage_base(unexpect_t, std::initializer_list il, - Args &&...args) + Args&&... args) : m_unexpect(il, std::forward(args)...), m_has_val(false) {} ~expected_storage_base() { @@ -2373,29 +2469,29 @@ struct expected_storage_base { constexpr expected_storage_base(no_init_t) : m_no_init(), m_has_val(false) {} template ::value> * = + detail::enable_if_t::value>* = nullptr> - constexpr expected_storage_base(in_place_t, Args &&...args) + constexpr expected_storage_base(in_place_t, Args&&... args) : m_val(std::forward(args)...), m_has_val(true) {} template &, Args &&...>::value> * = nullptr> + T, std::initializer_list&, Args&&...>::value>* = nullptr> constexpr expected_storage_base(in_place_t, std::initializer_list il, - Args &&...args) + Args&&... args) : m_val(il, std::forward(args)...), m_has_val(true) {} template ::value> * = + detail::enable_if_t::value>* = nullptr> - constexpr explicit expected_storage_base(unexpect_t, Args &&...args) + constexpr explicit expected_storage_base(unexpect_t, Args&&... args) : m_unexpect(std::forward(args)...), m_has_val(false) {} template &, Args &&...>::value> * = nullptr> + E, std::initializer_list&, Args&&...>::value>* = nullptr> constexpr explicit expected_storage_base(unexpect_t, std::initializer_list il, - Args &&...args) + Args&&... args) : m_unexpect(il, std::forward(args)...), m_has_val(false) {} ~expected_storage_base() { @@ -2426,17 +2522,17 @@ struct expected_storage_base { constexpr expected_storage_base(in_place_t) : m_has_val(true) {} template ::value> * = + detail::enable_if_t::value>* = nullptr> - constexpr explicit expected_storage_base(unexpect_t, Args &&...args) + constexpr explicit expected_storage_base(unexpect_t, Args&&... args) : m_unexpect(std::forward(args)...), m_has_val(false) {} template &, Args &&...>::value> * = nullptr> + E, std::initializer_list&, Args&&...>::value>* = nullptr> constexpr explicit expected_storage_base(unexpect_t, std::initializer_list il, - Args &&...args) + Args&&... args) : m_unexpect(il, std::forward(args)...), m_has_val(false) {} ~expected_storage_base() = default; @@ -2457,17 +2553,17 @@ struct expected_storage_base { constexpr expected_storage_base(in_place_t) : m_dummy(), m_has_val(true) {} template ::value> * = + detail::enable_if_t::value>* = nullptr> - constexpr explicit expected_storage_base(unexpect_t, Args &&...args) + constexpr explicit expected_storage_base(unexpect_t, Args&&... args) : m_unexpect(std::forward(args)...), m_has_val(false) {} template &, Args &&...>::value> * = nullptr> + E, std::initializer_list&, Args&&...>::value>* = nullptr> constexpr explicit expected_storage_base(unexpect_t, std::initializer_list il, - Args &&...args) + Args&&... args) : m_unexpect(il, std::forward(args)...), m_has_val(false) {} ~expected_storage_base() { @@ -2490,19 +2586,19 @@ struct expected_operations_base : expected_storage_base { using expected_storage_base::expected_storage_base; template - void construct(Args &&...args) noexcept { + void construct(Args&&... args) noexcept { new (std::addressof(this->m_val)) T(std::forward(args)...); this->m_has_val = true; } template - void construct_with(Rhs &&rhs) noexcept { + void construct_with(Rhs&& rhs) noexcept { new (std::addressof(this->m_val)) T(std::forward(rhs).get()); this->m_has_val = true; } template - void construct_error(Args &&...args) noexcept { + void construct_error(Args&&... args) noexcept { new (std::addressof(this->m_unexpect)) unexpected(std::forward(args)...); this->m_has_val = false; @@ -2517,9 +2613,9 @@ struct expected_operations_base : expected_storage_base { // This overload handles the case where we can just copy-construct `T` // directly into place without throwing. template ::value> - * = nullptr> - void assign(const expected_operations_base &rhs) noexcept { + detail::enable_if_t::value>* = + nullptr> + void assign(const expected_operations_base& rhs) noexcept { if (!this->m_has_val && rhs.m_has_val) { geterr().~unexpected(); construct(rhs.get()); @@ -2532,9 +2628,9 @@ struct expected_operations_base : expected_storage_base { // `T`, then no-throw move it into place if the copy was successful. template ::value && - std::is_nothrow_move_constructible::value> - * = nullptr> - void assign(const expected_operations_base &rhs) noexcept { + std::is_nothrow_move_constructible::value>* = + nullptr> + void assign(const expected_operations_base& rhs) noexcept { if (!this->m_has_val && rhs.m_has_val) { T tmp = rhs.get(); geterr().~unexpected(); @@ -2550,10 +2646,10 @@ struct expected_operations_base : expected_storage_base { // then we move the old unexpected value back into place before rethrowing the // exception. template ::value && - !std::is_nothrow_move_constructible::value> - * = nullptr> - void assign(const expected_operations_base &rhs) { + detail::enable_if_t< + !std::is_nothrow_copy_constructible::value && + !std::is_nothrow_move_constructible::value>* = nullptr> + void assign(const expected_operations_base& rhs) { if (!this->m_has_val && rhs.m_has_val) { auto tmp = std::move(geterr()); geterr().~unexpected(); @@ -2575,9 +2671,9 @@ struct expected_operations_base : expected_storage_base { // These overloads do the same as above, but for rvalues template ::value> - * = nullptr> - void assign(expected_operations_base &&rhs) noexcept { + detail::enable_if_t::value>* = + nullptr> + void assign(expected_operations_base&& rhs) noexcept { if (!this->m_has_val && rhs.m_has_val) { geterr().~unexpected(); construct(std::move(rhs).get()); @@ -2587,9 +2683,9 @@ struct expected_operations_base : expected_storage_base { } template ::value> - * = nullptr> - void assign(expected_operations_base &&rhs) { + detail::enable_if_t< + !std::is_nothrow_move_constructible::value>* = nullptr> + void assign(expected_operations_base&& rhs) { if (!this->m_has_val && rhs.m_has_val) { auto tmp = std::move(geterr()); geterr().~unexpected(); @@ -2611,7 +2707,7 @@ struct expected_operations_base : expected_storage_base { #else // If exceptions are disabled then we can just copy-construct - void assign(const expected_operations_base &rhs) noexcept { + void assign(const expected_operations_base& rhs) noexcept { if (!this->m_has_val && rhs.m_has_val) { geterr().~unexpected(); construct(rhs.get()); @@ -2620,7 +2716,7 @@ struct expected_operations_base : expected_storage_base { } } - void assign(expected_operations_base &&rhs) noexcept { + void assign(expected_operations_base&& rhs) noexcept { if (!this->m_has_val && rhs.m_has_val) { geterr().~unexpected(); construct(std::move(rhs).get()); @@ -2633,7 +2729,7 @@ struct expected_operations_base : expected_storage_base { // The common part of move/copy assigning template - void assign_common(Rhs &&rhs) { + void assign_common(Rhs&& rhs) { if (this->m_has_val) { if (rhs.m_has_val) { get() = std::forward(rhs).get(); @@ -2650,22 +2746,22 @@ struct expected_operations_base : expected_storage_base { bool has_value() const { return this->m_has_val; } - TL_EXPECTED_11_CONSTEXPR T &get() & { return this->m_val; } - constexpr const T &get() const & { return this->m_val; } - TL_EXPECTED_11_CONSTEXPR T &&get() && { return std::move(this->m_val); } + TL_EXPECTED_11_CONSTEXPR T& get() & { return this->m_val; } + constexpr const T& get() const& { return this->m_val; } + TL_EXPECTED_11_CONSTEXPR T&& get() && { return std::move(this->m_val); } #ifndef TL_EXPECTED_NO_CONSTRR - constexpr const T &&get() const && { return std::move(this->m_val); } + constexpr const T&& get() const&& { return std::move(this->m_val); } #endif - TL_EXPECTED_11_CONSTEXPR unexpected &geterr() & { + TL_EXPECTED_11_CONSTEXPR unexpected& geterr() & { return this->m_unexpect; } - constexpr const unexpected &geterr() const & { return this->m_unexpect; } - TL_EXPECTED_11_CONSTEXPR unexpected &&geterr() && { + constexpr const unexpected& geterr() const& { return this->m_unexpect; } + TL_EXPECTED_11_CONSTEXPR unexpected&& geterr() && { return std::move(this->m_unexpect); } #ifndef TL_EXPECTED_NO_CONSTRR - constexpr const unexpected &&geterr() const && { + constexpr const unexpected&& geterr() const&& { return std::move(this->m_unexpect); } #endif @@ -2687,19 +2783,19 @@ struct expected_operations_base : expected_storage_base { // This function doesn't use its argument, but needs it so that code in // levels above this can work independently of whether T is void template - void construct_with(Rhs &&) noexcept { + void construct_with(Rhs&&) noexcept { this->m_has_val = true; } template - void construct_error(Args &&...args) noexcept { + void construct_error(Args&&... args) noexcept { new (std::addressof(this->m_unexpect)) unexpected(std::forward(args)...); this->m_has_val = false; } template - void assign(Rhs &&rhs) noexcept { + void assign(Rhs&& rhs) noexcept { if (!this->m_has_val) { if (rhs.m_has_val) { geterr().~unexpected(); @@ -2716,15 +2812,15 @@ struct expected_operations_base : expected_storage_base { bool has_value() const { return this->m_has_val; } - TL_EXPECTED_11_CONSTEXPR unexpected &geterr() & { + TL_EXPECTED_11_CONSTEXPR unexpected& geterr() & { return this->m_unexpect; } - constexpr const unexpected &geterr() const & { return this->m_unexpect; } - TL_EXPECTED_11_CONSTEXPR unexpected &&geterr() && { + constexpr const unexpected& geterr() const& { return this->m_unexpect; } + TL_EXPECTED_11_CONSTEXPR unexpected&& geterr() && { return std::move(this->m_unexpect); } #ifndef TL_EXPECTED_NO_CONSTRR - constexpr const unexpected &&geterr() const && { + constexpr const unexpected&& geterr() const&& { return std::move(this->m_unexpect); } #endif @@ -2738,7 +2834,7 @@ struct expected_operations_base : expected_storage_base { // This specialization is for when T and E are trivially copy constructible template :: - value &&TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(E)::value> + value&& TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(E)::value> struct expected_copy_base : expected_operations_base { using expected_operations_base::expected_operations_base; }; @@ -2749,7 +2845,7 @@ struct expected_copy_base : expected_operations_base { using expected_operations_base::expected_operations_base; expected_copy_base() = default; - expected_copy_base(const expected_copy_base &rhs) + expected_copy_base(const expected_copy_base& rhs) : expected_operations_base(no_init) { if (rhs.has_value()) { this->construct_with(rhs); @@ -2758,9 +2854,9 @@ struct expected_copy_base : expected_operations_base { } } - expected_copy_base(expected_copy_base &&rhs) = default; - expected_copy_base &operator=(const expected_copy_base &rhs) = default; - expected_copy_base &operator=(expected_copy_base &&rhs) = default; + expected_copy_base(expected_copy_base&& rhs) = default; + expected_copy_base& operator=(const expected_copy_base& rhs) = default; + expected_copy_base& operator=(expected_copy_base&& rhs) = default; }; // This class manages conditionally having a trivial move constructor @@ -2770,8 +2866,8 @@ 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; }; @@ -2784,9 +2880,9 @@ struct expected_move_base : expected_copy_base { using expected_copy_base::expected_copy_base; expected_move_base() = default; - expected_move_base(const expected_move_base &rhs) = default; + expected_move_base(const expected_move_base& rhs) = default; - expected_move_base(expected_move_base &&rhs) noexcept( + expected_move_base(expected_move_base&& rhs) noexcept( std::is_nothrow_move_constructible::value) : expected_copy_base(no_init) { if (rhs.has_value()) { @@ -2795,8 +2891,8 @@ struct expected_move_base : expected_copy_base { this->construct_error(std::move(rhs.geterr())); } } - expected_move_base &operator=(const expected_move_base &rhs) = default; - expected_move_base &operator=(expected_move_base &&rhs) = default; + expected_move_base& operator=(const expected_move_base& rhs) = default; + expected_move_base& operator=(expected_move_base&& rhs) = default; }; // This class manages conditionally having a trivial copy assignment operator @@ -2804,10 +2900,10 @@ 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> + TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T)>>::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; }; @@ -2817,14 +2913,14 @@ struct expected_copy_assign_base : expected_move_base { using expected_move_base::expected_move_base; expected_copy_assign_base() = default; - expected_copy_assign_base(const expected_copy_assign_base &rhs) = default; + expected_copy_assign_base(const expected_copy_assign_base& rhs) = default; - expected_copy_assign_base(expected_copy_assign_base &&rhs) = default; - expected_copy_assign_base &operator=(const expected_copy_assign_base &rhs) { + expected_copy_assign_base(expected_copy_assign_base&& rhs) = default; + expected_copy_assign_base& operator=(const expected_copy_assign_base& rhs) { this->assign(rhs); return *this; } - expected_copy_assign_base &operator=(expected_copy_assign_base &&rhs) = + expected_copy_assign_base& operator=(expected_copy_assign_base&& rhs) = default; }; @@ -2839,9 +2935,9 @@ 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> + 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; }; @@ -2856,17 +2952,17 @@ struct expected_move_assign_base using expected_copy_assign_base::expected_copy_assign_base; expected_move_assign_base() = default; - expected_move_assign_base(const expected_move_assign_base &rhs) = default; + expected_move_assign_base(const expected_move_assign_base& rhs) = default; - expected_move_assign_base(expected_move_assign_base &&rhs) = default; + expected_move_assign_base(expected_move_assign_base&& rhs) = default; - expected_move_assign_base &operator=(const expected_move_assign_base &rhs) = + 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; } @@ -2881,44 +2977,44 @@ template ::value)> struct expected_delete_ctor_base { expected_delete_ctor_base() = default; - expected_delete_ctor_base(const expected_delete_ctor_base &) = default; - expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept = default; - expected_delete_ctor_base &operator=(const expected_delete_ctor_base &) = + expected_delete_ctor_base(const expected_delete_ctor_base&) = default; + expected_delete_ctor_base(expected_delete_ctor_base&&) noexcept = default; + expected_delete_ctor_base& operator=(const expected_delete_ctor_base&) = default; - expected_delete_ctor_base &operator=(expected_delete_ctor_base &&) noexcept = + expected_delete_ctor_base& operator=(expected_delete_ctor_base&&) noexcept = default; }; template struct expected_delete_ctor_base { expected_delete_ctor_base() = default; - expected_delete_ctor_base(const expected_delete_ctor_base &) = default; - expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept = delete; - expected_delete_ctor_base &operator=(const expected_delete_ctor_base &) = + expected_delete_ctor_base(const expected_delete_ctor_base&) = default; + expected_delete_ctor_base(expected_delete_ctor_base&&) noexcept = delete; + expected_delete_ctor_base& operator=(const expected_delete_ctor_base&) = default; - expected_delete_ctor_base &operator=(expected_delete_ctor_base &&) noexcept = + expected_delete_ctor_base& operator=(expected_delete_ctor_base&&) noexcept = default; }; template struct expected_delete_ctor_base { expected_delete_ctor_base() = default; - expected_delete_ctor_base(const expected_delete_ctor_base &) = delete; - expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept = default; - expected_delete_ctor_base &operator=(const expected_delete_ctor_base &) = + expected_delete_ctor_base(const expected_delete_ctor_base&) = delete; + expected_delete_ctor_base(expected_delete_ctor_base&&) noexcept = default; + expected_delete_ctor_base& operator=(const expected_delete_ctor_base&) = default; - expected_delete_ctor_base &operator=(expected_delete_ctor_base &&) noexcept = + expected_delete_ctor_base& operator=(expected_delete_ctor_base&&) noexcept = default; }; template struct expected_delete_ctor_base { expected_delete_ctor_base() = default; - expected_delete_ctor_base(const expected_delete_ctor_base &) = delete; - expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept = delete; - expected_delete_ctor_base &operator=(const expected_delete_ctor_base &) = + expected_delete_ctor_base(const expected_delete_ctor_base&) = delete; + expected_delete_ctor_base(expected_delete_ctor_base&&) noexcept = delete; + expected_delete_ctor_base& operator=(const expected_delete_ctor_base&) = default; - expected_delete_ctor_base &operator=(expected_delete_ctor_base &&) noexcept = + expected_delete_ctor_base& operator=(expected_delete_ctor_base&&) noexcept = default; }; @@ -2936,49 +3032,45 @@ template ::value)> struct expected_delete_assign_base { expected_delete_assign_base() = default; - expected_delete_assign_base(const expected_delete_assign_base &) = default; - expected_delete_assign_base(expected_delete_assign_base &&) noexcept = - default; - expected_delete_assign_base &operator=(const expected_delete_assign_base &) = + expected_delete_assign_base(const expected_delete_assign_base&) = default; + expected_delete_assign_base(expected_delete_assign_base&&) noexcept = default; + expected_delete_assign_base& operator=(const expected_delete_assign_base&) = default; - expected_delete_assign_base &operator=( - expected_delete_assign_base &&) noexcept = default; + expected_delete_assign_base& operator=( + expected_delete_assign_base&&) noexcept = default; }; template struct expected_delete_assign_base { expected_delete_assign_base() = default; - expected_delete_assign_base(const expected_delete_assign_base &) = default; - expected_delete_assign_base(expected_delete_assign_base &&) noexcept = + expected_delete_assign_base(const expected_delete_assign_base&) = default; + expected_delete_assign_base(expected_delete_assign_base&&) noexcept = default; + expected_delete_assign_base& operator=(const expected_delete_assign_base&) = default; - expected_delete_assign_base &operator=(const expected_delete_assign_base &) = - default; - expected_delete_assign_base &operator=( - expected_delete_assign_base &&) noexcept = delete; + expected_delete_assign_base& operator=( + expected_delete_assign_base&&) noexcept = delete; }; template struct expected_delete_assign_base { expected_delete_assign_base() = default; - expected_delete_assign_base(const expected_delete_assign_base &) = default; - expected_delete_assign_base(expected_delete_assign_base &&) noexcept = - default; - expected_delete_assign_base &operator=(const expected_delete_assign_base &) = + expected_delete_assign_base(const expected_delete_assign_base&) = default; + expected_delete_assign_base(expected_delete_assign_base&&) noexcept = default; + expected_delete_assign_base& operator=(const expected_delete_assign_base&) = delete; - expected_delete_assign_base &operator=( - expected_delete_assign_base &&) noexcept = default; + expected_delete_assign_base& operator=( + expected_delete_assign_base&&) noexcept = default; }; template struct expected_delete_assign_base { expected_delete_assign_base() = default; - expected_delete_assign_base(const expected_delete_assign_base &) = default; - expected_delete_assign_base(expected_delete_assign_base &&) noexcept = - default; - expected_delete_assign_base &operator=(const expected_delete_assign_base &) = + expected_delete_assign_base(const expected_delete_assign_base&) = default; + expected_delete_assign_base(expected_delete_assign_base&&) noexcept = default; + expected_delete_assign_base& operator=(const expected_delete_assign_base&) = delete; - expected_delete_assign_base &operator=( - expected_delete_assign_base &&) noexcept = delete; + expected_delete_assign_base& operator=( + expected_delete_assign_base&&) noexcept = delete; }; // This is needed to be able to construct the expected_default_ctor_base which @@ -2996,13 +3088,13 @@ template struct expected_default_ctor_base { constexpr expected_default_ctor_base() noexcept = delete; constexpr expected_default_ctor_base( - expected_default_ctor_base const &) noexcept = default; - constexpr expected_default_ctor_base(expected_default_ctor_base &&) noexcept = + expected_default_ctor_base const&) noexcept = default; + constexpr expected_default_ctor_base(expected_default_ctor_base&&) noexcept = + default; + expected_default_ctor_base& operator=( + expected_default_ctor_base const&) noexcept = default; + expected_default_ctor_base& operator=(expected_default_ctor_base&&) noexcept = default; - expected_default_ctor_base &operator=( - expected_default_ctor_base const &) noexcept = default; - expected_default_ctor_base &operator=( - expected_default_ctor_base &&) noexcept = default; constexpr explicit expected_default_ctor_base(default_constructor_tag) {} }; @@ -3029,14 +3121,14 @@ class bad_expected_access : public std::exception { public: explicit bad_expected_access(E e) : m_val(std::move(e)) {} - virtual const char *what() const noexcept override { + virtual const char* what() const noexcept override { return "Bad expected access"; } - const E &error() const & { return m_val; } - E &error() & { return m_val; } - const E &&error() const && { return std::move(m_val); } - E &&error() && { return std::move(m_val); } + const E& error() const& { return m_val; } + E& error() & { return m_val; } + const E&& error() const&& { return std::move(m_val); } + E&& error() && { return std::move(m_val); } private: E m_val; @@ -3064,26 +3156,26 @@ class expected : private detail::expected_move_assign_base, "T must not be unexpected"); static_assert(!std::is_reference::value, "E must not be a reference"); - T *valptr() { return std::addressof(this->m_val); } - const T *valptr() const { return std::addressof(this->m_val); } - unexpected *errptr() { return std::addressof(this->m_unexpect); } - const unexpected *errptr() const { + T* valptr() { return std::addressof(this->m_val); } + const T* valptr() const { return std::addressof(this->m_val); } + unexpected* errptr() { return std::addressof(this->m_unexpect); } + const unexpected* errptr() const { return std::addressof(this->m_unexpect); } template ::value> * = nullptr> - TL_EXPECTED_11_CONSTEXPR U &val() { + detail::enable_if_t::value>* = nullptr> + TL_EXPECTED_11_CONSTEXPR U& val() { return this->m_val; } - TL_EXPECTED_11_CONSTEXPR unexpected &err() { return this->m_unexpect; } + TL_EXPECTED_11_CONSTEXPR unexpected& err() { return this->m_unexpect; } template ::value> * = nullptr> - constexpr const U &val() const { + detail::enable_if_t::value>* = nullptr> + constexpr const U& val() const { return this->m_val; } - constexpr const unexpected &err() const { return this->m_unexpect; } + constexpr const unexpected& err() const { return this->m_unexpect; } using impl_base = detail::expected_move_assign_base; using ctor_base = detail::expected_default_ctor_base; @@ -3096,46 +3188,46 @@ class expected : private detail::expected_move_assign_base, #if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \ !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55) template - TL_EXPECTED_11_CONSTEXPR auto and_then(F &&f) & { + TL_EXPECTED_11_CONSTEXPR auto and_then(F&& f) & { return and_then_impl(*this, std::forward(f)); } template - TL_EXPECTED_11_CONSTEXPR auto and_then(F &&f) && { + TL_EXPECTED_11_CONSTEXPR auto and_then(F&& f) && { return and_then_impl(std::move(*this), std::forward(f)); } template - constexpr auto and_then(F &&f) const & { + constexpr auto and_then(F&& f) const& { return and_then_impl(*this, std::forward(f)); } #ifndef TL_EXPECTED_NO_CONSTRR template - constexpr auto and_then(F &&f) const && { + constexpr auto and_then(F&& f) const&& { return and_then_impl(std::move(*this), std::forward(f)); } #endif #else template - TL_EXPECTED_11_CONSTEXPR auto and_then(F &&f) & -> decltype(and_then_impl( - std::declval(), std::forward(f))) { + TL_EXPECTED_11_CONSTEXPR auto and_then(F&& f) & -> decltype( + and_then_impl(std::declval(), std::forward(f))) { return and_then_impl(*this, std::forward(f)); } template - TL_EXPECTED_11_CONSTEXPR auto and_then(F &&f) && -> decltype(and_then_impl( - std::declval(), std::forward(f))) { + TL_EXPECTED_11_CONSTEXPR auto and_then(F&& f) && -> decltype( + and_then_impl(std::declval(), std::forward(f))) { return and_then_impl(std::move(*this), std::forward(f)); } template - constexpr auto and_then(F &&f) const & -> decltype(and_then_impl( - std::declval(), std::forward(f))) { + constexpr auto and_then(F&& f) const& -> decltype( + and_then_impl(std::declval(), std::forward(f))) { return and_then_impl(*this, std::forward(f)); } #ifndef TL_EXPECTED_NO_CONSTRR template - constexpr auto and_then(F &&f) const && -> decltype(and_then_impl( - std::declval(), std::forward(f))) { + constexpr auto and_then(F&& f) const&& -> decltype( + and_then_impl(std::declval(), std::forward(f))) { return and_then_impl(std::move(*this), std::forward(f)); } #endif @@ -3144,46 +3236,46 @@ class expected : private detail::expected_move_assign_base, #if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \ !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55) template - TL_EXPECTED_11_CONSTEXPR auto map(F &&f) & { + TL_EXPECTED_11_CONSTEXPR auto map(F&& f) & { return expected_map_impl(*this, std::forward(f)); } template - TL_EXPECTED_11_CONSTEXPR auto map(F &&f) && { + TL_EXPECTED_11_CONSTEXPR auto map(F&& f) && { return expected_map_impl(std::move(*this), std::forward(f)); } template - constexpr auto map(F &&f) const & { + constexpr auto map(F&& f) const& { return expected_map_impl(*this, std::forward(f)); } template - constexpr auto map(F &&f) const && { + constexpr auto map(F&& f) const&& { return expected_map_impl(std::move(*this), std::forward(f)); } #else template - TL_EXPECTED_11_CONSTEXPR decltype(expected_map_impl( - std::declval(), std::declval())) - map(F &&f) & { + TL_EXPECTED_11_CONSTEXPR decltype(expected_map_impl(std::declval(), + std::declval())) + map(F&& f) & { return expected_map_impl(*this, std::forward(f)); } template TL_EXPECTED_11_CONSTEXPR decltype(expected_map_impl(std::declval(), - std::declval())) - map(F &&f) && { + std::declval())) + map(F&& f) && { return expected_map_impl(std::move(*this), std::forward(f)); } template - constexpr decltype(expected_map_impl(std::declval(), - std::declval())) - map(F &&f) const & { + constexpr decltype(expected_map_impl(std::declval(), + std::declval())) + map(F&& f) const& { return expected_map_impl(*this, std::forward(f)); } #ifndef TL_EXPECTED_NO_CONSTRR template - constexpr decltype(expected_map_impl(std::declval(), - std::declval())) - map(F &&f) const && { + constexpr decltype(expected_map_impl(std::declval(), + std::declval())) + map(F&& f) const&& { return expected_map_impl(std::move(*this), std::forward(f)); } #endif @@ -3192,46 +3284,46 @@ class expected : private detail::expected_move_assign_base, #if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \ !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55) template - TL_EXPECTED_11_CONSTEXPR auto transform(F &&f) & { + TL_EXPECTED_11_CONSTEXPR auto transform(F&& f) & { return expected_map_impl(*this, std::forward(f)); } template - TL_EXPECTED_11_CONSTEXPR auto transform(F &&f) && { + TL_EXPECTED_11_CONSTEXPR auto transform(F&& f) && { return expected_map_impl(std::move(*this), std::forward(f)); } template - constexpr auto transform(F &&f) const & { + constexpr auto transform(F&& f) const& { return expected_map_impl(*this, std::forward(f)); } template - constexpr auto transform(F &&f) const && { + constexpr auto transform(F&& f) const&& { return expected_map_impl(std::move(*this), std::forward(f)); } #else template - TL_EXPECTED_11_CONSTEXPR decltype(expected_map_impl( - std::declval(), std::declval())) - transform(F &&f) & { + TL_EXPECTED_11_CONSTEXPR decltype(expected_map_impl(std::declval(), + std::declval())) + transform(F&& f) & { return expected_map_impl(*this, std::forward(f)); } template TL_EXPECTED_11_CONSTEXPR decltype(expected_map_impl(std::declval(), - std::declval())) - transform(F &&f) && { + std::declval())) + transform(F&& f) && { return expected_map_impl(std::move(*this), std::forward(f)); } template - constexpr decltype(expected_map_impl(std::declval(), - std::declval())) - transform(F &&f) const & { + constexpr decltype(expected_map_impl(std::declval(), + std::declval())) + transform(F&& f) const& { return expected_map_impl(*this, std::forward(f)); } #ifndef TL_EXPECTED_NO_CONSTRR template - constexpr decltype(expected_map_impl(std::declval(), - std::declval())) - transform(F &&f) const && { + constexpr decltype(expected_map_impl(std::declval(), + std::declval())) + transform(F&& f) const&& { return expected_map_impl(std::move(*this), std::forward(f)); } #endif @@ -3240,46 +3332,46 @@ class expected : private detail::expected_move_assign_base, #if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \ !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55) template - TL_EXPECTED_11_CONSTEXPR auto map_error(F &&f) & { + TL_EXPECTED_11_CONSTEXPR auto map_error(F&& f) & { return map_error_impl(*this, std::forward(f)); } template - TL_EXPECTED_11_CONSTEXPR auto map_error(F &&f) && { + TL_EXPECTED_11_CONSTEXPR auto map_error(F&& f) && { return map_error_impl(std::move(*this), std::forward(f)); } template - constexpr auto map_error(F &&f) const & { + constexpr auto map_error(F&& f) const& { return map_error_impl(*this, std::forward(f)); } template - constexpr auto map_error(F &&f) const && { + constexpr auto map_error(F&& f) const&& { return map_error_impl(std::move(*this), std::forward(f)); } #else template - TL_EXPECTED_11_CONSTEXPR decltype(map_error_impl(std::declval(), - std::declval())) - map_error(F &&f) & { + TL_EXPECTED_11_CONSTEXPR decltype(map_error_impl(std::declval(), + std::declval())) + map_error(F&& f) & { return map_error_impl(*this, std::forward(f)); } template - TL_EXPECTED_11_CONSTEXPR decltype(map_error_impl(std::declval(), - std::declval())) - map_error(F &&f) && { + TL_EXPECTED_11_CONSTEXPR decltype(map_error_impl(std::declval(), + std::declval())) + map_error(F&& f) && { return map_error_impl(std::move(*this), std::forward(f)); } template - constexpr decltype(map_error_impl(std::declval(), - std::declval())) - map_error(F &&f) const & { + constexpr decltype(map_error_impl(std::declval(), + std::declval())) + map_error(F&& f) const& { return map_error_impl(*this, std::forward(f)); } #ifndef TL_EXPECTED_NO_CONSTRR template - constexpr decltype(map_error_impl(std::declval(), - std::declval())) - map_error(F &&f) const && { + constexpr decltype(map_error_impl(std::declval(), + std::declval())) + map_error(F&& f) const&& { return map_error_impl(std::move(*this), std::forward(f)); } #endif @@ -3287,149 +3379,147 @@ class expected : private detail::expected_move_assign_base, #if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \ !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55) template - TL_EXPECTED_11_CONSTEXPR auto transform_error(F &&f) & { + TL_EXPECTED_11_CONSTEXPR auto transform_error(F&& f) & { return map_error_impl(*this, std::forward(f)); } template - TL_EXPECTED_11_CONSTEXPR auto transform_error(F &&f) && { + TL_EXPECTED_11_CONSTEXPR auto transform_error(F&& f) && { return map_error_impl(std::move(*this), std::forward(f)); } template - constexpr auto transform_error(F &&f) const & { + constexpr auto transform_error(F&& f) const& { return map_error_impl(*this, std::forward(f)); } template - constexpr auto transform_error(F &&f) const && { + constexpr auto transform_error(F&& f) const&& { return map_error_impl(std::move(*this), std::forward(f)); } #else template - TL_EXPECTED_11_CONSTEXPR decltype(map_error_impl(std::declval(), - std::declval())) - transform_error(F &&f) & { + TL_EXPECTED_11_CONSTEXPR decltype(map_error_impl(std::declval(), + std::declval())) + transform_error(F&& f) & { return map_error_impl(*this, std::forward(f)); } template - TL_EXPECTED_11_CONSTEXPR decltype(map_error_impl(std::declval(), - std::declval())) - transform_error(F &&f) && { + TL_EXPECTED_11_CONSTEXPR decltype(map_error_impl(std::declval(), + std::declval())) + transform_error(F&& f) && { return map_error_impl(std::move(*this), std::forward(f)); } template - constexpr decltype(map_error_impl(std::declval(), - std::declval())) - transform_error(F &&f) const & { + constexpr decltype(map_error_impl(std::declval(), + std::declval())) + transform_error(F&& f) const& { return map_error_impl(*this, std::forward(f)); } #ifndef TL_EXPECTED_NO_CONSTRR template - constexpr decltype(map_error_impl(std::declval(), - std::declval())) - transform_error(F &&f) const && { + constexpr decltype(map_error_impl(std::declval(), + std::declval())) + transform_error(F&& f) const&& { return map_error_impl(std::move(*this), std::forward(f)); } #endif #endif template - expected TL_EXPECTED_11_CONSTEXPR or_else(F &&f) & { + expected TL_EXPECTED_11_CONSTEXPR or_else(F&& f) & { return or_else_impl(*this, std::forward(f)); } template - expected TL_EXPECTED_11_CONSTEXPR or_else(F &&f) && { + expected TL_EXPECTED_11_CONSTEXPR or_else(F&& f) && { return or_else_impl(std::move(*this), std::forward(f)); } template - expected constexpr or_else(F &&f) const & { + expected constexpr or_else(F&& f) const& { return or_else_impl(*this, std::forward(f)); } #ifndef TL_EXPECTED_NO_CONSTRR template - expected constexpr or_else(F &&f) const && { + expected constexpr or_else(F&& f) const&& { return or_else_impl(std::move(*this), std::forward(f)); } #endif constexpr expected() = default; - constexpr expected(const expected &rhs) = default; - constexpr expected(expected &&rhs) = default; - expected &operator=(const expected &rhs) = default; - expected &operator=(expected &&rhs) = default; + constexpr expected(const expected& rhs) = default; + constexpr expected(expected&& rhs) = default; + expected& operator=(const expected& rhs) = default; + expected& operator=(expected&& rhs) = default; template ::value> * = + detail::enable_if_t::value>* = nullptr> - constexpr expected(in_place_t, Args &&...args) + constexpr expected(in_place_t, Args&&... args) : impl_base(in_place, std::forward(args)...), ctor_base(detail::default_constructor_tag{}) {} template &, Args &&...>::value> * = nullptr> - constexpr expected(in_place_t, std::initializer_list il, Args &&...args) + T, std::initializer_list&, Args&&...>::value>* = nullptr> + constexpr expected(in_place_t, std::initializer_list il, Args&&... args) : impl_base(in_place, il, std::forward(args)...), ctor_base(detail::default_constructor_tag{}) {} - template ::value> * = - nullptr, - detail::enable_if_t::value> * = - nullptr> - explicit constexpr expected(const unexpected &e) + template < + class G = E, + detail::enable_if_t::value>* = nullptr, + detail::enable_if_t::value>* = nullptr> + explicit constexpr expected(const unexpected& e) : impl_base(unexpect, e.value()), ctor_base(detail::default_constructor_tag{}) {} template < class G = E, - detail::enable_if_t::value> * = - nullptr, - detail::enable_if_t::value> * = nullptr> - constexpr expected(unexpected const &e) + detail::enable_if_t::value>* = nullptr, + detail::enable_if_t::value>* = nullptr> + constexpr expected(unexpected const& e) : impl_base(unexpect, e.value()), ctor_base(detail::default_constructor_tag{}) {} template < class G = E, - detail::enable_if_t::value> * = nullptr, - detail::enable_if_t::value> * = nullptr> - explicit constexpr expected(unexpected &&e) noexcept( - std::is_nothrow_constructible::value) + detail::enable_if_t::value>* = nullptr, + detail::enable_if_t::value>* = nullptr> + explicit constexpr expected(unexpected&& e) noexcept( + std::is_nothrow_constructible::value) : impl_base(unexpect, std::move(e.value())), ctor_base(detail::default_constructor_tag{}) {} template < class G = E, - detail::enable_if_t::value> * = nullptr, - detail::enable_if_t::value> * = nullptr> - constexpr expected(unexpected &&e) noexcept( - std::is_nothrow_constructible::value) + detail::enable_if_t::value>* = nullptr, + detail::enable_if_t::value>* = nullptr> + constexpr expected(unexpected&& e) noexcept( + std::is_nothrow_constructible::value) : impl_base(unexpect, std::move(e.value())), ctor_base(detail::default_constructor_tag{}) {} template ::value> * = + detail::enable_if_t::value>* = nullptr> - constexpr explicit expected(unexpect_t, Args &&...args) + constexpr explicit expected(unexpect_t, Args&&... args) : impl_base(unexpect, std::forward(args)...), ctor_base(detail::default_constructor_tag{}) {} template &, Args &&...>::value> * = nullptr> + E, std::initializer_list&, Args&&...>::value>* = nullptr> constexpr explicit expected(unexpect_t, std::initializer_list il, - Args &&...args) + Args&&... args) : impl_base(unexpect, il, std::forward(args)...), ctor_base(detail::default_constructor_tag{}) {} template ::value && - std::is_convertible::value)> * = + detail::enable_if_t::value && + std::is_convertible::value)>* = nullptr, - detail::expected_enable_from_other - * = nullptr> - explicit TL_EXPECTED_11_CONSTEXPR expected(const expected &rhs) + detail::expected_enable_from_other* = nullptr> + explicit TL_EXPECTED_11_CONSTEXPR expected(const expected& rhs) : ctor_base(detail::default_constructor_tag{}) { if (rhs.has_value()) { this->construct(*rhs); @@ -3438,13 +3528,13 @@ class expected : private detail::expected_move_assign_base, } } - template ::value && - std::is_convertible::value)> * = - nullptr, - detail::expected_enable_from_other - * = nullptr> - TL_EXPECTED_11_CONSTEXPR expected(const expected &rhs) + template < + class U, class G, + detail::enable_if_t<(std::is_convertible::value && + std::is_convertible::value)>* = nullptr, + detail::expected_enable_from_other* = + nullptr> + TL_EXPECTED_11_CONSTEXPR expected(const expected& rhs) : ctor_base(detail::default_constructor_tag{}) { if (rhs.has_value()) { this->construct(*rhs); @@ -3455,10 +3545,10 @@ class expected : private detail::expected_move_assign_base, template < class U, class G, - detail::enable_if_t::value && - std::is_convertible::value)> * = nullptr, - detail::expected_enable_from_other * = nullptr> - explicit TL_EXPECTED_11_CONSTEXPR expected(expected &&rhs) + detail::enable_if_t::value && + std::is_convertible::value)>* = nullptr, + detail::expected_enable_from_other* = nullptr> + explicit TL_EXPECTED_11_CONSTEXPR expected(expected&& rhs) : ctor_base(detail::default_constructor_tag{}) { if (rhs.has_value()) { this->construct(std::move(*rhs)); @@ -3469,10 +3559,10 @@ class expected : private detail::expected_move_assign_base, template < class U, class G, - detail::enable_if_t<(std::is_convertible::value && - std::is_convertible::value)> * = nullptr, - detail::expected_enable_from_other * = nullptr> - TL_EXPECTED_11_CONSTEXPR expected(expected &&rhs) + detail::enable_if_t<(std::is_convertible::value && + std::is_convertible::value)>* = nullptr, + detail::expected_enable_from_other* = nullptr> + TL_EXPECTED_11_CONSTEXPR expected(expected&& rhs) : ctor_base(detail::default_constructor_tag{}) { if (rhs.has_value()) { this->construct(std::move(*rhs)); @@ -3481,33 +3571,31 @@ class expected : private detail::expected_move_assign_base, } } - template < - class U = T, - detail::enable_if_t::value> * = nullptr, - detail::expected_enable_forward_value * = nullptr> - explicit TL_EXPECTED_MSVC2015_CONSTEXPR expected(U &&v) + template ::value>* = nullptr, + detail::expected_enable_forward_value* = nullptr> + explicit TL_EXPECTED_MSVC2015_CONSTEXPR expected(U&& v) : expected(in_place, std::forward(v)) {} - template < - class U = T, - detail::enable_if_t::value> * = nullptr, - detail::expected_enable_forward_value * = nullptr> - TL_EXPECTED_MSVC2015_CONSTEXPR expected(U &&v) + template ::value>* = nullptr, + detail::expected_enable_forward_value* = nullptr> + TL_EXPECTED_MSVC2015_CONSTEXPR expected(U&& v) : expected(in_place, std::forward(v)) {} template < class U = T, class G = T, - detail::enable_if_t::value> * = + detail::enable_if_t::value>* = nullptr, - detail::enable_if_t::value> * = nullptr, + detail::enable_if_t::value>* = nullptr, detail::enable_if_t< (!std::is_same, detail::decay_t>::value && !detail::conjunction, std::is_same>>::value && std::is_constructible::value && - std::is_assignable::value && - std::is_nothrow_move_constructible::value)> * = nullptr> - expected &operator=(U &&v) { + std::is_assignable::value && + std::is_nothrow_move_constructible::value)>* = nullptr> + expected& operator=(U&& v) { if (has_value()) { val() = std::forward(v); } else { @@ -3521,17 +3609,17 @@ class expected : private detail::expected_move_assign_base, template < class U = T, class G = T, - detail::enable_if_t::value> * = + detail::enable_if_t::value>* = nullptr, - detail::enable_if_t::value> * = nullptr, + detail::enable_if_t::value>* = nullptr, detail::enable_if_t< (!std::is_same, detail::decay_t>::value && !detail::conjunction, std::is_same>>::value && std::is_constructible::value && - std::is_assignable::value && - std::is_nothrow_move_constructible::value)> * = nullptr> - expected &operator=(U &&v) { + std::is_assignable::value && + std::is_nothrow_move_constructible::value)>* = nullptr> + expected& operator=(U&& v) { if (has_value()) { val() = std::forward(v); } else { @@ -3557,8 +3645,8 @@ class expected : private detail::expected_move_assign_base, template ::value && - std::is_assignable::value> * = nullptr> - expected &operator=(const unexpected &rhs) { + std::is_assignable::value>* = nullptr> + expected& operator=(const unexpected& rhs) { if (!has_value()) { err() = rhs; } else { @@ -3572,8 +3660,8 @@ class expected : private detail::expected_move_assign_base, template ::value && - std::is_move_assignable::value> * = nullptr> - expected &operator=(unexpected &&rhs) noexcept { + std::is_move_assignable::value>* = nullptr> + expected& operator=(unexpected&& rhs) noexcept { if (!has_value()) { err() = std::move(rhs); } else { @@ -3586,8 +3674,8 @@ class expected : private detail::expected_move_assign_base, } template ::value> * = nullptr> - void emplace(Args &&...args) { + T, Args&&...>::value>* = nullptr> + void emplace(Args&&... args) { if (has_value()) { val().~T(); } else { @@ -3598,8 +3686,8 @@ class expected : private detail::expected_move_assign_base, } template ::value> * = nullptr> - void emplace(Args &&...args) { + T, Args&&...>::value>* = nullptr> + void emplace(Args&&... args) { if (has_value()) { val().~T(); ::new (valptr()) T(std::forward(args)...); @@ -3624,8 +3712,8 @@ class expected : private detail::expected_move_assign_base, template &, Args &&...>::value> * = nullptr> - void emplace(std::initializer_list il, Args &&...args) { + T, std::initializer_list&, Args&&...>::value>* = nullptr> + void emplace(std::initializer_list il, Args&&... args) { if (has_value()) { T t(il, std::forward(args)...); val() = std::move(t); @@ -3638,8 +3726,8 @@ class expected : private detail::expected_move_assign_base, template &, Args &&...>::value> * = nullptr> - void emplace(std::initializer_list il, Args &&...args) { + T, std::initializer_list&, Args&&...>::value>* = nullptr> + void emplace(std::initializer_list il, Args&&... args) { if (has_value()) { T t(il, std::forward(args)...); val() = std::move(t); @@ -3670,30 +3758,30 @@ class expected : private detail::expected_move_assign_base, using e_is_nothrow_move_constructible = std::true_type; using move_constructing_e_can_throw = std::false_type; - void swap_where_both_have_value(expected & /*rhs*/, t_is_void) noexcept { + void swap_where_both_have_value(expected& /*rhs*/, t_is_void) noexcept { // swapping void is a no-op } - void swap_where_both_have_value(expected &rhs, t_is_not_void) { + void swap_where_both_have_value(expected& rhs, t_is_not_void) { using std::swap; swap(val(), rhs.val()); } - void swap_where_only_one_has_value(expected &rhs, t_is_void) noexcept( + void swap_where_only_one_has_value(expected& rhs, t_is_void) noexcept( std::is_nothrow_move_constructible::value) { ::new (errptr()) unexpected_type(std::move(rhs.err())); rhs.err().~unexpected_type(); std::swap(this->m_has_val, rhs.m_has_val); } - void swap_where_only_one_has_value(expected &rhs, t_is_not_void) { + void swap_where_only_one_has_value(expected& rhs, t_is_not_void) { swap_where_only_one_has_value_and_t_is_not_void( rhs, typename std::is_nothrow_move_constructible::type{}, typename std::is_nothrow_move_constructible::type{}); } void swap_where_only_one_has_value_and_t_is_not_void( - expected &rhs, t_is_nothrow_move_constructible, + expected& rhs, t_is_nothrow_move_constructible, e_is_nothrow_move_constructible) noexcept { auto temp = std::move(val()); val().~T(); @@ -3704,7 +3792,7 @@ class expected : private detail::expected_move_assign_base, } void swap_where_only_one_has_value_and_t_is_not_void( - expected &rhs, t_is_nothrow_move_constructible, + expected& rhs, t_is_nothrow_move_constructible, move_constructing_e_can_throw) { auto temp = std::move(val()); val().~T(); @@ -3727,7 +3815,7 @@ class expected : private detail::expected_move_assign_base, } void swap_where_only_one_has_value_and_t_is_not_void( - expected &rhs, move_constructing_t_can_throw, + expected& rhs, move_constructing_t_can_throw, e_is_nothrow_move_constructible) { auto temp = std::move(rhs.err()); rhs.err().~unexpected_type(); @@ -3755,11 +3843,11 @@ 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()) { @@ -3772,36 +3860,36 @@ class expected : private detail::expected_move_assign_base, } } - constexpr const T *operator->() const { + constexpr const T* operator->() const { TL_ASSERT(has_value()); return valptr(); } - TL_EXPECTED_11_CONSTEXPR T *operator->() { + TL_EXPECTED_11_CONSTEXPR T* operator->() { TL_ASSERT(has_value()); return valptr(); } template ::value> * = nullptr> - constexpr const U &operator*() const & { + detail::enable_if_t::value>* = nullptr> + constexpr const U& operator*() const& { TL_ASSERT(has_value()); return val(); } template ::value> * = nullptr> - TL_EXPECTED_11_CONSTEXPR U &operator*() & { + detail::enable_if_t::value>* = nullptr> + TL_EXPECTED_11_CONSTEXPR U& operator*() & { TL_ASSERT(has_value()); return val(); } template ::value> * = nullptr> - constexpr const U &&operator*() const && { + detail::enable_if_t::value>* = nullptr> + constexpr const U&& operator*() const&& { TL_ASSERT(has_value()); return std::move(val()); } template ::value> * = nullptr> - TL_EXPECTED_11_CONSTEXPR U &&operator*() && { + detail::enable_if_t::value>* = nullptr> + TL_EXPECTED_11_CONSTEXPR U&& operator*() && { TL_ASSERT(has_value()); return std::move(val()); } @@ -3810,62 +3898,62 @@ class expected : private detail::expected_move_assign_base, constexpr explicit operator bool() const noexcept { return this->m_has_val; } template ::value> * = nullptr> - TL_EXPECTED_11_CONSTEXPR const U &value() const & { + detail::enable_if_t::value>* = nullptr> + TL_EXPECTED_11_CONSTEXPR const U& value() const& { if (!has_value()) detail::throw_exception(bad_expected_access(err().value())); return val(); } template ::value> * = nullptr> - TL_EXPECTED_11_CONSTEXPR U &value() & { + detail::enable_if_t::value>* = nullptr> + TL_EXPECTED_11_CONSTEXPR U& value() & { if (!has_value()) detail::throw_exception(bad_expected_access(err().value())); return val(); } template ::value> * = nullptr> - TL_EXPECTED_11_CONSTEXPR const U &&value() const && { + detail::enable_if_t::value>* = nullptr> + TL_EXPECTED_11_CONSTEXPR const U&& value() const&& { if (!has_value()) detail::throw_exception(bad_expected_access(std::move(err()).value())); return std::move(val()); } template ::value> * = nullptr> - TL_EXPECTED_11_CONSTEXPR U &&value() && { + detail::enable_if_t::value>* = nullptr> + TL_EXPECTED_11_CONSTEXPR U&& value() && { if (!has_value()) detail::throw_exception(bad_expected_access(std::move(err()).value())); return std::move(val()); } - constexpr const E &error() const & { + constexpr const E& error() const& { TL_ASSERT(!has_value()); return err().value(); } - TL_EXPECTED_11_CONSTEXPR E &error() & { + TL_EXPECTED_11_CONSTEXPR E& error() & { TL_ASSERT(!has_value()); return err().value(); } - constexpr const E &&error() const && { + constexpr const E&& error() const&& { TL_ASSERT(!has_value()); return std::move(err().value()); } - TL_EXPECTED_11_CONSTEXPR E &&error() && { + TL_EXPECTED_11_CONSTEXPR E&& error() && { TL_ASSERT(!has_value()); return std::move(err().value()); } template - constexpr T value_or(U &&v) const & { + constexpr T value_or(U&& v) const& { static_assert(std::is_copy_constructible::value && - std::is_convertible::value, + std::is_convertible::value, "T must be copy-constructible and convertible to from U&&"); return bool(*this) ? **this : static_cast(std::forward(v)); } template - TL_EXPECTED_11_CONSTEXPR T value_or(U &&v) && { + TL_EXPECTED_11_CONSTEXPR T value_or(U&& v) && { static_assert(std::is_move_constructible::value && - std::is_convertible::value, + std::is_convertible::value, "T must be move-constructible and convertible to from U&&"); return bool(*this) ? std::move(**this) : static_cast(std::forward(v)); } @@ -3881,10 +3969,10 @@ using ret_t = expected>; #ifdef TL_EXPECTED_CXX14 template >::value> * = nullptr, + detail::enable_if_t>::value>* = nullptr, class Ret = decltype(detail::invoke(std::declval(), *std::declval()))> -constexpr auto and_then_impl(Exp &&exp, F &&f) { +constexpr auto and_then_impl(Exp&& exp, F&& f) { static_assert(detail::is_expected::value, "F must return an expected"); return exp.has_value() @@ -3893,9 +3981,9 @@ constexpr auto and_then_impl(Exp &&exp, F &&f) { } template >::value> * = nullptr, + detail::enable_if_t>::value>* = nullptr, class Ret = decltype(detail::invoke(std::declval()))> -constexpr auto and_then_impl(Exp &&exp, F &&f) { +constexpr auto and_then_impl(Exp&& exp, F&& f) { static_assert(detail::is_expected::value, "F must return an expected"); return exp.has_value() ? detail::invoke(std::forward(f)) @@ -3907,8 +3995,8 @@ struct TC; template (), *std::declval())), - detail::enable_if_t>::value> * = nullptr> -auto and_then_impl(Exp &&exp, F &&f) -> Ret { + detail::enable_if_t>::value>* = nullptr> +auto and_then_impl(Exp&& exp, F&& f) -> Ret { static_assert(detail::is_expected::value, "F must return an expected"); return exp.has_value() @@ -3918,8 +4006,8 @@ auto and_then_impl(Exp &&exp, F &&f) -> Ret { template ())), - detail::enable_if_t>::value> * = nullptr> -constexpr auto and_then_impl(Exp &&exp, F &&f) -> Ret { + detail::enable_if_t>::value>* = nullptr> +constexpr auto and_then_impl(Exp&& exp, F&& f) -> Ret { static_assert(detail::is_expected::value, "F must return an expected"); return exp.has_value() ? detail::invoke(std::forward(f)) @@ -3929,11 +4017,11 @@ constexpr auto and_then_impl(Exp &&exp, F &&f) -> Ret { #ifdef TL_EXPECTED_CXX14 template >::value> * = nullptr, + detail::enable_if_t>::value>* = nullptr, class Ret = decltype(detail::invoke(std::declval(), *std::declval())), - detail::enable_if_t::value> * = nullptr> -constexpr auto expected_map_impl(Exp &&exp, F &&f) { + detail::enable_if_t::value>* = nullptr> +constexpr auto expected_map_impl(Exp&& exp, F&& f) { using result = ret_t>; return exp.has_value() ? result(detail::invoke(std::forward(f), *std::forward(exp))) @@ -3941,11 +4029,11 @@ constexpr auto expected_map_impl(Exp &&exp, F &&f) { } template >::value> * = nullptr, + detail::enable_if_t>::value>* = nullptr, class Ret = decltype(detail::invoke(std::declval(), *std::declval())), - detail::enable_if_t::value> * = nullptr> -auto expected_map_impl(Exp &&exp, F &&f) { + detail::enable_if_t::value>* = nullptr> +auto expected_map_impl(Exp&& exp, F&& f) { using result = expected>; if (exp.has_value()) { detail::invoke(std::forward(f), *std::forward(exp)); @@ -3956,20 +4044,20 @@ auto expected_map_impl(Exp &&exp, F &&f) { } template >::value> * = nullptr, + detail::enable_if_t>::value>* = nullptr, class Ret = decltype(detail::invoke(std::declval())), - detail::enable_if_t::value> * = nullptr> -constexpr auto expected_map_impl(Exp &&exp, F &&f) { + detail::enable_if_t::value>* = nullptr> +constexpr auto expected_map_impl(Exp&& exp, F&& f) { using result = ret_t>; return exp.has_value() ? result(detail::invoke(std::forward(f))) : result(unexpect, std::forward(exp).error()); } template >::value> * = nullptr, + detail::enable_if_t>::value>* = nullptr, class Ret = decltype(detail::invoke(std::declval())), - detail::enable_if_t::value> * = nullptr> -auto expected_map_impl(Exp &&exp, F &&f) { + detail::enable_if_t::value>* = nullptr> +auto expected_map_impl(Exp&& exp, F&& f) { using result = expected>; if (exp.has_value()) { detail::invoke(std::forward(f)); @@ -3980,12 +4068,12 @@ auto expected_map_impl(Exp &&exp, F &&f) { } #else template >::value> * = nullptr, + detail::enable_if_t>::value>* = nullptr, class Ret = decltype(detail::invoke(std::declval(), *std::declval())), - detail::enable_if_t::value> * = nullptr> + detail::enable_if_t::value>* = nullptr> -constexpr auto expected_map_impl(Exp &&exp, F &&f) +constexpr auto expected_map_impl(Exp&& exp, F&& f) -> ret_t> { using result = ret_t>; @@ -3995,12 +4083,12 @@ constexpr auto expected_map_impl(Exp &&exp, F &&f) } template >::value> * = nullptr, + detail::enable_if_t>::value>* = nullptr, class Ret = decltype(detail::invoke(std::declval(), *std::declval())), - detail::enable_if_t::value> * = nullptr> + detail::enable_if_t::value>* = nullptr> -auto expected_map_impl(Exp &&exp, F &&f) -> expected> { +auto expected_map_impl(Exp&& exp, F&& f) -> expected> { if (exp.has_value()) { detail::invoke(std::forward(f), *std::forward(exp)); return {}; @@ -4010,11 +4098,11 @@ auto expected_map_impl(Exp &&exp, F &&f) -> expected> { } template >::value> * = nullptr, + detail::enable_if_t>::value>* = nullptr, class Ret = decltype(detail::invoke(std::declval())), - detail::enable_if_t::value> * = nullptr> + detail::enable_if_t::value>* = nullptr> -constexpr auto expected_map_impl(Exp &&exp, F &&f) +constexpr auto expected_map_impl(Exp&& exp, F&& f) -> ret_t> { using result = ret_t>; @@ -4023,11 +4111,11 @@ constexpr auto expected_map_impl(Exp &&exp, F &&f) } template >::value> * = nullptr, + detail::enable_if_t>::value>* = nullptr, class Ret = decltype(detail::invoke(std::declval())), - detail::enable_if_t::value> * = nullptr> + detail::enable_if_t::value>* = nullptr> -auto expected_map_impl(Exp &&exp, F &&f) -> expected> { +auto expected_map_impl(Exp&& exp, F&& f) -> expected> { if (exp.has_value()) { detail::invoke(std::forward(f)); return {}; @@ -4040,11 +4128,11 @@ auto expected_map_impl(Exp &&exp, F &&f) -> expected> { #if defined(TL_EXPECTED_CXX14) && !defined(TL_EXPECTED_GCC49) && \ !defined(TL_EXPECTED_GCC54) && !defined(TL_EXPECTED_GCC55) template >::value> * = nullptr, + detail::enable_if_t>::value>* = nullptr, class Ret = decltype(detail::invoke(std::declval(), std::declval().error())), - detail::enable_if_t::value> * = nullptr> -constexpr auto map_error_impl(Exp &&exp, F &&f) { + detail::enable_if_t::value>* = nullptr> +constexpr auto map_error_impl(Exp&& exp, F&& f) { using result = expected, detail::decay_t>; return exp.has_value() ? result(*std::forward(exp)) @@ -4052,11 +4140,11 @@ constexpr auto map_error_impl(Exp &&exp, F &&f) { std::forward(exp).error())); } template >::value> * = nullptr, + detail::enable_if_t>::value>* = nullptr, class Ret = decltype(detail::invoke(std::declval(), std::declval().error())), - detail::enable_if_t::value> * = nullptr> -auto map_error_impl(Exp &&exp, F &&f) { + detail::enable_if_t::value>* = nullptr> +auto map_error_impl(Exp&& exp, F&& f) { using result = expected, monostate>; if (exp.has_value()) { return result(*std::forward(exp)); @@ -4066,11 +4154,11 @@ auto map_error_impl(Exp &&exp, F &&f) { return result(unexpect, monostate{}); } template >::value> * = nullptr, + detail::enable_if_t>::value>* = nullptr, class Ret = decltype(detail::invoke(std::declval(), std::declval().error())), - detail::enable_if_t::value> * = nullptr> -constexpr auto map_error_impl(Exp &&exp, F &&f) { + detail::enable_if_t::value>* = nullptr> +constexpr auto map_error_impl(Exp&& exp, F&& f) { using result = expected, detail::decay_t>; return exp.has_value() ? result() @@ -4078,11 +4166,11 @@ constexpr auto map_error_impl(Exp &&exp, F &&f) { std::forward(exp).error())); } template >::value> * = nullptr, + detail::enable_if_t>::value>* = nullptr, class Ret = decltype(detail::invoke(std::declval(), std::declval().error())), - detail::enable_if_t::value> * = nullptr> -auto map_error_impl(Exp &&exp, F &&f) { + detail::enable_if_t::value>* = nullptr> +auto map_error_impl(Exp&& exp, F&& f) { using result = expected, monostate>; if (exp.has_value()) { return result(); @@ -4093,11 +4181,11 @@ auto map_error_impl(Exp &&exp, F &&f) { } #else template >::value> * = nullptr, + detail::enable_if_t>::value>* = nullptr, class Ret = decltype(detail::invoke(std::declval(), std::declval().error())), - detail::enable_if_t::value> * = nullptr> -constexpr auto map_error_impl(Exp &&exp, F &&f) + detail::enable_if_t::value>* = nullptr> +constexpr auto map_error_impl(Exp&& exp, F&& f) -> expected, detail::decay_t> { using result = expected, detail::decay_t>; @@ -4108,11 +4196,11 @@ constexpr auto map_error_impl(Exp &&exp, F &&f) } template >::value> * = nullptr, + detail::enable_if_t>::value>* = nullptr, class Ret = decltype(detail::invoke(std::declval(), std::declval().error())), - detail::enable_if_t::value> * = nullptr> -auto map_error_impl(Exp &&exp, F &&f) -> expected, monostate> { + detail::enable_if_t::value>* = nullptr> +auto map_error_impl(Exp&& exp, F&& f) -> expected, monostate> { using result = expected, monostate>; if (exp.has_value()) { return result(*std::forward(exp)); @@ -4123,11 +4211,11 @@ auto map_error_impl(Exp &&exp, F &&f) -> expected, monostate> { } template >::value> * = nullptr, + detail::enable_if_t>::value>* = nullptr, class Ret = decltype(detail::invoke(std::declval(), std::declval().error())), - detail::enable_if_t::value> * = nullptr> -constexpr auto map_error_impl(Exp &&exp, F &&f) + detail::enable_if_t::value>* = nullptr> +constexpr auto map_error_impl(Exp&& exp, F&& f) -> expected, detail::decay_t> { using result = expected, detail::decay_t>; @@ -4138,11 +4226,11 @@ constexpr auto map_error_impl(Exp &&exp, F &&f) } template >::value> * = nullptr, + detail::enable_if_t>::value>* = nullptr, class Ret = decltype(detail::invoke(std::declval(), std::declval().error())), - detail::enable_if_t::value> * = nullptr> -auto map_error_impl(Exp &&exp, F &&f) -> expected, monostate> { + detail::enable_if_t::value>* = nullptr> +auto map_error_impl(Exp&& exp, F&& f) -> expected, monostate> { using result = expected, monostate>; if (exp.has_value()) { return result(); @@ -4157,8 +4245,8 @@ auto map_error_impl(Exp &&exp, F &&f) -> expected, monostate> { template (), std::declval().error())), - detail::enable_if_t::value> * = nullptr> -constexpr auto or_else_impl(Exp &&exp, F &&f) { + detail::enable_if_t::value>* = nullptr> +constexpr auto or_else_impl(Exp&& exp, F&& f) { static_assert(detail::is_expected::value, "F must return an expected"); return exp.has_value() ? std::forward(exp) : detail::invoke(std::forward(f), @@ -4168,8 +4256,8 @@ constexpr auto or_else_impl(Exp &&exp, F &&f) { template (), std::declval().error())), - detail::enable_if_t::value> * = nullptr> -detail::decay_t or_else_impl(Exp &&exp, F &&f) { + detail::enable_if_t::value>* = nullptr> +detail::decay_t or_else_impl(Exp&& exp, F&& f) { return exp.has_value() ? std::forward(exp) : (detail::invoke(std::forward(f), std::forward(exp).error()), @@ -4179,8 +4267,8 @@ detail::decay_t or_else_impl(Exp &&exp, F &&f) { template (), std::declval().error())), - detail::enable_if_t::value> * = nullptr> -auto or_else_impl(Exp &&exp, F &&f) -> Ret { + detail::enable_if_t::value>* = nullptr> +auto or_else_impl(Exp&& exp, F&& f) -> Ret { static_assert(detail::is_expected::value, "F must return an expected"); return exp.has_value() ? std::forward(exp) : detail::invoke(std::forward(f), @@ -4190,8 +4278,8 @@ auto or_else_impl(Exp &&exp, F &&f) -> Ret { template (), std::declval().error())), - detail::enable_if_t::value> * = nullptr> -detail::decay_t or_else_impl(Exp &&exp, F &&f) { + detail::enable_if_t::value>* = nullptr> +detail::decay_t or_else_impl(Exp&& exp, F&& f) { return exp.has_value() ? std::forward(exp) : (detail::invoke(std::forward(f), std::forward(exp).error()), @@ -4201,65 +4289,65 @@ detail::decay_t or_else_impl(Exp &&exp, F &&f) { } // namespace detail template -constexpr bool operator==(const expected &lhs, - const expected &rhs) { +constexpr bool operator==(const expected& lhs, + const expected& rhs) { return (lhs.has_value() != rhs.has_value()) ? false : (!lhs.has_value() ? lhs.error() == rhs.error() : *lhs == *rhs); } template -constexpr bool operator!=(const expected &lhs, - const expected &rhs) { +constexpr bool operator!=(const expected& lhs, + const expected& rhs) { return (lhs.has_value() != rhs.has_value()) ? true : (!lhs.has_value() ? lhs.error() != rhs.error() : *lhs != *rhs); } template -constexpr bool operator==(const expected &lhs, - const expected &rhs) { +constexpr bool operator==(const expected& lhs, + const expected& rhs) { return (lhs.has_value() != rhs.has_value()) ? false : (!lhs.has_value() ? lhs.error() == rhs.error() : true); } template -constexpr bool operator!=(const expected &lhs, - const expected &rhs) { +constexpr bool operator!=(const expected& lhs, + const expected& rhs) { return (lhs.has_value() != rhs.has_value()) ? true : (!lhs.has_value() ? lhs.error() == rhs.error() : false); } template -constexpr bool operator==(const expected &x, const U &v) { +constexpr bool operator==(const expected& x, const U& v) { return x.has_value() ? *x == v : false; } template -constexpr bool operator==(const U &v, const expected &x) { +constexpr bool operator==(const U& v, const expected& x) { return x.has_value() ? *x == v : false; } template -constexpr bool operator!=(const expected &x, const U &v) { +constexpr bool operator!=(const expected& x, const U& v) { return x.has_value() ? *x != v : true; } template -constexpr bool operator!=(const U &v, const expected &x) { +constexpr bool operator!=(const U& v, const expected& x) { return x.has_value() ? *x != v : true; } template -constexpr bool operator==(const expected &x, const unexpected &e) { +constexpr bool operator==(const expected& x, const unexpected& e) { return x.has_value() ? false : x.error() == e.value(); } template -constexpr bool operator==(const unexpected &e, const expected &x) { +constexpr bool operator==(const unexpected& e, const expected& x) { return x.has_value() ? false : x.error() == e.value(); } template -constexpr bool operator!=(const expected &x, const unexpected &e) { +constexpr bool operator!=(const expected& x, const unexpected& e) { return x.has_value() ? true : x.error() != e.value(); } template -constexpr bool operator!=(const unexpected &e, const expected &x) { +constexpr bool operator!=(const unexpected& e, const expected& x) { return x.has_value() ? true : x.error() != e.value(); } @@ -4268,9 +4356,9 @@ template ::value) && detail::is_swappable::value && std::is_move_constructible::value && - detail::is_swappable::value> * = nullptr> -void swap(expected &lhs, - expected &rhs) noexcept(noexcept(lhs.swap(rhs))) { + detail::is_swappable::value>* = nullptr> +void swap(expected& lhs, + expected& rhs) noexcept(noexcept(lhs.swap(rhs))) { lhs.swap(rhs); } } // namespace tl @@ -4278,9 +4366,6 @@ void swap(expected &lhs, #endif /* end file include/ada/expected.h */ -#include -#include - /** * @private */ @@ -4294,9 +4379,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, @@ -4307,6 +4394,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 @@ -4319,7 +4414,6 @@ extern template url parse_url(std::string_view user_input, #ifndef ADA_SCHEME_INL_H #define ADA_SCHEME_INL_H - namespace ada::scheme { /** @@ -4335,6 +4429,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; @@ -4383,7 +4501,6 @@ constexpr ada::scheme::type get_scheme_type(std::string_view scheme) noexcept { #ifndef ADA_SERIALIZERS_H #define ADA_SERIALIZERS_H - #include #include #include @@ -4429,17 +4546,21 @@ std::string ipv4(uint64_t address) noexcept; #ifndef ADA_UNICODE_H #define ADA_UNICODE_H - -#include #include +#include /** + * Unicode operations. These functions are not part of our public API and may + * change at any time. + * + * @private * @namespace ada::unicode * @brief Includes the definitions for unicode operations */ namespace ada::unicode { /** + * @private * We receive a UTF-8 string representing a domain name. * If the string is percent encoded, we apply percent decoding. * @@ -4483,11 +4604,7 @@ bool to_ascii(std::optional& out, std::string_view plain, size_t first_percent); /** - * @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. * * @attention The has_tabs_or_newline function is a bottleneck and it is simple @@ -4497,12 +4614,14 @@ ada_really_inline bool has_tabs_or_newline( std::string_view user_input) noexcept; /** + * @private * Checks if the input is a forbidden host code point. * @see https://url.spec.whatwg.org/#forbidden-host-code-point */ ada_really_inline constexpr bool is_forbidden_host_code_point(char c) noexcept; /** + * @private * Checks if the input contains a forbidden domain code point. * @see https://url.spec.whatwg.org/#forbidden-domain-code-point */ @@ -4510,6 +4629,7 @@ ada_really_inline constexpr bool contains_forbidden_domain_code_point( const char* input, size_t length) noexcept; /** + * @private * Checks if the input contains a forbidden domain code point in which case * the first bit is set to 1. If the input contains an upper case ASCII letter, * then the second bit is set to 1. @@ -4520,6 +4640,7 @@ contains_forbidden_domain_code_point_or_upper(const char* input, size_t length) noexcept; /** + * @private * Checks if the input is a forbidden domain code point. * @see https://url.spec.whatwg.org/#forbidden-domain-code-point */ @@ -4527,11 +4648,13 @@ ada_really_inline constexpr bool is_forbidden_domain_code_point( char c) noexcept; /** + * @private * Checks if the input is alphanumeric, '+', '-' or '.' */ ada_really_inline constexpr bool is_alnum_plus(char c) noexcept; /** + * @private * @details An ASCII hex digit is an ASCII upper hex digit or ASCII lower hex * digit. An ASCII upper hex digit is an ASCII digit or a code point in the * range U+0041 (A) to U+0046 (F), inclusive. An ASCII lower hex digit is an @@ -4540,6 +4663,7 @@ ada_really_inline constexpr bool is_alnum_plus(char c) noexcept; ada_really_inline constexpr bool is_ascii_hex_digit(char c) noexcept; /** + * @private * Checks if the input is a C0 control or space character. * * @details A C0 control or space is a C0 control or U+0020 SPACE. @@ -4549,6 +4673,7 @@ ada_really_inline constexpr bool is_ascii_hex_digit(char c) noexcept; ada_really_inline constexpr bool is_c0_control_or_space(char c) noexcept; /** + * @private * Checks if the input is a ASCII tab or newline character. * * @details An ASCII tab or newline is U+0009 TAB, U+000A LF, or U+000D CR. @@ -4556,6 +4681,7 @@ ada_really_inline constexpr bool is_c0_control_or_space(char c) noexcept; ada_really_inline constexpr bool is_ascii_tab_or_newline(char c) noexcept; /** + * @private * @details A double-dot path segment must be ".." or an ASCII case-insensitive * match for ".%2e", "%2e.", or "%2e%2e". */ @@ -4563,6 +4689,7 @@ ada_really_inline ada_constexpr bool is_double_dot_path_segment( std::string_view input) noexcept; /** + * @private * @details A single-dot path segment must be "." or an ASCII case-insensitive * match for "%2e". */ @@ -4570,17 +4697,20 @@ ada_really_inline constexpr bool is_single_dot_path_segment( std::string_view input) noexcept; /** + * @private * @details ipv4 character might contain 0-9 or a-f character ranges. */ ada_really_inline constexpr bool is_lowercase_hex(char c) noexcept; /** + * @private * @details Convert hex to binary. Caller is responsible to ensure that * the parameter is an hexadecimal digit (0-9, A-F, a-f). */ ada_really_inline unsigned constexpr convert_hex_to_binary(char c) noexcept; /** + * @private * first_percent should be = input.find('%') * * @todo It would be faster as noexcept maybe, but it could be unsafe since. @@ -4591,12 +4721,14 @@ ada_really_inline unsigned constexpr convert_hex_to_binary(char c) noexcept; std::string percent_decode(std::string_view input, size_t first_percent); /** + * @private * Returns a percent-encoding string whether percent encoding was needed or not. * @see https://github.com/nodejs/node/blob/main/src/node_url.cc#L226 */ std::string percent_encode(std::string_view input, const uint8_t character_set[]); /** + * @private * Returns a percent-encoded string version of input, while starting the percent * encoding at the provided index. * @see https://github.com/nodejs/node/blob/main/src/node_url.cc#L226 @@ -4604,6 +4736,7 @@ std::string percent_encode(std::string_view input, std::string percent_encode(std::string_view input, const uint8_t character_set[], size_t index); /** + * @private * Returns true if percent encoding was needed, in which case, we store * the percent-encoded content in 'out'. If the boolean 'append' is set to * true, the content is appended to 'out'. @@ -4614,12 +4747,14 @@ template bool percent_encode(std::string_view input, const uint8_t character_set[], std::string& out); /** + * @private * Returns the index at which percent encoding should start, or (equivalently), * the length of the prefix that does not require percent encoding. */ ada_really_inline size_t percent_encode_index(std::string_view input, const uint8_t character_set[]); /** + * @private * Lowers the string in-place, assuming that the content is ASCII. * Return true if the content was ASCII. */ @@ -4644,7 +4779,6 @@ constexpr bool to_lower_ascii(char* input, size_t length) noexcept; #ifndef ADA_URL_AGGREGATOR_H #define ADA_URL_AGGREGATOR_H - #include #include @@ -4660,10 +4794,10 @@ namespace ada { */ struct url_aggregator : url_base { url_aggregator() = default; - url_aggregator(const url_aggregator &u) = default; - url_aggregator(url_aggregator &&u) noexcept = default; - url_aggregator &operator=(url_aggregator &&u) noexcept = default; - url_aggregator &operator=(const url_aggregator &u) = default; + url_aggregator(const url_aggregator& u) = default; + url_aggregator(url_aggregator&& u) noexcept = default; + url_aggregator& operator=(url_aggregator&& u) noexcept = default; + url_aggregator& operator=(const url_aggregator& u) = default; ~url_aggregator() override = default; bool set_href(std::string_view input); @@ -4797,7 +4931,7 @@ struct url_aggregator : url_base { * @see * https://github.com/servo/rust-url/blob/b65a45515c10713f6d212e6726719a020203cc98/url/src/quirks.rs#L31 */ - [[nodiscard]] ada_really_inline const ada::url_components &get_components() + [[nodiscard]] ada_really_inline const ada::url_components& get_components() const noexcept; /** * Returns a string representation of this URL. @@ -4838,9 +4972,13 @@ struct url_aggregator : url_base { private: friend ada::url_aggregator ada::parser::parse_url( - std::string_view, const ada::url_aggregator *); + 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; + ada::url_aggregator>(ada::url_aggregator& url) noexcept; + friend ada::url_aggregator ada::parser::parse_url_impl< + ada::url_aggregator, true>(std::string_view, const ada::url_aggregator*); + friend ada::url_aggregator ada::parser::parse_url_impl< + ada::url_aggregator, false>(std::string_view, const ada::url_aggregator*); std::string buffer{}; url_components components{}; @@ -4868,10 +5006,12 @@ struct url_aggregator : url_base { } /** - * Return true on success. + * Return true on success. The 'in_place' parameter indicates whether the + * the string_view input is pointing in the buffer. When in_place is false, + * we must nearly always update the buffer. * @see https://url.spec.whatwg.org/#concept-ipv4-parser */ - [[nodiscard]] bool parse_ipv4(std::string_view input); + [[nodiscard]] bool parse_ipv4(std::string_view input, bool in_place); /** * Return true on success. @@ -4899,12 +5039,12 @@ struct url_aggregator : url_base { ada_really_inline bool parse_host(std::string_view input); inline void update_base_authority(std::string_view base_buffer, - const ada::url_components &base); + const ada::url_components& base); 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); inline void update_base_search(std::string_view input, - const uint8_t *query_percent_encode_set); + const uint8_t* query_percent_encode_set); inline void update_base_pathname(std::string_view input); inline void update_base_username(std::string_view input); inline void append_base_username(std::string_view input); @@ -4933,11 +5073,11 @@ struct url_aggregator : url_base { */ inline void set_scheme_from_view_with_colon( std::string_view new_scheme_with_colon) noexcept; - inline void copy_scheme(const url_aggregator &u) noexcept; + inline void copy_scheme(const url_aggregator& u) noexcept; }; // url_aggregator -inline std::ostream &operator<<(std::ostream &out, const ada::url &u); +inline std::ostream& operator<<(std::ostream& out, const ada::url& u); } // namespace ada #endif @@ -4950,17 +5090,20 @@ inline std::ostream &operator<<(std::ostream &out, const ada::url &u); #ifndef ADA_CHECKERS_H #define ADA_CHECKERS_H - -#include #include +#include /** + * These functions are not part of our public API and may + * change at any time. + * @private * @namespace ada::checkers * @brief Includes the definitions for validation functions */ namespace ada::checkers { /** + * @private * Assuming that x is an ASCII letter, this function returns the lower case * equivalent. * @details More likely to be inlined by the compiler and constexpr. @@ -4968,6 +5111,7 @@ namespace ada::checkers { constexpr char to_lower(char x) noexcept; /** + * @private * Returns true if the character is an ASCII letter. Equivalent to std::isalpha * but more likely to be inlined by the compiler. * @@ -4976,6 +5120,7 @@ constexpr char to_lower(char x) noexcept; constexpr bool is_alpha(char x) noexcept; /** + * @private * Check whether a string starts with 0x or 0X. The function is only * safe if input.size() >=2. * @@ -4983,17 +5128,20 @@ constexpr bool is_alpha(char x) noexcept; */ inline bool has_hex_prefix_unsafe(std::string_view input); /** + * @private * Check whether a string starts with 0x or 0X. */ inline bool has_hex_prefix(std::string_view input); /** + * @private * Check whether x is an ASCII digit. More likely to be inlined than * std::isdigit. */ constexpr bool is_digit(char x) noexcept; /** + * @private * @details A string starts with a Windows drive letter if all of the following * are true: * @@ -5007,6 +5155,7 @@ constexpr bool is_digit(char x) noexcept; inline constexpr bool is_windows_drive_letter(std::string_view input) noexcept; /** + * @private * @details A normalized Windows drive letter is a Windows drive letter of which * the second code point is U+003A (:). */ @@ -5014,12 +5163,14 @@ inline constexpr bool is_normalized_windows_drive_letter( std::string_view input) noexcept; /** + * @private * @warning Will be removed when Ada requires C++20. */ ada_really_inline bool begins_with(std::string_view view, std::string_view prefix); /** + * @private * Returns true if an input is an ipv4 address. It is assumed that the string * does not contain uppercase ASCII characters (the input should have been * lowered cased before calling this function) and is not empty. @@ -5027,6 +5178,7 @@ ada_really_inline bool begins_with(std::string_view view, ada_really_inline ada_constexpr bool is_ipv4(std::string_view view) noexcept; /** + * @private * Returns a bitset. If the first bit is set, then at least one character needs * percent encoding. If the second bit is set, a \\ is found. If the third bit * is set then we have a dot. If the fourth bit is set, then we have a percent @@ -5036,6 +5188,7 @@ ada_really_inline constexpr uint8_t path_signature( std::string_view input) noexcept; /** + * @private * Returns true if the length of the domain name and its labels are according to * the specifications. The length of the domain must be 255 octets (253 * characters not including the last 2 which are the empty label reserved at the @@ -5060,7 +5213,6 @@ ada_really_inline constexpr bool verify_dns_length( #ifndef ADA_URL_H #define ADA_URL_H - #include #include #include @@ -5084,10 +5236,10 @@ namespace ada { */ struct url : url_base { url() = default; - url(const url &u) = default; - url(url &&u) noexcept = default; - url &operator=(url &&u) noexcept = default; - url &operator=(const url &u) = default; + url(const url& u) = default; + url(url&& u) noexcept = default; + url& operator=(url&& u) noexcept = default; + url& operator=(const url& u) = default; ~url() override = default; /** @@ -5218,7 +5370,7 @@ struct url : url_base { * @return a constant reference to the underlying string. * @see https://url.spec.whatwg.org/#dom-url-username */ - [[nodiscard]] const std::string &get_username() const noexcept; + [[nodiscard]] const std::string& get_username() const noexcept; /** * @return Returns true on successful operation. @@ -5284,7 +5436,7 @@ struct url : url_base { * @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; + [[nodiscard]] const std::string& get_password() const noexcept; /** * Return this's URL's port, serialized. @@ -5336,11 +5488,16 @@ struct url : url_base { private: friend ada::url ada::parser::parse_url(std::string_view, - const ada::url *); + const ada::url*); friend ada::url_aggregator ada::parser::parse_url( - std::string_view, const ada::url_aggregator *); + std::string_view, const ada::url_aggregator*); friend void ada::helpers::strip_trailing_spaces_from_opaque_path( - ada::url &url) noexcept; + 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); @@ -5407,7 +5564,7 @@ struct url : url_base { * Take the scheme from another URL. The scheme string is copied from the * provided url. */ - inline void copy_scheme(const ada::url &u); + inline void copy_scheme(const ada::url& u); /** * Parse the host from the provided input. We assume that @@ -5443,17 +5600,17 @@ struct url : url_base { * scheme string, be lower-cased, not contain spaces or tabs. It should * have no spurious trailing or leading content. */ - inline void set_scheme(std::string &&new_scheme) noexcept; + inline void set_scheme(std::string&& new_scheme) noexcept; /** * Take the scheme from another URL. The scheme string is moved from the * provided url. */ - inline void copy_scheme(ada::url &&u) noexcept; + inline void copy_scheme(ada::url&& u) noexcept; }; // struct url -inline std::ostream &operator<<(std::ostream &out, const ada::url &u); +inline std::ostream& operator<<(std::ostream& out, const ada::url& u); } // namespace ada #endif // ADA_URL_H @@ -5492,7 +5649,6 @@ url_base::scheme_default_port() const noexcept { #ifndef ADA_URL_INL_H #define ADA_URL_INL_H - #include #include #if ADA_REGULAR_VISUAL_STUDIO @@ -5519,7 +5675,7 @@ namespace ada { [[nodiscard]] inline bool url::has_hostname() const noexcept { return host.has_value(); } -inline std::ostream &operator<<(std::ostream &out, const ada::url &u) { +inline std::ostream& operator<<(std::ostream& out, const ada::url& u) { return out << u.to_string(); } @@ -5587,7 +5743,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++; } } @@ -5646,7 +5802,7 @@ inline void url::clear_search() { query = std::nullopt; } inline void url::set_protocol_as_file() { type = ada::scheme::type::FILE; } -inline void url::set_scheme(std::string &&new_scheme) noexcept { +inline void url::set_scheme(std::string&& new_scheme) noexcept { type = ada::scheme::get_scheme_type(new_scheme); // We only move the 'scheme' if it is non-special. if (!is_special()) { @@ -5654,12 +5810,12 @@ inline void url::set_scheme(std::string &&new_scheme) noexcept { } } -inline void url::copy_scheme(ada::url &&u) noexcept { +inline void url::copy_scheme(ada::url&& u) noexcept { non_special_scheme = u.non_special_scheme; type = u.type; } -inline void url::copy_scheme(const ada::url &u) { +inline void url::copy_scheme(const ada::url& u) { non_special_scheme = u.non_special_scheme; type = u.type; } @@ -5749,6 +5905,10 @@ ada_really_inline size_t url::parse_port(std::string_view view, #include /** + * Unicode operations. These functions are not part of our public API and may + * change at any time. + * + * private * @namespace ada::unicode * @brief Includes the declarations for unicode operations */ @@ -5772,7 +5932,7 @@ ada_really_inline size_t percent_encode_index(const std::string_view input, namespace ada { inline void url_aggregator::update_base_authority( - std::string_view base_buffer, const ada::url_components &base) { + std::string_view base_buffer, const ada::url_components& base) { std::string_view input = base_buffer.substr( base.protocol_end, base.host_start - base.protocol_end); ada_log("url_aggregator::update_base_authority ", input); @@ -6054,7 +6214,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()); @@ -6124,7 +6284,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(); @@ -6154,7 +6314,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)); @@ -6280,7 +6440,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)); @@ -6477,7 +6637,7 @@ inline bool url_aggregator::cannot_have_credentials_or_port() const { components.host_start == components.host_end; } -[[nodiscard]] ada_really_inline const ada::url_components & +[[nodiscard]] ada_really_inline const ada::url_components& url_aggregator::get_components() const noexcept { return components; } @@ -6664,8 +6824,8 @@ inline void url_aggregator::set_protocol_as_file() { ADA_ASSERT_TRUE(validate()); } -inline std::ostream &operator<<(std::ostream &out, - const ada::url_aggregator &u) { +inline std::ostream& operator<<(std::ostream& out, + const ada::url_aggregator& u) { return out << u.to_string(); } } // namespace ada @@ -6719,10 +6879,10 @@ struct url_search_params { */ 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(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; @@ -6767,7 +6927,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 @@ -6805,6 +6965,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{}; @@ -6827,11 +6995,11 @@ struct url_search_params { template struct url_search_params_iter { inline url_search_params_iter() : params(EMPTY) {} - url_search_params_iter(const url_search_params_iter &u) = default; - url_search_params_iter(url_search_params_iter &&u) noexcept = default; - url_search_params_iter &operator=(url_search_params_iter &&u) noexcept = + url_search_params_iter(const url_search_params_iter& u) = default; + url_search_params_iter(url_search_params_iter&& u) noexcept = default; + url_search_params_iter& operator=(url_search_params_iter&& u) noexcept = default; - url_search_params_iter &operator=(const url_search_params_iter &u) = default; + url_search_params_iter& operator=(const url_search_params_iter& u) = default; ~url_search_params_iter() = default; /** @@ -6843,9 +7011,9 @@ struct url_search_params_iter { private: static url_search_params EMPTY; - inline url_search_params_iter(url_search_params ¶ms_) : params(params_) {} + inline url_search_params_iter(url_search_params& params_) : params(params_) {} - url_search_params ¶ms; + url_search_params& params; size_t pos = 0; friend struct url_search_params; @@ -6862,7 +7030,6 @@ struct url_search_params_iter { #ifndef ADA_URL_SEARCH_PARAMS_INL_H #define ADA_URL_SEARCH_PARAMS_INL_H - #include #include #include @@ -6875,6 +7042,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); @@ -6884,12 +7056,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(), '+', ' '); @@ -6925,7 +7097,7 @@ 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; }); + [&key](auto& param) { return param.first == key; }); if (entry == params.end()) { return std::nullopt; @@ -6938,7 +7110,7 @@ inline std::vector url_search_params::get_all( const std::string_view key) { std::vector out{}; - for (auto ¶m : params) { + for (auto& param : params) { if (param.first == key) { out.emplace_back(param.second); } @@ -6949,20 +7121,20 @@ inline std::vector url_search_params::get_all( 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; }); + [&key](auto& param) { return param.first == key; }); return entry != params.end(); } inline bool url_search_params::has(std::string_view key, std::string_view value) noexcept { auto entry = - std::find_if(params.begin(), params.end(), [&key, &value](auto ¶m) { + std::find_if(params.begin(), params.end(), [&key, &value](auto& param) { return param.first == key && param.second == value; }); 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++) { @@ -6985,7 +7157,7 @@ inline std::string url_search_params::to_string() { 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; }; + const auto find = [&key](auto& param) { return param.first == key; }; auto it = std::find_if(params.begin(), params.end(), find); @@ -7001,14 +7173,14 @@ inline void url_search_params::set(const std::string_view key, 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; }), + [&key](auto& param) { 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) { + [&key, &value](auto& param) { return param.first == key && param.second == value; }), @@ -7017,7 +7189,7 @@ inline void url_search_params::remove(const std::string_view key, inline void url_search_params::sort() { std::stable_sort(params.begin(), params.end(), - [](const key_value_pair &lhs, const key_value_pair &rhs) { + [](const key_value_pair& lhs, const key_value_pair& rhs) { return lhs.first < rhs.first; }); } @@ -7047,20 +7219,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++]; } @@ -7078,14 +7256,14 @@ url_search_params_entries_iter::next() { #ifndef ADA_ADA_VERSION_H #define ADA_ADA_VERSION_H -#define ADA_VERSION "2.7.4" +#define ADA_VERSION "2.9.0" namespace ada { enum { ADA_VERSION_MAJOR = 2, - ADA_VERSION_MINOR = 7, - ADA_VERSION_REVISION = 4, + ADA_VERSION_MINOR = 9, + ADA_VERSION_REVISION = 0, }; } // namespace ada @@ -7101,9 +7279,8 @@ enum { #ifndef ADA_IMPLEMENTATION_H #define ADA_IMPLEMENTATION_H -#include #include - +#include namespace ada { enum class errors { generic_error };