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