1
0
Fork 0

Merge branch 'devel' of https://github.com/arangodb/arangodb into spdvpk

This commit is contained in:
jsteemann 2016-02-26 21:56:26 +01:00
commit 67514b60b6
4 changed files with 130 additions and 27 deletions

View File

@ -24,11 +24,13 @@
#define ARANGODB_PROGRAM_OPTIONS_OPTION_H 1
#include "Basics/Common.h"
#include "ProgramOptions2/Parameters.h"
#include <velocypack/Builder.h>
#include <velocypack/velocypack-aliases.h>
#include <iostream>
#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;

View File

@ -25,6 +25,12 @@
#include "Basics/Common.h"
#include <velocypack/Builder.h>
#include <velocypack/velocypack-aliases.h>
#include <numeric>
#include <type_traits>
namespace arangodb {
namespace options {
@ -33,7 +39,7 @@ template <typename T>
typename std::enable_if<std::is_signed<T>::value, T>::type toNumber(
std::string const& value) {
auto v = static_cast<T>(std::stoll(value));
if (v < std::numeric_limits<T>::min() || v > std::numeric_limits<T>::max()) {
if (v < (std::numeric_limits<T>::min)() || v > (std::numeric_limits<T>::max)()) {
throw std::out_of_range(value);
}
return static_cast<T>(v);
@ -44,7 +50,7 @@ template <typename T>
typename std::enable_if<std::is_unsigned<T>::value, T>::type toNumber(
std::string const& value) {
auto v = static_cast<T>(std::stoull(value));
if (v < std::numeric_limits<T>::min() || v > std::numeric_limits<T>::max()) {
if (v < (std::numeric_limits<T>::min)() || v > (std::numeric_limits<T>::max)()) {
throw std::out_of_range(value);
}
return static_cast<T>(v);
@ -56,6 +62,20 @@ double toNumber<double>(std::string const& value) {
return std::stod(value);
}
// convert a string into another type, specialized version for numbers
template <typename T>
typename std::enable_if<std::is_arithmetic<T>::value, T>::type fromString(
std::string const& value) {
return toNumber<T>(value);
}
// convert a string into another type, specialized version for string -> string
template <typename T>
typename std::enable_if<std::is_same<T, std::string>::value, T>::type fromString(
std::string const& value) {
return value;
}
// stringify a value, base version for any type
template <typename T>
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<ValueType>(value);
if (v >= std::numeric_limits<T>::min() &&
v <= std::numeric_limits<T>::max()) {
if (v >= (std::numeric_limits<T>::min)() &&
v <= (std::numeric_limits<T>::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<uint64_t> {
template <typename T>
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<typename T::ValueType>(value);
if (v >= std::numeric_limits<typename T::ValueType>::min() &&
v <= std::numeric_limits<typename T::ValueType>::max() && v >= min &&
v <= max) {
if (v >= (std::numeric_limits<typename T::ValueType>::min)() &&
v <= (std::numeric_limits<typename T::ValueType>::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 <typename T>
struct DiscreteValuesParameter : public T {
DiscreteValuesParameter(typename T::ValueType* ptr,
std::unordered_set<typename T::ValueType> const& allowed)
: T(ptr), allowed(allowed) {}
std::string set(std::string const& value) override {
auto it = allowed.find(fromString<typename T::ValueType>(value));
if (it == allowed.end()) {
return "invalid value " + value;
}
return "";
}
std::unordered_set<typename T::ValueType> allowed;
};
// specialized type for vectors of values
// this templated type needs a concrete value type
template <typename T>
@ -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<typename T::ValueType>* 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));
}
};
}
}

View File

@ -28,6 +28,11 @@
#include "ProgramOptions2/Option.h"
#include "ProgramOptions2/Section.h"
#include <velocypack/Builder.h>
#include <velocypack/velocypack-aliases.h>
#include <functional>
#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<std::string> 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<void(Section const&, Option const&)> const& callback,
bool onlyTouched) {
bool onlyTouched) const {
for (auto const& it : _sections) {
if (it.second.obsolete) {
// obsolete section. ignore it

View File

@ -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;