with comments, less is more
[uri.git] / uri.hpp
blob07611bd200d845d223820056fb182af4b0e48f9b
1 #ifndef URI_HPP_INCLUDED
2 #define URI_HPP_INCLUDED
4 #include "dll_spec.h"
6 #include <cctype>
7 #include <iostream>
8 #include <optional>
9 #include <string>
10 #include <string_view>
12 namespace uri {
14 enum class error {
15 // parser errors
16 invalid_syntax = 1,
19 class DLL_PUBLIC syntax_error : public std::system_error {
20 public:
21 syntax_error();
22 virtual ~syntax_error() noexcept;
25 const std::error_category& category();
27 struct components {
28 std::optional<std::string> scheme;
29 std::optional<std::string> authority; // further brokwn down into:
30 std::optional<std::string> userinfo; // from authority
31 std::optional<std::string> host; // from authority
32 std::optional<std::string> port; // from authority
33 std::optional<std::string> path;
34 std::optional<std::string> query;
35 std::optional<std::string> fragment;
37 bool operator==(components const& rhs) const
39 return (scheme == rhs.scheme) && (authority == rhs.authority)
40 && (userinfo == rhs.userinfo) && (host == rhs.host)
41 && (port == rhs.port) && (path == rhs.path) && (query == rhs.query)
42 && (fragment == rhs.fragment);
44 bool operator!=(components const& rhs) const { return !(*this == rhs); }
47 DLL_PUBLIC bool parse_generic(std::string_view uri, components& comp);
48 DLL_PUBLIC bool parse_relative_ref(std::string_view uri, components& comp);
49 DLL_PUBLIC bool parse_reference(std::string_view uri, components& comp);
50 DLL_PUBLIC bool parse_absolute(std::string_view uri, components& comp);
52 DLL_PUBLIC std::string to_string(components const&);
54 DLL_PUBLIC std::string normalize(components);
56 class uri {
57 public:
58 uri() = default;
60 // clang-format off
61 auto scheme() const { return parts_.scheme; }
62 auto authority() const { return parts_.authority; }
63 auto userinfo() const { return parts_.userinfo; }
64 auto host() const { return parts_.host; }
65 auto port() const { return parts_.port; }
66 auto path() const { return parts_.path; }
67 auto query() const { return parts_.query; }
68 auto fragment() const { return parts_.fragment; }
69 // clang-format on
71 components const& parts() const { return parts_; }
73 std::string_view string() const { return uri_; }
75 bool empty() const
77 return !(parts_.scheme || parts_.authority || parts_.userinfo || parts_.host
78 || parts_.port || (parts_.path && !parts_.path->empty())
79 || parts_.query || parts_.fragment);
82 protected:
83 std::string uri_;
84 components parts_;
87 class generic : public uri {
88 public:
89 explicit generic(std::string uri_in)
91 uri_ = uri_in;
92 if (!parse_generic(uri_, parts_)) {
93 throw syntax_error();
97 explicit generic(components const& uri_in)
98 : generic(to_string(uri_in))
103 class absolute : public uri {
104 public:
105 explicit absolute(std::string uri_in)
107 uri_ = uri_in;
108 if (!parse_absolute(uri_, parts_)) {
109 throw syntax_error();
113 explicit absolute(components const& uri_in)
114 : absolute(to_string(uri_in))
119 class reference : public uri {
120 public:
121 explicit reference(std::string uri_in)
123 uri_ = uri_in;
124 if (!parse_reference(uri_, parts_)) {
125 throw syntax_error();
129 explicit reference(components const& uri_in)
130 : reference(to_string(uri_in))
135 DLL_PUBLIC std::string to_string(uri const&);
137 DLL_PUBLIC uri resolve_ref(absolute const& base, reference const& ref);
139 } // namespace uri
141 DLL_PUBLIC std::ostream& operator<<(std::ostream& os,
142 uri::components const& uri);
143 DLL_PUBLIC std::ostream& operator<<(std::ostream& os, uri::uri const&);
145 #endif // URI_HPP_INCLUDED