14bool url::parse_opaque_host(std::string_view
input) {
16 if (std::ranges::any_of(
input, ada::unicode::is_forbidden_host_code_point)) {
22 host = ada::unicode::percent_encode(
27bool url::parse_ipv4(std::string_view
input) {
29 if (
input.back() ==
'.') {
30 input.remove_suffix(1);
43 ((
input.length() > 2) && (
input[2] ==
'.')))) {
46 input.remove_prefix(2);
48 std::from_chars_result
r{};
52 }
else if ((
input.length() >= 2) &&
input[0] ==
'0' &&
61 if (
r.ec != std::errc()) {
84 input.remove_prefix(1);
102bool url::parse_ipv6(std::string_view
input) {
109 std::array<uint16_t, 8>
address{};
121 if (
input[0] ==
':') {
125 ada_log(
"parse_ipv6 starts with : but the rest does not start with :");
140 ada_log(
"parse_ipv6 piece_index == 8");
148 ada_log(
"parse_ipv6 compress is non-null");
166 unicode::is_ascii_hex_digit(*
pointer)) {
168 value =
uint16_t(value * 0x10 + unicode::convert_hex_to_binary(*
pointer));
177 ada_log(
"parse_ipv6 length is 0");
186 ada_log(
"parse_ipv6 piece_index > 6");
207 ada_log(
"parse_ipv6 Otherwise, validation error, return failure");
215 "parse_ipv6 If c is not an ASCII digit, validation error, return "
231 ada_log(
"parse_ipv6 if ipv4Piece is 0, validation error");
241 ada_log(
"parse_ipv6 ipv4_piece > 255");
280 "parse_ipv6 If c is the EOF code point, validation error, return "
289 "parse_ipv6 Otherwise, if c is not the EOF code point, validation "
290 "error, return failure");
322 "parse_ipv6 if compress is null and pieceIndex is not 8, validation "
323 "error, return failure");
332template <
bool has_state_overr
ide>
358 host.value().empty()) {
402 host.value().empty()) {
407 set_scheme(std::move(
_buffer));
432 if (
input[0] ==
'[') {
434 if (
input.back() !=
']') {
441 input.remove_prefix(1);
442 input.remove_suffix(1);
443 return parse_ipv6(
input);
449 return parse_opaque_host(
input);
462 ada_log(
"parse_host fast path decimal ipv4");
470 std::string buffer = std::string(
input);
474 unicode::to_lower_ascii(buffer.data(), buffer.size());
475 bool is_forbidden = unicode::contains_forbidden_domain_code_point(
476 buffer.data(), buffer.size());
477 if (
is_forbidden == 0 && buffer.find(
"xn-") == std::string_view::npos) {
479 host = std::move(buffer);
482 if (checkers::is_ipv4(host.value())) {
483 ada_log(
"parse_host fast path ipv4");
484 return parse_ipv4(host.value());
486 ada_log(
"parse_host fast path ", *host);
489 ada_log(
"parse_host calling to_ascii");
492 ada_log(
"parse_host to_ascii returns false");
495 ada_log(
"parse_host to_ascii succeeded ", *host,
" [", host->size(),
498 if (std::any_of(host.value().begin(), host.value().end(),
499 ada::unicode::is_forbidden_domain_code_point)) {
506 if (checkers::is_ipv4(host.value())) {
507 ada_log(
"parse_host got ipv4 ", *host);
508 return parse_ipv4(host.value());
518 if (unicode::has_tabs_or_newline(
input)) {
522 helpers::remove_ascii_tab_or_newline(
tmp_buffer);
533 helpers::parse_prepared_path(
internal_input.substr(1), type, path);
539 helpers::parse_prepared_path(
internal_input.substr(1), type, path);
544 if (!host.has_value()) {
555 auto back = std::back_insert_iterator(
answer);
557 answer.append(
"\t\"protocol\":\"");
561 answer.append(
"\t\"username\":\"");
562 helpers::encode_json(username, back);
564 answer.append(
"\t\"password\":\"");
565 helpers::encode_json(password, back);
568 if (host.has_value()) {
569 answer.append(
"\t\"host\":\"");
570 helpers::encode_json(host.value(), back);
573 if (port.has_value()) {
574 answer.append(
"\t\"port\":\"");
575 answer.append(std::to_string(port.value()));
578 answer.append(
"\t\"path\":\"");
579 helpers::encode_json(path, back);
581 answer.append(
"\t\"opaque path\":");
585 answer.append(
"\t\"query\":\"");
587 helpers::encode_json(query.value(), back);
590 if (hash.has_value()) {
592 answer.append(
"\t\"hash\":\"");
593 helpers::encode_json(hash.value(), back);
601 if (!host.has_value()) {
604 return checkers::verify_dns_length(host.value());
616 if (non_special_scheme ==
"blob") {
623 return ada::helpers::concat(
result->get_protocol(),
"//",
638 return helpers::concat(non_special_scheme,
":");
646 if (!host.has_value()) {
649 if (port.has_value()) {
650 return host.value() +
":" +
get_port();
656 return host.value_or(
"");
662 return (!query.has_value() || (query.value().empty())) ?
""
663 :
"?" + query.value();
675 return port.has_value() ? std::to_string(port.value()) :
"";
681 return (!hash.has_value() || (hash.value().empty())) ?
""
682 :
"#" + hash.value();
685template <
bool overr
ide_hostname>
686bool url::set_host_or_hostname(
const std::string_view
input) {
698 helpers::remove_ascii_tab_or_newline(
_host);
715 if (buffer.empty()) {
776 if (
location != std::string_view::npos) {
792 if (host ==
"localhost") {
808 if (cannot_have_credentials_or_port()) {
811 username = ada::unicode::percent_encode(
817 if (cannot_have_credentials_or_port()) {
820 password = ada::unicode::percent_encode(
826 if (cannot_have_credentials_or_port()) {
836 helpers::remove_ascii_tab_or_newline(
trimmed);
843 if (!ada::unicode::is_ascii_digit(
trimmed.front())) {
849 std::ranges::find_if_not(
trimmed, ada::unicode::is_ascii_digit);
867 helpers::strip_trailing_spaces_from_opaque_path(*
this);
873 helpers::remove_ascii_tab_or_newline(
new_value);
874 hash = unicode::percent_encode(
new_value,
880 query = std::nullopt;
881 helpers::strip_trailing_spaces_from_opaque_path(*
this);
887 helpers::remove_ascii_tab_or_newline(
new_value);
907 helpers::remove_ascii_tab_or_newline(
view);
919 std::string::iterator
pointer =
920 std::ranges::find_if_not(
view, unicode::is_alnum_plus);
936 return out.has_value();
#define ada_really_inline
constexpr uint8_t QUERY_PERCENT_ENCODE[32]
constexpr uint8_t SPECIAL_QUERY_PERCENT_ENCODE[32]
constexpr uint8_t C0_CONTROL_PERCENT_ENCODE[32]
constexpr uint8_t USERINFO_PERCENT_ENCODE[32]
constexpr uint8_t FRAGMENT_PERCENT_ENCODE[32]
constexpr bool has_hex_prefix(std::string_view input)
constexpr uint64_t ipv4_fast_fail
constexpr bool is_alpha(char x) noexcept
constexpr bool is_digit(char x) noexcept
ada_really_inline constexpr uint64_t try_parse_ipv4_fast(std::string_view input) noexcept
constexpr std::string_view is_special_list[]
constexpr ada::scheme::type get_scheme_type(std::string_view scheme) noexcept
type
Enumeration of URL scheme types.
constexpr uint16_t get_special_port(std::string_view scheme) noexcept
std::string ipv6(const std::array< uint16_t, 8 > &address)
std::string ipv4(uint64_t address)
tl::expected< result_type, ada::errors > result
ada_warn_unused ada::result< result_type > parse(std::string_view input, const result_type *base_url=nullptr)
Definitions for the URL scheme.
ada_really_inline constexpr bool is_special() const noexcept
void set_hash(std::string_view input)
bool set_hostname(std::string_view input)
bool set_host(std::string_view input)
ada_really_inline bool has_credentials() const noexcept
bool set_password(std::string_view input)
void set_search(std::string_view input)
std::string get_search() const
bool set_href(std::string_view input)
std::string get_port() const
std::string get_protocol() const
std::string get_host() const
bool set_username(std::string_view input)
bool set_pathname(std::string_view input)
std::string get_hostname() const
std::string get_origin() const override
const std::string & get_password() const noexcept
bool set_protocol(std::string_view input)
const std::string & get_username() const noexcept
bool set_port(std::string_view input)
constexpr bool has_search() const noexcept override
std::string to_string() const override
std::string get_hash() const
bool has_valid_domain() const noexcept override
Definitions for unicode operations.