|
6 | 6 | // (See accompanying file LICENSE_1_0.txt or copy at |
7 | 7 | // http://www.boost.org/LICENSE_1_0.txt) |
8 | 8 |
|
9 | | -#include<boost/spirit/include/phoenix_operator.hpp> |
10 | | -#include<boost/spirit/include/qi_attr.hpp> |
11 | | -#include<boost/spirit/include/qi_core.hpp> |
12 | | -#include<boost/spirit/include/qi_eps.hpp> |
13 | | -#include<boost/spirit/include/qi_grammar.hpp> |
14 | | -#include<boost/spirit/include/qi_omit.hpp> |
15 | | -#include<boost/spirit/include/qi_raw.hpp> |
16 | | -#include<boost/spirit/include/qi_rule.hpp> |
17 | | -#include<boost/spirit/include/qi_sequence.hpp> |
18 | | -#include<boost/spirit/include/version.hpp> |
19 | 9 | #include<boost/network/uri/detail/uri_parts.hpp> |
20 | | - |
21 | | - |
22 | | -namespaceboost {namespacespirit {namespacetraits { |
23 | | -template<classTag> |
24 | | -structtransform_attribute< |
25 | | - boost::network::uri::detail::uri_parts<Tag>, |
26 | | -typename boost::network::uri::detail::uri_parts_tuple<Tag>::type |
27 | | -#if SPIRIT_VERSION >= 0x2030 |
28 | | - , boost::spirit::qi::domain |
29 | | -#endif |
30 | | - > |
31 | | -{ |
32 | | -typedeftypename boost::network::uri::detail::uri_parts_tuple<Tag>::type type; |
33 | | - |
34 | | -static typepre(boost::network::uri::detail::uri_parts<Tag> & parts) { |
35 | | -typedeftypename boost::network::string<Tag>::type string_type; |
36 | | - |
37 | | - boost::fusion::tuple< |
38 | | - boost::optional<string_type> &, |
39 | | - boost::optional<string_type> &, |
40 | | - boost::optional<boost::uint16_t> &, |
41 | | - string_type & |
42 | | - > hier_part = |
43 | | -boost::fusion::tie( |
44 | | - parts.user_info, |
45 | | - parts.host, |
46 | | - parts.port, |
47 | | - parts.path |
48 | | - ); |
49 | | - |
50 | | -returnboost::fusion::tie( |
51 | | - parts.scheme, |
52 | | - hier_part, |
53 | | - parts.query, |
54 | | - parts.fragment |
55 | | - ); |
56 | | -} |
57 | | - |
58 | | -staticvoidpost(boost::network::uri::detail::uri_parts<Tag> &, typeconst &) { } |
59 | | - |
60 | | -#if SPIRIT_VERSION >= 0x2030 |
61 | | -staticvoidfail(boost::network::uri::detail::uri_parts<Tag> & val) { } |
62 | | -#endif |
63 | | -}; |
64 | | - |
65 | | -#if SPIRIT_VERSION < 0x2030 |
66 | | -template<typename Exposed,typename Transformed> |
67 | | -structtransform_attribute< |
68 | | - optional<Exposed>, |
69 | | - Transformed, |
70 | | -typename disable_if<is_same<optional<Exposed>, Transformed> >::type |
71 | | - > |
72 | | -{ |
73 | | -typedef Transformed & type; |
74 | | - |
75 | | -static Transformed &pre(optional<Exposed> & val) { |
76 | | -if (!val) |
77 | | - val =Transformed(); |
78 | | -return boost::get<Transformed>(val); |
79 | | - } |
80 | | - |
81 | | -staticvoidpost(optional<Exposed> &, Transformedconst &) { } |
82 | | -}; |
83 | | -#endif |
84 | | -}// namespace traits |
85 | | -}// namespace spirit |
86 | | -}// namespace boost |
| 10 | +#include<boost/network/support/is_default_string.hpp> |
| 11 | +#include<boost/range/iterator_range.hpp> |
87 | 12 |
|
88 | 13 | namespaceboost {namespacenetwork {namespaceuri {namespacedetail { |
89 | 14 |
|
90 | | -namespaceqi= boost::spirit::qi; |
91 | | - |
92 | | -template<typename Iterator,classTag> |
93 | | -structuri_grammar : qi::grammar<Iterator, uri_parts<Tag>()> { |
94 | | -uri_grammar() : uri_grammar::base_type(start,"uri") { |
95 | | -// gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@" |
96 | | - gen_delims %=qi::char_(":/?#[]@"); |
97 | | -// sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "=" |
98 | | - sub_delims %=qi::char_("!$&'()*+,;="); |
99 | | -// reserved = gen-delims / sub-delims |
100 | | - reserved %= gen_delims | sub_delims; |
101 | | -// unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" |
102 | | - unreserved %= qi::alnum |qi::char_("-._~"); |
103 | | -// pct-encoded = "%" HEXDIG HEXDIG |
104 | | - pct_encoded %=qi::char_("%") >>qi::repeat(2)[qi::xdigit]; |
105 | | - |
106 | | -// pchar = unreserved / pct-encoded / sub-delims / ":" / "@" |
107 | | - pchar %= qi::raw[ |
108 | | - unreserved | pct_encoded | sub_delims |qi::char_(":@") |
109 | | - ]; |
110 | | - |
111 | | -// segment = *pchar |
112 | | - segment %= qi::raw[*pchar]; |
113 | | -// segment-nz = 1*pchar |
114 | | - segment_nz %= qi::raw[+pchar]; |
115 | | -// segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" ) |
116 | | - segment_nz_nc %= qi::raw[ |
117 | | - +(unreserved | pct_encoded | sub_delims |qi::char_("@")) |
118 | | - ]; |
119 | | -// path-abempty = *( "/" segment ) |
120 | | - path_abempty %= qi::raw[*(qi::char_("/") >> segment)]; |
121 | | -// path-absolute = "/" [ segment-nz *( "/" segment ) ] |
122 | | - path_absolute %= qi::raw[ |
123 | | -qi::char_("/") |
124 | | - >> -(segment_nz >> *(qi::char_("/") >> segment)) |
125 | | - ]; |
126 | | -// path-rootless = segment-nz *( "/" segment ) |
127 | | - path_rootless %= qi::raw[ |
128 | | - segment_nz >> *(qi::char_("/") >> segment) |
129 | | - ]; |
130 | | -// path-empty = 0<pchar> |
131 | | - path_empty %= qi::eps; |
132 | | - |
133 | | -// scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) |
134 | | - scheme %= qi::alpha >> *(qi::alnum |qi::char_("+.-")); |
135 | | - |
136 | | -// user_info = *( unreserved / pct-encoded / sub-delims / ":" ) |
137 | | - user_info %= qi::raw[ |
138 | | - *(unreserved | pct_encoded | sub_delims |qi::char_(":")) |
139 | | - ]; |
140 | | - |
141 | | -// dec-octet = DIGIT / %x31-39 DIGIT / "1" 2DIGIT / "2" %x30-34 DIGIT / "25" %x30-35 |
142 | | - dec_octet %= |
143 | | - !(qi::lit('0') >> qi::digit) |
144 | | - >> qi::raw[ |
145 | | - qi::uint_parser<boost::uint8_t,10,1,3>() |
146 | | - ]; |
147 | | -// IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet |
148 | | - ipv4address %= qi::raw[ |
149 | | - dec_octet >>qi::repeat(3)[qi::lit('.') >> dec_octet] |
150 | | - ]; |
151 | | -// reg-name = *( unreserved / pct-encoded / sub-delims ) |
152 | | - reg_name %= qi::raw[ |
153 | | - *(unreserved | pct_encoded | sub_delims) |
154 | | - ]; |
155 | | -// TODO, host = IP-literal / IPv4address / reg-name |
156 | | - host %= ipv4address | reg_name; |
157 | | - |
158 | | -// query = *( pchar / "/" / "?" ) |
159 | | - query %= qi::raw[*(pchar |qi::char_("/?"))]; |
160 | | -// fragment = *( pchar / "/" / "?" ) |
161 | | - fragment %= qi::raw[*(pchar |qi::char_("/?"))]; |
162 | | - |
163 | | -// hier-part = "//" authority path-abempty / path-absolute / path-rootless / path-empty |
164 | | -// authority = [ userinfo "@" ] host [ ":" port ] |
165 | | - hier_part %= |
166 | | - ( |
167 | | -"//" |
168 | | - >> -(user_info >>'@') |
169 | | - >> host |
170 | | - >> -(':' >> qi::ushort_) |
171 | | -// >> -(':' >> *qi::digit) |
172 | | - >> path_abempty |
173 | | - ) |
174 | | - | |
175 | | - ( |
176 | | -qi::attr(optional<typename boost::network::string<Tag>::type>()) |
177 | | - >>qi::attr(optional<typename boost::network::string<Tag>::type>()) |
178 | | -// >> qi::attr(optional<typename boost::network::string<Tag>::type>()) |
179 | | - >>qi::attr(optional<boost::uint16_t>()) |
180 | | - >> ( |
181 | | - path_absolute |
182 | | - | path_rootless |
183 | | - | path_empty |
184 | | - ) |
185 | | - ); |
186 | | - |
187 | | - uri %= |
188 | | - scheme >>':' |
189 | | - >> hier_part |
190 | | - >> -('?' >> query) |
191 | | - >> -('#' >> fragment); |
192 | | - |
193 | | - start %= uri.alias(); |
194 | | - } |
195 | | - |
196 | | -typedeftypename string<Tag>::type string_type; |
197 | | - |
198 | | - qi::rule<Iterator,typenamestring_type::value_type()> |
199 | | - gen_delims, sub_delims, reserved, unreserved; |
200 | | - qi::rule<Iterator, string_type()> |
201 | | - pct_encoded, pchar; |
202 | | - |
203 | | - qi::rule<Iterator, string_type()> |
204 | | - segment, segment_nz, segment_nz_nc; |
205 | | - qi::rule<Iterator, string_type()> |
206 | | - path_abempty, path_absolute, path_rootless, path_empty; |
207 | | - |
208 | | - qi::rule<Iterator, string_type()> |
209 | | - dec_octet, ipv4address, reg_name, host; |
210 | | - |
211 | | - qi::rule<Iterator, string_type()> |
212 | | - scheme, user_info, query, fragment; |
213 | | - |
214 | | - qi::rule<Iterator, boost::fusion::tuple< |
215 | | - optional<string_type> &, |
216 | | - optional<string_type> &, |
217 | | -// optional<string_type> &, |
218 | | - optional<boost::uint16_t> &, |
219 | | - string_type & |
220 | | - >()> hier_part; |
221 | | - |
222 | | -// start rule of grammar |
223 | | -qi::rule<Iterator, uri_parts<Tag>()> start; |
224 | | - |
225 | | -// actual uri parser |
226 | | -qi::rule<Iterator,typename uri_parts_tuple<Tag>::type()> uri; |
227 | | -}; |
228 | | - |
229 | | -template< |
230 | | -classTag |
231 | | - > |
232 | | -inline |
233 | | -boolparse_specific(uri_parts<Tag> & parts) { |
| 15 | +template<classTag> |
| 16 | +inlineboolparse_specific(uri_parts<Tag> & parts) { |
234 | 17 | returntrue; |
235 | 18 | } |
236 | 19 |
|
237 | | -template< |
238 | | -classRange, |
239 | | -classTag |
240 | | - > |
241 | | -inline |
242 | | -boolparse_uri(Range & range, uri_parts<Tag> & parts) { |
243 | | -typedeftypename range_iterator<Range>::type iterator; |
244 | | - |
245 | | -// Qualified boost::begin and boost::end because MSVC complains |
246 | | -// of ambiguity on call to begin(range) and end(rand). |
247 | | - iterator start_ =boost::begin(range); |
248 | | - iterator end_ =boost::end(range); |
| 20 | +externboolparse_uri_impl(boost::iterator_range<std::string::const_iterator> & range, uri_parts_default_base & parts, tags::default_string); |
| 21 | +externboolparse_uri_impl(boost::iterator_range<std::wstring::const_iterator> & range, uri_parts_wide_base & parts, tags::default_wstring); |
249 | 22 |
|
250 | | -static uri_grammar<iterator, Tag> grammar; |
251 | | - |
252 | | -bool ok =qi::parse(start_, end_, grammar, parts); |
253 | | - |
254 | | -if (ok) |
255 | | - ok =parse_specific(parts); |
256 | | - |
257 | | -return ok && start_ == end_; |
| 23 | +template<classTag> |
| 24 | +structunsupported_tag; |
| 25 | + |
| 26 | +template<classRange,classTag> |
| 27 | +inlineboolparse_uri(Range & range, uri_parts<Tag> & parts) { |
| 28 | +typedeftypename range_iterator<Rangeconst>::type iterator; |
| 29 | + boost::iterator_range<iterator> local_range =boost::make_iterator_range(range); |
| 30 | +returnparse_uri_impl(local_range, parts, |
| 31 | +typename mpl::if_< |
| 32 | + is_default_string<Tag>, |
| 33 | + tags::default_string, |
| 34 | +typename mpl::if_< |
| 35 | + is_default_wstring<Tag>, |
| 36 | + tags::default_wstring, |
| 37 | + unsupported_tag<Tag> |
| 38 | + >::type |
| 39 | + >::type()); |
258 | 40 | } |
| 41 | + |
259 | 42 | }// namespace detail |
260 | 43 | }// namespace uri |
261 | 44 | }// namespace network |
|