From dac2f93383f2f6c43b1277181f68c77c663f28ea Mon Sep 17 00:00:00 2001 From: Michael Krasnyk Date: Wed, 20 Apr 2016 20:40:17 +0200 Subject: [PATCH] Refactoring of parameter garammars * signature changed from void() to void(engine::api::Parameters&) * performance increase due to use "static const GrammarT" and avoid construction and destruction of grammars during parsing * removed code duplication in inherited grammars * rule unlimited changed to qi::lit * added rule size_t_ * parser accepts "&geometries=" and "&overview=" and fails at "foo" instead of "&geometries=foo" and &overview=foo * added expectations checks for derived grammars * changed rules qi::list(".") to character rules '.' --- .../server/api/base_parameters_grammar.hpp | 128 +++++++++++------- .../server/api/match_parameter_grammar.hpp | 70 ++++------ .../server/api/nearest_parameter_grammar.hpp | 39 +++--- include/server/api/parameters_parser.hpp | 3 +- .../server/api/route_parameters_grammar.hpp | 104 +++++++------- .../server/api/table_parameter_grammar.hpp | 68 ++++++---- include/server/api/tile_parameter_grammar.hpp | 33 ++--- include/server/api/trip_parameter_grammar.hpp | 58 +++----- src/server/api/parameters_parser.cpp | 51 +++---- unit_tests/extractor/raster_source.cpp | 10 +- unit_tests/server/parameters_parser.cpp | 24 +++- 11 files changed, 298 insertions(+), 290 deletions(-) diff --git a/include/server/api/base_parameters_grammar.hpp b/include/server/api/base_parameters_grammar.hpp index 4d441a573..be7bdb916 100644 --- a/include/server/api/base_parameters_grammar.hpp +++ b/include/server/api/base_parameters_grammar.hpp @@ -8,7 +8,7 @@ #include "engine/polyline_compressor.hpp" #include -//#define BOOST_SPIRIT_DEBUG +#include #include #include @@ -21,7 +21,11 @@ namespace server namespace api { +namespace +{ +namespace ph = boost::phoenix; namespace qi = boost::spirit::qi; +} template struct no_trailing_dot_policy : qi::real_policies { @@ -63,76 +67,100 @@ template struct no_trailing_dot_policy : qi::real_poli } }; -struct BaseParametersGrammar : boost::spirit::qi::grammar +template +struct BaseParametersGrammar : boost::spirit::qi::grammar { - using Iterator = std::string::iterator; - using RadiusesT = std::vector>; using json_policy = no_trailing_dot_policy; - BaseParametersGrammar(qi::rule &root_rule_, engine::api::BaseParameters ¶meters_) - : BaseParametersGrammar::base_type(root_rule_), base_parameters(parameters_) + BaseParametersGrammar(qi::rule &root_rule) + : BaseParametersGrammar::base_type(root_rule) { - const auto add_bearing = - [this](boost::optional> bearing_range) { - boost::optional bearing; - if (bearing_range) - { - bearing = engine::Bearing{boost::fusion::at_c<0>(*bearing_range), - boost::fusion::at_c<1>(*bearing_range)}; - } - base_parameters.bearings.push_back(std::move(bearing)); - }; - const auto set_radiuses = [this](RadiusesT radiuses) { - base_parameters.radiuses = std::move(radiuses); - }; - const auto add_hint = [this](const std::string &hint_string) { + const auto add_hint = [](engine::api::BaseParameters &base_parameters, const std::string &hint_string) + { if (hint_string.size() > 0) { - base_parameters.hints.push_back(engine::Hint::FromBase64(hint_string)); + base_parameters.hints.emplace_back(engine::Hint::FromBase64(hint_string)); } }; - const auto add_coordinate = [this](const boost::fusion::vector &lonLat) { - base_parameters.coordinates.emplace_back(util::Coordinate( - util::FixedLongitude(boost::fusion::at_c<0>(lonLat) * COORDINATE_PRECISION), - util::FixedLatitude(boost::fusion::at_c<1>(lonLat) * COORDINATE_PRECISION))); - }; - const auto polyline_to_coordinates = [this](const std::string &polyline) { - base_parameters.coordinates = engine::decodePolyline(polyline); + + const auto add_bearing = [](engine::api::BaseParameters &base_parameters, + boost::optional> bearing_range) + { + boost::optional bearing; + if (bearing_range) + { + bearing = engine::Bearing{boost::fusion::at_c<0>(*bearing_range), + boost::fusion::at_c<1>(*bearing_range)}; + } + base_parameters.bearings.push_back(std::move(bearing)); }; - alpha_numeral = +qi::char_("a-zA-Z0-9"); polyline_chars = qi::char_("a-zA-Z0-9_.--[]{}@?|\\%~`^"); base64_char = qi::char_("a-zA-Z0-9--_="); + unlimited_rule = qi::lit("unlimited")[qi::_val = std::numeric_limits::infinity()]; - unlimited.add("unlimited", std::numeric_limits::infinity()); + bearing_rule + = (qi::short_ > ',' > qi::short_) + [qi::_val = ph::bind([](short bearing, short range) { + return osrm::engine::Bearing{bearing, range}; + }, qi::_1, qi::_2)] + ; - radiuses_rule = qi::lit("radiuses=") > -(unlimited | qi::double_) % ";"; - hints_rule = - qi::lit("hints=") > - qi::as_string[qi::repeat(engine::ENCODED_HINT_SIZE)[base64_char]][add_hint] % ";"; - bearings_rule = - qi::lit("bearings=") > (-(qi::short_ > ',' > qi::short_))[add_bearing] % ";"; - polyline_rule = qi::as_string[qi::lit("polyline(") > +polyline_chars > qi::lit(")")] - [polyline_to_coordinates]; - location_rule = (double_ > qi::lit(',') > double_)[add_coordinate]; - query_rule = (location_rule % ';') | polyline_rule; + location_rule + = (double_ > qi::lit(',') > double_) + [qi::_val = ph::bind([](double lon, double lat) { + return util::Coordinate(util::FixedLongitude(lon * COORDINATE_PRECISION), + util::FixedLatitude(lat * COORDINATE_PRECISION)); + }, qi::_1, qi::_2)] + ; - base_rule = bearings_rule | radiuses_rule[set_radiuses] | hints_rule; + polyline_rule + = qi::as_string[qi::lit("polyline(") > +polyline_chars > ')'] + [qi::_val = ph::bind([](const std::string &polyline) { + return engine::decodePolyline(polyline); + }, qi::_1)] + ; + + query_rule + = ((location_rule % ';') | polyline_rule) + [ph::bind(&engine::api::BaseParameters::coordinates, qi::_r1) = qi::_1] + ; + + radiuses_rule + = qi::lit("radiuses=") + > (-(qi::double_ | unlimited_rule) % ';') + [ph::bind(&engine::api::BaseParameters::radiuses, qi::_r1) = qi::_1] + ; + + hints_rule + = qi::lit("hints=") + > qi::as_string[qi::repeat(engine::ENCODED_HINT_SIZE)[base64_char]][ph::bind(add_hint, qi::_r1, qi::_1)] % ';' + ; + + bearings_rule + = qi::lit("bearings=") > + (-(qi::short_ > ',' > qi::short_))[ph::bind(add_bearing, qi::_r1, qi::_1)] % ';' + ; + + base_rule = radiuses_rule(qi::_r1) | hints_rule(qi::_r1) | bearings_rule(qi::_r1); } protected: - qi::rule base_rule; - qi::rule query_rule; + qi::rule base_rule; + qi::rule query_rule; private: - engine::api::BaseParameters &base_parameters; - qi::rule bearings_rule; - qi::rule hints_rule; - qi::rule polyline_rule, location_rule; - qi::symbols unlimited; - qi::rule radiuses_rule; + qi::rule bearings_rule; + qi::rule radiuses_rule; + qi::rule hints_rule; + + qi::rule bearing_rule; + qi::rule location_rule; + qi::rule()> polyline_rule; + qi::rule base64_char; - qi::rule alpha_numeral, polyline_chars; + qi::rule polyline_chars; + qi::rule unlimited_rule; qi::real_parser double_; }; } diff --git a/include/server/api/match_parameter_grammar.hpp b/include/server/api/match_parameter_grammar.hpp index 6671a58b6..a775e49d8 100644 --- a/include/server/api/match_parameter_grammar.hpp +++ b/include/server/api/match_parameter_grammar.hpp @@ -2,9 +2,9 @@ #define MATCH_PARAMETERS_GRAMMAR_HPP #include "engine/api/match_parameters.hpp" -#include "server/api/base_parameters_grammar.hpp" +#include "server/api/route_parameters_grammar.hpp" -//#define BOOST_SPIRIT_DEBUG +#include #include namespace osrm @@ -14,58 +14,34 @@ namespace server namespace api { -namespace qi = boost::spirit::qi; - -struct MatchParametersGrammar final : public BaseParametersGrammar +namespace { - using Iterator = std::string::iterator; - using StepsT = bool; - using TimestampsT = std::vector; - using GeometriesT = engine::api::RouteParameters::GeometriesType; - using OverviewT = engine::api::RouteParameters::OverviewType; +namespace ph = boost::phoenix; +namespace qi = boost::spirit::qi; +} - MatchParametersGrammar() : BaseParametersGrammar(root_rule, parameters) +template +struct MatchParametersGrammar final : public RouteParametersGrammar +{ + using BaseGrammar = RouteParametersGrammar; + + MatchParametersGrammar() : BaseGrammar(root_rule) { - const auto set_geojson_type = [this] { - parameters.geometries = engine::api::RouteParameters::GeometriesType::GeoJSON; - }; - const auto set_polyline_type = [this] { - parameters.geometries = engine::api::RouteParameters::GeometriesType::Polyline; - }; + timestamps_rule + = qi::lit("timestamps=") + > (qi::uint_ % ';')[ph::bind(&engine::api::MatchParameters::timestamps, qi::_r1) = qi::_1] + ; - const auto set_simplified_type = [this] { - parameters.overview = engine::api::RouteParameters::OverviewType::Simplified; - }; - const auto set_full_type = [this] { - parameters.overview = engine::api::RouteParameters::OverviewType::Full; - }; - const auto set_false_type = [this] { - parameters.overview = engine::api::RouteParameters::OverviewType::False; - }; - const auto set_steps = [this](const StepsT steps) { parameters.steps = steps; }; - const auto set_timestamps = [this](TimestampsT timestamps) { - parameters.timestamps = std::move(timestamps); - }; - - steps_rule = qi::lit("steps=") > qi::bool_; - geometries_rule = qi::lit("geometries=geojson")[set_geojson_type] | - qi::lit("geometries=polyline")[set_polyline_type]; - overview_rule = qi::lit("overview=simplified")[set_simplified_type] | - qi::lit("overview=full")[set_full_type] | - qi::lit("overview=false")[set_false_type]; - timestamps_rule = qi::lit("timestamps=") > qi::uint_ % ";"; - match_rule = steps_rule[set_steps] | geometries_rule | overview_rule | - timestamps_rule[set_timestamps]; - root_rule = - query_rule > -qi::lit(".json") > -(qi::lit("?") > (match_rule | base_rule) % '&'); + root_rule + = BaseGrammar::query_rule(qi::_r1) > -qi::lit(".json") + > -('?' > (timestamps_rule(qi::_r1) | BaseGrammar::base_rule(qi::_r1)) % '&') + ; } - engine::api::MatchParameters parameters; - private: - qi::rule root_rule, match_rule, geometries_rule, overview_rule; - qi::rule timestamps_rule; - qi::rule steps_rule; + qi::rule root_rule; + qi::rule timestamps_rule; }; } } diff --git a/include/server/api/nearest_parameter_grammar.hpp b/include/server/api/nearest_parameter_grammar.hpp index 09b6c2ab5..b9bc21b23 100644 --- a/include/server/api/nearest_parameter_grammar.hpp +++ b/include/server/api/nearest_parameter_grammar.hpp @@ -4,7 +4,7 @@ #include "engine/api/nearest_parameters.hpp" #include "server/api/base_parameters_grammar.hpp" -//#define BOOST_SPIRIT_DEBUG +#include #include namespace osrm @@ -14,27 +14,34 @@ namespace server namespace api { -namespace qi = boost::spirit::qi; - -struct NearestParametersGrammar final : public BaseParametersGrammar +namespace { - using Iterator = std::string::iterator; +namespace ph = boost::phoenix; +namespace qi = boost::spirit::qi; +} - NearestParametersGrammar() : BaseParametersGrammar(root_rule, parameters) +template +struct NearestParametersGrammar final : public BaseParametersGrammar +{ + using BaseGrammar = BaseParametersGrammar; + + NearestParametersGrammar() : BaseGrammar(root_rule) { - const auto set_number = [this](const unsigned number) { - parameters.number_of_results = number; - }; - nearest_rule = (qi::lit("number=") > qi::uint_)[set_number]; - root_rule = - query_rule > -qi::lit(".json") > -(qi::lit("?") > (nearest_rule | base_rule) % '&'); + nearest_rule + = (qi::lit("number=") > qi::uint_) + [ph::bind(&engine::api::NearestParameters::number_of_results, qi::_r1) = qi::_1] + ; + + root_rule + = BaseGrammar::query_rule(qi::_r1) > -qi::lit(".json") + > -('?' > (nearest_rule(qi::_r1) | BaseGrammar::base_rule(qi::_r1)) % '&') + ; } - engine::api::NearestParameters parameters; - private: - qi::rule root_rule; - qi::rule nearest_rule; + qi::rule root_rule; + qi::rule nearest_rule; }; } } diff --git a/include/server/api/parameters_parser.hpp b/include/server/api/parameters_parser.hpp index 161910dbe..08083edb5 100644 --- a/include/server/api/parameters_parser.hpp +++ b/include/server/api/parameters_parser.hpp @@ -30,7 +30,8 @@ using is_parameter_t = // Starts parsing and iter and modifies it until iter == end or parsing failed template ::value, int>::type = 0> -boost::optional parseParameters(std::string::iterator &iter, const std::string::iterator end); +boost::optional parseParameters(std::string::iterator &iter, + const std::string::iterator end); // Copy on purpose because we need mutability template #include namespace osrm @@ -14,64 +14,66 @@ namespace server namespace api { -namespace qi = boost::spirit::qi; - -struct RouteParametersGrammar : public BaseParametersGrammar +namespace { - using Iterator = std::string::iterator; - using StepsT = bool; - using AlternativeT = bool; - using GeometriesT = engine::api::RouteParameters::GeometriesType; - using OverviewT = engine::api::RouteParameters::OverviewType; - using UturnsT = bool; +namespace ph = boost::phoenix; +namespace qi = boost::spirit::qi; +} - RouteParametersGrammar() : BaseParametersGrammar(root_rule, parameters) +template +struct RouteParametersGrammar : public BaseParametersGrammar +{ + using BaseGrammar = BaseParametersGrammar; + + RouteParametersGrammar() : RouteParametersGrammar(root_rule) { - const auto set_geojson_type = [this] { - parameters.geometries = engine::api::RouteParameters::GeometriesType::GeoJSON; - }; - const auto set_polyline_type = [this] { - parameters.geometries = engine::api::RouteParameters::GeometriesType::Polyline; - }; + route_rule + = (qi::lit("alternatives=") > qi::bool_[ph::bind(&engine::api::RouteParameters::alternatives, qi::_r1) = qi::_1]) + | (qi::lit("continue_straight=") + > (qi::lit("default") + | qi::bool_[ph::bind(&engine::api::RouteParameters::continue_straight, qi::_r1) = qi::_1])) + ; - const auto set_simplified_type = [this] { - parameters.overview = engine::api::RouteParameters::OverviewType::Simplified; - }; - const auto set_full_type = [this] { - parameters.overview = engine::api::RouteParameters::OverviewType::Full; - }; - const auto set_false_type = [this] { - parameters.overview = engine::api::RouteParameters::OverviewType::False; - }; - const auto set_steps = [this](const StepsT steps) { parameters.steps = steps; }; - const auto set_alternatives = [this](const AlternativeT alternatives) { - parameters.alternatives = alternatives; - }; - const auto set_continue_straight = [this](UturnsT continue_straight) { parameters.continue_straight = std::move(continue_straight); }; - - alternatives_rule = qi::lit("alternatives=") > qi::bool_; - steps_rule = qi::lit("steps=") > qi::bool_; - geometries_rule = qi::lit("geometries=geojson")[set_geojson_type] | - qi::lit("geometries=polyline")[set_polyline_type]; - overview_rule = qi::lit("overview=simplified")[set_simplified_type] | - qi::lit("overview=full")[set_full_type] | - qi::lit("overview=false")[set_false_type]; - continue_straight_rule = qi::lit("continue_straight=default") | (qi::lit("continue_straight=") > qi::bool_)[set_continue_straight]; - route_rule = steps_rule[set_steps] | alternatives_rule[set_alternatives] | geometries_rule | - overview_rule | continue_straight_rule; - - root_rule = - query_rule > -qi::lit(".json") > -(qi::lit("?") > (route_rule | base_rule) % '&'); + root_rule + = query_rule(qi::_r1) > -qi::lit(".json") + > -('?' > (route_rule(qi::_r1) | base_rule(qi::_r1)) % '&') + ; } - engine::api::RouteParameters parameters; + RouteParametersGrammar(qi::rule &root_rule_) : BaseGrammar(root_rule_) + { + geometries_type.add + ("geojson", engine::api::RouteParameters::GeometriesType::GeoJSON) + ("polyline", engine::api::RouteParameters::GeometriesType::Polyline) + ; + + overview_type.add + ("simplified", engine::api::RouteParameters::OverviewType::Simplified) + ("full", engine::api::RouteParameters::OverviewType::Full) + ("false", engine::api::RouteParameters::OverviewType::False) + ; + + base_rule = + BaseGrammar::base_rule(qi::_r1) + | (qi::lit("steps=") > qi::bool_[ph::bind(&engine::api::RouteParameters::steps, qi::_r1) = qi::_1]) + | (qi::lit("geometries=") > geometries_type[ph::bind(&engine::api::RouteParameters::geometries, qi::_r1) = qi::_1]) + | (qi::lit("overview=") > overview_type[ph::bind(&engine::api::RouteParameters::overview, qi::_r1) = qi::_1]) + ; + + query_rule = BaseGrammar::query_rule(qi::_r1); + } + + protected: + qi::rule base_rule; + qi::rule query_rule; private: - qi::rule root_rule; - qi::rule route_rule, geometries_rule, overview_rule; - qi::rule continue_straight_rule; - qi::rule steps_rule; - qi::rule alternatives_rule; + qi::rule root_rule; + qi::rule route_rule; + + qi::symbols geometries_type; + qi::symbols overview_type; }; } } diff --git a/include/server/api/table_parameter_grammar.hpp b/include/server/api/table_parameter_grammar.hpp index b95b1b8c5..73ff3c6e9 100644 --- a/include/server/api/table_parameter_grammar.hpp +++ b/include/server/api/table_parameter_grammar.hpp @@ -4,7 +4,7 @@ #include "engine/api/table_parameters.hpp" #include "server/api/base_parameters_grammar.hpp" -//#define BOOST_SPIRIT_DEBUG +#include #include namespace osrm @@ -14,43 +14,53 @@ namespace server namespace api { -namespace qi = boost::spirit::qi; - -struct TableParametersGrammar final : public BaseParametersGrammar +namespace { - using Iterator = std::string::iterator; - using SourcesT = std::vector; - using DestinationsT = std::vector; +namespace ph = boost::phoenix; +namespace qi = boost::spirit::qi; +} - TableParametersGrammar() : BaseParametersGrammar(root_rule, parameters) +template +struct TableParametersGrammar final : public BaseParametersGrammar +{ + using BaseGrammar = BaseParametersGrammar; + + TableParametersGrammar() : BaseGrammar(root_rule) { - const auto set_destiantions = [this](DestinationsT dests) { - parameters.destinations = std::move(dests); - }; - const auto set_sources = [this](SourcesT sources) { - parameters.sources = std::move(sources); - }; -// TODO: ulonglong -> size_t not only on Windows but on all 32 bit platforms; unsupported anyway as of now -#ifdef WIN32 - destinations_rule = qi::lit("destinations=all") | (qi::lit("destinations=") > (qi::ulong_long % ";")[set_destiantions]); - sources_rule = qi::lit("sources=all") | (qi::lit("sources=") > (qi::ulong_long % ";")[set_sources]); +#ifdef BOOST_HAS_LONG_LONG + if (std::is_same::value) + size_t_ = qi::ulong_long; + else + size_t_ = qi::ulong_; #else - destinations_rule = qi::lit("destinations=all") | (qi::lit("destinations=") > (qi::ulong_ % ";")[set_destiantions]); - sources_rule = qi::lit("sources=all") | (qi::lit("sources=") > (qi::ulong_ % ";")[set_sources]); + size_t_ = qi::ulong_; #endif - table_rule = destinations_rule | sources_rule; - root_rule = - query_rule > -qi::lit(".json") > -(qi::lit("?") > (table_rule | base_rule) % '&'); + destinations_rule + = qi::lit("destinations=") + > (qi::lit("all") | (size_t_ % ';')[ph::bind(&engine::api::TableParameters::destinations, qi::_r1) = qi::_1]) + ; + + sources_rule + = qi::lit("sources=") + > (qi::lit("all") | (size_t_ % ';')[ph::bind(&engine::api::TableParameters::sources, qi::_r1) = qi::_1]) + ; + + table_rule = destinations_rule(qi::_r1) | sources_rule(qi::_r1); + + root_rule + = BaseGrammar::query_rule(qi::_r1) > -qi::lit(".json") + > -('?' > (table_rule(qi::_r1) | BaseGrammar::base_rule(qi::_r1)) % '&') + ; } - engine::api::TableParameters parameters; - private: - qi::rule root_rule; - qi::rule table_rule; - qi::rule sources_rule; - qi::rule destinations_rule; + qi::rule root_rule; + qi::rule table_rule; + qi::rule sources_rule; + qi::rule destinations_rule; + qi::rule size_t_; }; } } diff --git a/include/server/api/tile_parameter_grammar.hpp b/include/server/api/tile_parameter_grammar.hpp index ef73357b9..f0d79b655 100644 --- a/include/server/api/tile_parameter_grammar.hpp +++ b/include/server/api/tile_parameter_grammar.hpp @@ -6,7 +6,7 @@ #include "engine/hint.hpp" #include "engine/polyline_compressor.hpp" -//#define BOOST_SPIRIT_DEBUG +#include #include #include @@ -18,28 +18,29 @@ namespace server namespace api { -namespace qi = boost::spirit::qi; -struct TileParametersGrammar final : boost::spirit::qi::grammar +namespace { - using Iterator = std::string::iterator; +namespace ph = boost::phoenix; +namespace qi = boost::spirit::qi; +} +template +struct TileParametersGrammar final : boost::spirit::qi::grammar +{ TileParametersGrammar() : TileParametersGrammar::base_type(root_rule) { - const auto set_x = [this](const unsigned x_) { parameters.x = x_; }; - const auto set_y = [this](const unsigned y_) { parameters.y = y_; }; - const auto set_z = [this](const unsigned z_) { parameters.z = z_; }; - - query_rule = qi::lit("tile(") > qi::uint_[set_x] // - > qi::lit(",") > qi::uint_[set_y] > // - qi::lit(",") > qi::uint_[set_z] > qi::lit(")"); // - - root_rule = query_rule > qi::lit(".mvt"); + root_rule + = qi::lit("tile(") + > qi::uint_[ph::bind(&engine::api::TileParameters::x, qi::_r1) = qi::_1] > ',' + > qi::uint_[ph::bind(&engine::api::TileParameters::y, qi::_r1) = qi::_1] > ',' + > qi::uint_[ph::bind(&engine::api::TileParameters::z, qi::_r1) = qi::_1] + > qi::lit(").mvt") + ; } - engine::api::TileParameters parameters; private: - qi::rule root_rule; - qi::rule query_rule; + qi::rule root_rule; }; } } diff --git a/include/server/api/trip_parameter_grammar.hpp b/include/server/api/trip_parameter_grammar.hpp index 52c66223a..b9a7ee04a 100644 --- a/include/server/api/trip_parameter_grammar.hpp +++ b/include/server/api/trip_parameter_grammar.hpp @@ -2,9 +2,8 @@ #define TRIP_PARAMETERS_GRAMMAR_HPP #include "engine/api/trip_parameters.hpp" -#include "server/api/base_parameters_grammar.hpp" +#include "server/api/route_parameters_grammar.hpp" -//#define BOOST_SPIRIT_DEBUG #include namespace osrm @@ -14,52 +13,27 @@ namespace server namespace api { -namespace qi = boost::spirit::qi; - -struct TripParametersGrammar final : public BaseParametersGrammar +namespace { - using Iterator = std::string::iterator; - using StepsT = bool; - using GeometriesT = engine::api::RouteParameters::GeometriesType; - using OverviewT = engine::api::RouteParameters::OverviewType; +namespace qi = boost::spirit::qi; +} - TripParametersGrammar() : BaseParametersGrammar(root_rule, parameters) +template +struct TripParametersGrammar final : public RouteParametersGrammar +{ + using BaseGrammar = RouteParametersGrammar; + + TripParametersGrammar() : BaseGrammar(root_rule) { - const auto set_geojson_type = [this] { - parameters.geometries = engine::api::RouteParameters::GeometriesType::GeoJSON; - }; - const auto set_polyline_type = [this] { - parameters.geometries = engine::api::RouteParameters::GeometriesType::Polyline; - }; - - const auto set_simplified_type = [this] { - parameters.overview = engine::api::RouteParameters::OverviewType::Simplified; - }; - const auto set_full_type = [this] { - parameters.overview = engine::api::RouteParameters::OverviewType::Full; - }; - const auto set_false_type = [this] { - parameters.overview = engine::api::RouteParameters::OverviewType::False; - }; - const auto set_steps = [this](const StepsT steps) { parameters.steps = steps; }; - - steps_rule = qi::lit("steps=") > qi::bool_; - geometries_rule = qi::lit("geometries=geojson")[set_geojson_type] | - qi::lit("geometries=polyline")[set_polyline_type]; - overview_rule = qi::lit("overview=simplified")[set_simplified_type] | - qi::lit("overview=full")[set_full_type] | - qi::lit("overview=false")[set_false_type]; - trip_rule = steps_rule[set_steps] | geometries_rule | overview_rule; - - root_rule = - query_rule > -qi::lit(".json") > -(qi::lit("?") > (trip_rule | base_rule) % '&'); + root_rule + = BaseGrammar::query_rule(qi::_r1) > -qi::lit(".json") + > -('?' > (BaseGrammar::base_rule(qi::_r1)) % '&') + ; } - engine::api::TripParameters parameters; - private: - qi::rule root_rule, trip_rule, geometries_rule, overview_rule; - qi::rule steps_rule; + qi::rule root_rule; }; } } diff --git a/src/server/api/parameters_parser.cpp b/src/server/api/parameters_parser.cpp index 1d4485a03..d4a530f4d 100644 --- a/src/server/api/parameters_parser.cpp +++ b/src/server/api/parameters_parser.cpp @@ -19,28 +19,28 @@ namespace api namespace detail { template -using is_grammar_t = std::integral_constant::value || - std::is_same::value>; +using is_grammar_t = std::integral_constant, T>::value || + std::is_same, T>::value || std::is_same, T>::value || + std::is_same, T>::value || std::is_same, T>::value || + std::is_same, T>::value>; -template ::value, int>::type = 0, typename std::enable_if::value, int>::type = 0> -boost::optional parseParameters(std::string::iterator &iter, - const std::string::iterator end) +boost::optional parseParameters(std::string::iterator &iter, const std::string::iterator end) { using It = std::decay::type; - GrammarT grammar; + static const GrammarT grammar; try { - const auto ok = boost::spirit::qi::parse(iter, end, grammar); + ParameterT parameters; + const auto ok = boost::spirit::qi::parse(iter, end, grammar(boost::phoenix::ref(parameters))); // return move(a.b) is needed to move b out of a and then return the rvalue by implicit move if (ok && iter == end) - return std::move(grammar.parameters); + return std::move(parameters); } catch (const qi::expectation_failure &failure) { @@ -54,46 +54,39 @@ boost::optional parseParameters(std::string::iterator &iter, } // ns detail template <> -boost::optional parseParameters(std::string::iterator &iter, - const std::string::iterator end) +boost::optional parseParameters(std::string::iterator &iter, const std::string::iterator end) { - return detail::parseParameters(iter, end); + return detail::parseParameters>(iter, end); } template <> -boost::optional parseParameters(std::string::iterator &iter, - const std::string::iterator end) +boost::optional parseParameters(std::string::iterator &iter, const std::string::iterator end) { - return detail::parseParameters(iter, end); + return detail::parseParameters>(iter, end); } template <> -boost::optional parseParameters(std::string::iterator &iter, - const std::string::iterator end) +boost::optional parseParameters(std::string::iterator &iter, const std::string::iterator end) { - return detail::parseParameters(iter, - end); + return detail::parseParameters>(iter, end); } template <> -boost::optional parseParameters(std::string::iterator &iter, - const std::string::iterator end) +boost::optional parseParameters(std::string::iterator &iter, const std::string::iterator end) { - return detail::parseParameters(iter, end); + return detail::parseParameters>(iter, end); } template <> -boost::optional parseParameters(std::string::iterator &iter, - const std::string::iterator end) +boost::optional parseParameters(std::string::iterator &iter, const std::string::iterator end) { - return detail::parseParameters(iter, end); + return detail::parseParameters>(iter, end); } template <> -boost::optional parseParameters(std::string::iterator &iter, - const std::string::iterator end) +boost::optional parseParameters(std::string::iterator &iter, const std::string::iterator end) { - return detail::parseParameters(iter, end); + return detail::parseParameters>(iter, end); } } // ns api diff --git a/unit_tests/extractor/raster_source.cpp b/unit_tests/extractor/raster_source.cpp index 1c66f12d3..c2f1b1b10 100644 --- a/unit_tests/extractor/raster_source.cpp +++ b/unit_tests/extractor/raster_source.cpp @@ -1,6 +1,6 @@ #include "extractor/raster_source.hpp" -#include "util/typedefs.hpp" #include "util/exception.hpp" +#include "util/typedefs.hpp" #include @@ -15,14 +15,10 @@ using namespace osrm::extractor; int normalize(double coord) { return static_cast(coord * COORDINATE_PRECISION); } #define CHECK_QUERY(source_id, lon, lat, expected) \ - BOOST_CHECK_EQUAL( \ - sources.getRasterDataFromSource(source_id, lon, lat).datum, \ - expected) + BOOST_CHECK_EQUAL(sources.getRasterDataFromSource(source_id, lon, lat).datum, expected) #define CHECK_INTERPOLATE(source_id, lon, lat, expected) \ - BOOST_CHECK_EQUAL( \ - sources.getRasterInterpolateFromSource(source_id, lon, lat).datum, \ - expected) + BOOST_CHECK_EQUAL(sources.getRasterInterpolateFromSource(source_id, lon, lat).datum, expected) BOOST_AUTO_TEST_CASE(raster_test) { diff --git a/unit_tests/server/parameters_parser.cpp b/unit_tests/server/parameters_parser.cpp index ecf98f205..04b08733f 100644 --- a/unit_tests/server/parameters_parser.cpp +++ b/unit_tests/server/parameters_parser.cpp @@ -45,9 +45,9 @@ BOOST_AUTO_TEST_CASE(invalid_route_urls) BOOST_CHECK_EQUAL(testInvalidOptions("1,2;3,4?overview=false&hints=foo"), 29UL); BOOST_CHECK_EQUAL(testInvalidOptions("1,2;3,4?overview=false&geometries=foo"), - 22UL); + 34UL); BOOST_CHECK_EQUAL(testInvalidOptions("1,2;3,4?overview=false&overview=foo"), - 22L); + 32L); BOOST_CHECK_EQUAL( testInvalidOptions("1,2;3,4?overview=false&alternatives=foo"), 36UL); BOOST_CHECK_EQUAL(testInvalidOptions(""), 0); @@ -273,6 +273,16 @@ BOOST_AUTO_TEST_CASE(valid_match_urls) CHECK_EQUAL_RANGE(reference_1.bearings, result_1->bearings); CHECK_EQUAL_RANGE(reference_1.radiuses, result_1->radiuses); CHECK_EQUAL_RANGE(reference_1.coordinates, result_1->coordinates); + + MatchParameters reference_2{}; + reference_2.coordinates = coords_1; + reference_2.timestamps = {5, 6}; + auto result_2 = parseParameters("1,2;3,4?timestamps=5;6"); + BOOST_CHECK(result_2); + CHECK_EQUAL_RANGE(reference_2.timestamps, result_2->timestamps); + CHECK_EQUAL_RANGE(reference_2.bearings, result_2->bearings); + CHECK_EQUAL_RANGE(reference_2.radiuses, result_2->radiuses); + CHECK_EQUAL_RANGE(reference_2.coordinates, result_2->coordinates); } BOOST_AUTO_TEST_CASE(valid_nearest_urls) @@ -287,6 +297,16 @@ BOOST_AUTO_TEST_CASE(valid_nearest_urls) CHECK_EQUAL_RANGE(reference_1.bearings, result_1->bearings); CHECK_EQUAL_RANGE(reference_1.radiuses, result_1->radiuses); CHECK_EQUAL_RANGE(reference_1.coordinates, result_1->coordinates); + + NearestParameters reference_2{}; + reference_2.coordinates = coords_1; + reference_2.number_of_results = 42; + auto result_2 = parseParameters("1,2?number=42"); + BOOST_CHECK(result_2); + BOOST_CHECK_EQUAL(reference_2.number_of_results, result_2->number_of_results); + CHECK_EQUAL_RANGE(reference_2.bearings, result_2->bearings); + CHECK_EQUAL_RANGE(reference_2.radiuses, result_2->radiuses); + CHECK_EQUAL_RANGE(reference_2.coordinates, result_2->coordinates); } BOOST_AUTO_TEST_CASE(valid_tile_urls)