Skip to content

Instantly share code, notes, and snippets.

@microcai
Created December 13, 2018 09:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save microcai/516ffa19cfbb92d1ea4f5dd1d9c00472 to your computer and use it in GitHub Desktop.
Save microcai/516ffa19cfbb92d1ea4f5dd1d9c00472 to your computer and use it in GitHub Desktop.
use boost.spirit to parse url
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
struct KV
{
std::string k;
std::string v;
};
struct URL
{
std::string schema; // http/https
std::string host;
std::string username;
std::string password;
std::optional<int> port;
std::string query_path = "/";
std::vector<KV> query_params;
std::string anchor;
};
namespace qi = boost::spirit::qi;
BOOST_FUSION_ADAPT_STRUCT(
KV,
(std::string, k)
(std::string, v)
)
BOOST_FUSION_ADAPT_STRUCT(
URL,
(std::string, schema)
(std::string, host)
(std::string, username)
(std::string, password)
(std::optional<int>, port)
(std::string, query_path)
(std::vector<KV>, query_params)
(std::string, anchor)
)
template <typename Iterator>
struct uri_grammer : qi::grammar<Iterator, URL()>
{
typedef unsigned long ulong;
uri_grammer() : uri_grammer::base_type(url)
{
url = schema [ boost::phoenix::at_c<0>(qi::_val) = qi::_1 ]
>> "://" -( username [ boost::phoenix::at_c<2>(qi::_val) = qi::_1 ] >> -( ':' >> password [ boost::phoenix::at_c<3>(qi::_val) = qi::_1 ] ) >> '@' ) >> host [ boost::phoenix::at_c<1>(qi::_val) = qi::_1 ]
>> -(qi::lit(':') >> qi::int_ [ boost::phoenix::at_c<4>(qi::_val) = qi::_1 ] )
>> -(
query [ boost::phoenix::at_c<5>(qi::_val) = qi::_1 ] // >> -('?' >> params[ boost::phoenix::at_c<6>(qi::_val) = qi::_1 ] )
)
>> - (
'#' >> anchor [ boost::phoenix::at_c<7>(qi::_val) = qi::_1 ]
);
host = *(qi::char_ - '/' - ':');
username = *(qi::char_ - ':' - '@');
password = *(qi::char_ - '@');
schema = *(qi::char_ - ':' - '/');
query = *(qi::char_ - '#');
params = param % '&';
param = key >> '=' >> value;
anchor = *(qi::char_);
key = *(qi::char_ - '=' - '#');
value = *(qi::char_ - '&' - '#');
};
qi::rule<Iterator, std::string()> key;
qi::rule<Iterator, std::string()> value;
qi::rule<Iterator, URL()> url;
qi::rule<Iterator, std::string()> schema, host, username, password;
qi::rule<Iterator, std::string()> query;
qi::rule<Iterator, std::vector<KV>()> params;
qi::rule<Iterator, KV()> param;
qi::rule<Iterator, std::string()> anchor;
};
URL parse_url(const std::string& url)
{
URL ast;
uri_grammer<std::string::const_iterator> gramer;
auto first = url.begin();
bool r = boost::spirit::qi::parse(first, url.end(), gramer, ast);
return ast;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment