18 if (not
Host.empty()) {
23 if (not
Port.empty()) {
28 if (not
Path.empty()) {
31 if (not
Query.empty()) {
51 const auto uri_end = uri.cend();
54 const auto schema_begin = uri.cbegin();
55 auto schema_end = std::find(schema_begin, uri_end,
':');
57 if (schema_end == uri_end or uri_end - schema_end <= 3
58 or std::string_view(schema_end, 3) !=
"://") {
59 schema_end = uri.cbegin();
61 result.
Schema.assign(schema_begin, schema_end);
64 schema_begin, schema_end, [](
auto ch) {
return std::isalpha(ch); })
66 if (not result.
error_.has_value()) {
67 result.
error_.emplace(
"Invalid schema");
72 const auto host_begin =
73 schema_end + (std::string_view(schema_end, 3) ==
"://" ? 3 : 0);
74 const auto host_end = std::find_if(host_begin, uri_end, [](
auto ch) {
75 return ch ==
':' or ch ==
'/' or ch ==
'?' or ch ==
'#';
77 result.
Host.assign(host_begin, host_end);
81 [](
auto ch) {
return std::isalnum(ch) or ch ==
'.' or ch ==
'-'; })
83 or host_begin == host_end) {
84 if (not result.
error_.has_value()) {
85 result.
error_.emplace(
"Invalid hostname");
90 const auto port_begin = host_end + (*host_end ==
':' ? 1 : 0);
91 const auto port_end = std::find_if(port_begin, uri_end, [](
auto ch) {
92 return ch ==
'/' or ch ==
'?' or ch ==
'#';
95 result.
Port.assign(port_begin, port_end);
98 port_begin, port_end, [](
auto ch) {
return std::isdigit(ch); })
100 or (result.
Port.empty() and *host_end ==
':') or (result.
Port ==
"0")
101 or (result.
Port.size() == 5 and result.
Port >
"65535")
102 or result.
Port.size() > 5) {
103 if (not result.
error_.has_value()) {
104 result.
error_.emplace(
"Invalid port");
109 const auto path_begin = port_end;
110 const auto path_end = std::find_if(
111 path_begin, uri_end, [](
auto ch) {
return ch ==
'?' or ch ==
'#'; });
113 result.
Path.assign(path_begin, path_end);
116 const auto query_begin = path_end + (*path_end ==
'?' ? 1 : 0);
117 const auto query_end = std::find(query_begin, uri_end,
'#');
119 result.
Query.assign(query_begin, query_end);
122 const auto fragment_begin = query_end + (*query_end ==
'#' ? 1 : 0);
123 const auto fragment_end = uri_end;
125 result.
Fragment.assign(fragment_begin, fragment_end);
std::string to_string() const
static Uri parse(std::string_view uri)
std::optional< std::string_view > error_