#pragma once #include #include #include #include namespace jvalidate { class URI { private: std::string uri_; size_t scheme_{0}; size_t resource_{0}; public: URI() = default; explicit URI(std::string_view uri) : uri_(uri) { if (not uri_.empty() && uri_.back() == '#') { uri_.pop_back(); } if (size_t n = uri_.find("://"); n != std::string::npos) { scheme_ = n; resource_ = n + 3; } else if (uri_.starts_with("urn:")) { n = uri_.find(':', 4); scheme_ = n; resource_ = scheme_ + 1; } } URI parent() const { return URI(std::string_view(uri_).substr(0, uri_.rfind('/'))); } URI operator/(URI const & relative) const { std::string div = uri_.ends_with("/") || relative.uri_.starts_with("/") ? "" : "/"; return URI(uri_ + div + relative.uri_); } std::string_view scheme() const { return std::string_view(uri_).substr(0, scheme_); } std::string_view resource() const { return std::string_view(uri_).substr(resource_); } explicit operator std::string const &() const { return uri_; } char const * c_str() const { return uri_.c_str(); } bool empty() const { return uri_.empty(); } friend std::ostream & operator<<(std::ostream & os, URI const & self) { return os << self.uri_; } auto operator<=>(URI const & lhs) const = default; }; }