Skip to content

Commit b17a4f3

Browse files
committed
Added accessor to fill a map with the key-value pairs in the URI query; added accessors to get the username and password individually; added a class that will eventually become an e-mail address.
1 parent 5bc6c29 commit b17a4f3

File tree

6 files changed

+288
-46
lines changed

6 files changed

+288
-46
lines changed

boost/network/uri/mailto/uri.hpp

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
#ifndef __BOOST_NETWORK_URI_MAILTO_URI_INC__
2+
# define __BOOST_NETWORK_URI_MAILTO_URI_INC__
3+
4+
5+
# include <boost/network/uri/uri.hpp>
6+
7+
8+
namespace boost {
9+
namespace network {
10+
namespace uri {
11+
namespace mailto {
12+
namespace details {
13+
template <
14+
class String
15+
>
16+
struct uri_parts
17+
: boost::fusion::vector<
18+
iterator_range<String> // to
19+
// headers
20+
>
21+
{ };
22+
} // namespace details
23+
} // namespace mailto
24+
} // namespace uri
25+
} // namespace network
26+
} // namespace boost
27+
28+
29+
namespace boost {
30+
namespace network {
31+
namespace uri {
32+
namespace mailto {
33+
34+
template <
35+
class Tag
36+
>
37+
class basic_uri
38+
: public boost::network::uri::basic_uri<Tag> {
39+
40+
typedef boost::network::uri::basic_uri<Tag> base_type;
41+
42+
public:
43+
44+
basic_uri() {
45+
46+
}
47+
48+
basic_uri(const typename base_type::string_type &uri) : base_type(uri) {
49+
50+
}
51+
52+
basic_uri &operator = (const typename base_type::string_type &uri) {
53+
basic_uri(uri).swap(*this);
54+
return *this;
55+
}
56+
57+
58+
59+
};
60+
} // namespace mailto
61+
62+
template <
63+
class Tag
64+
>
65+
bool is_mailto(const mailto::basic_uri<Tag> &uri) {
66+
static const char scheme_mailto[] = {'m', 'a', 'i', 'l', 't', 'o'};
67+
return boost::equal(uri.scheme_range(), scheme_mailto);
68+
}
69+
} // namespace uri
70+
} // namespace network
71+
} // namespace boost
72+
73+
74+
#endif // __BOOST_NETWORK_URI_MAILTO_URI_INC__

boost/network/uri/uri.hpp

+14-34
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
# ifdef BOOST_NETWORK_NO_LIB
1616
# include <boost/network/uri/detail/parse_uri.hpp>
1717
# endif // #ifdef BOOST_NETWORK_NO_LIB
18+
# include <boost/fusion/include/std_pair.hpp>
1819
# include <boost/algorithm/string.hpp>
1920
# include <boost/range/iterator_range.hpp>
2021
# include <boost/operators.hpp>
@@ -111,50 +112,26 @@ class basic_uri
111112

112113
const_range_type user_info_range() const {
113114
using boost::fusion::at_c;
114-
const boost::fusion::vector<
115-
detail::iterator_range<typename string<Tag>::type>
116-
, detail::iterator_range<typename string<Tag>::type>
117-
, detail::iterator_range<typename string<Tag>::type>
118-
, detail::iterator_range<typename string<Tag>::type> > &hier_part = at_c<1>(uri_parts_);
119-
120-
return const_range_type(at_c<0>(at_c<0>(hier_part)),
121-
at_c<1>(at_c<0>(hier_part)));
115+
return const_range_type(at_c<0>(at_c<0>(at_c<1>(uri_parts_))),
116+
at_c<1>(at_c<0>(at_c<1>(uri_parts_))));
122117
}
123118

