-
Notifications
You must be signed in to change notification settings - Fork 30
/
Copy pathurl.hpp
208 lines (152 loc) · 6.24 KB
/
url.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
#ifndef URL_HPP
#define URL_HPP
#include <vector>
#include <utility>
#include <stdexcept>
#include <cstdint>
#include <ostream>
#include <utility>
#include "string.hpp"
class Url {
public:
// Exception thut may be thrown when decoding an URL or an assigning value
class parse_error: public std::invalid_argument {
public:
parse_error(const std::string &reason) : std::invalid_argument(reason) {}
};
// Exception that may be thrown when building an URL
class build_error: public std::runtime_error {
public:
build_error(const std::string &reason) : std::runtime_error(reason) {}
};
// Default constructor
Url() : m_parse(true),m_built(true),m_ip_v(-1) {}
// Copy initializer constructor
Url(const Url &url) : m_ip_v(-1) {assign(url);}
// Move constructor
Url(Url&& url) : m_ip_v(-1) {assign(std::move(url));}
// Construct Url with the given string
Url(const std::string &url_str) : m_url(url_str),m_parse(false),m_built(false),m_ip_v(-1) {}
// Assign the given URL string
Url &operator=(const std::string &url_str) {return str(url_str);}
// Assign the given Url object
Url &operator=(const Url &url) {assign(url); return *this;}
// Move the given Url object
Url &operator=(Url&& url) {assign(std::move(url)); return *this;}
// Clear the Url object
Url &clear();
// Build Url if needed and return it as string
std::string str() const {if(!m_built) build_url(); return m_url;}
// Set the Url to the given string. All fields are overwritten
Url& str(const std::string &url_str) {m_url=url_str; m_built=m_parse=false; return *this;}
// Get scheme
const std::string& scheme() const {lazy_parse(); return m_scheme;}
// Set scheme
Url &scheme(const std::string& s);
// Get user info
const std::string& user_info() const {lazy_parse(); return m_user;}
// Set user info
Url &user_info(const std::string& s);
// Get host
const std::string& host() const {lazy_parse(); return m_host;}
// Set host
Url &host(const std::string& h, uint8_t ip_v=0);
// Get host IP version: 0=name, 4=IPv4, 6=IPv6, -1=undefined
std::int8_t ip_version() const {lazy_parse(); return m_ip_v;}
// Get port
const std::string& port() const {lazy_parse(); return m_port;}
// Set Port given as string
Url &port(const std::string& str);
// Set port given as a 16bit unsigned integer
Url &port(std::uint16_t num) {return port(std::to_string(num));}
// Get path
const std::string& path() const {lazy_parse(); return m_path;}
// Set path
Url &path(const std::string& str);
class KeyVal {
public:
// Default constructor
KeyVal() {}
// Construct with provided Key and Value strings
KeyVal(const std::string &key, const std::string &val) : m_key(key),m_val(val) {}
// Construct with provided Key string, val will be empty
KeyVal(const std::string &key) : m_key(key) {}
// Equality test operator
bool operator==(const KeyVal &q) const {return m_key==q.m_key&&m_val==q.m_val;}
// Swap this with q
void swap(KeyVal& q) {std::swap(m_key,q.m_key); std::swap(m_val,q.m_val);}
// Get key
const std::string& key() const {return m_key;}
// Set key
void key(const std::string &k) {m_key=k;}
// Get value
const std::string& val() const {return m_val;}
// Set value
void val(const std::string &v) {m_val=v;}
// Output key value pair
friend std::ostream& operator<<(std::ostream &o, const KeyVal &kv)
{o<<"<key("<<kv.m_key<<") val("<<kv.m_val<<")> "; return o;}
private:
std::string m_key;
std::string m_val;
};
// Define Query as vector of Key Value pairs
typedef std::vector<KeyVal> Query;
// Get a reference to the query vector for read only access
const Query& query() const {lazy_parse(); return m_query;}
// Get a reference to a specific Key Value pair in the query vector for read only access
const KeyVal& query(size_t i) const {
lazy_parse();
if (i>=m_query.size())
throw std::out_of_range("Invalid Url query index ("+std::to_string(i)+")");
return m_query[i];
}
// Get a reference to the query vector for a writable access
Query& set_query() {lazy_parse(); m_built=false; return m_query;}
// Get a reference to specific Key Value pair in the query vector for a writable access
KeyVal& set_query(size_t i) {
lazy_parse();
if (i>=m_query.size())
throw std::out_of_range("Invalid Url query index ("+std::to_string(i)+")");
m_built=false;
return m_query[i];
}
// Set the query vector to the Query vector q
Url &set_query(const Query &q)
{lazy_parse(); if (q != m_query) {m_query=q; m_built=false;} return *this;}
// Append KeyVal kv to the query
Url &add_query(const KeyVal &kv)
{lazy_parse(); m_built=false; m_query.push_back(kv); return *this;}
// Append key val pair to the query
Url &add_query(const std::string &key, const std::string &val)
{lazy_parse(); m_built=false; m_query.emplace_back(key,val); return *this;}
// Append key with empty val to the query
Url &add_query(const std::string &key)
{lazy_parse(); m_built=false; m_query.emplace_back(key); return *this;}
// Get the fragment
const std::string& fragment() const {lazy_parse(); return m_fragment;}
// Set the fragment
Url &fragment(const std::string& f);
// Output
std::ostream& output(std::ostream &o) const;
// Output strean operator
friend std::ostream& operator<<(std::ostream &o, const Url &u) {return u.output(o);}
private:
void assign(const Url &url);
void assign(Url&& url);
void build_url() const;
void lazy_parse() const {if (!m_parse) parse_url();}
void parse_url() const;
mutable std::string m_scheme;
mutable std::string m_user;
mutable std::string m_host;
mutable std::string m_port;
mutable std::string m_path;
mutable Query m_query;
mutable std::string m_fragment;
mutable std::string m_url;
mutable bool m_parse;
mutable bool m_built;
mutable std::int8_t m_ip_v;
};
#endif // URL_HPP