17template <
bool has_state_overr
ide>
24 input.remove_suffix(1);
114inline void url_aggregator::copy_scheme(
const url_aggregator&
u) {
115 ada_log(
"url_aggregator::copy_scheme ",
u.buffer);
122 buffer.insert(0,
u.get_protocol());
144inline void url_aggregator::set_scheme_from_view_with_colon(
146 ada_log(
"url_aggregator::set_scheme_from_view_with_colon ",
156 if (buffer.empty()) {
178inline void url_aggregator::set_scheme(std::string_view
new_scheme) {
188 if (buffer.empty()) {
189 buffer.append(helpers::concat(
new_scheme,
":"));
192 buffer.insert(0, helpers::concat(
new_scheme,
":"));
215 helpers::remove_ascii_tab_or_newline(
view);
227 std::string::iterator
pointer =
228 std::ranges::find_if_not(
view, unicode::is_alnum_plus);
241 if (cannot_have_credentials_or_port()) {
247 update_base_username(
input);
250 update_base_username(ada::unicode::percent_encode(
261 if (cannot_have_credentials_or_port()) {
267 update_base_password(
input);
270 update_base_password(ada::unicode::percent_encode(
281 if (cannot_have_credentials_or_port()) {
291 helpers::remove_ascii_tab_or_newline(
trimmed);
298 if (!ada::unicode::is_ascii_digit(
trimmed.front())) {
304 std::ranges::find_if_not(
trimmed, ada::unicode::is_ascii_digit);
349 if (unicode::has_tabs_or_newline(
input)) {
353 helpers::remove_ascii_tab_or_newline(
tmp_buffer);
362 update_base_pathname(
"/");
378 update_base_pathname(
"/");
396 helpers::remove_ascii_tab_or_newline(
new_value);
421 helpers::remove_ascii_tab_or_newline(
new_value);
430 ada_log(
"url_aggregator::set_href, success :",
out.has_value());
433 ada_log(
"url_aggregator::set_href, parsed ",
out->to_string());
438 return out.has_value();
450 if (
input[0] ==
'[') {
452 if (
input.back() !=
']') {
459 input.remove_prefix(1);
460 input.remove_suffix(1);
461 return parse_ipv6(
input);
467 return parse_opaque_host(
input);
484 update_base_hostname(
input.substr(0,
input.size() - 1));
486 update_base_hostname(
input);
489 ada_log(
"parse_host fast path decimal ipv4");
494 unicode::contains_forbidden_domain_code_point_or_upper(
input.data(),
503 input.find(
"xn-") == std::string_view::npos) {
505 update_base_hostname(
input);
509 ada_log(
"parse_host fast path ipv4");
519 ada_log(
"parse_host calling to_ascii");
520 std::optional<std::string> host = std::string(
get_hostname());
523 ada_log(
"parse_host to_ascii returns false");
526 ada_log(
"parse_host to_ascii succeeded ", *host,
" [", host->size(),
529 if (std::ranges::any_of(host.value(),
530 ada::unicode::is_forbidden_domain_code_point)) {
536 if (checkers::is_ipv4(host.value())) {
537 ada_log(
"parse_host got ipv4 ", *host);
538 return parse_ipv4(host.value(),
false);
541 update_base_hostname(host.value());
546template <
bool overr
ide_hostname>
547bool url_aggregator::set_host_or_hostname(
const std::string_view
input) {
548 ada_log(
"url_aggregator::set_host_or_hostname ",
input);
562 helpers::remove_ascii_tab_or_newline(
_host);
627 }
else if (has_dash_dot()) {
628 add_authority_slashes_if_needed();
639 }
else if (has_dash_dot()) {
648 if (
location != std::string_view::npos) {
664 if (helpers::substring(buffer, components.
host_start,
665 components.
host_end) ==
"localhost") {
688 ada_log(
"url_aggregator::get_origin");
705 return helpers::concat(
out->get_protocol(),
"//",
out->get_host());
716 ada_log(
"url_aggregator::get_username");
718 return helpers::substring(buffer, components.
protocol_end + 2,
726 ada_log(
"url_aggregator::get_password");
728 return helpers::substring(buffer, components.
username_end + 1,
736 ada_log(
"url_aggregator::get_port");
740 return helpers::substring(buffer, components.
host_end + 1,
746 ada_log(
"url_aggregator::get_hash");
752 if (buffer.size() - components.
hash_start <= 1) {
755 return helpers::substring(buffer, components.
hash_start);
760 ada_log(
"url_aggregator::get_host");
779 ada_log(
"url_aggregator::get_hostname");
789 return helpers::substring(buffer,
start, components.
host_end);
794 ada_log(
"url_aggregator::get_search");
812 ada_log(
"url_aggregator::get_protocol");
813 return helpers::substring(buffer, 0, components.
protocol_end);
817 ada_log(
"url_aggregator::to_string buffer:", buffer,
" [", buffer.size(),
824 auto back = std::back_insert_iterator(
answer);
827 answer.append(
"\t\"buffer\":\"");
828 helpers::encode_json(buffer, back);
831 answer.append(
"\t\"protocol\":\"");
832 helpers::encode_json(get_protocol(), back);
835 if (has_credentials()) {
836 answer.append(
"\t\"username\":\"");
837 helpers::encode_json(get_username(), back);
839 answer.append(
"\t\"password\":\"");
840 helpers::encode_json(get_password(), back);
844 answer.append(
"\t\"host\":\"");
845 helpers::encode_json(get_host(), back);
848 answer.append(
"\t\"path\":\"");
849 helpers::encode_json(get_pathname(), back);
851 answer.append(
"\t\"opaque path\":");
852 answer.append((has_opaque_path ?
"true" :
"false"));
856 answer.append(
"\t\"query\":\"");
857 helpers::encode_json(get_search(), back);
861 answer.append(
"\t\"fragment\":\"");
862 helpers::encode_json(get_hash(), back);
870 return std::to_string(
offset);
874 answer.append(
"\t\"protocol_end\":");
878 answer.append(
"\t\"username_end\":");
882 answer.append(
"\t\"host_start\":");
886 answer.append(
"\t\"host_end\":");
890 answer.append(
"\t\"port\":");
894 answer.append(
"\t\"pathname_start\":");
898 answer.append(
"\t\"search_start\":");
902 answer.append(
"\t\"hash_start\":");
916bool url_aggregator::parse_ipv4(std::string_view
input,
bool in_place) {
918 " bytes], overlaps with buffer: ",
919 helpers::overlaps(
input, buffer) ?
"yes" :
"no");
923 input.remove_suffix(1);
934 ((
input.length() > 2) && (
input[2] ==
'.')))) {
937 input.remove_prefix(2);
939 std::from_chars_result
r{};
941 ada_log(
"parse_ipv4 trying to parse hex number");
944 }
else if ((
input.length() >= 2) &&
input[0] ==
'0' &&
946 ada_log(
"parse_ipv4 trying to parse octal number");
950 ada_log(
"parse_ipv4 trying to parse decimal number");
955 if (
r.ec != std::errc()) {
956 ada_log(
"parse_ipv4 parsing failed");
980 input.remove_prefix(1);
984 ada_log(
"parse_ipv4 found invalid (more than 4 numbers or empty) ");
994 "url_aggregator::parse_ipv4 completed and was already correct in the "
999 ada_log(
"url_aggregator::parse_ipv4 completed and we need to update it");
1004 update_base_hostname(
1012bool url_aggregator::parse_ipv6(std::string_view
input) {
1020 if (
input.empty()) {
1024 std::array<uint16_t, 8>
address{};
1036 if (
input[0] ==
':') {
1040 ada_log(
"parse_ipv6 starts with : but the rest does not start with :");
1055 ada_log(
"parse_ipv6 piece_index == 8");
1063 ada_log(
"parse_ipv6 compress is non-null");
1081 unicode::is_ascii_hex_digit(*
pointer)) {
1083 value =
uint16_t(value * 0x10 + unicode::convert_hex_to_binary(*
pointer));
1092 ada_log(
"parse_ipv6 length is 0");
1101 ada_log(
"parse_ipv6 piece_index > 6");
1121 ada_log(
"parse_ipv6 Otherwise, validation error, return failure");
1129 "parse_ipv6 If c is not an ASCII digit, validation error, return "
1145 ada_log(
"parse_ipv6 if ipv4Piece is 0, validation error");
1155 ada_log(
"parse_ipv6 ipv4_piece > 255");
1194 "parse_ipv6 If c is the EOF code point, validation error, return "
1203 "parse_ipv6 Otherwise, if c is not the EOF code point, validation "
1204 "error, return failure");
1236 "parse_ipv6 if compress is null and pieceIndex is not 8, validation "
1237 "error, return failure");
1250bool url_aggregator::parse_opaque_host(std::string_view
input) {
1254 if (std::ranges::any_of(
input, ada::unicode::is_forbidden_host_code_point)) {
1263 update_base_hostname(
input);
1266 update_base_hostname(ada::unicode::percent_encode(
1280 answer.append(std::to_string(buffer.size()));
1281 answer.append(
" bytes]");
1285 line1.resize(buffer.size(),
' ');
1295 if (components.
host_end != buffer.size()) {
1298 if (components.
host_start != buffer.size()) {
1318 line2.append(
" hash_start");
1331 line3.append(
" search_start ");
1344 line4.append(
" pathname_start ");
1351 if (components.
host_end != buffer.size()) {
1358 line5.append(
" host_end ");
1365 if (components.
host_start != buffer.size()) {
1372 line6.append(
" host_start ");
1386 line7.append(
" username_end ");
1400 line8.append(
" protocol_end ");
1407 answer.append(
"note: hash omitted\n");
1410 answer.append(
"note: search omitted\n");
1413 answer.append(
"warning: protocol_end overflows\n");
1416 answer.append(
"warning: username_end overflows\n");
1419 answer.append(
"warning: host_start overflows\n");
1421 if (components.
host_end > buffer.size()) {
1422 answer.append(
"warning: host_end overflows\n");
1425 answer.append(
"warning: pathname_start overflows\n");
1430void url_aggregator::delete_dash_dot() {
1431 ada_log(
"url_aggregator::delete_dash_dot");
1434 buffer.erase(components.
host_end, 2);
1446inline void url_aggregator::consume_prepared_path(std::string_view
input) {
1447 ada_log(
"url_aggregator::consume_prepared_path ",
input);
1482 if (
input[0] !=
'.') {
1487 if (
slashdot == std::string_view::npos) {
1500 ada_log(
"parse_path trivial");
1515 ada_log(
"parse_prepared_path fast");
1531 update_base_pathname(path);
1535 if (path.back() ==
'/') {
1536 update_base_pathname(path);
1541 path.resize(path.rfind(
'/') + 1);
1542 update_base_pathname(path);
1549 update_base_pathname(path);
1574 ?
input.find_first_of(
"/\\")
1577 if (
location != std::string_view::npos) {
1585 ada::unicode::percent_encode<false>(
1589 if (unicode::is_double_dot_path_segment(
path_buffer)) {
1590 helpers::shorten_path(path, type);
1591 if (
location == std::string_view::npos) {
1594 }
else if (unicode::is_single_dot_path_segment(
path_buffer) &&
1595 (
location == std::string_view::npos)) {
1599 else if (!unicode::is_single_dot_path_segment(
path_buffer)) {
1616 if (
location == std::string_view::npos) {
1617 update_base_pathname(path);
Definitions for URL specific checkers used within Ada.
#define ADA_ASSERT_TRUE(COND)
#define ada_lifetime_bound
#define ada_really_inline
Definitions for helper functions used within Ada.
User-facing functions for URL parsing and manipulation.
constexpr uint8_t QUERY_PERCENT_ENCODE[32]
constexpr uint8_t SPECIAL_QUERY_PERCENT_ENCODE[32]
constexpr uint8_t PATH_PERCENT_ENCODE[32]
constexpr uint8_t C0_CONTROL_PERCENT_ENCODE[32]
constexpr uint8_t USERINFO_PERCENT_ENCODE[32]
constexpr bool has_hex_prefix(std::string_view input)
constexpr bool is_windows_drive_letter(std::string_view input) noexcept
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 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)
ada_really_inline size_t percent_encode_index(const std::string_view input, const uint8_t character_set[])
tl::expected< result_type, ada::errors > result
template ada::result< url_aggregator > parse< url_aggregator >(std::string_view input, const url_aggregator *base_url)
ada_warn_unused ada::result< result_type > parse(std::string_view input, const result_type *base_url=nullptr)
URL scheme type definitions and utilities.
constexpr bool has_non_empty_password() const noexcept
void set_hash(std::string_view input)
constexpr bool validate() const noexcept
void clear_search() override
std::string_view get_search() const ada_lifetime_bound
std::string_view get_hash() const ada_lifetime_bound
friend void helpers::strip_trailing_spaces_from_opaque_path(url_aggregator &url)
std::string to_string() const override
std::string_view get_password() const ada_lifetime_bound
std::string_view get_host() const ada_lifetime_bound
std::string_view get_username() const ada_lifetime_bound
std::string_view get_port() const ada_lifetime_bound
std::string to_diagram() const
constexpr bool has_hostname() const noexcept
bool set_protocol(std::string_view input)
std::string get_origin() const override
constexpr std::string_view get_href() const noexcept ada_lifetime_bound
bool has_valid_domain() const noexcept override
bool set_hostname(std::string_view input)
bool set_password(std::string_view input)
bool set_pathname(std::string_view input)
bool set_href(std::string_view input)
constexpr std::string_view get_pathname() const ada_lifetime_bound
void set_search(std::string_view input)
std::string_view get_hostname() const ada_lifetime_bound
std::string_view get_protocol() const ada_lifetime_bound
constexpr bool has_port() const noexcept
ada_really_inline constexpr bool has_credentials() const noexcept
bool set_host(std::string_view input)
bool set_port(std::string_view input)
constexpr bool has_non_empty_username() const noexcept
bool set_username(std::string_view input)
ada_really_inline constexpr bool is_special() const noexcept
static constexpr uint32_t omitted
Definitions for unicode operations.
Inline functions for url aggregator.
Declaration for the ada::url_aggregator class.
Declaration for the URL Components.