124119
const_range_type host_range() const {
125120
using boost::fusion::at_c;
126-
const boost::fusion::vector<
127-
detail::iterator_range<typename string<Tag>::type>
128-
, detail::iterator_range<typename string<Tag>::type>
129-
, detail::iterator_range<typename string<Tag>::type>
130-
, detail::iterator_range<typename string<Tag>::type> > &hier_part = at_c<1>(uri_parts_);
131-
132-
return const_range_type(at_c<0>(at_c<1>(hier_part)),
133-
at_c<1>(at_c<1>(hier_part)));
121+
return const_range_type(at_c<0>(at_c<1>(at_c<1>(uri_parts_))),
122+
at_c<1>(at_c<1>(at_c<1>(uri_parts_))));
134123
}
135124

136125
const_range_type port_range() const {
137126
using boost::fusion::at_c;
138-
const boost::fusion::vector<
139-
detail::iterator_range<typename string<Tag>::type>
140-
, detail::iterator_range<typename string<Tag>::type>
141-
, detail::iterator_range<typename string<Tag>::type>
142-
, detail::iterator_range<typename string<Tag>::type> > &hier_part = at_c<1>(uri_parts_);
143-
144-
return const_range_type(at_c<0>(at_c<2>(hier_part)),
145-
at_c<1>(at_c<2>(hier_part)));
127+
return const_range_type(at_c<0>(at_c<2>(at_c<1>(uri_parts_))),
128+
at_c<1>(at_c<2>(at_c<1>(uri_parts_))));
146129
}
147130

148131
const_range_type path_range() const {
149132
using boost::fusion::at_c;
150-
const boost::fusion::vector<
151-
detail::iterator_range<typename string<Tag>::type>
152-
, detail::iterator_range<typename string<Tag>::type>
153-
, detail::iterator_range<typename string<Tag>::type>
154-
, detail::iterator_range<typename string<Tag>::type> > &hier_part = at_c<1>(uri_parts_);
155-
156-
return const_range_type(at_c<0>(at_c<3>(hier_part)),
157-
at_c<1>(at_c<3>(hier_part)));
133+
return const_range_type(at_c<0>(at_c<3>(at_c<1>(uri_parts_))),
134+
at_c<1>(at_c<3>(at_c<1>(uri_parts_))));
158135
}
159136

160137
const_range_type query_range() const {
@@ -208,6 +185,10 @@ class basic_uri
208185
return uri_;
209186
}
210187

188+
string_type raw() const {
189+
return to_string();
190+
}
191+
211192
bool is_valid() const {
212193
return is_valid_;
213194
}
@@ -222,10 +203,10 @@ class basic_uri
222203

223204
};
224205

225-
226206
template <
227207
class Tag
228208
>
209+
inline
229210
void basic_uri<Tag>::parse() {
230211
const_iterator_type first(boost::begin(uri_)), last(boost::end(uri_));
231212
is_valid_ = detail::parse(first, last, uri_parts_);
@@ -301,7 +282,6 @@ struct port_wrapper {
301282
}
302283
};
303284

304-
305285
template <
306286
class Tag
307287
>

boost/network/uri/uri_accessors.hpp

