mirror of https://gitee.com/bigwinds/arangodb
Merge branch 'devel' of https://github.com/arangodb/arangodb into spdvpk
This commit is contained in:
commit
67514b60b6
|
@ -24,11 +24,13 @@
|
||||||
#define ARANGODB_PROGRAM_OPTIONS_OPTION_H 1
|
#define ARANGODB_PROGRAM_OPTIONS_OPTION_H 1
|
||||||
|
|
||||||
#include "Basics/Common.h"
|
#include "Basics/Common.h"
|
||||||
|
#include "ProgramOptions2/Parameters.h"
|
||||||
|
|
||||||
|
#include <velocypack/Builder.h>
|
||||||
|
#include <velocypack/velocypack-aliases.h>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include "ProgramOptions2/Parameters.h"
|
|
||||||
|
|
||||||
namespace arangodb {
|
namespace arangodb {
|
||||||
namespace options {
|
namespace options {
|
||||||
|
|
||||||
|
@ -57,6 +59,10 @@ struct Option {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void toVPack(VPackBuilder& builder) const {
|
||||||
|
parameter->toVPack(builder);
|
||||||
|
}
|
||||||
|
|
||||||
// get display name for the option
|
// get display name for the option
|
||||||
std::string displayName() const { return "--" + fullName(); }
|
std::string displayName() const { return "--" + fullName(); }
|
||||||
|
|
||||||
|
@ -69,8 +75,9 @@ struct Option {
|
||||||
}
|
}
|
||||||
|
|
||||||
// print help for an option
|
// print help for an option
|
||||||
void printHelp(size_t tw, size_t ow) const {
|
// the special search string "." will show help for all sections, even if hidden
|
||||||
if (!hidden) {
|
void printHelp(std::string const& search, size_t tw, size_t ow) const {
|
||||||
|
if (search == "." || !hidden) {
|
||||||
std::cout << " " << pad(nameWithType(), ow) << " ";
|
std::cout << " " << pad(nameWithType(), ow) << " ";
|
||||||
|
|
||||||
std::string value = description;
|
std::string value = description;
|
||||||
|
|
|
@ -25,6 +25,12 @@
|
||||||
|
|
||||||
#include "Basics/Common.h"
|
#include "Basics/Common.h"
|
||||||
|
|
||||||
|
#include <velocypack/Builder.h>
|
||||||
|
#include <velocypack/velocypack-aliases.h>
|
||||||
|
|
||||||
|
#include <numeric>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
namespace arangodb {
|
namespace arangodb {
|
||||||
namespace options {
|
namespace options {
|
||||||
|
|
||||||
|
@ -33,7 +39,7 @@ template <typename T>
|
||||||
typename std::enable_if<std::is_signed<T>::value, T>::type toNumber(
|
typename std::enable_if<std::is_signed<T>::value, T>::type toNumber(
|
||||||
std::string const& value) {
|
std::string const& value) {
|
||||||
auto v = static_cast<T>(std::stoll(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);
|
throw std::out_of_range(value);
|
||||||
}
|
}
|
||||||
return static_cast<T>(v);
|
return static_cast<T>(v);
|
||||||
|
@ -44,7 +50,7 @@ template <typename T>
|
||||||
typename std::enable_if<std::is_unsigned<T>::value, T>::type toNumber(
|
typename std::enable_if<std::is_unsigned<T>::value, T>::type toNumber(
|
||||||
std::string const& value) {
|
std::string const& value) {
|
||||||
auto v = static_cast<T>(std::stoull(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);
|
throw std::out_of_range(value);
|
||||||
}
|
}
|
||||||
return static_cast<T>(v);
|
return static_cast<T>(v);
|
||||||
|
@ -56,6 +62,20 @@ double toNumber<double>(std::string const& value) {
|
||||||
return std::stod(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
|
// stringify a value, base version for any type
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline std::string stringifyValue(T const& value) {
|
inline std::string stringifyValue(T const& value) {
|
||||||
|
@ -90,6 +110,8 @@ struct Parameter {
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void toVPack(VPackBuilder&) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// specialized type for boolean values
|
// specialized type for boolean values
|
||||||
|
@ -119,6 +141,10 @@ struct BooleanParameter : public Parameter {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void toVPack(VPackBuilder& builder) const override {
|
||||||
|
builder.add(VPackValue(*ptr));
|
||||||
|
}
|
||||||
|
|
||||||
ValueType* ptr;
|
ValueType* ptr;
|
||||||
bool required;
|
bool required;
|
||||||
};
|
};
|
||||||
|
@ -136,8 +162,8 @@ struct NumericParameter : public Parameter {
|
||||||
std::string set(std::string const& value) override {
|
std::string set(std::string const& value) override {
|
||||||
try {
|
try {
|
||||||
ValueType v = toNumber<ValueType>(value);
|
ValueType v = toNumber<ValueType>(value);
|
||||||
if (v >= std::numeric_limits<T>::min() &&
|
if (v >= (std::numeric_limits<T>::min)() &&
|
||||||
v <= std::numeric_limits<T>::max()) {
|
v <= (std::numeric_limits<T>::max)()) {
|
||||||
*ptr = v;
|
*ptr = v;
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
@ -147,6 +173,10 @@ struct NumericParameter : public Parameter {
|
||||||
return "number out of range";
|
return "number out of range";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void toVPack(VPackBuilder& builder) const override {
|
||||||
|
builder.add(VPackValue(*ptr));
|
||||||
|
}
|
||||||
|
|
||||||
ValueType* ptr;
|
ValueType* ptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -206,28 +236,28 @@ struct UInt64Parameter : public NumericParameter<uint64_t> {
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct BoundedParameter : public T {
|
struct BoundedParameter : public T {
|
||||||
BoundedParameter(typename T::ValueType* ptr, typename T::ValueType min,
|
BoundedParameter(typename T::ValueType* ptr, typename T::ValueType minValue,
|
||||||
typename T::ValueType max)
|
typename T::ValueType maxValue)
|
||||||
: T(ptr), min(min), max(max) {}
|
: T(ptr), minValue(minValue), maxValue(maxValue) {}
|
||||||
|
|
||||||
std::string set(std::string const& value) override {
|
std::string set(std::string const& value) override {
|
||||||
try {
|
try {
|
||||||
typename T::ValueType v = toNumber<typename T::ValueType>(value);
|
typename T::ValueType v = toNumber<typename T::ValueType>(value);
|
||||||
if (v >= std::numeric_limits<typename T::ValueType>::min() &&
|
if (v >= (std::numeric_limits<typename T::ValueType>::min)() &&
|
||||||
v <= std::numeric_limits<typename T::ValueType>::max() && v >= min &&
|
v <= (std::numeric_limits<typename T::ValueType>::max)() && v >= minValue &&
|
||||||
v <= max) {
|
v <= maxValue) {
|
||||||
*this->ptr = v;
|
*this->ptr = v;
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
return "invalid numeric value";
|
return "invalid numeric value";
|
||||||
}
|
}
|
||||||
return "number out of allowed range (" + std::to_string(min) + " - " +
|
return "number out of allowed range (" + std::to_string(minValue) + " - " +
|
||||||
std::to_string(max) + ")";
|
std::to_string(maxValue) + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
typename T::ValueType min;
|
typename T::ValueType minValue;
|
||||||
typename T::ValueType max;
|
typename T::ValueType maxValue;
|
||||||
};
|
};
|
||||||
|
|
||||||
// concrete double number value type
|
// concrete double number value type
|
||||||
|
@ -253,9 +283,33 @@ struct StringParameter : public Parameter {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void toVPack(VPackBuilder& builder) const override {
|
||||||
|
builder.add(VPackValue(*ptr));
|
||||||
|
}
|
||||||
|
|
||||||
ValueType* 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
|
// specialized type for vectors of values
|
||||||
// this templated type needs a concrete value type
|
// this templated type needs a concrete value type
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
@ -290,6 +344,13 @@ struct VectorParameter : public Parameter {
|
||||||
return result;
|
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;
|
std::vector<typename T::ValueType>* ptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -299,6 +360,9 @@ struct ObsoleteParameter : public Parameter {
|
||||||
std::string name() const override { return "obsolete"; }
|
std::string name() const override { return "obsolete"; }
|
||||||
std::string valueString() const override { return "-"; }
|
std::string valueString() const override { return "-"; }
|
||||||
std::string set(std::string const&) override { return ""; }
|
std::string set(std::string const&) override { return ""; }
|
||||||
|
void toVPack(VPackBuilder& builder) const override {
|
||||||
|
builder.add(VPackValue(VPackValueType::Null));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,11 @@
|
||||||
#include "ProgramOptions2/Option.h"
|
#include "ProgramOptions2/Option.h"
|
||||||
#include "ProgramOptions2/Section.h"
|
#include "ProgramOptions2/Section.h"
|
||||||
|
|
||||||
|
#include <velocypack/Builder.h>
|
||||||
|
#include <velocypack/velocypack-aliases.h>
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
#define ARANGODB_PROGRAM_OPTIONS_PROGNAME "#progname#"
|
#define ARANGODB_PROGRAM_OPTIONS_PROGNAME "#progname#"
|
||||||
|
|
||||||
namespace arangodb {
|
namespace arangodb {
|
||||||
|
@ -149,20 +154,24 @@ class ProgramOptions {
|
||||||
// prints usage information
|
// prints usage information
|
||||||
void printUsage() const { std::cout << _usage << std::endl << std::endl; }
|
void printUsage() const { std::cout << _usage << std::endl << std::endl; }
|
||||||
|
|
||||||
// prints a help for all options
|
// prints a help for all options, or the options of a section
|
||||||
void printHelp(std::string const& section) const {
|
// 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();
|
printUsage();
|
||||||
|
|
||||||
size_t const tw = _terminalWidth();
|
size_t const tw = _terminalWidth();
|
||||||
size_t const ow = optionsWidth();
|
size_t const ow = optionsWidth();
|
||||||
|
|
||||||
for (auto const& it : _sections) {
|
for (auto const& it : _sections) {
|
||||||
if (section == "*" || section == it.second.name) {
|
if (search == "*" || search == "." || search == it.second.name) {
|
||||||
it.second.printHelp(tw, ow);
|
it.second.printHelp(search, tw, ow);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
printSectionsHelp();
|
if (search == "*") {
|
||||||
|
printSectionsHelp();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// prints the names for all section help options
|
// prints the names for all section help options
|
||||||
|
@ -177,6 +186,28 @@ class ProgramOptions {
|
||||||
std::cout << std::endl;
|
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
|
// translate a shorthand option
|
||||||
std::string translateShorthand(std::string const& name) const {
|
std::string translateShorthand(std::string const& name) const {
|
||||||
auto it = _shorthands.find(name);
|
auto it = _shorthands.find(name);
|
||||||
|
@ -188,7 +219,7 @@ class ProgramOptions {
|
||||||
}
|
}
|
||||||
|
|
||||||
void walk(std::function<void(Section const&, Option const&)> const& callback,
|
void walk(std::function<void(Section const&, Option const&)> const& callback,
|
||||||
bool onlyTouched) {
|
bool onlyTouched) const {
|
||||||
for (auto const& it : _sections) {
|
for (auto const& it : _sections) {
|
||||||
if (it.second.obsolete) {
|
if (it.second.obsolete) {
|
||||||
// obsolete section. ignore it
|
// obsolete section. ignore it
|
||||||
|
|
|
@ -61,8 +61,9 @@ struct Section {
|
||||||
}
|
}
|
||||||
|
|
||||||
// print help for a section
|
// print help for a section
|
||||||
void printHelp(size_t tw, size_t ow) const {
|
// the special search string "." will show help for all sections, even if hidden
|
||||||
if (hidden || !hasOptions()) {
|
void printHelp(std::string const& search, size_t tw, size_t ow) const {
|
||||||
|
if (search != "." && (hidden || !hasOptions())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,7 +72,7 @@ struct Section {
|
||||||
|
|
||||||
// propagate print command to options
|
// propagate print command to options
|
||||||
for (auto const& it : options) {
|
for (auto const& it : options) {
|
||||||
it.second.printHelp(tw, ow);
|
it.second.printHelp(search, tw, ow);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
|
|
Loading…
Reference in New Issue