113 lines
3.2 KiB
C++
113 lines
3.2 KiB
C++
// Copyright (c) Glyn Matthews 2011.
|
|
// Distributed under the Boost Software License, Version 1.0.
|
|
// (See accompanying file LICENSE_1_0.txt or copy at
|
|
// http://www.boost.org/LICENSE_1_0.txt)
|
|
|
|
|
|
#ifndef __BOOST_NETWORK_URI_URI_ACCESSORS_INC__
|
|
# define __BOOST_NETWORK_URI_URI_ACCESSORS_INC__
|
|
|
|
|
|
# include <boost/network/uri/uri.hpp>
|
|
# include <boost/network/uri/encode.hpp>
|
|
# include <boost/network/uri/decode.hpp>
|
|
# include <boost/spirit/include/qi.hpp>
|
|
# include <boost/fusion/include/std_pair.hpp>
|
|
|
|
|
|
namespace boost {
|
|
namespace network {
|
|
namespace uri {
|
|
namespace details {
|
|
template <
|
|
typename Map
|
|
>
|
|
struct key_value_sequence
|
|
: spirit::qi::grammar<uri::const_iterator, Map()>
|
|
{
|
|
typedef typename Map::key_type key_type;
|
|
typedef typename Map::mapped_type mapped_type;
|
|
typedef std::pair<key_type, mapped_type> pair_type;
|
|
|
|
key_value_sequence()
|
|
: key_value_sequence::base_type(query)
|
|
{
|
|
query = pair >> *((spirit::qi::lit(';') | '&') >> pair);
|
|
pair = key >> -('=' >> value);
|
|
key = spirit::qi::char_("a-zA-Z_") >> *spirit::qi::char_("-+.~a-zA-Z_0-9/%");
|
|
value = +spirit::qi::char_("-+.~a-zA-Z_0-9/%");
|
|
}
|
|
|
|
spirit::qi::rule<uri::const_iterator, Map()> query;
|
|
spirit::qi::rule<uri::const_iterator, pair_type()> pair;
|
|
spirit::qi::rule<uri::const_iterator, key_type()> key;
|
|
spirit::qi::rule<uri::const_iterator, mapped_type()> value;
|
|
};
|
|
} // namespace details
|
|
|
|
template <
|
|
class Map
|
|
>
|
|
inline
|
|
Map &query_map(const uri &uri_, Map &map) {
|
|
const uri::string_type range = uri_.query();
|
|
details::key_value_sequence<Map> parser;
|
|
spirit::qi::parse(boost::begin(range), boost::end(range), parser, map);
|
|
return map;
|
|
}
|
|
|
|
inline
|
|
uri::string_type username(const uri &uri_) {
|
|
const uri::string_type user_info = uri_.user_info();
|
|
uri::const_iterator it(boost::begin(user_info)), end(boost::end(user_info));
|
|
for (; it != end; ++it) {
|
|
if (*it == ':') {
|
|
break;
|
|
}
|
|
}
|
|
return uri::string_type(boost::begin(user_info), it);
|
|
}
|
|
|
|
inline
|
|
uri::string_type password(const uri &uri_) {
|
|
const uri::string_type user_info = uri_.user_info();
|
|
uri::const_iterator it(boost::begin(user_info)), end(boost::end(user_info));
|
|
for (; it != end; ++it) {
|
|
if (*it == ':') {
|
|
++it;
|
|
break;
|
|
}
|
|
}
|
|
return uri::string_type(it, boost::end(user_info));
|
|
}
|
|
|
|
inline
|
|
uri::string_type decoded_path(const uri &uri_) {
|
|
const uri::string_type path = uri_.path();
|
|
uri::string_type decoded_path;
|
|
decode(path, std::back_inserter(decoded_path));
|
|
return decoded_path;
|
|
}
|
|
|
|
inline
|
|
uri::string_type decoded_query(const uri &uri_) {
|
|
const uri::string_type query = uri_.query();
|
|
uri::string_type decoded_query;
|
|
decode(query, std::back_inserter(decoded_query));
|
|
return decoded_query;
|
|
}
|
|
|
|
inline
|
|
uri::string_type decoded_fragment(const uri &uri_) {
|
|
const uri::string_type fragment = uri_.fragment();
|
|
uri::string_type decoded_fragment;
|
|
decode(fragment, std::back_inserter(decoded_fragment));
|
|
return decoded_fragment;
|
|
}
|
|
} // namespace uri
|
|
} // namespace network
|
|
} // namespace boost
|
|
|
|
|
|
#endif // __BOOST_NETWORK_URI_URI_ACCESSORS_INC__
|