+82
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
#ifndef __BOOST_NETWORK_URI_URI_ACCESSORS_INC__
2+
# define __BOOST_NETWORK_URI_URI_ACCESSORS_INC__
3+
4+
5+
# include <boost/network/uri/uri.hpp>
6+
# include <boost/spirit/include/qi.hpp>
7+
8+
9+
namespace boost {
10+
namespace network {
11+
namespace uri {
12+
namespace details {
13+
template <
14+
typename Uri,
15+
typename Map
16+
>
17+
struct key_value_sequence
18+
: spirit::qi::grammar<typename Uri::const_iterator_type, Map()>
19+
{
20+
typedef typename Uri::const_iterator_type const_iterator_type;
21+
22+
key_value_sequence()
23+
: key_value_sequence::base_type(query)
24+
{
25+
query = pair >> *((spirit::qi::lit(';') | '&') >> pair);
26+
pair = key >> -('=' >> value);
27+
key = spirit::qi::char_("a-zA-Z_") >> *spirit::qi::char_("a-zA-Z_0-9%");
28+
value = +spirit::qi::char_("a-zA-Z_0-9%");
29+
}
30+
31+
spirit::qi::rule<const_iterator_type, Map()> query;
32+
spirit::qi::rule<const_iterator_type, std::pair<typename Uri::string_type, typename Uri::string_type>()> pair;
33+
spirit::qi::rule<const_iterator_type, typename Uri::string_type()> key, value;
34+
};
35+
} // namespace details
36+
37+
template <
38+
class Tag,
39+
class Map
40+
>
41+
inline
42+
Map &query_map(const basic_uri<Tag> &uri, Map &map) {
43+
typename basic_uri<Tag>::const_range_type range = uri.query_range();
44+
details::key_value_sequence<basic_uri<Tag>, Map> parser;
45+
spirit::qi::parse(boost::begin(range), boost::end(range), parser, map);
46+
return map;
47+
}
48+
49+
template <
50+
class Tag
51+
>
52+
typename basic_uri<Tag>::string_type username(const basic_uri<Tag> &uri) {
53+
typename basic_uri<Tag>::const_range_type user_info_range = uri.user_info_range();
54+
typename basic_uri<Tag>::const_iterator_type it(boost::begin(user_info_range)), end(boost::end(user_info_range));
55+
for (; it != end; ++it) {
56+
if (*it == ':') {
57+
break;
58+
}
59+
}
60+
return typename string<Tag>::type(boost::begin(user_info_range), it);
61+
}
62+
63+
template <
64+
class Tag
65+
>
66+
typename basic_uri<Tag>::string_type password(const basic_uri<Tag> &uri) {
67+
typename basic_uri<Tag>::const_range_type user_info_range = uri.user_info_range();
68+
typename basic_uri<Tag>::const_iterator_type it(boost::begin(user_info_range)), end(boost::end(user_info_range));
69+
for (; it != end; ++it) {
70+
if (*it == ':') {
71+
++it;
72+
break;
73+
}
74+
}
75+
return typename string<Tag>::type(it, boost::end(user_info_range));
76+
}
77+
} // namespace uri
78+
} // namespace network
79+
} // namespace boost
80+
81+
82+
#endif // __BOOST_NETWORK_URI_URI_ACCESSORS_INC__

libs/network/test/uri/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ if (Boost_FOUND)
1616
TESTS
1717
url_test
1818
url_http_test
19+
url_mailto_test
1920
)
2021
foreach (test ${TESTS})
2122
set_source_files_properties(${test}.cpp
+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Copyright (c) Glyn Matthews 2011.
2+
// Distributed under the Boost Software License, Version 1.0.
3+
// (See accompanying file LICENSE_1_0.txt or copy at
4+
// http://www.boost.org/LICENSE_1_0.txt)
5+
6+
7+
#define BOOST_TEST_MODULE mailto URL Test
8+
#include <boost/config/warning_disable.hpp>
9+
#include <boost/test/unit_test.hpp>
10+
#include <boost/network/uri/mailto/uri.hpp>
11+
#include <boost/mpl/list.hpp>
12+
#include <boost/range/algorithm/equal.hpp>
13+
14+
using namespace boost::network;
15+
16+
typedef boost::mpl::list<
17+
tags::default_string
18+
// , tags::default_wstring
19+
> tag_types;
20+
21+
22+
BOOST_AUTO_TEST_CASE_TEMPLATE(valid_mailto, T, tag_types)
23+
{
24+
typedef uri::mailto::basic_uri<T> uri_type;
25+
typedef typename uri_type::string_type string_type;
26+
const std::string url("mailto:[email protected]");
27+
uri_type instance(string_type(boost::begin(url), boost::end(url)));
28+
BOOST_REQUIRE(uri::is_mailto(instance));
29+
BOOST_REQUIRE(uri::is_valid(instance));
30+
}

0 commit comments

Comments
 (0)