Loading...
Searching...
No Matches
url-inl.h
Go to the documentation of this file.
#ifndef ADA_URL_INL_H
#define ADA_URL_INL_H
#include "ada/url.h"
#include "ada/url_components.h"
#include <charconv>
#include <optional>
#include <string>
#if ADA_REGULAR_VISUAL_STUDIO
#include <intrin.h>
#endif // ADA_REGULAR_VISUAL_STUDIO
namespace ada {
[[nodiscard]] ada_really_inline bool url::has_credentials() const noexcept {
return !username.empty() || !password.empty();
}
[[nodiscard]] ada_really_inline bool url::has_port() const noexcept {
return port.has_value();
}
[[nodiscard]] inline bool url::cannot_have_credentials_or_port() const {
return !host.has_value() || host.value().empty() ||
type == ada::scheme::type::FILE;
}
[[nodiscard]] inline bool url::has_empty_hostname() const noexcept {
if (!host.has_value()) {
return false;
}
return host.value().empty();
}
[[nodiscard]] inline bool url::has_hostname() const noexcept {
return host.has_value();
}
inline std::ostream &operator<<(std::ostream &out, const ada::url &u) {
return out << u.to_string();
}
[[nodiscard]] size_t url::get_pathname_length() const noexcept {
return path.size();
}
[[nodiscard]] constexpr std::string_view url::get_pathname() const noexcept {
return path;
}
[[nodiscard]] ada_really_inline ada::url_components url::get_components()
const noexcept {
url_components out{};
// protocol ends with ':'. for example: "https:"
out.protocol_end = uint32_t(get_protocol().size());
// Trailing index is always the next character of the current one.
// NOLINTNEXTLINE(clang-analyzer-deadcode.DeadStores)
size_t running_index = out.protocol_end;
if (host.has_value()) {
// 2 characters for "//" and 1 character for starting index
out.host_start = out.protocol_end + 2;
if (has_credentials()) {
out.username_end = uint32_t(out.host_start + username.size());
out.host_start += uint32_t(username.size());
if (!password.empty()) {
out.host_start += uint32_t(password.size() + 1);
}
out.host_end = uint32_t(out.host_start + host.value().size());
} else {
out.username_end = out.host_start;
// Host does not start with "@" if it does not include credentials.
out.host_end = uint32_t(out.host_start + host.value().size()) - 1;
}
running_index = out.host_end + 1;
} else {
// Update host start and end date to the same index, since it does not
// exist.
out.host_start = out.protocol_end;
out.host_end = out.host_start;
if (!has_opaque_path && path.starts_with("//")) {
// If url's host is null, url does not have an opaque path, url's path's
// size is greater than 1, and url's path[0] is the empty string, then
// append U+002F (/) followed by U+002E (.) to output.
running_index = out.protocol_end + 2;
} else {
running_index = out.protocol_end;
}
}
if (port.has_value()) {
out.port = *port;
running_index += helpers::fast_digit_count(*port) + 1; // Port omits ':'
}
out.pathname_start = uint32_t(running_index);
running_index += path.size();
if (query.has_value()) {
out.search_start = uint32_t(running_index);
running_index += get_search().size();
if (get_search().empty()) {
running_index++;
}
}
if (hash.has_value()) {
out.hash_start = uint32_t(running_index);
}
return out;
}
inline void url::update_base_hostname(std::string_view input) { host = input; }
inline void url::update_unencoded_base_hash(std::string_view input) {
// We do the percent encoding
hash = unicode::percent_encode(input,
ada::character_sets::FRAGMENT_PERCENT_ENCODE);
}
inline void url::update_base_search(std::string_view input,
const uint8_t query_percent_encode_set[]) {
query = ada::unicode::percent_encode(input, query_percent_encode_set);
}
inline void url::update_base_search(std::optional<std::string> &&input) {
query = std::move(input);
}
inline void url::update_base_pathname(const std::string_view input) {
path = input;
}
inline void url::update_base_username(const std::string_view input) {
username = input;
}
inline void url::update_base_password(const std::string_view input) {
password = input;
}
inline void url::update_base_port(std::optional<uint16_t> input) {
port = input;
}
constexpr void url::clear_pathname() { path.clear(); }
constexpr void url::clear_search() { query = std::nullopt; }
[[nodiscard]] constexpr bool url::has_hash() const noexcept {
return hash.has_value();
}
[[nodiscard]] constexpr bool url::has_search() const noexcept {
return query.has_value();
}
constexpr void url::set_protocol_as_file() { type = ada::scheme::type::FILE; }
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()) {
non_special_scheme = std::move(new_scheme);
}
}
constexpr void url::copy_scheme(ada::url &&u) {
non_special_scheme = u.non_special_scheme;
type = u.type;
}
constexpr void url::copy_scheme(const ada::url &u) {
non_special_scheme = u.non_special_scheme;
type = u.type;
}
[[nodiscard]] ada_really_inline std::string url::get_href() const {
std::string output = get_protocol();
if (host.has_value()) {
output += "//";
if (has_credentials()) {
output += username;
if (!password.empty()) {
output += ":" + get_password();
}
output += "@";
}
output += host.value();
if (port.has_value()) {
output += ":" + get_port();
}
} else if (!has_opaque_path && path.starts_with("//")) {
// If url's host is null, url does not have an opaque path, url's path's
// size is greater than 1, and url's path[0] is the empty string, then
// append U+002F (/) followed by U+002E (.) to output.
output += "/.";
}
output += path;
if (query.has_value()) {
output += "?" + query.value();
}
if (hash.has_value()) {
output += "#" + hash.value();
}
return output;
}
ada_really_inline size_t url::parse_port(std::string_view view,
bool check_trailing_content) noexcept {
ada_log("parse_port('", view, "') ", view.size());
if (!view.empty() && view[0] == '-') {
ada_log("parse_port: view[0] == '0' && view.size() > 1");
is_valid = false;
return 0;
}
uint16_t parsed_port{};
auto r = std::from_chars(view.data(), view.data() + view.size(), parsed_port);
if (r.ec == std::errc::result_out_of_range) {
ada_log("parse_port: r.ec == std::errc::result_out_of_range");
is_valid = false;
return 0;
}
ada_log("parse_port: ", parsed_port);
const auto consumed = size_t(r.ptr - view.data());
ada_log("parse_port: consumed ", consumed);
if (check_trailing_content) {
is_valid &=
(consumed == view.size() || view[consumed] == '/' ||
view[consumed] == '?' || (is_special() && view[consumed] == '\\'));
}
ada_log("parse_port: is_valid = ", is_valid);
if (is_valid) {
// scheme_default_port can return 0, and we should allow 0 as a base port.
auto default_port = scheme_default_port();
bool is_port_valid = (default_port == 0 && parsed_port == 0) ||
(default_port != parsed_port);
port = (r.ec == std::errc() && is_port_valid) ? std::optional(parsed_port)
: std::nullopt;
}
return consumed;
}
} // namespace ada
#endif // ADA_URL_H
ada_really_inline
#define ada_really_inline
Definition common_defs.h:85
ada::character_sets::FRAGMENT_PERCENT_ENCODE
constexpr uint8_t FRAGMENT_PERCENT_ENCODE[32]
Definition character_sets-inl.h:251
ada::scheme::get_scheme_type
constexpr ada::scheme::type get_scheme_type(std::string_view scheme) noexcept
Definition scheme-inl.h:107
ada::scheme::FILE
@ FILE
Definition scheme.h:48
ada
Definition ada_idna.h:13
ada::operator<<
std::ostream & operator<<(std::ostream &out, const ada::url &u)
Definition url-inl.h:38
ada::url_base::has_opaque_path
bool has_opaque_path
Definition url_base.h:62
ada::url_components
Stores byte offsets for URL components within a buffer.
Definition url_components.h:39
ada::url_components::pathname_start
uint32_t pathname_start
Definition url_components.h:69
ada::url_components::hash_start
uint32_t hash_start
Definition url_components.h:75
ada::url_components::port
uint32_t port
Definition url_components.h:66
ada::url_components::protocol_end
uint32_t protocol_end
Definition url_components.h:51
ada::url_components::search_start
uint32_t search_start
Definition url_components.h:72
ada::url_components::host_end
uint32_t host_end
Definition url_components.h:63
ada::url_components::username_end
uint32_t username_end
Definition url_components.h:57
ada::url_components::host_start
uint32_t host_start
Definition url_components.h:60
ada::url
Represents a parsed URL with individual string components.
Definition url.h:62
ada::url::get_components
ada_really_inline ada::url_components get_components() const noexcept
Definition url-inl.h:50
ada::url::has_empty_hostname
bool has_empty_hostname() const noexcept
Definition url-inl.h:29
ada::url::has_port
bool has_port() const noexcept
Definition url-inl.h:22
ada::url::has_credentials
ada_really_inline bool has_credentials() const noexcept
Definition url-inl.h:19
ada::url::get_pathname_length
ada_really_inline size_t get_pathname_length() const noexcept
Definition url-inl.h:42
ada::url::get_search
std::string get_search() const
Definition url.cpp:659
ada::url::get_port
std::string get_port() const
Definition url.cpp:674
ada::url::get_protocol
std::string get_protocol() const
Definition url.cpp:633
ada::url::has_hostname
bool has_hostname() const noexcept
Definition url-inl.h:35
ada::url::get_pathname
constexpr std::string_view get_pathname() const noexcept
Definition url-inl.h:46
ada::url::get_href
ada_really_inline std::string get_href() const
Definition url-inl.h:188
ada::url::get_password
const std::string & get_password() const noexcept
Definition url.cpp:670
ada::url::has_search
constexpr bool has_search() const noexcept override
Definition url-inl.h:164
ada::url::to_string
std::string to_string() const override
Definition url.cpp:550
ada::url::has_hash
constexpr bool has_hash() const noexcept override
Definition url-inl.h:160
url.h
Declaration for the ada::url class.
url_components.h
Declaration for the URL Components.