|
| 1 | +// Copyright (c) Glyn Matthews 2011, 2012. |
| 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 | +#ifndef __BOOST_NETWORK_URI_URI_ACCESSORS_INC__ |
| 8 | +# define __BOOST_NETWORK_URI_URI_ACCESSORS_INC__ |
| 9 | + |
| 10 | + |
| 11 | +# include <network/uri/uri.hpp> |
| 12 | +# include <network/uri/encode.hpp> |
| 13 | +# include <network/uri/decode.hpp> |
| 14 | +# include <boost/spirit/include/qi.hpp> |
| 15 | +# include <boost/fusion/include/std_pair.hpp> |
| 16 | + |
| 17 | + |
| 18 | +namespace network { |
| 19 | +namespace details { |
| 20 | +template < |
| 21 | + typename Map |
| 22 | + > |
| 23 | +struct key_value_sequence |
| 24 | + : boost::spirit::qi::grammar<uri::const_iterator, Map()> |
| 25 | +{ |
| 26 | + typedef typename Map::key_type key_type; |
| 27 | + typedef typename Map::mapped_type mapped_type; |
| 28 | + typedef std::pair<key_type, mapped_type> pair_type; |
| 29 | + |
| 30 | + key_value_sequence() |
| 31 | + : key_value_sequence::base_type(query) |
| 32 | + { |
| 33 | + query = pair >> *((boost::spirit::qi::lit(';') | '&') >> pair); |
| 34 | + pair = key >> -('=' >> value); |
| 35 | + key = boost::spirit::qi::char_("a-zA-Z_") >> *boost::spirit::qi::char_("a-zA-Z_0-9/%"); |
| 36 | + value = +boost::spirit::qi::char_("a-zA-Z_0-9/%"); |
| 37 | + } |
| 38 | + |
| 39 | + boost::spirit::qi::rule<uri::const_iterator, Map()> query; |
| 40 | + boost::spirit::qi::rule<uri::const_iterator, pair_type()> pair; |
| 41 | + boost::spirit::qi::rule<uri::const_iterator, key_type()> key; |
| 42 | + boost::spirit::qi::rule<uri::const_iterator, mapped_type()> value; |
| 43 | +}; |
| 44 | +} // namespace details |
| 45 | + |
| 46 | +template < |
| 47 | + class Map |
| 48 | + > |
| 49 | +inline |
| 50 | +Map &query_map(const uri &uri_, Map &map) { |
| 51 | + const uri::string_type range = uri_.query(); |
| 52 | + details::key_value_sequence<Map> parser; |
| 53 | + boost::spirit::qi::parse(boost::begin(range), boost::end(range), parser, map); |
| 54 | + return map; |
| 55 | +} |
| 56 | + |
| 57 | +inline |
| 58 | +uri::string_type username(const uri &uri_) { |
| 59 | + const uri::string_type user_info = uri_.user_info(); |
| 60 | + uri::const_iterator it(boost::begin(user_info)), end(boost::end(user_info)); |
| 61 | + for (; it != end; ++it) { |
| 62 | + if (*it == ':') { |
| 63 | + break; |
| 64 | + } |
| 65 | + } |
| 66 | + return uri::string_type(boost::begin(user_info), it); |
| 67 | +} |
| 68 | + |
| 69 | +inline |
| 70 | +uri::string_type password(const uri &uri_) { |
| 71 | + const uri::string_type user_info = uri_.user_info(); |
| 72 | + uri::const_iterator it(boost::begin(user_info)), end(boost::end(user_info)); |
| 73 | + for (; it != end; ++it) { |
| 74 | + if (*it == ':') { |
| 75 | + ++it; |
| 76 | + break; |
| 77 | + } |
| 78 | + } |
| 79 | + return uri::string_type(it, boost::end(user_info)); |
| 80 | +} |
| 81 | + |
| 82 | +inline |
| 83 | +uri::string_type decoded_path(const uri &uri_) { |
| 84 | + const uri::string_type path = uri_.path(); |
| 85 | + uri::string_type decoded_path; |
| 86 | + decode(path, std::back_inserter(decoded_path)); |
| 87 | + return decoded_path; |
| 88 | +} |
| 89 | + |
| 90 | +inline |
| 91 | +uri::string_type decoded_query(const uri &uri_) { |
| 92 | + const uri::string_type query = uri_.query(); |
| 93 | + uri::string_type decoded_query; |
| 94 | + decode(query, std::back_inserter(decoded_query)); |
| 95 | + return decoded_query; |
| 96 | +} |
| 97 | + |
| 98 | +inline |
| 99 | +uri::string_type decoded_fragment(const uri &uri_) { |
| 100 | + const uri::string_type fragment = uri_.fragment(); |
| 101 | + uri::string_type decoded_fragment; |
| 102 | + decode(fragment, std::back_inserter(decoded_fragment)); |
| 103 | + return decoded_fragment; |
| 104 | +} |
| 105 | +} // namespace network |
| 106 | + |
| 107 | + |
| 108 | +#endif // __BOOST_NETWORK_URI_URI_ACCESSORS_INC__ |
0 commit comments