modify build setup
[c11concurrency-benchmarks.git] / gdax-orderbook-hpp / demo / dependencies / websocketpp-0.7.0 / websocketpp / uri.hpp
1 /*
2  * Copyright (c) 2014, Peter Thorson. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *     * Redistributions of source code must retain the above copyright
7  *       notice, this list of conditions and the following disclaimer.
8  *     * Redistributions in binary form must reproduce the above copyright
9  *       notice, this list of conditions and the following disclaimer in the
10  *       documentation and/or other materials provided with the distribution.
11  *     * Neither the name of the WebSocket++ Project nor the
12  *       names of its contributors may be used to endorse or promote products
13  *       derived from this software without specific prior written permission.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL PETER THORSON BE LIABLE FOR ANY
19  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *
26  */
27
28 #ifndef WEBSOCKETPP_URI_HPP
29 #define WEBSOCKETPP_URI_HPP
30
31 #include <websocketpp/error.hpp>
32
33 #include <websocketpp/common/memory.hpp>
34
35 #include <algorithm>
36 #include <sstream>
37 #include <string>
38
39 namespace websocketpp {
40
41 // TODO: figure out why this fixes horrible linking errors.
42
43 /// Default port for ws://
44 static uint16_t const uri_default_port = 80;
45 /// Default port for wss://
46 static uint16_t const uri_default_secure_port = 443;
47
48 class uri {
49 public:
50     explicit uri(std::string const & uri_string) : m_valid(false) {
51         std::string::const_iterator it;
52         std::string::const_iterator temp;
53
54         int state = 0;
55
56         it = uri_string.begin();
57         size_t uri_len = uri_string.length();
58
59         if (uri_len >= 7 && std::equal(it,it+6,"wss://")) {
60             m_secure = true;
61             m_scheme = "wss";
62             it += 6;
63         } else if (uri_len >= 6 && std::equal(it,it+5,"ws://")) {
64             m_secure = false;
65             m_scheme = "ws";
66             it += 5;
67         } else if (uri_len >= 8 && std::equal(it,it+7,"http://")) {
68             m_secure = false;
69             m_scheme = "http";
70             it += 7;
71         } else if (uri_len >= 9 && std::equal(it,it+8,"https://")) {
72             m_secure = true;
73             m_scheme = "https";
74             it += 8;
75         } else {
76             return;
77         }
78
79         // extract host.
80         // either a host string
81         // an IPv4 address
82         // or an IPv6 address
83         if (*it == '[') {
84             ++it;
85             // IPv6 literal
86             // extract IPv6 digits until ]
87
88             // TODO: this doesn't work on g++... not sure why
89             //temp = std::find(it,it2,']');
90
91             temp = it;
92             while (temp != uri_string.end()) {
93                 if (*temp == ']') {
94                     break;
95                 }
96                 ++temp;
97             }
98
99             if (temp == uri_string.end()) {
100                 return;
101             } else {
102                 // validate IPv6 literal parts
103                 // can contain numbers, a-f and A-F
104                 m_host.append(it,temp);
105             }
106             it = temp+1;
107             if (it == uri_string.end()) {
108                 state = 2;
109             } else if (*it == '/') {
110                 state = 2;
111                 ++it;
112             } else if (*it == ':') {
113                 state = 1;
114                 ++it;
115             } else {
116                 // problem
117                 return;
118             }
119         } else {
120             // IPv4 or hostname
121             // extract until : or /
122             while (state == 0) {
123                 if (it == uri_string.end()) {
124                     state = 2;
125                     break;
126                 } else if (*it == '/') {
127                     state = 2;
128                 } else if (*it == ':') {
129                     // end hostname start port
130                     state = 1;
131                 } else {
132                     m_host += *it;
133                 }
134                 ++it;
135             }
136         }
137
138         // parse port
139         std::string port;
140         while (state == 1) {
141             if (it == uri_string.end()) {
142                 // state is not used after this point presently.
143                 // this should be re-enabled if it ever is needed in a future
144                 // refactoring
145                 //state = 3;
146                 break;
147             } else if (*it == '/') {
148                 state = 3;
149             } else {
150                 port += *it;
151             }
152             ++it;
153         }
154
155         lib::error_code ec;
156         m_port = get_port_from_string(port, ec);
157
158         if (ec) {
159             return;
160         }
161
162         m_resource = "/";
163         m_resource.append(it,uri_string.end());
164
165
166         m_valid = true;
167     }
168
169     uri(bool secure, std::string const & host, uint16_t port,
170         std::string const & resource)
171       : m_scheme(secure ? "wss" : "ws")
172       , m_host(host)
173       , m_resource(resource.empty() ? "/" : resource)
174       , m_port(port)
175       , m_secure(secure)
176       , m_valid(true) {}
177
178     uri(bool secure, std::string const & host, std::string const & resource)
179       : m_scheme(secure ? "wss" : "ws")
180       , m_host(host)
181       , m_resource(resource.empty() ? "/" : resource)
182       , m_port(secure ? uri_default_secure_port : uri_default_port)
183       , m_secure(secure)
184       , m_valid(true) {}
185
186     uri(bool secure, std::string const & host, std::string const & port,
187         std::string const & resource)
188       : m_scheme(secure ? "wss" : "ws")
189       , m_host(host)
190       , m_resource(resource.empty() ? "/" : resource)
191       , m_secure(secure)
192     {
193         lib::error_code ec;
194         m_port = get_port_from_string(port,ec);
195         m_valid = !ec;
196     }
197
198     uri(std::string const & scheme, std::string const & host, uint16_t port,
199         std::string const & resource)
200       : m_scheme(scheme)
201       , m_host(host)
202       , m_resource(resource.empty() ? "/" : resource)
203       , m_port(port)
204       , m_secure(scheme == "wss" || scheme == "https")
205       , m_valid(true) {}
206
207     uri(std::string scheme, std::string const & host, std::string const & resource)
208       : m_scheme(scheme)
209       , m_host(host)
210       , m_resource(resource.empty() ? "/" : resource)
211       , m_port((scheme == "wss" || scheme == "https") ? uri_default_secure_port : uri_default_port)
212       , m_secure(scheme == "wss" || scheme == "https")
213       , m_valid(true) {}
214
215     uri(std::string const & scheme, std::string const & host,
216         std::string const & port, std::string const & resource)
217       : m_scheme(scheme)
218       , m_host(host)
219       , m_resource(resource.empty() ? "/" : resource)
220       , m_secure(scheme == "wss" || scheme == "https")
221     {
222         lib::error_code ec;
223         m_port = get_port_from_string(port,ec);
224         m_valid = !ec;
225     }
226
227     bool get_valid() const {
228         return m_valid;
229     }
230
231     bool get_secure() const {
232         return m_secure;
233     }
234
235     std::string const & get_scheme() const {
236         return m_scheme;
237     }
238
239     std::string const & get_host() const {
240         return m_host;
241     }
242
243     std::string get_host_port() const {
244         if (m_port == (m_secure ? uri_default_secure_port : uri_default_port)) {
245             return m_host;
246         } else {
247             std::stringstream p;
248             p << m_host << ":" << m_port;
249             return p.str();
250         }
251     }
252
253     std::string get_authority() const {
254         std::stringstream p;
255         p << m_host << ":" << m_port;
256         return p.str();
257     }
258
259     uint16_t get_port() const {
260         return m_port;
261     }
262
263     std::string get_port_str() const {
264         std::stringstream p;
265         p << m_port;
266         return p.str();
267     }
268
269     std::string const & get_resource() const {
270         return m_resource;
271     }
272
273     std::string str() const {
274         std::stringstream s;
275
276         s << m_scheme << "://" << m_host;
277
278         if (m_port != (m_secure ? uri_default_secure_port : uri_default_port)) {
279             s << ":" << m_port;
280         }
281
282         s << m_resource;
283         return s.str();
284     }
285
286     /// Return the query portion
287     /**
288      * Returns the query portion (after the ?) of the URI or an empty string if
289      * there is none.
290      *
291      * @return query portion of the URI.
292      */
293     std::string get_query() const {
294         std::size_t found = m_resource.find('?');
295         if (found != std::string::npos) {
296             return m_resource.substr(found + 1);
297         } else {
298             return "";
299         }
300     }
301
302     // get fragment
303
304     // hi <3
305
306     // get the string representation of this URI
307
308     //std::string base() const; // is this still needed?
309
310     // setter methods set some or all (in the case of parse) based on the input.
311     // These functions throw a uri_exception on failure.
312     /*void set_uri(const std::string& uri);
313
314     void set_secure(bool secure);
315     void set_host(const std::string& host);
316     void set_port(uint16_t port);
317     void set_port(const std::string& port);
318     void set_resource(const std::string& resource);*/
319 private:
320     uint16_t get_port_from_string(std::string const & port, lib::error_code &
321         ec) const
322     {
323         ec = lib::error_code();
324
325         if (port.empty()) {
326             return (m_secure ? uri_default_secure_port : uri_default_port);
327         }
328
329         unsigned int t_port = static_cast<unsigned int>(atoi(port.c_str()));
330
331         if (t_port > 65535) {
332             ec = error::make_error_code(error::invalid_port);
333         }
334
335         if (t_port == 0) {
336             ec = error::make_error_code(error::invalid_port);
337         }
338
339         return static_cast<uint16_t>(t_port);
340     }
341
342     std::string m_scheme;
343     std::string m_host;
344     std::string m_resource;
345     uint16_t    m_port;
346     bool        m_secure;
347     bool        m_valid;
348 };
349
350 /// Pointer to a URI
351 typedef lib::shared_ptr<uri> uri_ptr;
352
353 } // namespace websocketpp
354
355 #endif // WEBSOCKETPP_URI_HPP