Re-factor URL parser: make grammar stateless
This commit is contained in:
parent
b25cd6aaf2
commit
6f0b6a8158
@ -3,6 +3,8 @@
|
||||
|
||||
#include "util/coordinate.hpp"
|
||||
|
||||
#include <boost/fusion/include/adapt_struct.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@ -13,15 +15,18 @@ namespace server
|
||||
namespace api
|
||||
{
|
||||
|
||||
struct ParsedURL
|
||||
struct ParsedURL final
|
||||
{
|
||||
std::string service;
|
||||
unsigned version;
|
||||
std::string profile;
|
||||
std::string query;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // api
|
||||
} // server
|
||||
} // osrm
|
||||
|
||||
BOOST_FUSION_ADAPT_STRUCT(osrm::server::api::ParsedURL, service, version, profile, query)
|
||||
|
||||
#endif
|
||||
|
@ -1,17 +1,55 @@
|
||||
#include "server/api/url_parser.hpp"
|
||||
|
||||
#include "engine/polyline_compressor.hpp"
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/spirit/include/qi_char_.hpp>
|
||||
#include <boost/spirit/include/qi_grammar.hpp>
|
||||
#include <boost/spirit/include/qi_uint.hpp>
|
||||
#include <boost/spirit/include/qi_real.hpp>
|
||||
#include <boost/spirit/include/qi_lit.hpp>
|
||||
#include <boost/spirit/include/qi_action.hpp>
|
||||
#include <boost/spirit/include/qi_as_string.hpp>
|
||||
#include <boost/spirit/include/qi_operator.hpp>
|
||||
#include <boost/spirit/include/qi_plus.hpp>
|
||||
//#define BOOST_SPIRIT_DEBUG
|
||||
#include <boost/spirit/include/qi.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
// Keep impl. TU local
|
||||
namespace
|
||||
{
|
||||
namespace qi = boost::spirit::qi;
|
||||
|
||||
template <typename Iterator, typename Into> //
|
||||
struct URLParser final : qi::grammar<Iterator, Into>
|
||||
{
|
||||
|
||||
URLParser() : URLParser::base_type(start)
|
||||
{
|
||||
alpha_numeral = qi::char_("a-zA-Z0-9");
|
||||
polyline_chars = qi::char_("a-zA-Z0-9_.--[]{}@?|\\%~`^");
|
||||
all_chars = polyline_chars | qi::char_("=,;:&().");
|
||||
|
||||
service = +alpha_numeral;
|
||||
version = qi::uint_;
|
||||
profile = +alpha_numeral;
|
||||
query = +all_chars;
|
||||
|
||||
// Example input: /route/v1/driving/7.416351,43.731205;7.420363,43.736189
|
||||
|
||||
start = qi::lit('/') >> service //
|
||||
>> qi::lit('/') >> qi::lit('v') >> version //
|
||||
>> qi::lit('/') >> profile //
|
||||
>> qi::lit('/') >> query; //
|
||||
|
||||
BOOST_SPIRIT_DEBUG_NODES((start)(service)(version)(profile)(query))
|
||||
}
|
||||
|
||||
qi::rule<Iterator, Into> start;
|
||||
|
||||
qi::rule<Iterator, std::string()> service;
|
||||
qi::rule<Iterator, unsigned()> version;
|
||||
qi::rule<Iterator, std::string()> profile;
|
||||
qi::rule<Iterator, std::string()> query;
|
||||
|
||||
qi::rule<Iterator, char()> alpha_numeral;
|
||||
qi::rule<Iterator, char()> all_chars;
|
||||
qi::rule<Iterator, char()> polyline_chars;
|
||||
};
|
||||
|
||||
} // anon.
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
@ -20,70 +58,21 @@ namespace server
|
||||
namespace api
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
namespace qi = boost::spirit::qi;
|
||||
using Iterator = std::string::iterator;
|
||||
struct URLGrammar : boost::spirit::qi::grammar<Iterator>
|
||||
{
|
||||
URLGrammar() : URLGrammar::base_type(url_rule)
|
||||
{
|
||||
const auto set_service = [this](std::string service)
|
||||
{
|
||||
parsed_url.service = std::move(service);
|
||||
};
|
||||
const auto set_version = [this](const unsigned version)
|
||||
{
|
||||
parsed_url.version = version;
|
||||
};
|
||||
const auto set_profile = [this](std::string profile)
|
||||
{
|
||||
parsed_url.profile = std::move(profile);
|
||||
};
|
||||
const auto set_query = [this](std::string query)
|
||||
{
|
||||
parsed_url.query = std::move(query);
|
||||
};
|
||||
|
||||
alpha_numeral = qi::char_("a-zA-Z0-9");
|
||||
polyline_chars = qi::char_("a-zA-Z0-9_.--[]{}@?|\\%~`^");
|
||||
all_chars = polyline_chars | qi::char_("=,;:&().");
|
||||
|
||||
service_rule = +alpha_numeral;
|
||||
version_rule = qi::uint_;
|
||||
profile_rule = +alpha_numeral;
|
||||
query_rule = +all_chars;
|
||||
|
||||
url_rule = qi::lit('/') >> service_rule[set_service] //
|
||||
>> qi::lit('/') >> qi::lit('v') >> version_rule[set_version] //
|
||||
>> qi::lit('/') >> profile_rule[set_profile] //
|
||||
>> qi::lit('/') >> query_rule[set_query];
|
||||
}
|
||||
|
||||
ParsedURL parsed_url;
|
||||
|
||||
qi::rule<Iterator> url_rule;
|
||||
qi::rule<Iterator, std::string()> service_rule, profile_rule, query_rule;
|
||||
qi::rule<Iterator, unsigned()> version_rule;
|
||||
qi::rule<Iterator, char()> alpha_numeral, all_chars, polyline_chars;
|
||||
};
|
||||
}
|
||||
|
||||
boost::optional<ParsedURL> parseURL(std::string::iterator &iter, const std::string::iterator end)
|
||||
{
|
||||
boost::optional<ParsedURL> parsed_url;
|
||||
using It = std::decay<decltype(iter)>::type;
|
||||
|
||||
URLGrammar grammar;
|
||||
const auto result = boost::spirit::qi::parse(iter, end, grammar);
|
||||
URLParser<It, ParsedURL> parser;
|
||||
ParsedURL out;
|
||||
|
||||
if (result && iter == end)
|
||||
{
|
||||
parsed_url = std::move(grammar.parsed_url);
|
||||
}
|
||||
const auto ok = boost::spirit::qi::parse(iter, end, parser, out);
|
||||
|
||||
return parsed_url;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ok && iter == end)
|
||||
return boost::make_optional(out);
|
||||
|
||||
return boost::none;
|
||||
}
|
||||
|
||||
} // api
|
||||
} // server
|
||||
} // osrm
|
||||
|
Loading…
Reference in New Issue
Block a user