Loading...
Searching...
No Matches
urlparser.h
Go to the documentation of this file.
1
43#ifndef URLPARSER_H
44#define URLPARSER_H
45
46// Single source of truth for the project version. Read by:
47// - cmake/DynamicVersion.cmake (sets PROJECT_VERSION for the CMake build)
48// - pyproject.toml's [tool.scikit-build.metadata.version] regex provider
49// - version.py (bump/tag helper)
50#define URLPARSER_VERSION_MAJOR 2
51#define URLPARSER_VERSION_MINOR 1
52#define URLPARSER_VERSION_PATCH 0
53
54#define URLPARSER_VERSION_ENCODE(maj,min,pat) (((maj)*10000)+((min)*100)+(pat))
55#define URLPARSER_VERSION \
56 URLPARSER_VERSION_ENCODE(URLPARSER_VERSION_MAJOR,URLPARSER_VERSION_MINOR,URLPARSER_VERSION_PATCH)
57
59#define URLPARSER_VERSION_HEX \
60 ((URLPARSER_VERSION_MAJOR << 16) | (URLPARSER_VERSION_MINOR << 8) | URLPARSER_VERSION_PATCH)
61
62/* Internal helpers for URLPARSER_VERSION_STRING */
63#define _URLPARSER_VERSION_XSTR(a,b,c) #a"."#b"."#c
64#define _URLPARSER_VERSION_STR(a,b,c) _URLPARSER_VERSION_XSTR(a,b,c)
65
67#define URLPARSER_VERSION_STRING \
68 _URLPARSER_VERSION_STR(URLPARSER_VERSION_MAJOR,URLPARSER_VERSION_MINOR,URLPARSER_VERSION_PATCH)
69
70// Single source of truth for the Public Suffix List URL. Read by:
71// - cmake/PublicSuffixList.cmake (downloads the .dat file this URL
72// points to, to embed into the compiled extension at build time)
73// - urlparser::psl::source_url() below (src/urlparser.cpp), so
74// psl.url / psl.update() in Python point at the same place the
75// build itself downloaded from - one URL, not two to keep in sync.
76#define URLPARSER_PUBLIC_SUFFIX_LIST_URL "https://publicsuffix.org/list/public_suffix_list.dat"
77
78#include <array>
79#include <cstdint>
80#include <iostream>
81#include <memory>
82#include <optional>
83#include <string>
84#include <string_view>
85#include <unordered_map>
86#include <utility>
87#include <variant>
88#include <vector>
89
90namespace urlparser {
91constexpr bool DEFAULT_IGNORE_WWW = false;
92
98class version {
99 public:
100 static unsigned int major() noexcept { return URLPARSER_VERSION_MAJOR; }
101 static unsigned int minor() noexcept { return URLPARSER_VERSION_MINOR; }
102 static unsigned int patch() noexcept { return URLPARSER_VERSION_PATCH; }
103 static unsigned int hex() noexcept { return URLPARSER_VERSION_HEX; }
104 static std::string_view string() noexcept { return URLPARSER_VERSION_STRING; }
105
106 private:
107 version();
108};
109
114using query_params = std::vector<std::string>;
115
128class hostname {
129 public:
139 static hostname from_url(std::string_view url,
140 const bool ignore_www = DEFAULT_IGNORE_WWW);
141
148 static hostname from_url(const char* url,
149 const bool ignore_www = DEFAULT_IGNORE_WWW);
150
157 static hostname from_url(const std::string& url,
158 const bool ignore_www = DEFAULT_IGNORE_WWW);
159
171 static hostname from_url(std::string&& url,
172 const bool ignore_www = DEFAULT_IGNORE_WWW);
173
179 static std::string_view remove_www(const std::string_view& host) noexcept;
180
181 public:
187 hostname(std::string host, const bool ignore_www = DEFAULT_IGNORE_WWW);
188
193 hostname() noexcept = default;
194
198 bool operator==(const hostname& other) const noexcept;
199
203 bool operator==(const std::string& other) const noexcept;
204
206 const std::string& suffix() const noexcept;
208 const std::string& domain() const noexcept;
210 std::string domain_name() const noexcept;
212 const std::string& subdomain() const noexcept;
214 const std::string& full_domain() const noexcept;
216 const std::string& str() const noexcept;
225 std::string normalized_ascii() const;
226
227 private:
228 // Runs the PSL lookup + domain/subdomain/suffix split exactly once, the
229 // first time any of those fields is actually requested.
230 void ensure_parsed() const noexcept;
231
232 std::string host_;
233 bool ignore_www_ = false;
234 mutable bool parsed_ = false;
235 mutable std::string domain_;
236 mutable std::string subdomain_;
237 mutable std::string suffix_;
238 mutable std::string fulldomain_;
239};
240
251namespace detail {
252// Wraps ankerl::unordered_dense::map<std::string, size_t> (vendored in
253// src/ankerl/ - see src/ankerl/README.md). Forward-
254// declared here and defined only in urlparser.cpp so that including this
255// public header doesn't require the vendored third-party header too -
256// psl::levels_ is a private implementation detail, and callers of the
257// public API never need to know what's actually inside it.
258class suffix_table;
259} // namespace detail
260
261class psl {
262 public:
264 static psl& instance() noexcept;
265
267 std::string_view source_url() const noexcept;
268
270 std::string_view version() const noexcept { return version_; }
271
273 bool is_loaded() const noexcept;
274
280 void load_from_path(const std::string& filepath);
281
287 void load_from_string(const std::string& filestr);
288
296 bool is_suffix(std::string_view text) const noexcept;
297
305 std::string suffix_of(const std::string& hostname_text) const;
306
307 private:
308 // levels_ is a std::unique_ptr<detail::suffix_table> (an incomplete
309 // type here), so the compiler-generated destructor/move members
310 // would need that type complete to know how to delete/move it -
311 // declared here, defined in urlparser.cpp where suffix_table is
312 // fully visible. Both the singleton instance (instance()'s static
313 // local) and the self-move-assignments in load_from_path()/
314 // load_from_string() are psl's own member functions, so these stay
315 // private along with the constructors - nothing outside the class
316 // should ever construct, move, or destroy a psl directly. Copy is
317 // deleted outright for the same reason (a unique_ptr member already
318 // makes an implicit copy ill-formed; an explicit delete fails at the
319 // call site with a clear reason instead of a unique_ptr error deep
320 // in a template instantiation).
321 ~psl();
322 psl(const psl&) = delete;
323 psl& operator=(const psl&) = delete;
324 psl(psl&&) noexcept;
325 psl& operator=(psl&&) noexcept;
326
327 psl() noexcept;
328 explicit psl(std::istream& stream);
329
330 size_t segment_count(const std::string& text) const;
331 void add_rule(std::string& rule, int level_adjust, size_t trim);
332
333 std::unique_ptr<detail::suffix_table> levels_;
334 std::string version_;
335};
336
350class ipv4 {
351 public:
353 ipv4() noexcept = default;
354
359 ipv4(std::string_view text);
360
362 static bool is_valid(std::string_view text) noexcept;
363
365 static ipv4 from_uint32(uint32_t address) noexcept;
366
371 static ipv4 from_url(std::string_view url);
372
374 std::string str() const;
375
377 uint32_t to_uint32() const noexcept { return value_; }
378
380 std::array<uint8_t, 4> bytes() const noexcept;
381
382 ipv4& operator++() noexcept {
383 ++value_;
384 return *this;
385 }
386 ipv4 operator++(int) noexcept {
387 ipv4 tmp = *this;
388 ++value_;
389 return tmp;
390 }
391 ipv4& operator--() noexcept {
392 --value_;
393 return *this;
394 }
395 ipv4 operator--(int) noexcept {
396 ipv4 tmp = *this;
397 --value_;
398 return tmp;
399 }
401 ipv4& operator+=(int64_t delta) noexcept {
402 value_ += static_cast<uint32_t>(delta);
403 return *this;
404 }
405 ipv4& operator-=(int64_t delta) noexcept {
406 value_ -= static_cast<uint32_t>(delta);
407 return *this;
408 }
409
410 friend ipv4 operator+(ipv4 lhs, int64_t delta) noexcept { return lhs += delta; }
411 friend ipv4 operator-(ipv4 lhs, int64_t delta) noexcept { return lhs -= delta; }
413 friend int64_t operator-(const ipv4& a, const ipv4& b) noexcept {
414 return static_cast<int64_t>(a.value_) - static_cast<int64_t>(b.value_);
415 }
416
417 friend bool operator==(const ipv4& a, const ipv4& b) noexcept { return a.value_ == b.value_; }
418 friend bool operator!=(const ipv4& a, const ipv4& b) noexcept { return a.value_ != b.value_; }
419 friend bool operator<(const ipv4& a, const ipv4& b) noexcept { return a.value_ < b.value_; }
420 friend bool operator<=(const ipv4& a, const ipv4& b) noexcept { return a.value_ <= b.value_; }
421 friend bool operator>(const ipv4& a, const ipv4& b) noexcept { return a.value_ > b.value_; }
422 friend bool operator>=(const ipv4& a, const ipv4& b) noexcept { return a.value_ >= b.value_; }
423
424 private:
425 explicit ipv4(uint32_t v) noexcept : value_(v) {}
426 uint32_t value_ = 0;
427};
428
442class ipv6 {
443 public:
445 ipv6() noexcept = default;
446
453 ipv6(std::string_view text);
454
456 static bool is_valid(std::string_view text) noexcept;
457
459 static ipv6 from_uint64_pair(uint64_t high, uint64_t low) noexcept;
460
465 static ipv6 from_url(std::string_view url);
466
468 std::string str() const;
469
471 std::array<uint8_t, 16> bytes() const noexcept;
472
474 uint64_t high64() const noexcept { return hi_; }
476 uint64_t low64() const noexcept { return lo_; }
477
478 ipv6& operator++() noexcept {
479 add_bits(1);
480 return *this;
481 }
482 ipv6 operator++(int) noexcept {
483 ipv6 tmp = *this;
484 ++(*this);
485 return tmp;
486 }
487 ipv6& operator--() noexcept {
488 add_bits(~uint64_t{0}); // two's-complement bit pattern of -1
489 return *this;
490 }
491 ipv6 operator--(int) noexcept {
492 ipv6 tmp = *this;
493 --(*this);
494 return tmp;
495 }
497 ipv6& operator+=(int64_t delta) noexcept {
498 add_bits(static_cast<uint64_t>(delta));
499 return *this;
500 }
501 ipv6& operator-=(int64_t delta) noexcept {
502 // -delta's bit pattern, computed in unsigned arithmetic so this is
503 // well-defined even when delta == INT64_MIN (no positive int64_t
504 // counterpart, so negating it as a signed value would overflow).
505 add_bits(~static_cast<uint64_t>(delta) + 1);
506 return *this;
507 }
508
509 friend ipv6 operator+(ipv6 lhs, int64_t delta) noexcept { return lhs += delta; }
510 friend ipv6 operator-(ipv6 lhs, int64_t delta) noexcept { return lhs -= delta; }
511
512 friend bool operator==(const ipv6& a, const ipv6& b) noexcept {
513 return a.hi_ == b.hi_ && a.lo_ == b.lo_;
514 }
515 friend bool operator!=(const ipv6& a, const ipv6& b) noexcept { return !(a == b); }
516 friend bool operator<(const ipv6& a, const ipv6& b) noexcept {
517 return a.hi_ != b.hi_ ? a.hi_ < b.hi_ : a.lo_ < b.lo_;
518 }
519 friend bool operator<=(const ipv6& a, const ipv6& b) noexcept { return !(b < a); }
520 friend bool operator>(const ipv6& a, const ipv6& b) noexcept { return b < a; }
521 friend bool operator>=(const ipv6& a, const ipv6& b) noexcept { return !(a < b); }
522
523 private:
524 ipv6(uint64_t hi, uint64_t lo) noexcept : hi_(hi), lo_(lo) {}
525
526 // Adds the 128-bit sign-extension of the two's-complement 64-bit
527 // pattern `low64_bits` to (hi_, lo_), wrapping mod 2^128.
528 void add_bits(uint64_t low64_bits) noexcept;
529
530 uint64_t hi_ = 0;
531 uint64_t lo_ = 0;
532};
533
550class host {
551 public:
552 using variant_type = std::variant<hostname, ipv4, ipv6>;
553
555 host() noexcept = default;
556
558 static host wrap(hostname h) noexcept {
559 host result;
560 result.value_ = std::move(h);
561 return result;
562 }
563 static host wrap(ipv4 v) noexcept {
564 host result;
565 result.value_ = v;
566 return result;
567 }
568 static host wrap(ipv6 v) noexcept {
569 host result;
570 result.value_ = v;
571 return result;
572 }
573
583 host(std::string_view host_text, bool ignore_www = DEFAULT_IGNORE_WWW) noexcept;
584
590 host(const char* host_text, bool ignore_www = DEFAULT_IGNORE_WWW) noexcept;
591
599 host(std::string&& host_text, bool ignore_www = DEFAULT_IGNORE_WWW) noexcept;
600
605 static host from_url(std::string_view url, bool ignore_www = DEFAULT_IGNORE_WWW) noexcept;
606
611 static host from_url(const char* url, bool ignore_www = DEFAULT_IGNORE_WWW) noexcept;
612
619 static host from_url(std::string&& url, bool ignore_www = DEFAULT_IGNORE_WWW) noexcept;
620
621 bool is_hostname() const noexcept { return std::holds_alternative<hostname>(value_); }
622 bool is_ipv4() const noexcept { return std::holds_alternative<ipv4>(value_); }
623 bool is_ipv6() const noexcept { return std::holds_alternative<ipv6>(value_); }
625 bool is_ip() const noexcept { return !is_hostname(); }
626
628 const hostname& get_hostname() const { return std::get<hostname>(value_); }
630 const ipv4& get_ipv4() const { return std::get<ipv4>(value_); }
632 const ipv6& get_ipv6() const { return std::get<ipv6>(value_); }
633
635 const hostname* try_hostname() const noexcept { return std::get_if<hostname>(&value_); }
637 const ipv4* try_ipv4() const noexcept { return std::get_if<ipv4>(&value_); }
639 const ipv6* try_ipv6() const noexcept { return std::get_if<ipv6>(&value_); }
640
642 std::string str() const;
643
645 const variant_type& variant() const noexcept { return value_; }
646
647 friend bool operator==(const host& a, const host& b) noexcept { return a.value_ == b.value_; }
648 friend bool operator!=(const host& a, const host& b) noexcept { return !(a == b); }
649
650 private:
651 variant_type value_;
652};
653
673class url {
674 public:
678 static bool is_psl_loaded() noexcept;
679
683 static std::string extract_host(std::string_view url) noexcept;
684
692 static std::string extract_host(const char* url) noexcept;
693
701 static std::string extract_host(std::string&& url) noexcept;
702
703 public:
710 url(std::string_view url, const bool ignore_www = DEFAULT_IGNORE_WWW);
711
716 url() noexcept = default;
717
721 bool operator==(const url& other) const noexcept;
722
724 std::string str() const noexcept;
726 std::string_view protocol() const noexcept { return field(scheme_); }
728 std::string_view query() const noexcept { return field(query_); }
730 std::string_view fragment() const noexcept { return field(fragment_); }
732 std::string_view userinfo() const noexcept { return field(userinfo_); }
734 std::string_view path() const noexcept { return field(path_); }
736 const std::string& abspath() const noexcept;
758 std::string normalized() const;
760 std::string_view host_text() const noexcept { return field(host_); }
762 int port() const noexcept { return port_; }
764 query_params params() const noexcept;
784 using search_params = std::unordered_map<std::string, std::vector<std::string>>;
786 search_params get_search_params() const;
792 const urlparser::host& host() const noexcept;
793
794 private:
795 // An (offset, length) pair into storage_ - not a raw pointer/view, so
796 // that copying a url (which deep-copies storage_) never needs to
797 // "rebase" anything: the offsets stay correct as-is.
798 struct Span {
799 uint32_t pos = 0;
800 uint32_t len = 0;
801 };
802 std::string_view field(Span s) const noexcept {
803 return std::string_view(storage_).substr(s.pos, s.len);
804 }
805
806 const urlparser::host& ensure_host() const noexcept;
807
808 std::string storage_;
809 Span scheme_, userinfo_, host_, path_, params_, query_, fragment_;
810 int port_ = 0;
811 bool has_params_ = false;
812 bool has_query_ = false;
813 bool ignore_www_ = false;
814 mutable std::optional<urlparser::host> host_cache_;
815 mutable std::optional<std::string> abspath_cache_;
816};
817
834class scp_url {
835 public:
844 static bool is_scp_like(std::string_view input) noexcept;
845
850 static std::string normalize(std::string_view input);
851
860 explicit scp_url(std::string_view input);
861
863 const url& as_url() const noexcept { return url_; }
865 operator const url&() const noexcept { return url_; }
866
868 bool was_scp_like() const noexcept { return was_scp_like_; }
869
870 private:
871 url url_;
872 bool was_scp_like_;
873};
874
884
898std::string build_search_params(const std::vector<std::pair<std::string, std::string>>& pairs);
899
908std::string build_search_params(const url::search_params& params);
909
917inline std::string normalize(std::string_view input) { return url(input).normalized(); }
918
919} // namespace urlparser
920
924std::ostream& operator<<(std::ostream& os, const urlparser::query_params& dt);
925
929std::ostream& operator<<(std::ostream& os, const urlparser::url& dt);
930
934std::ostream& operator<<(std::ostream& os, const urlparser::hostname& dt);
935
939std::ostream& operator<<(std::ostream& os, const urlparser::ipv4& dt);
940
944std::ostream& operator<<(std::ostream& os, const urlparser::ipv6& dt);
945
949std::ostream& operator<<(std::ostream& os, const urlparser::host& dt);
950
951// ============================================================================
952// IDNA (Internationalized Domain Names): Unicode <-> ASCII/Punycode.
953// ============================================================================
954namespace urlparser {
955
972namespace idna {
973
983std::string to_ascii(std::string_view utf8_domain);
984
985} // namespace idna
986} // namespace urlparser
987
988// ============================================================================
989// Percent-encoding ("quote") / percent-decoding ("unquote").
990// ============================================================================
991namespace urlparser {
992
1009namespace percent_codec {
1010
1013using character_set = std::array<uint64_t, 4>;
1014
1015constexpr bool contains(const character_set& set, unsigned char c) noexcept {
1016 return (set[c >> 6] >> (c & 63)) & 1ULL;
1017}
1018
1021character_set unreserved_set();
1022
1025character_set path_safe_set();
1026
1034std::string decode(std::string_view input);
1035
1041std::string encode(std::string_view input,
1042 const character_set& safe = unreserved_set());
1043
1044} // namespace percent_codec
1045} // namespace urlparser
1046
1047// ============================================================================
1048// URL reference resolution ("join"): RFC 3986 §5.
1049// ============================================================================
1050namespace urlparser {
1051
1080std::string resolve(std::string_view base, std::string_view ref);
1081
1082} // namespace urlparser
1083
1084#endif // URLPARSER_H
hostname, ipv4, or ipv6: whatever a URL's host actually is (RFC 3986's host grammar),...
Definition urlparser.h:550
bool is_ipv6() const noexcept
Definition urlparser.h:623
const variant_type & variant() const noexcept
Direct access to the underlying variant - for std::visit, std::get, etc.
Definition urlparser.h:645
static host wrap(ipv4 v) noexcept
Definition urlparser.h:563
bool is_ip() const noexcept
True for either IP family - the opposite of is_hostname().
Definition urlparser.h:625
static host from_url(const char *url, bool ignore_www=DEFAULT_IGNORE_WWW) noexcept
Classify and parse the host of a URL string literal. Disambiguation overload, same reason as host(con...
const ipv6 & get_ipv6() const
Definition urlparser.h:632
const hostname & get_hostname() const
Definition urlparser.h:628
const hostname * try_hostname() const noexcept
nullptr if this isn't a hostname.
Definition urlparser.h:635
static host from_url(std::string_view url, bool ignore_www=DEFAULT_IGNORE_WWW) noexcept
Extract the host from a full URL and classify/parse it, in one step.
const ipv4 & get_ipv4() const
Definition urlparser.h:630
static host from_url(std::string &&url, bool ignore_www=DEFAULT_IGNORE_WWW) noexcept
Extract the host from a full URL and classify/parse it, taking ownership of the URL string - reuses i...
static host wrap(ipv6 v) noexcept
Definition urlparser.h:568
std::variant< hostname, ipv4, ipv6 > variant_type
Definition urlparser.h:552
host(const char *host_text, bool ignore_www=DEFAULT_IGNORE_WWW) noexcept
Classify a host string literal. Disambiguation overload: without this, host("literal") would be ambig...
friend bool operator!=(const host &a, const host &b) noexcept
Definition urlparser.h:648
host(std::string &&host_text, bool ignore_www=DEFAULT_IGNORE_WWW) noexcept
Classify an already-isolated host string, taking ownership of it. When the text turns out to be a dom...
host() noexcept=default
Default-constructs an empty hostname.
friend bool operator==(const host &a, const host &b) noexcept
Definition urlparser.h:647
std::string str() const
The text form, whichever of hostname/ipv4/ipv6 this is.
bool is_hostname() const noexcept
Definition urlparser.h:621
bool is_ipv4() const noexcept
Definition urlparser.h:622
host(std::string_view host_text, bool ignore_www=DEFAULT_IGNORE_WWW) noexcept
Classify and parse an already-isolated host string (no scheme, no path - e.g. what url::host_text() g...
const ipv4 * try_ipv4() const noexcept
nullptr if this isn't an ipv4.
Definition urlparser.h:637
const ipv6 * try_ipv6() const noexcept
nullptr if this isn't an ipv6.
Definition urlparser.h:639
A domain name used as a URL's host, e.g. "www.example.com".
Definition urlparser.h:128
std::string normalized_ascii() const
The IDNA/Punycode-normalized, all-ASCII form of str(). Unlike str(), which keeps whatever the input l...
const std::string & full_domain() const noexcept
The full domain of the host (e.g., "example.com").
static std::string_view remove_www(const std::string_view &host) noexcept
Remove "www." from the beginning of a hostname string.
std::string domain_name() const noexcept
The domain name, i.e. "<domain>.<suffix>".
const std::string & suffix() const noexcept
The suffix of the host (e.g., "com" in "example.com").
const std::string & domain() const noexcept
The domain of the host (e.g., "example" in "www.example.com").
static hostname from_url(const char *url, const bool ignore_www=DEFAULT_IGNORE_WWW)
Create a hostname from a URL string literal. Disambiguation overload: without this,...
static hostname from_url(std::string_view url, const bool ignore_www=DEFAULT_IGNORE_WWW)
Create a hostname from a URL string, without taking ownership. Prefer this overload when the caller o...
static hostname from_url(std::string &&url, const bool ignore_www=DEFAULT_IGNORE_WWW)
Create a hostname from a URL string, taking ownership of it. Prefer this overload when you already ha...
hostname(std::string host, const bool ignore_www=DEFAULT_IGNORE_WWW)
Construct a hostname object from a hostname string.
const std::string & subdomain() const noexcept
The subdomain of the host (e.g., "www" in "www.example.com").
static hostname from_url(const std::string &url, const bool ignore_www=DEFAULT_IGNORE_WWW)
Create a hostname from a URL string.
const std::string & str() const noexcept
The complete host string (same as full_domain()).
hostname() noexcept=default
Default constructor for the hostname class. Creates an empty hostname object.
An IPv4 address used as a URL's host, e.g. "192.0.2.1".
Definition urlparser.h:350
ipv4 operator++(int) noexcept
Definition urlparser.h:386
friend bool operator>=(const ipv4 &a, const ipv4 &b) noexcept
Definition urlparser.h:422
friend int64_t operator-(const ipv4 &a, const ipv4 &b) noexcept
Distance between two addresses (always fits in int64_t: the range is only 2^32).
Definition urlparser.h:413
friend ipv4 operator-(ipv4 lhs, int64_t delta) noexcept
Definition urlparser.h:411
friend ipv4 operator+(ipv4 lhs, int64_t delta) noexcept
Definition urlparser.h:410
friend bool operator!=(const ipv4 &a, const ipv4 &b) noexcept
Definition urlparser.h:418
friend bool operator==(const ipv4 &a, const ipv4 &b) noexcept
Definition urlparser.h:417
ipv4() noexcept=default
Default-constructs 0.0.0.0.
std::array< uint8_t, 4 > bytes() const noexcept
The address as 4 bytes, most significant first.
friend bool operator>(const ipv4 &a, const ipv4 &b) noexcept
Definition urlparser.h:421
ipv4 & operator--() noexcept
Definition urlparser.h:391
friend bool operator<(const ipv4 &a, const ipv4 &b) noexcept
Definition urlparser.h:419
friend bool operator<=(const ipv4 &a, const ipv4 &b) noexcept
Definition urlparser.h:420
ipv4 & operator-=(int64_t delta) noexcept
Definition urlparser.h:405
ipv4 & operator+=(int64_t delta) noexcept
Steps the address by delta, wrapping around mod 2^32.
Definition urlparser.h:401
ipv4 operator--(int) noexcept
Definition urlparser.h:395
An IPv6 address used as a URL's host, e.g. "2001:db8::1".
Definition urlparser.h:442
uint64_t low64() const noexcept
The low 64 bits (last 8 bytes).
Definition urlparser.h:476
friend bool operator>=(const ipv6 &a, const ipv6 &b) noexcept
Definition urlparser.h:521
ipv6 operator++(int) noexcept
Definition urlparser.h:482
friend ipv6 operator-(ipv6 lhs, int64_t delta) noexcept
Definition urlparser.h:510
friend bool operator<(const ipv6 &a, const ipv6 &b) noexcept
Definition urlparser.h:516
ipv6 & operator++() noexcept
Definition urlparser.h:478
friend bool operator==(const ipv6 &a, const ipv6 &b) noexcept
Definition urlparser.h:512
friend bool operator>(const ipv6 &a, const ipv6 &b) noexcept
Definition urlparser.h:520
ipv6 & operator-=(int64_t delta) noexcept
Definition urlparser.h:501
friend ipv6 operator+(ipv6 lhs, int64_t delta) noexcept
Definition urlparser.h:509
ipv6 & operator--() noexcept
Definition urlparser.h:487
friend bool operator<=(const ipv6 &a, const ipv6 &b) noexcept
Definition urlparser.h:519
ipv6() noexcept=default
Default-constructs "::" (all zero).
ipv6 operator--(int) noexcept
Definition urlparser.h:491
friend bool operator!=(const ipv6 &a, const ipv6 &b) noexcept
Definition urlparser.h:515
ipv6 & operator+=(int64_t delta) noexcept
Steps the address by delta, wrapping around mod 2^128.
Definition urlparser.h:497
Definition urlparser.h:261
bool is_loaded() const noexcept
Whether a PSL is currently loaded (true even for the bundled default).
static psl & instance() noexcept
The one, lazily-built, shared PSL instance.
Parses an SSH "scp-like" address - user@host:path (what scp, rsync, sshfs, and git all accept,...
Definition urlparser.h:834
scp_url(std::string_view input)
Parse input - scp-like or already a normal URI - as a URL. scp-like input is normalize()d to "ssh://"...
const url & as_url() const noexcept
The parsed result, as a normal url.
Definition urlparser.h:863
static std::string normalize(std::string_view input)
Rewrite an scp-like address to an equivalent "ssh://" URI. Input that doesn't match is_scp_like() is ...
static bool is_scp_like(std::string_view input) noexcept
True iff input matches the scp-like address shape: [user@]host:path. Per git's own rule for this synt...
bool was_scp_like() const noexcept
Whether input (as given to the constructor) was scp-like, as opposed to already a normal URI.
Definition urlparser.h:868
Represents a URL.
Definition urlparser.h:673
std::string_view userinfo() const noexcept
The userinfo of the URL (e.g., "username:password").
Definition urlparser.h:732
std::string_view path() const noexcept
The raw path of the URL, exactly as it appears in the source (no dot-segment resolution - see abspath...
Definition urlparser.h:734
std::string_view query() const noexcept
The query string of the URL (e.g., "a=1&b=2").
Definition urlparser.h:728
std::string_view fragment() const noexcept
The fragment of the URL (the part after '#').
Definition urlparser.h:730
std::string normalized() const
The URL's canonical, normalized form (roughly WHATWG URL "serialize a URL" / ada's normalize_url()): ...
query_params params() const noexcept
The '&'-separated query parameters, split into a vector.
const std::string & abspath() const noexcept
The path, with '.'/'..' segments resolved.
static bool is_psl_loaded() noexcept
Check if the Public Suffix List (PSL) is loaded.
int port() const noexcept
The port number of the URL, or 0 if not specified.
Definition urlparser.h:762
std::unordered_map< std::string, std::vector< std::string > > search_params
A decoded key → values map of the query string (like JS's URLSearchParams, or ada_url....
Definition urlparser.h:784
Exposes the library version (from the URLPARSER_VERSION_* macros) at runtime, without needing to #inc...
Definition urlparser.h:98
static unsigned int major() noexcept
Definition urlparser.h:100
static unsigned int hex() noexcept
Definition urlparser.h:103
static std::string_view string() noexcept
Definition urlparser.h:104
static unsigned int minor() noexcept
Definition urlparser.h:101
static unsigned int patch() noexcept
Definition urlparser.h:102
Definition urlparser.h:90
std::string build_search_params(const std::vector< std::pair< std::string, std::string > > &pairs)
Build an application/x-www-form-urlencoded query string from ordered key/value pairs - the inverse of...
constexpr bool DEFAULT_IGNORE_WWW
Definition urlparser.h:91
std::vector< std::string > query_params
A vector of strings representing query parameters in a URL.
Definition urlparser.h:114
std::string normalize(std::string_view input)
Convenience wrapper: url(input).normalized(). Prefer calling .normalized() directly on a url you alre...
Definition urlparser.h:917
#define URLPARSER_VERSION_STRING
Definition urlparser.h:67
#define URLPARSER_VERSION_MAJOR
Definition urlparser.h:50
std::ostream & operator<<(std::ostream &os, const urlparser::query_params &dt)
Output stream operator for query_params.
#define URLPARSER_VERSION_HEX
Definition urlparser.h:59
#define URLPARSER_VERSION_MINOR
Definition urlparser.h:51
#define URLPARSER_VERSION_PATCH
Definition urlparser.h:52