diff --git a/include/engine/api/table_parameters.hpp b/include/engine/api/table_parameters.hpp index 395e506f3..2b748f3b9 100644 --- a/include/engine/api/table_parameters.hpp +++ b/include/engine/api/table_parameters.hpp @@ -21,6 +21,16 @@ struct TableParameters : public BaseParameters std::vector sources; std::vector destinations; + TableParameters() = default; + template + TableParameters(std::vector sources_, + std::vector destinations_, + Args... args_) + : BaseParameters{std::forward(args_)...}, sources{std::move(sources_)}, + destinations{std::move(destinations_)} + { + } + bool IsValid() const { if (!BaseParameters::IsValid()) diff --git a/include/server/api/parameters_parser.hpp b/include/server/api/parameters_parser.hpp new file mode 100644 index 000000000..751235555 --- /dev/null +++ b/include/server/api/parameters_parser.hpp @@ -0,0 +1,35 @@ +#ifndef SERVER_API_ROUTE_PARAMETERS_PARSER_HPP +#define SERVER_API_ROUTE_PARAMETERS_PARSER_HPP + +#include "engine/api/route_parameters.hpp" +#include "engine/api/table_parameters.hpp" + +namespace osrm +{ +namespace server +{ +namespace api +{ + +// Starts parsing and iter and modifies it until iter == end or parsing failed +template +boost::optional parseParameters(std::string::iterator& iter, std::string::iterator end); + +// copy on purpose because we need mutability +template +inline boost::optional parseParameters(std::string options_string) +{ + auto iter = options_string.begin(); + return parseParameters(iter, options_string.end()); +} + +template<> +boost::optional parseParameters(std::string::iterator& iter, std::string::iterator end); +template<> +boost::optional parseParameters(std::string::iterator& iter, std::string::iterator end); + +} +} +} + +#endif diff --git a/include/server/api/route_parameters_grammar.hpp b/include/server/api/route_parameters_grammar.hpp index 8a0313960..321609fc1 100644 --- a/include/server/api/route_parameters_grammar.hpp +++ b/include/server/api/route_parameters_grammar.hpp @@ -29,40 +29,40 @@ struct RouteParametersGrammar : public BaseParametersGrammar using UturnsT = std::vector>; RouteParametersGrammar() - : BaseParametersGrammar(root_rule, route_parameters) + : BaseParametersGrammar(root_rule, parameters) { const auto set_geojson_type = [this]() { - route_parameters.geometries = engine::api::RouteParameters::GeometriesType::GeoJSON; + parameters.geometries = engine::api::RouteParameters::GeometriesType::GeoJSON; }; const auto set_polyline_type = [this]() { - route_parameters.geometries = engine::api::RouteParameters::GeometriesType::Polyline; + parameters.geometries = engine::api::RouteParameters::GeometriesType::Polyline; }; const auto set_simplified_type = [this]() { - route_parameters.overview = engine::api::RouteParameters::OverviewType::Simplified; + parameters.overview = engine::api::RouteParameters::OverviewType::Simplified; }; const auto set_full_type = [this]() { - route_parameters.overview = engine::api::RouteParameters::OverviewType::Full; + parameters.overview = engine::api::RouteParameters::OverviewType::Full; }; const auto set_false_type = [this]() { - route_parameters.overview = engine::api::RouteParameters::OverviewType::False; + parameters.overview = engine::api::RouteParameters::OverviewType::False; }; const auto set_steps = [this](const StepsT steps) { - route_parameters.steps = steps; + parameters.steps = steps; }; const auto set_alternative = [this](const AlternativeT alternative) { - route_parameters.alternative = alternative; + parameters.alternative = alternative; }; const auto set_uturns = [this](UturnsT &uturns) { - route_parameters.uturns = std::move(uturns); + parameters.uturns = std::move(uturns); }; alternative_rule = qi::lit("alternative=") >> qi::bool_; @@ -78,7 +78,7 @@ struct RouteParametersGrammar : public BaseParametersGrammar root_rule = -((base_rule | route_rule) % '&'); } - engine::api::RouteParameters route_parameters; + engine::api::RouteParameters parameters; private: qi::rule root_rule, route_rule, geometries_rule, overview_rule; qi::rule uturns_rule; diff --git a/include/server/api/route_parameters_parser.hpp b/include/server/api/route_parameters_parser.hpp deleted file mode 100644 index 467c3e345..000000000 --- a/include/server/api/route_parameters_parser.hpp +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SERVER_API_ROUTE_PARAMETERS_PARSER_HPP -#define SERVER_API_ROUTE_PARAMETERS_PARSER_HPP - -#include "engine/api/route_parameters.hpp" -#include "server/api/route_parameters_parser.hpp" - -namespace osrm -{ -namespace server -{ -namespace api -{ - -// Starts parsing and iter and modifies it until iter == end or parsing failed -boost::optional parseRouteParameters(std::string::iterator& iter, std::string::iterator end); - -// copy on purpose because we need mutability -inline boost::optional parseRouteParameters(std::string options_string) -{ - auto iter = options_string.begin(); - return parseRouteParameters(iter, options_string.end()); -} - -} -} -} - -#endif diff --git a/include/server/api/table_parameter_grammar.hpp b/include/server/api/table_parameter_grammar.hpp new file mode 100644 index 000000000..80ee43bbb --- /dev/null +++ b/include/server/api/table_parameter_grammar.hpp @@ -0,0 +1,55 @@ +#ifndef TABLE_PARAMETERS_GRAMMAR_HPP +#define TABLE_PARAMETERS_GRAMMAR_HPP + +#include "engine/api/table_parameters.hpp" + +#include "server/api/base_parameters_grammar.hpp" + +#include +#include +#include +#include +#include + +namespace osrm +{ +namespace server +{ +namespace api +{ + +namespace qi = boost::spirit::qi; +struct TableParametersGrammar : public BaseParametersGrammar +{ + using Iterator = std::string::iterator; + using SourcesT = std::vector; + using DestinationsT = std::vector; + + TableParametersGrammar() : BaseParametersGrammar(root_rule, parameters) + { + const auto set_destiantions = [this](DestinationsT &dests) + { + parameters.destinations = std::move(dests); + }; + const auto set_sources = [this](SourcesT &sources) + { + parameters.sources = std::move(sources); + }; + destinations_rule = qi::lit("destinations=") >> -qi::uint_ % ";"; + sources_rule = qi::lit("sources=") >> -qi::uint_ % ";"; + table_rule = destinations_rule[set_destiantions] | sources_rule[set_sources]; + root_rule = -((base_rule | table_rule) % '&'); + } + + engine::api::TableParameters parameters; + + private: + qi::rule root_rule, table_rule; + qi::rule sources_rule; + qi::rule destinations_rule; +}; +} +} +} + +#endif diff --git a/include/server/request_handler.hpp b/include/server/request_handler.hpp index a02736188..d76ba6dac 100644 --- a/include/server/request_handler.hpp +++ b/include/server/request_handler.hpp @@ -20,7 +20,7 @@ class RequestHandler { public: - RequestHandler(); + RequestHandler() = default; RequestHandler(const RequestHandler &) = delete; RequestHandler &operator=(const RequestHandler &) = delete; diff --git a/src/server/api/parameters_parser.cpp b/src/server/api/parameters_parser.cpp new file mode 100644 index 000000000..33eb8c7d7 --- /dev/null +++ b/src/server/api/parameters_parser.cpp @@ -0,0 +1,46 @@ +#include "server/api/parameters_parser.hpp" + +#include "server/api/route_parameters_grammar.hpp" +#include "server/api/table_parameter_grammar.hpp" + +namespace osrm +{ +namespace server +{ +namespace api +{ + +template<> +boost::optional parseParameters(std::string::iterator& iter, std::string::iterator end) +{ + RouteParametersGrammar grammar; + const auto result = boost::spirit::qi::parse(iter, end, grammar); + + boost::optional parameters; + if (result && iter == end) + { + parameters = std::move(grammar.parameters); + } + + return parameters; +} + +template<> +boost::optional parseParameters(std::string::iterator& iter, std::string::iterator end) +{ + TableParametersGrammar grammar; + const auto result = boost::spirit::qi::parse(iter, end, grammar); + + boost::optional parameters; + if (result && iter == end) + { + parameters = std::move(grammar.parameters); + } + + return parameters; +} + +} +} +} + diff --git a/src/server/api/route_parameters_parser.cpp b/src/server/api/route_parameters_parser.cpp deleted file mode 100644 index 1a0ff2075..000000000 --- a/src/server/api/route_parameters_parser.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#include "server/api/route_parameters_parser.hpp" -#include "server/api/route_parameters_grammar.hpp" - -namespace osrm -{ -namespace server -{ -namespace api -{ - -boost::optional parseRouteParameters(std::string::iterator& iter, std::string::iterator end) -{ - RouteParametersGrammar grammar; - const auto result = boost::spirit::qi::parse(iter, end, grammar); - - boost::optional parameters; - if (result && iter == end) - { - parameters = std::move(grammar.route_parameters); - } - - return parameters; -} - -} -} -} - diff --git a/src/server/service/route_service.cpp b/src/server/service/route_service.cpp index dd72daa62..21c11d341 100644 --- a/src/server/service/route_service.cpp +++ b/src/server/service/route_service.cpp @@ -1,7 +1,7 @@ #include "server/service/route_service.hpp" #include "engine/api/route_parameters.hpp" -#include "server/api/route_parameters_parser.hpp" +#include "server/api/parameters_parser.hpp" #include "util/json_container.hpp" @@ -55,7 +55,7 @@ engine::Status RouteService::RunQuery(std::vector co { auto options_iterator = options.begin(); - auto parameters = api::parseRouteParameters(options_iterator, options.end()); + auto parameters = api::parseParameters(options_iterator, options.end()); if (!parameters || options_iterator != options.end()) { const auto position = std::distance(options.begin(), options_iterator); diff --git a/unit_tests/server/route_parameters_parser.cpp b/unit_tests/server/parameters_parser.cpp similarity index 57% rename from unit_tests/server/route_parameters_parser.cpp rename to unit_tests/server/parameters_parser.cpp index 339d7d796..2648bb7c6 100644 --- a/unit_tests/server/route_parameters_parser.cpp +++ b/unit_tests/server/parameters_parser.cpp @@ -1,4 +1,4 @@ -#include "server/api/route_parameters_parser.hpp" +#include "server/api/parameters_parser.hpp" #include @@ -57,36 +57,53 @@ std::ostream &operator<<(std::ostream &out, api::RouteParameters::Bearing bearin #define CHECK_EQUAL_RANGE(R1, R2) \ BOOST_CHECK_EQUAL_COLLECTIONS(R1.begin(), R1.end(), R2.begin(), R2.end()); -BOOST_AUTO_TEST_SUITE(api_route_parameters_parser) +BOOST_AUTO_TEST_SUITE(api_parameters_parser) using namespace osrm; using namespace osrm::server; // returns distance to front -std::size_t testInvalidOptions(std::string options) +template std::size_t testInvalidOptions(std::string options) { auto iter = options.begin(); - auto result = api::parseRouteParameters(iter, options.end()); + auto result = api::parseParameters(iter, options.end()); BOOST_CHECK(!result); return std::distance(options.begin(), iter); } -BOOST_AUTO_TEST_CASE(invalid_urls) +BOOST_AUTO_TEST_CASE(invalid_route_urls) { - BOOST_CHECK_EQUAL(testInvalidOptions("overview=false&bla=foo"), 14UL); - BOOST_CHECK_EQUAL(testInvalidOptions("overview=false&bearings=foo"), 24UL); - BOOST_CHECK_EQUAL(testInvalidOptions("overview=false&uturns=foo"), 22UL); - BOOST_CHECK_EQUAL(testInvalidOptions("overview=false&radiuses=foo"), 24UL); - BOOST_CHECK_EQUAL(testInvalidOptions("overview=false&hints=foo"), 14UL); - BOOST_CHECK_EQUAL(testInvalidOptions("overview=false&geometries=foo"), 14UL); - BOOST_CHECK_EQUAL(testInvalidOptions("overview=false&overview=foo"), 14UL); - BOOST_CHECK_EQUAL(testInvalidOptions("overview=false&alternative=foo"), 14UL); + BOOST_CHECK_EQUAL(testInvalidOptions("overview=false&bla=foo"), + 14UL); + BOOST_CHECK_EQUAL( + testInvalidOptions("overview=false&bearings=foo"), 24UL); + BOOST_CHECK_EQUAL(testInvalidOptions("overview=false&uturns=foo"), + 22UL); + BOOST_CHECK_EQUAL( + testInvalidOptions("overview=false&radiuses=foo"), 24UL); + BOOST_CHECK_EQUAL(testInvalidOptions("overview=false&hints=foo"), + 14UL); + BOOST_CHECK_EQUAL( + testInvalidOptions("overview=false&geometries=foo"), 14UL); + BOOST_CHECK_EQUAL( + testInvalidOptions("overview=false&overview=foo"), 14UL); + BOOST_CHECK_EQUAL( + testInvalidOptions("overview=false&alternative=foo"), 14UL); } -BOOST_AUTO_TEST_CASE(valid_urls) +BOOST_AUTO_TEST_CASE(invalid_table_urls) +{ + BOOST_CHECK_EQUAL(testInvalidOptions("sources=1&bla=foo"), 9UL); + BOOST_CHECK_EQUAL(testInvalidOptions("destinations=1&bla=foo"), 14UL); + BOOST_CHECK_EQUAL(testInvalidOptions("sources=1&destinations=1&bla=foo"), 24UL); + BOOST_CHECK_EQUAL(testInvalidOptions("sources=foo"), 8UL); + BOOST_CHECK_EQUAL(testInvalidOptions("destinations=foo"), 13UL); +} + +BOOST_AUTO_TEST_CASE(valid_route_urls) { engine::api::RouteParameters reference_1{}; - auto result_1 = api::parseRouteParameters(""); + auto result_1 = api::parseParameters(""); BOOST_CHECK(result_1); BOOST_CHECK_EQUAL(reference_1.steps, result_1->steps); BOOST_CHECK_EQUAL(reference_1.alternative, result_1->alternative); @@ -97,14 +114,8 @@ BOOST_AUTO_TEST_CASE(valid_urls) CHECK_EQUAL_RANGE(reference_1.radiuses, result_1->radiuses); CHECK_EQUAL_RANGE(reference_1.coordinates, result_1->coordinates); - // bool steps = true; - // bool alternative = true; - // GeometriesType geometries = GeometriesType::Polyline; - // OverviewType overview = OverviewType::False; - // std::vector> uturns; - engine::api::RouteParameters reference_2{}; - auto result_2 = api::parseRouteParameters( + auto result_2 = api::parseParameters( "steps=true&alternative=true&geometries=polyline&overview=simplified"); BOOST_CHECK(result_2); BOOST_CHECK_EQUAL(reference_2.steps, result_2->steps); @@ -120,7 +131,7 @@ BOOST_AUTO_TEST_CASE(valid_urls) engine::api::RouteParameters reference_3{ false, false, engine::api::RouteParameters::GeometriesType::GeoJSON, engine::api::RouteParameters::OverviewType::False, uturns_3}; - auto result_3 = api::parseRouteParameters( + auto result_3 = api::parseParameters( "steps=false&alternative=false&geometries=geojson&overview=false&uturns=true;false;"); BOOST_CHECK(result_3); BOOST_CHECK_EQUAL(reference_3.steps, result_3->steps); @@ -139,17 +150,17 @@ BOOST_AUTO_TEST_CASE(valid_urls) "_4ghA4JuzAD_IAAAo28BAOYAAAAzAAAAAgAAAEwAAAAAAAAAdIwAAJ4AAAAXiSEDfm7MAAEAAQGLSzmR"), engine::Hint::FromBase64( "03AhA0vnzAA_SAAA_____3wEAAAYAAAAQAAAAB4AAABAAAAAoUYBAJ4AAADlcCEDSefMAAMAAQGLSzmR")}; - engine::api::RouteParameters reference_4{false, - true, - engine::api::RouteParameters::GeometriesType::Polyline, - engine::api::RouteParameters::OverviewType::Simplified, - std::vector>{}, - std::vector{}, - hints_4, - std::vector>{}, - std::vector>{} - }; - auto result_4 = api::parseRouteParameters( + engine::api::RouteParameters reference_4{ + false, + true, + engine::api::RouteParameters::GeometriesType::Polyline, + engine::api::RouteParameters::OverviewType::Simplified, + std::vector>{}, + std::vector{}, + hints_4, + std::vector>{}, + std::vector>{}}; + auto result_4 = api::parseParameters( "steps=false&hints=rVghAzxMzABMAwAA5h4CAKMIAAAQAAAAGAAAAAYAAAAAAAAAch8BAJ4AAACpWCED_" "0vMAAEAAQGLSzmR;_4ghA4JuzAD_" "IAAAo28BAOYAAAAzAAAAAgAAAEwAAAAAAAAAdIwAAJ4AAAAXiSEDfm7MAAEAAQGLSzmR;03AhA0vnzAA_SAAA_____" @@ -165,4 +176,27 @@ BOOST_AUTO_TEST_CASE(valid_urls) CHECK_EQUAL_RANGE(reference_4.coordinates, result_4->coordinates); } +BOOST_AUTO_TEST_CASE(valid_table_urls) +{ + engine::api::TableParameters reference_1{}; + auto result_1 = api::parseParameters(""); + BOOST_CHECK(result_1); + CHECK_EQUAL_RANGE(reference_1.sources, result_1->sources); + CHECK_EQUAL_RANGE(reference_1.destinations, result_1->destinations); + 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); + + std::vector sources_2 = {1, 2, 3}; + std::vector destinations_2 = {4, 5}; + engine::api::TableParameters reference_2{sources_2, destinations_2}; + auto result_2 = api::parseParameters("sources=1;2;3&destinations=4;5"); + BOOST_CHECK(result_2); + CHECK_EQUAL_RANGE(reference_2.sources, result_2->sources); + CHECK_EQUAL_RANGE(reference_2.destinations, result_2->destinations); + 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_SUITE_END()