#include "server/api/url_parser.hpp" #include "engine/polyline_compressor.hpp" #include #include #include #include #include #include BOOST_FUSION_ADAPT_STRUCT(osrm::server::api::ParsedURL, (std::string, service) (unsigned, version) (std::string, profile) (std::string, query) ) // Keep impl. TU local namespace { namespace ph = boost::phoenix; namespace qi = boost::spirit::qi; template // struct URLParser final : qi::grammar { URLParser() : URLParser::base_type(start) { using boost::spirit::repository::qi::iter_pos; 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('/') > qi::omit[iter_pos[ph::bind(&osrm::server::api::ParsedURL::prefix_length, qi::_val) = qi::_1 - qi::_r1]] > query ; BOOST_SPIRIT_DEBUG_NODES((start)(service)(version)(profile)(query)) } qi::rule start; qi::rule service; qi::rule version; qi::rule profile; qi::rule query; qi::rule alpha_numeral; qi::rule all_chars; qi::rule polyline_chars; }; } // anon. namespace osrm { namespace server { namespace api { boost::optional parseURL(std::string::iterator &iter, const std::string::iterator end) { using It = std::decay::type; static URLParser const parser; ParsedURL out; try { const auto ok = boost::spirit::qi::parse(iter, end, parser(boost::phoenix::val(iter)), out); if (ok && iter == end) return boost::make_optional(out); } catch (const qi::expectation_failure &failure) { // The grammar above using expectation parsers ">" does not automatically increment the // iterator to the failing position. Extract the position from the exception ourselves. iter = failure.first; } return boost::none; } } // api } // server } // osrm