forked from arc/libarc-uri
285 lines
5.1 KiB
C++
285 lines
5.1 KiB
C++
#include <arc/uri/uri.hxx>
|
|
|
|
#include <sstream>
|
|
#include <vector>
|
|
#include <iostream>
|
|
|
|
namespace arc::uri
|
|
{
|
|
|
|
uri_t::
|
|
uri_t()
|
|
{}
|
|
|
|
uri_t::
|
|
uri_t(std::string scheme, std::string host, std::string path)
|
|
: scheme_{std::move(scheme)},
|
|
host_{std::move(host)},
|
|
path_{std::move(path)}
|
|
{}
|
|
|
|
uri_t::
|
|
uri_t(std::string scheme,
|
|
std::string host,
|
|
std::string port,
|
|
std::string path)
|
|
: scheme_{std::move(scheme)},
|
|
host_{std::move(host)},
|
|
port_{std::move(port)},
|
|
path_{std::move(path)}
|
|
{}
|
|
|
|
uri_t::
|
|
uri_t(std::string scheme,
|
|
std::string host,
|
|
std::string port,
|
|
std::string path,
|
|
std::string query)
|
|
: scheme_{std::move(scheme)},
|
|
host_{std::move(host)},
|
|
port_{std::move(port)},
|
|
path_{std::move(path)},
|
|
query_{std::move(query)}
|
|
{}
|
|
|
|
uri_t::
|
|
uri_t(std::string scheme,
|
|
std::string host,
|
|
std::string port,
|
|
std::string path,
|
|
std::string query,
|
|
std::string fragment)
|
|
: scheme_{std::move(scheme)},
|
|
host_{std::move(host)},
|
|
port_{std::move(port)},
|
|
path_{std::move(path)},
|
|
query_{std::move(query)},
|
|
fragment_{std::move(fragment)}
|
|
{}
|
|
|
|
uri_t::
|
|
uri_t(std::string scheme,
|
|
std::string userinfo,
|
|
std::string host,
|
|
std::string port,
|
|
std::string path,
|
|
std::string query,
|
|
std::string fragment)
|
|
: scheme_{std::move(scheme)},
|
|
userinfo_{std::move(userinfo)},
|
|
host_{std::move(host)},
|
|
port_{std::move(port)},
|
|
path_{std::move(path)},
|
|
query_{std::move(query)},
|
|
fragment_{std::move(fragment)}
|
|
{}
|
|
|
|
uri_t::
|
|
uri_t(std::optional<std::string> scheme,
|
|
std::optional<std::string> userinfo,
|
|
std::optional<std::string> host,
|
|
std::optional<std::string> port,
|
|
std::string path,
|
|
std::optional<std::string> query,
|
|
std::optional<std::string> fragment)
|
|
: scheme_{std::move(scheme)},
|
|
userinfo_{std::move(userinfo)},
|
|
host_{std::move(host)},
|
|
port_{std::move(port)},
|
|
path_{std::move(path)},
|
|
query_{std::move(query)},
|
|
fragment_{std::move(fragment)}
|
|
{}
|
|
|
|
std::optional<std::string> const&
|
|
uri_t::
|
|
scheme() const
|
|
{
|
|
return scheme_;
|
|
}
|
|
|
|
std::string
|
|
uri_t::
|
|
scheme_str() const
|
|
{
|
|
return scheme().value_or(std::string{});
|
|
}
|
|
|
|
std::optional<std::string> const&
|
|
uri_t::
|
|
userinfo() const
|
|
{
|
|
return userinfo_;
|
|
}
|
|
|
|
std::string
|
|
uri_t::
|
|
userinfo_str() const
|
|
{
|
|
return userinfo().value_or(std::string{});
|
|
}
|
|
|
|
std::optional<std::string> const&
|
|
uri_t::
|
|
host() const
|
|
{
|
|
return host_;
|
|
}
|
|
|
|
std::string
|
|
uri_t::
|
|
host_str() const
|
|
{
|
|
return host().value_or(std::string{});
|
|
}
|
|
|
|
std::optional<std::string> const&
|
|
uri_t::
|
|
port() const
|
|
{
|
|
return port_;
|
|
}
|
|
|
|
std::string
|
|
uri_t::
|
|
port_str() const
|
|
{
|
|
return port().value_or(std::string{});
|
|
}
|
|
|
|
std::string
|
|
uri_t::
|
|
path_str() const
|
|
{
|
|
return path_;
|
|
}
|
|
|
|
std::optional<std::string> const&
|
|
uri_t::
|
|
query() const
|
|
{
|
|
return query_;
|
|
}
|
|
|
|
std::string
|
|
uri_t::
|
|
query_str() const
|
|
{
|
|
return query().value_or(std::string{});
|
|
}
|
|
|
|
std::optional<std::string> const&
|
|
uri_t::
|
|
fragment() const
|
|
{
|
|
return fragment_;
|
|
}
|
|
|
|
std::string
|
|
uri_t::
|
|
fragment_str() const
|
|
{
|
|
return fragment().value_or(std::string{});
|
|
}
|
|
|
|
std::string
|
|
to_string(uri_t const& uri)
|
|
{
|
|
std::ostringstream str;
|
|
|
|
// Scheme
|
|
//
|
|
if (auto scheme = uri.scheme(); scheme) {
|
|
str <<*scheme <<':';
|
|
}
|
|
|
|
// Authority
|
|
//
|
|
if (auto host = uri.host(); host) {
|
|
str <<"//";
|
|
|
|
// Userinfo
|
|
//
|
|
if (auto userinfo = uri.userinfo(); userinfo) {
|
|
str <<*userinfo <<'@';
|
|
}
|
|
|
|
// Host
|
|
//
|
|
str <<*host;
|
|
|
|
// Port
|
|
if (auto port = uri.port(); port) {
|
|
str <<':' <<*port;
|
|
}
|
|
}
|
|
|
|
// Path
|
|
//
|
|
str <<uri.path_str();
|
|
|
|
// Query
|
|
//
|
|
if (auto query = uri.query(); query) {
|
|
str <<'?' <<*query;
|
|
}
|
|
|
|
// Fragment
|
|
//
|
|
if (auto fragment = uri.fragment(); fragment) {
|
|
str <<'#' <<*fragment;
|
|
}
|
|
|
|
return str.str();
|
|
}
|
|
|
|
uri_t
|
|
normalize_path(uri_t const& uri)
|
|
{
|
|
std::stringstream path{uri.path_str()};
|
|
std::vector<std::string> segments;
|
|
|
|
for (std::string segment; std::getline(path, segment, '/');) {
|
|
std::cout << "found segment: " << segment << '\n';
|
|
|
|
if (segment.empty()) {
|
|
continue;
|
|
}
|
|
if (segment == ".") {
|
|
continue;
|
|
}
|
|
if (segment == "..") {
|
|
if (!segments.empty()) {
|
|
segments.pop_back();
|
|
}
|
|
continue;
|
|
}
|
|
segments.push_back(segment);
|
|
}
|
|
|
|
std::string normalized;
|
|
|
|
for (auto const& j : segments) {
|
|
normalized += '/';
|
|
normalized += j;
|
|
}
|
|
|
|
return uri_t{
|
|
uri.scheme(),
|
|
uri.userinfo(),
|
|
uri.host(),
|
|
uri.port(),
|
|
normalized.empty() ? "/" : normalized,
|
|
uri.query(),
|
|
uri.fragment()
|
|
};
|
|
}
|
|
|
|
std::optional<uri_t>
|
|
try_parse(std::string const& str)
|
|
{
|
|
return try_parse(str.begin(), str.end());
|
|
}
|
|
|
|
} // namespace uri
|