From dac929f8df284707c5edecfb2f3ca9ce21b5956f Mon Sep 17 00:00:00 2001 From: Michael Krasnyk Date: Tue, 28 Mar 2017 16:56:22 +0200 Subject: [PATCH] Make max-cell-sizes parameter a comma-separated list --- features/options/partition/invalid.feature | 6 ++ features/testbot/multi_level_routing.feature | 6 +- src/tools/partition.cpp | 74 ++++++++++++++------ 3 files changed, 60 insertions(+), 26 deletions(-) diff --git a/features/options/partition/invalid.feature b/features/options/partition/invalid.feature index fc832d93f..195abd609 100644 --- a/features/options/partition/invalid.feature +++ b/features/options/partition/invalid.feature @@ -18,3 +18,9 @@ Feature: osrm-partition command line options: invalid options And stderr should contain "option" And stderr should contain "fly-me-to-the-moon" And it should exit with an error + + Scenario: osrm-partition - Check non-descending order + When I try to run "osrm-partition --max-cell-sizes 4,64,16 fly-me-to-the-moon.osrm" + Then stdout should be empty + And stderr should contain "must be sorted in non-descending order" + And it should exit with an error diff --git a/features/testbot/multi_level_routing.feature b/features/testbot/multi_level_routing.feature index f4a02a898..b3c479bf7 100644 --- a/features/testbot/multi_level_routing.feature +++ b/features/testbot/multi_level_routing.feature @@ -3,7 +3,7 @@ Feature: Multi level routing Background: Given the profile "testbot" - And the partition extra arguments "--small-component-size 1 --max-cell-sizes 4 16 64 --" + And the partition extra arguments "--small-component-size 1 --max-cell-sizes 4,16,64" Scenario: Testbot - Multi level routing check partition Given the node map @@ -31,7 +31,7 @@ Feature: Multi level routing | be | primary | And the data has been extracted - When I run "osrm-partition --max-cell-sizes 4 16 --small-component-size 1 {processed_file}" + When I run "osrm-partition --max-cell-sizes 4,16 --small-component-size 1 {processed_file}" Then it should exit successfully And stdout should not contain "level 1 #cells 1 bit size 1" @@ -111,7 +111,7 @@ Feature: Multi level routing │ │ l───k """ - And the partition extra arguments "--small-component-size 1 --max-cell-sizes 4 16 --" + And the partition extra arguments "--small-component-size 1 --max-cell-sizes 4,16" And the ways | nodes | maxspeed | | abcda | 5 | diff --git a/src/tools/partition.cpp b/src/tools/partition.cpp index ba9536525..488f99d3c 100644 --- a/src/tools/partition.cpp +++ b/src/tools/partition.cpp @@ -12,7 +12,9 @@ #include #include #include +#include #include +#include #include @@ -25,6 +27,45 @@ enum class return_code : unsigned exit }; +struct MaxCellSizesArgument +{ + std::vector value; +}; + +std::ostream &operator<<(std::ostream &os, const MaxCellSizesArgument &arg) +{ + return os << boost::algorithm::join( + arg.value | boost::adaptors::transformed([](auto x) { return std::to_string(x); }), + ","); +} + +void validate(boost::any &v, const std::vector &values, MaxCellSizesArgument *, int) +{ + using namespace boost::program_options; + using namespace boost::adaptors; + + // Make sure no previous assignment to 'v' was made. + validators::check_first_occurrence(v); + // Extract the first string from 'values'. If there is more than + // one string, it's an error, and exception will be thrown. + const std::string &s = validators::get_single_string(values); + + std::vector output; + boost::copy(s | tokenized(boost::regex(","), -1) | transformed([](const auto &x) { + try + { + return boost::lexical_cast(x); + } + catch (const boost::bad_lexical_cast &) + { + throw validation_error(validation_error::invalid_option_value); + } + }), + std::back_inserter(output)); + + v = boost::any(MaxCellSizesArgument{output}); +} + return_code parseArguments(int argc, char *argv[], partition::PartitionConfig &config) { // declare a group of options that will be allowed only on command line @@ -60,14 +101,8 @@ return_code parseArguments(int argc, char *argv[], partition::PartitionConfig &c "Size threshold for small components.") // ("max-cell-sizes", - boost::program_options::value>(&config.max_cell_sizes) - ->multitoken() - ->default_value(config.max_cell_sizes, - boost::algorithm::join( - config.max_cell_sizes | - boost::adaptors::transformed( - static_cast(std::to_string)), - " ")), + boost::program_options::value()->default_value( + MaxCellSizesArgument{config.max_cell_sizes}), "Maximum cell sizes starting from the level 1. The first cell size value is a bisection " "termination citerion"); @@ -128,23 +163,16 @@ return_code parseArguments(int argc, char *argv[], partition::PartitionConfig &c return return_code::fail; } - if (config.max_cell_sizes.empty()) + if (option_variables.count("max-cell-sizes")) { - util::Log(logERROR) << "The maximum cell sizes array must be non-empty"; - return return_code::fail; - } + config.max_cell_sizes = option_variables["max-cell-sizes"].as().value; - if (!std::is_sorted(config.max_cell_sizes.begin(), config.max_cell_sizes.end())) - { - util::Log(logERROR) - << "The maximum cell sizes array must be sorted in non-descending order."; - return return_code::fail; - } - - if (config.max_cell_sizes.front() < 2) - { - util::Log(logERROR) << "Cells on the first level must have at least 2 nodes"; - return return_code::fail; + if (!std::is_sorted(config.max_cell_sizes.begin(), config.max_cell_sizes.end())) + { + util::Log(logERROR) + << "The maximum cell sizes array must be sorted in non-descending order."; + return return_code::fail; + } } return return_code::ok;