From a0cec698529b7cc0876e71225e1f482e110b044f Mon Sep 17 00:00:00 2001 From: jsteemann Date: Fri, 26 Feb 2016 21:45:41 +0100 Subject: [PATCH] added some features --- lib/ProgramOptions2/Option.h | 15 +++-- lib/ProgramOptions2/Parameters.h | 92 +++++++++++++++++++++++----- lib/ProgramOptions2/ProgramOptions.h | 43 +++++++++++-- lib/ProgramOptions2/Section.h | 7 ++- 4 files changed, 130 insertions(+), 27 deletions(-) diff --git a/lib/ProgramOptions2/Option.h b/lib/ProgramOptions2/Option.h index 147ccc5fa4..3b95af0953 100644 --- a/lib/ProgramOptions2/Option.h +++ b/lib/ProgramOptions2/Option.h @@ -24,11 +24,13 @@ #define ARANGODB_PROGRAM_OPTIONS_OPTION_H 1 #include "Basics/Common.h" +#include "ProgramOptions2/Parameters.h" + +#include +#include #include -#include "ProgramOptions2/Parameters.h" - namespace arangodb { namespace options { @@ -57,6 +59,10 @@ struct Option { } } + void toVPack(VPackBuilder& builder) const { + parameter->toVPack(builder); + } + // get display name for the option std::string displayName() const { return "--" + fullName(); } @@ -69,8 +75,9 @@ struct Option { } // print help for an option - void printHelp(size_t tw, size_t ow) const { - if (!hidden) { + // the special search string "." will show help for all sections, even if hidden + void printHelp(std::string const& search, size_t tw, size_t ow) const { + if (search == "." || !hidden) { std::cout << " " << pad(nameWithType(), ow) << " "; std::string value = description; diff --git a/lib/ProgramOptions2/Parameters.h b/lib/ProgramOptions2/Parameters.h index d452a2046f..72217abb5b 100644 --- a/lib/ProgramOptions2/Parameters.h +++ b/lib/ProgramOptions2/Parameters.h @@ -25,6 +25,12 @@ #include "Basics/Common.h" +#include +#include + +#include +#include + namespace arangodb { namespace options { @@ -33,7 +39,7 @@ template typename std::enable_if::value, T>::type toNumber( std::string const& value) { auto v = static_cast(std::stoll(value)); - if (v < std::numeric_limits::min() || v > std::numeric_limits::max()) { + if (v < (std::numeric_limits::min)() || v > (std::numeric_limits::max)()) { throw std::out_of_range(value); } return static_cast(v); @@ -44,7 +50,7 @@ template typename std::enable_if::value, T>::type toNumber( std::string const& value) { auto v = static_cast(std::stoull(value)); - if (v < std::numeric_limits::min() || v > std::numeric_limits::max()) { + if (v < (std::numeric_limits::min)() || v > (std::numeric_limits::max)()) { throw std::out_of_range(value); } return static_cast(v); @@ -56,6 +62,20 @@ double toNumber(std::string const& value) { return std::stod(value); } +// convert a string into another type, specialized version for numbers +template +typename std::enable_if::value, T>::type fromString( + std::string const& value) { + return toNumber(value); +} + +// convert a string into another type, specialized version for string -> string +template +typename std::enable_if::value, T>::type fromString( + std::string const& value) { + return value; +} + // stringify a value, base version for any type template inline std::string stringifyValue(T const& value) { @@ -90,6 +110,8 @@ struct Parameter { } return ""; } + + virtual void toVPack(VPackBuilder&) const = 0; }; // specialized type for boolean values @@ -119,6 +141,10 @@ struct BooleanParameter : public Parameter { return ""; } + void toVPack(VPackBuilder& builder) const override { + builder.add(VPackValue(*ptr)); + } + ValueType* ptr; bool required; }; @@ -136,8 +162,8 @@ struct NumericParameter : public Parameter { std::string set(std::string const& value) override { try { ValueType v = toNumber(value); - if (v >= std::numeric_limits::min() && - v <= std::numeric_limits::max()) { + if (v >= (std::numeric_limits::min)() && + v <= (std::numeric_limits::max)()) { *ptr = v; return ""; } @@ -147,6 +173,10 @@ struct NumericParameter : public Parameter { return "number out of range"; } + void toVPack(VPackBuilder& builder) const override { + builder.add(VPackValue(*ptr)); + } + ValueType* ptr; }; @@ -206,28 +236,28 @@ struct UInt64Parameter : public NumericParameter { template struct BoundedParameter : public T { - BoundedParameter(typename T::ValueType* ptr, typename T::ValueType min, - typename T::ValueType max) - : T(ptr), min(min), max(max) {} + BoundedParameter(typename T::ValueType* ptr, typename T::ValueType minValue, + typename T::ValueType maxValue) + : T(ptr), minValue(minValue), maxValue(maxValue) {} std::string set(std::string const& value) override { try { typename T::ValueType v = toNumber(value); - if (v >= std::numeric_limits::min() && - v <= std::numeric_limits::max() && v >= min && - v <= max) { + if (v >= (std::numeric_limits::min)() && + v <= (std::numeric_limits::max)() && v >= minValue && + v <= maxValue) { *this->ptr = v; return ""; } } catch (...) { return "invalid numeric value"; } - return "number out of allowed range (" + std::to_string(min) + " - " + - std::to_string(max) + ")"; + return "number out of allowed range (" + std::to_string(minValue) + " - " + + std::to_string(maxValue) + ")"; } - typename T::ValueType min; - typename T::ValueType max; + typename T::ValueType minValue; + typename T::ValueType maxValue; }; // concrete double number value type @@ -253,9 +283,33 @@ struct StringParameter : public Parameter { return ""; } + void toVPack(VPackBuilder& builder) const override { + builder.add(VPackValue(*ptr)); + } + ValueType* ptr; }; +// specialized type for discrete values (defined in the unordered_set) +// this templated type needs a concrete value type +template +struct DiscreteValuesParameter : public T { + DiscreteValuesParameter(typename T::ValueType* ptr, + std::unordered_set const& allowed) + : T(ptr), allowed(allowed) {} + + std::string set(std::string const& value) override { + auto it = allowed.find(fromString(value)); + + if (it == allowed.end()) { + return "invalid value " + value; + } + return ""; + } + + std::unordered_set allowed; +}; + // specialized type for vectors of values // this templated type needs a concrete value type template @@ -290,6 +344,13 @@ struct VectorParameter : public Parameter { return result; } + void toVPack(VPackBuilder& builder) const override { + builder.openArray(); + for (size_t i = 0; i < ptr->size(); ++i) { + builder.add(VPackValue(ptr->at(i))); + } + } + std::vector* ptr; }; @@ -299,6 +360,9 @@ struct ObsoleteParameter : public Parameter { std::string name() const override { return "obsolete"; } std::string valueString() const override { return "-"; } std::string set(std::string const&) override { return ""; } + void toVPack(VPackBuilder& builder) const override { + builder.add(VPackValue(VPackValueType::Null)); + } }; } } diff --git a/lib/ProgramOptions2/ProgramOptions.h b/lib/ProgramOptions2/ProgramOptions.h index 74aa711548..ee58cc4d99 100644 --- a/lib/ProgramOptions2/ProgramOptions.h +++ b/lib/ProgramOptions2/ProgramOptions.h @@ -28,6 +28,11 @@ #include "ProgramOptions2/Option.h" #include "ProgramOptions2/Section.h" +#include +#include + +#include + #define ARANGODB_PROGRAM_OPTIONS_PROGNAME "#progname#" namespace arangodb { @@ -149,20 +154,24 @@ class ProgramOptions { // prints usage information void printUsage() const { std::cout << _usage << std::endl << std::endl; } - // prints a help for all options - void printHelp(std::string const& section) const { + // prints a help for all options, or the options of a section + // the special search string "*" will show help for all sections + // the special search string "." will show help for all sections, even if hidden + void printHelp(std::string const& search) const { printUsage(); size_t const tw = _terminalWidth(); size_t const ow = optionsWidth(); for (auto const& it : _sections) { - if (section == "*" || section == it.second.name) { - it.second.printHelp(tw, ow); + if (search == "*" || search == "." || search == it.second.name) { + it.second.printHelp(search, tw, ow); } } - printSectionsHelp(); + if (search == "*") { + printSectionsHelp(); + } } // prints the names for all section help options @@ -177,6 +186,28 @@ class ProgramOptions { std::cout << std::endl; } + // returns a VPack representation of the option values + VPackBuilder toVPack(bool onlyTouched, std::unordered_set const& exclude) const { + VPackBuilder builder; + builder.openObject(); + + walk([&builder, &exclude](Section const&, Option const& option) { + std::string full(option.fullName()); + if (exclude.find(full) != exclude.end()) { + // excluded option + return; + } + + // add key + builder.add(VPackValue(full)); + // add value + option.toVPack(builder); + }, onlyTouched); + + builder.close(); + return builder; + } + // translate a shorthand option std::string translateShorthand(std::string const& name) const { auto it = _shorthands.find(name); @@ -188,7 +219,7 @@ class ProgramOptions { } void walk(std::function const& callback, - bool onlyTouched) { + bool onlyTouched) const { for (auto const& it : _sections) { if (it.second.obsolete) { // obsolete section. ignore it diff --git a/lib/ProgramOptions2/Section.h b/lib/ProgramOptions2/Section.h index 329fc30bfb..08a9f47e33 100644 --- a/lib/ProgramOptions2/Section.h +++ b/lib/ProgramOptions2/Section.h @@ -61,8 +61,9 @@ struct Section { } // print help for a section - void printHelp(size_t tw, size_t ow) const { - if (hidden || !hasOptions()) { + // the special search string "." will show help for all sections, even if hidden + void printHelp(std::string const& search, size_t tw, size_t ow) const { + if (search != "." && (hidden || !hasOptions())) { return; } @@ -71,7 +72,7 @@ struct Section { // propagate print command to options for (auto const& it : options) { - it.second.printHelp(tw, ow); + it.second.printHelp(search, tw, ow); } std::cout << std::endl;