uri.h 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. #pragma once
  2. #include <string>
  3. #include <string_view>
  4. #include <jvalidate/detail/compare.h>
  5. #include <jvalidate/detail/expect.h>
  6. namespace jvalidate {
  7. class URI {
  8. private:
  9. std::string uri_;
  10. size_t scheme_{0};
  11. size_t resource_{0};
  12. public:
  13. URI() = default;
  14. explicit URI(std::string_view uri) : uri_(uri) {
  15. if (not uri_.empty() && uri_.back() == '#') {
  16. uri_.pop_back();
  17. }
  18. if (size_t n = uri_.find("://"); n != std::string::npos) {
  19. scheme_ = n;
  20. resource_ = n + 3;
  21. } else if (uri_.starts_with("urn:")) {
  22. n = uri_.find(':', 4);
  23. scheme_ = n;
  24. resource_ = scheme_ + 1;
  25. }
  26. }
  27. URI parent() const { return URI(std::string_view(uri_).substr(0, uri_.rfind('/'))); }
  28. URI root() const { return URI(std::string_view(uri_).substr(0, uri_.find('/', resource_))); }
  29. URI operator/(URI const & relative) const {
  30. std::string div = uri_.ends_with("/") || relative.uri_.starts_with("/") ? "" : "/";
  31. return URI(uri_ + div + relative.uri_);
  32. }
  33. bool is_rootless() const { return scheme_ == 0; }
  34. bool is_relative() const { return uri_[resource_] != '/'; }
  35. std::string_view scheme() const { return std::string_view(uri_).substr(0, scheme_); }
  36. std::string_view resource() const { return std::string_view(uri_).substr(resource_); }
  37. explicit operator std::string const &() const { return uri_; }
  38. char const * c_str() const { return uri_.c_str(); }
  39. bool empty() const { return uri_.empty(); }
  40. friend std::ostream & operator<<(std::ostream & os, URI const & self) { return os << self.uri_; }
  41. auto operator<=>(URI const & lhs) const = default;
  42. };
  43. }