Line data Source code
1 : /* Copyright (c) 2013-2014, ahmet.bilgili@epfl.ch
2 : * 2014, Stefan.Eilemann@epfl.ch
3 : *
4 : * This file is part of Lunchbox <https://github.com/Eyescale/Lunchbox>
5 : *
6 : * This library is free software; you can redistribute it and/or modify it under
7 : * the terms of the GNU Lesser General Public License version 2.1 as published
8 : * by the Free Software Foundation.
9 : *
10 : * This library is distributed in the hope that it will be useful, but WITHOUT
11 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 : * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
13 : * details.
14 : *
15 : * You should have received a copy of the GNU Lesser General Public License
16 : * along with this library; if not, write to the Free Software Foundation, Inc.,
17 : * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 : */
19 :
20 : #ifndef LUNCHBOX_URI_H
21 : #define LUNCHBOX_URI_H
22 :
23 : #include <lunchbox/api.h>
24 : #include <lunchbox/types.h>
25 : #include <boost/unordered_map.hpp> // iterator typedefs
26 : #include <boost/lexical_cast.hpp>
27 :
28 : namespace lunchbox
29 : {
30 : namespace detail { class URI; }
31 :
32 : /**
33 : * The URI class parses the given uri string according to the regex given in
34 : * RFC3986.
35 : * @verbatim
36 : * http://bob@www.example.com:8080/path/?key=value,foo=bar#fragment
37 : * ^ ^ ^ ^ ^ ^ ^ ^
38 : * a b c d e f g h
39 : *
40 : * URI part Range String
41 : * scheme [a, b) "http"
42 : * userinfo [c, d) bob
43 : * host [d, e) "www.example.com"
44 : * port (e, f) 8080
45 : * path [f, g) "/path/"
46 : * query (g, h) "key=value"
47 : * fragment (h,-) "fragment"
48 : * @endverbatim
49 : *
50 : * Queries are parsed into key-value pairs and can be accessed using
51 : * findQuery(), queryBegin() and queryEnd().
52 : *
53 : * Example: @include tests/uri.cpp
54 : */
55 : class URI
56 : {
57 : public:
58 : typedef boost::unordered_map< std::string, std::string > KVMap;
59 : typedef KVMap::const_iterator ConstKVIter;
60 :
61 : /** Construct an empty URI. @version 1.9.2 */
62 : LUNCHBOX_API URI();
63 :
64 : /**
65 : * @param uri URI string to parse.
66 : * @throw std::exception for incomplete URIs, and boost::bad_lexical_cast
67 : * if the port is not a number.
68 : * @version 1.9.2
69 : */
70 : LUNCHBOX_API explicit URI( const std::string& uri );
71 :
72 : /** @overload URI::URI( const std::string& ) */
73 : LUNCHBOX_API explicit URI( const char* uri );
74 :
75 : /** Copy-construct an URI. @version 1.9.2 */
76 : LUNCHBOX_API URI( const URI& from );
77 :
78 : LUNCHBOX_API ~URI();
79 :
80 : /** Assign the data from another URI. @version 1.9.2 */
81 : LUNCHBOX_API URI& operator = ( const URI& rhs );
82 :
83 : /** @name Getters for the uri data @version 1.9.2 */
84 : //@{
85 : LUNCHBOX_API const std::string& getScheme() const;
86 : LUNCHBOX_API const std::string& getUserinfo() const;
87 : LUNCHBOX_API uint16_t getPort() const;
88 : LUNCHBOX_API const std::string& getHost() const;
89 : LUNCHBOX_API const std::string& getPath() const;
90 : LUNCHBOX_API const std::string& getQuery() const;
91 : LUNCHBOX_API const std::string& getFragment() const;
92 : //@}
93 :
94 : /** @name Access to key-value data in query @version 1.9.2 */
95 : //@{
96 : /**
97 : * @return a const iterator to the beginning of the query map.
98 : * @version 1.9.2
99 : */
100 : LUNCHBOX_API ConstKVIter queryBegin() const;
101 :
102 : /**
103 : * @return a const iterator to end beginning of the query map.
104 : * @version 1.9.2
105 : */
106 : LUNCHBOX_API ConstKVIter queryEnd() const;
107 :
108 : /**
109 : * @return a const iterator to the given key, or queryEnd().
110 : * @version 1.9.2
111 : */
112 : LUNCHBOX_API ConstKVIter findQuery( const std::string& key ) const;
113 :
114 : /** Add a key-value pair to the query. @version 1.9.2 */
115 : LUNCHBOX_API void addQuery( const std::string& key,
116 : const std::string& value );
117 : //@}
118 :
119 : private:
120 : detail::URI* const _impl;
121 : };
122 :
123 5 : inline std::ostream& operator << ( std::ostream& os, const URI& uri )
124 : {
125 5 : if( !uri.getScheme().empty( ))
126 4 : os << uri.getScheme() << "://";
127 5 : if( !uri.getUserinfo().empty( ))
128 1 : os << uri.getUserinfo() << "@";
129 5 : os << uri.getHost();
130 5 : if( uri.getPort( ))
131 1 : os << ':' << uri.getPort();
132 5 : os << uri.getPath();
133 5 : if( !uri.getQuery().empty( ))
134 1 : os << '?' << uri.getQuery();
135 5 : if( !uri.getFragment().empty( ))
136 1 : os << '#' << uri.getFragment();
137 5 : return os;
138 : }
139 : }
140 :
141 : namespace boost
142 : {
143 2 : template<> inline std::string lexical_cast( const lunchbox::URI& uri )
144 : {
145 2 : std::ostringstream os;
146 2 : os << uri;
147 2 : return os.str();
148 : }
149 : }
150 : #endif // LUNCHBOX_URI_H
|