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 "util/coordinate.hpp"
|
||||||
|
|
||||||
|
#include <boost/fusion/include/adapt_struct.hpp>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@ -13,15 +15,18 @@ namespace server
|
|||||||
namespace api
|
namespace api
|
||||||
{
|
{
|
||||||
|
|
||||||
struct ParsedURL
|
struct ParsedURL final
|
||||||
{
|
{
|
||||||
std::string service;
|
std::string service;
|
||||||
unsigned version;
|
unsigned version;
|
||||||
std::string profile;
|
std::string profile;
|
||||||
std::string query;
|
std::string query;
|
||||||
};
|
};
|
||||||
}
|
|
||||||
}
|
} // api
|
||||||
}
|
} // server
|
||||||
|
} // osrm
|
||||||
|
|
||||||
|
BOOST_FUSION_ADAPT_STRUCT(osrm::server::api::ParsedURL, service, version, profile, query)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,17 +1,55 @@
|
|||||||
#include "server/api/url_parser.hpp"
|
#include "server/api/url_parser.hpp"
|
||||||
|
|
||||||
#include "engine/polyline_compressor.hpp"
|
#include "engine/polyline_compressor.hpp"
|
||||||
|
|
||||||
#include <boost/bind.hpp>
|
//#define BOOST_SPIRIT_DEBUG
|
||||||
#include <boost/spirit/include/qi_char_.hpp>
|
#include <boost/spirit/include/qi.hpp>
|
||||||
#include <boost/spirit/include/qi_grammar.hpp>
|
|
||||||
#include <boost/spirit/include/qi_uint.hpp>
|
#include <string>
|
||||||
#include <boost/spirit/include/qi_real.hpp>
|
#include <type_traits>
|
||||||
#include <boost/spirit/include/qi_lit.hpp>
|
|
||||||
#include <boost/spirit/include/qi_action.hpp>
|
// Keep impl. TU local
|
||||||
#include <boost/spirit/include/qi_as_string.hpp>
|
namespace
|
||||||
#include <boost/spirit/include/qi_operator.hpp>
|
{
|
||||||
#include <boost/spirit/include/qi_plus.hpp>
|
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
|
namespace osrm
|
||||||
{
|
{
|
||||||
@ -20,70 +58,21 @@ namespace server
|
|||||||
namespace api
|
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> parseURL(std::string::iterator &iter, const std::string::iterator end)
|
||||||
{
|
{
|
||||||
boost::optional<ParsedURL> parsed_url;
|
using It = std::decay<decltype(iter)>::type;
|
||||||
|
|
||||||
URLGrammar grammar;
|
URLParser<It, ParsedURL> parser;
|
||||||
const auto result = boost::spirit::qi::parse(iter, end, grammar);
|
ParsedURL out;
|
||||||
|
|
||||||
if (result && iter == end)
|
const auto ok = boost::spirit::qi::parse(iter, end, parser, out);
|
||||||
{
|
|
||||||
parsed_url = std::move(grammar.parsed_url);
|
if (ok && iter == end)
|
||||||
|
return boost::make_optional(out);
|
||||||
|
|
||||||
|
return boost::none;
|
||||||
}
|
}
|
||||||
|
|
||||||
return parsed_url;
|
} // api
|
||||||
}
|
} // server
|
||||||
}
|
} // osrm
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user