29#if defined CLI11_HAS_FILESYSTEM && CLI11_HAS_FILESYSTEM > 0
60 std::function<std::string(std::string &)>
func_{[](std::string &) {
return std::string{}; }};
70 Validator(std::string validator_desc, std::function<std::string(std::string &)> func)
78 Validator(std::function<std::string(std::string &)> op, std::string validator_desc, std::string validator_name =
"")
80 name_(std::move(validator_name)) {}
83 func_ = std::move(op);
93 std::string value = str;
110 return std::string{};
114 name_ = std::move(validator_name);
120 newval.
name_ = std::move(validator_name);
173 void _merge_description(
const Validator &val1,
const Validator &val2,
const std::string &merger);
252 :
Validator(validator_name, [](std::string &input_string) {
254 auto val = DesiredType();
255 if(!lexical_cast(input_string, val)) {
256 return std::string(
"Failed parsing ") + input_string +
" as a " + detail::type_name<DesiredType>();
258 return std::string();
280 template <
typename T>
281 Range(T min_val, T max_val,
const std::string &validator_name = std::string{}) :
Validator(validator_name) {
282 if(validator_name.empty()) {
283 std::stringstream out;
284 out << detail::type_name<T>() <<
" in [" << min_val <<
" - " << max_val <<
"]";
285 description(out.str());
288 func_ = [min_val, max_val](std::string &input) {
289 using CLI::detail::lexical_cast;
291 bool converted = lexical_cast(input, val);
292 if((!converted) || (val < min_val || val > max_val)) {
293 std::stringstream out;
294 out <<
"Value " << input <<
" not in range [";
295 out << min_val <<
" - " << max_val <<
"]";
298 return std::string{};
303 template <
typename T>
304 explicit Range(T max_val,
const std::string &validator_name = std::string{})
305 :
Range(static_cast<T>(0), max_val, validator_name) {}
312const Range PositiveNumber((std::numeric_limits<double>::min)(), (std::numeric_limits<double>::max)(),
"POSITIVE");
321 template <
typename T>
Bound(T min_val, T max_val) {
322 std::stringstream out;
323 out << detail::type_name<T>() <<
" bounded to [" << min_val <<
" - " << max_val <<
"]";
324 description(out.str());
326 func_ = [min_val, max_val](std::string &input) {
329 bool converted = lexical_cast(input, val);
331 return std::string(
"Value ") + input +
" could not be converted";
334 input = detail::to_string(min_val);
335 else if(val > max_val)
336 input = detail::to_string(max_val);
338 return std::string{};
343 template <
typename T>
explicit Bound(T max_val) :
Bound(static_cast<T>(0), max_val) {}
348 enable_if_t<is_copyable_ptr<typename std::remove_reference<T>::type>::value, detail::enabler> = detail::dummy>
363 std::string out(1,
'{');
364 out.append(detail::join(
365 detail::smart_deref(set),
373template <
typename T> std::string
generate_map(
const T &map,
bool key_only =
false) {
376 std::string out(1,
'{');
377 out.append(detail::join(
378 detail::smart_deref(map),
379 [key_only](
const iteration_type_t &v) {
394 template <
typename CC,
typename VV>
395 static auto test(
int) ->
decltype(std::declval<CC>().find(std::declval<VV>()), std::true_type());
396 template <
typename,
typename>
static auto test(...) ->
decltype(std::false_type());
398 static const auto value =
decltype(test<C, V>(0))::value;
399 using type = std::integral_constant<bool, value>;
403template <typename T, typename V, enable_if_t<!has_find<T, V>::value,
detail::enabler> = detail::dummy>
404auto search(
const T &set,
const V &val) -> std::pair<bool,
decltype(std::begin(detail::smart_deref(set)))> {
406 auto &setref = detail::smart_deref(set);
407 auto it = std::find_if(std::begin(setref), std::end(setref), [&val](
decltype(*std::begin(setref)) v) {
410 return {(it != std::end(setref)), it};
414template <typename T, typename V, enable_if_t<has_find<T, V>::value,
detail::enabler> = detail::dummy>
415auto search(
const T &set,
const V &val) -> std::pair<bool,
decltype(std::begin(detail::smart_deref(set)))> {
416 auto &setref = detail::smart_deref(set);
417 auto it = setref.find(val);
418 return {(it != std::end(setref)), it};
422template <
typename T,
typename V>
423auto search(
const T &set,
const V &val,
const std::function<V(V)> &filter_function)
424 -> std::pair<bool,
decltype(std::begin(detail::smart_deref(set)))> {
427 auto res =
search(set, val);
428 if((res.first) || (!(filter_function))) {
432 auto &setref = detail::smart_deref(set);
433 auto it = std::find_if(std::begin(setref), std::end(setref), [&](
decltype(*std::begin(setref)) v) {
435 a = filter_function(a);
438 return {(it != std::end(setref)), it};
446inline typename std::enable_if<std::is_signed<T>::value, T>::type
overflowCheck(
const T &a,
const T &b) {
447 if((a > 0) == (b > 0)) {
448 return ((std::numeric_limits<T>::max)() / (std::abs)(a) < (std::abs)(b));
450 return ((std::numeric_limits<T>::min)() / (std::abs)(a) > -(std::abs)(b));
454inline typename std::enable_if<!std::is_signed<T>::value, T>::type
overflowCheck(
const T &a,
const T &b) {
455 return ((std::numeric_limits<T>::max)() / a < b);
459template <
typename T>
typename std::enable_if<std::is_integral<T>::value,
bool>::type
checked_multiply(T &a, T b) {
460 if(a == 0 || b == 0 || a == 1 || b == 1) {
464 if(a == (std::numeric_limits<T>::min)() || b == (std::numeric_limits<T>::min)()) {
476typename std::enable_if<std::is_floating_point<T>::value,
bool>::type
checked_multiply(T &a, T b) {
478 if(std::isinf(c) && !std::isinf(a) && !std::isinf(b)) {
492 template <
typename T,
typename... Args>
493 IsMember(std::initializer_list<T> values, Args &&...args)
494 :
IsMember(std::vector<T>(values), std::forward<Args>(args)...) {}
497 template <
typename T>
explicit IsMember(T &&set) :
IsMember(std::forward<T>(set), nullptr) {}
501 template <
typename T,
typename F>
explicit IsMember(T set, F filter_function) {
512 std::function<local_item_t(local_item_t)> filter_fn = filter_function;
515 desc_function_ = [set]() {
return detail::generate_set(detail::smart_deref(set)); };
519 func_ = [set, filter_fn](std::string &input) {
522 if(!lexical_cast(input, b)) {
528 auto res = detail::search(set, b, filter_fn);
536 return std::string{};
540 return input +
" not in " + detail::generate_set(detail::smart_deref(set));
545 template <
typename T,
typename... Args>
548 std::forward<T>(set),
549 [filter_fn_1, filter_fn_2](std::string a) {
return filter_fn_2(filter_fn_1(a)); },
554template <
typename T>
using TransformPairs = std::vector<std::pair<std::string, T>>;
562 template <
typename... Args>
563 Transformer(std::initializer_list<std::pair<std::string, std::string>> values, Args &&...args)
571 template <
typename T,
typename F>
explicit Transformer(T mapping, F filter_function) {
574 "mapping must produce value pairs");
583 std::function<local_item_t(local_item_t)> filter_fn = filter_function;
586 desc_function_ = [mapping]() {
return detail::generate_map(detail::smart_deref(mapping)); };
588 func_ = [mapping, filter_fn](std::string &input) {
591 if(!lexical_cast(input, b)) {
592 return std::string();
598 auto res = detail::search(mapping, b, filter_fn);
602 return std::string{};
607 template <
typename T,
typename... Args>
610 std::forward<T>(mapping),
611 [filter_fn_1, filter_fn_2](std::string a) {
return filter_fn_2(filter_fn_1(a)); },
621 template <
typename... Args>
622 CheckedTransformer(std::initializer_list<std::pair<std::string, std::string>> values, Args &&...args)
633 "mapping must produce value pairs");
643 std::function<local_item_t(local_item_t)> filter_fn = filter_function;
645 auto tfunc = [mapping]() {
646 std::string out(
"value in ");
647 out += detail::generate_map(detail::smart_deref(mapping)) +
" OR {";
649 detail::smart_deref(mapping),
656 desc_function_ = tfunc;
658 func_ = [mapping, tfunc, filter_fn](std::string &input) {
661 bool converted = lexical_cast(input, b);
666 auto res = detail::search(mapping, b, filter_fn);
669 return std::string{};
672 for(
const auto &v : detail::smart_deref(mapping)) {
674 if(output_string == input) {
675 return std::string();
679 return "Check " + input +
" " + tfunc() +
" FAILED";
684 template <
typename T,
typename... Args>
687 std::forward<T>(mapping),
688 [filter_fn_1, filter_fn_2](std::string a) {
return filter_fn_2(filter_fn_1(a)); },
693inline std::string
ignore_case(std::string item) {
return detail::to_lower(item); }
696inline std::string
ignore_underscore(std::string item) {
return detail::remove_underscore(item); }
700 item.erase(std::remove(std::begin(item), std::end(item),
' '), std::end(item));
701 item.erase(std::remove(std::begin(item), std::end(item),
'\t'), std::end(item));
724 CASE_INSENSITIVE = 1,
727 DEFAULT = CASE_INSENSITIVE | UNIT_OPTIONAL
730 template <
typename Number>
733 const std::string &unit_name =
"UNIT") {
734 description(generate_description<Number>(unit_name, opts));
735 validate_mapping(mapping, opts);
738 func_ = [mapping, opts](std::string &input) -> std::string {
741 detail::rtrim(input);
747 auto unit_begin = input.end();
748 while(unit_begin > input.begin() && std::isalpha(*(unit_begin - 1), std::locale())) {
752 std::string unit{unit_begin, input.end()};
753 input.resize(
static_cast<std::size_t
>(std::distance(input.begin(), unit_begin)));
756 if(opts & UNIT_REQUIRED && unit.empty()) {
759 if(opts & CASE_INSENSITIVE) {
760 unit = detail::to_lower(unit);
764 if(!lexical_cast(input, num)) {
765 throw ValidationError(std::string(
"Value ") + input +
" could not be converted to " +
766 detail::type_name<Number>());
773 auto it = mapping.find(unit);
774 if(it == mapping.end()) {
776 " unit not recognized. "
778 detail::generate_map(mapping,
true));
783 bool converted = lexical_cast(input, num);
785 throw ValidationError(std::string(
"Value ") + input +
" could not be converted to " +
786 detail::type_name<Number>());
789 bool ok = detail::checked_multiply(num, it->second);
791 throw ValidationError(detail::to_string(num) +
" multiplied by " + unit +
792 " factor would cause number overflow. Use smaller value.");
795 num =
static_cast<Number>(it->second);
798 input = detail::to_string(num);
807 template <
typename Number>
static void validate_mapping(std::map<std::string, Number> &mapping, Options opts) {
808 for(
auto &kv : mapping) {
809 if(kv.first.empty()) {
812 if(!detail::isalpha(kv.first)) {
813 throw ValidationError(
"Unit must contain only letters.");
818 if(opts & CASE_INSENSITIVE) {
819 std::map<std::string, Number> lower_mapping;
820 for(
auto &kv : mapping) {
821 auto s = detail::to_lower(kv.first);
822 if(lower_mapping.count(s)) {
823 throw ValidationError(std::string(
"Several matching lowercase unit representations are found: ") +
826 lower_mapping[detail::to_lower(kv.first)] = kv.second;
828 mapping = std::move(lower_mapping);
833 template <
typename Number>
static std::string generate_description(
const std::string &name, Options opts) {
834 std::stringstream out;
835 out << detail::type_name<Number>() <<
' ';
836 if(opts & UNIT_REQUIRED) {
839 out <<
'[' << name <<
']';
875 static std::map<std::string, result_t> init_mapping(
bool kb_is_1000);
878 static std::map<std::string, result_t> get_mapping(
bool kb_is_1000);
895#include "impl/Validators_inl.hpp"
#define CLI11_INLINE
Definition Macros.hpp:129
#define CLI11_NODISCARD
Definition Macros.hpp:47
Definition Validators.hpp:716
Options
Definition Validators.hpp:722
AsNumberWithUnit(std::map< std::string, Number > mapping, Options opts=DEFAULT, const std::string &unit_name="UNIT")
Definition Validators.hpp:731
Definition Validators.hpp:860
AsSizeValue(bool kb_is_1000)
std::uint64_t result_t
Definition Validators.hpp:862
Produce a bounded range (factory). Min and max are inclusive.
Definition Validators.hpp:315
Bound(T min_val, T max_val)
Definition Validators.hpp:321
Bound(T max_val)
Range of one value is 0 to value.
Definition Validators.hpp:343
Class wrapping some of the accessors of Validator.
Definition Validators.hpp:177
Definition Validators.hpp:268
FileOnDefaultPath(std::string default_path, bool enableErrorReturn=true)
Verify items are in a set.
Definition Validators.hpp:487
IsMember(T &&set)
This checks to see if an item is in a set (empty function)
Definition Validators.hpp:497
IsMember(T set, F filter_function)
Definition Validators.hpp:501
IsMember(T &&set, filter_fn_t filter_fn_1, filter_fn_t filter_fn_2, Args &&...other)
You can pass in as many filter functions as you like, they nest (string only currently)
Definition Validators.hpp:546
IsMember(std::initializer_list< T > values, Args &&...args)
This allows in-place construction using an initializer list.
Definition Validators.hpp:493
std::function< std::string(std::string)> filter_fn_t
Definition Validators.hpp:489
Produce a range (factory). Min and max are inclusive.
Definition Validators.hpp:274
Range(T min_val, T max_val, const std::string &validator_name=std::string{})
Definition Validators.hpp:281
Range(T max_val, const std::string &validator_name=std::string{})
Range of one value is 0 to value.
Definition Validators.hpp:304
Validate the input as a particular type.
Definition Validators.hpp:249
TypeValidator()
Definition Validators.hpp:260
TypeValidator(const std::string &validator_name)
Definition Validators.hpp:251
Thrown when validation of results fails.
Definition Error.hpp:219
Some validators that are provided.
Definition Validators.hpp:53
CLI11_NODISCARD int get_application_index() const
Get the current value of the application index.
Definition Validators.hpp:154
int application_index_
A Validator will only apply to an indexed value (-1 is all elements)
Definition Validators.hpp:64
Validator & non_modifying(bool no_modify=true)
Specify whether the Validator can be modifying or not.
Definition Validators.hpp:138
Validator & description(std::string validator_desc)
Specify the type string.
Definition Validators.hpp:98
std::string operator()(const std::string &str) const
Definition Validators.hpp:92
CLI11_NODISCARD Validator application_index(int app_index) const
Specify the application index of a validator.
Definition Validators.hpp:148
CLI11_NODISCARD bool get_active() const
Get a boolean if the validator is active.
Definition Validators.hpp:156
Validator operator&(const Validator &other) const
bool active_
Enable for Validator to allow it to be disabled if need be.
Definition Validators.hpp:66
bool non_modifying_
specify that a validator should not modify the input
Definition Validators.hpp:68
Validator(std::string validator_desc)
Construct a Validator with just the description string.
Definition Validators.hpp:76
Validator(std::string validator_desc, std::function< std::string(std::string &)> func)
Definition Validators.hpp:70
CLI11_NODISCARD Validator description(std::string validator_desc) const
Specify the type string.
Validator & name(std::string validator_name)
Specify the type string.
Definition Validators.hpp:113
std::string operator()(std::string &str) const
std::function< std::string()> desc_function_
This is the description function, if empty the description_ will be used.
Definition Validators.hpp:56
std::function< std::string(std::string &)> func_
Definition Validators.hpp:60
CLI11_NODISCARD std::string get_description() const
Generate type description information for the Validator.
Definition Validators.hpp:106
Validator operator!() const
Create a validator that fails when a given validator succeeds.
CLI11_NODISCARD Validator active(bool active_val=true) const
Specify whether the Validator is active or not.
Definition Validators.hpp:131
CLI11_NODISCARD const std::string & get_name() const
Get the name of the Validator.
Definition Validators.hpp:124
Validator operator|(const Validator &other) const
Validator & active(bool active_val=true)
Specify whether the Validator is active or not.
Definition Validators.hpp:126
std::string name_
The name for search purposes of the Validator.
Definition Validators.hpp:62
CLI11_NODISCARD bool get_modifying() const
Get a boolean if the validator is allowed to modify the input returns true if it can modify the input...
Definition Validators.hpp:159
CLI11_NODISCARD Validator name(std::string validator_name) const
Specify the type string.
Definition Validators.hpp:118
Validator & application_index(int app_index)
Specify the application index of a validator.
Definition Validators.hpp:143
Validator(std::function< std::string(std::string &)> op, std::string validator_desc, std::string validator_name="")
Construct Validator from basic information.
Definition Validators.hpp:78
Validator & operation(std::function< std::string(std::string &)> op)
Set the Validator operation function.
Definition Validators.hpp:82
Check for an existing directory (returns error message if check fails)
Definition Validators.hpp:198
ExistingDirectoryValidator()
Check for an existing file (returns error message if check fails)
Definition Validators.hpp:192
Check for an existing path.
Definition Validators.hpp:204
Validate the given string is a legal ipv4 address.
Definition Validators.hpp:216
Check for an non-existing path.
Definition Validators.hpp:210
NonexistentPathValidator()
auto smart_deref(T value) -> decltype(*value)
Definition Validators.hpp:349
path_type
CLI enumeration of different file types.
Definition Validators.hpp:186
std::string generate_map(const T &map, bool key_only=false)
Generate a string representation of a map.
Definition Validators.hpp:373
std::enable_if< std::is_signed< T >::value, T >::type overflowCheck(const T &a, const T &b)
Do a check for overflow on signed numbers.
Definition Validators.hpp:446
std::enable_if< std::is_integral< T >::value, bool >::type checked_multiply(T &a, T b)
Performs a *= b; if it doesn't cause integer overflow. Returns false otherwise.
Definition Validators.hpp:459
std::string generate_set(const T &set)
Generate a string representation of a set.
Definition Validators.hpp:360
CLI11_INLINE path_type check_path(const char *file) noexcept
get the type of the path from a file name
auto search(const T &set, const V &val) -> std::pair< bool, decltype(std::begin(detail::smart_deref(set)))>
A search function.
Definition Validators.hpp:404
CLI11_INLINE std::pair< std::string, std::string > split_program_name(std::string commandline)
enabler
Simple empty scoped class.
Definition TypeTools.hpp:34
bool lexical_cast(const std::string &input, T &output)
Integer conversion.
Definition TypeTools.hpp:1015
std::string ignore_case(std::string item)
Helper function to allow ignore_case to be passed to IsMember or Transform.
Definition Validators.hpp:693
std::string ignore_underscore(std::string item)
Helper function to allow ignore_underscore to be passed to IsMember or Transform.
Definition Validators.hpp:696
const detail::ExistingDirectoryValidator ExistingDirectory
Check for an existing directory (returns error message if check fails)
Definition Validators.hpp:234
typename std::enable_if< B, T >::type enable_if_t
Definition TypeTools.hpp:45
AsNumberWithUnit::Options operator|(const AsNumberWithUnit::Options &a, const AsNumberWithUnit::Options &b)
Definition Validators.hpp:845
const detail::EscapedStringTransformer EscapedString
convert escaped characters into their associated values
Definition Validators.hpp:246
const detail::NonexistentPathValidator NonexistentPath
Check for an non-existing path.
Definition Validators.hpp:240
const detail::IPV4Validator ValidIPV4
Check for an IP4 address.
Definition Validators.hpp:243
const detail::ExistingPathValidator ExistingPath
Check for an existing path.
Definition Validators.hpp:237
const detail::ExistingFileValidator ExistingFile
Check for existing file (returns error message if check fails)
Definition Validators.hpp:231
const Range NonNegativeNumber((std::numeric_limits< double >::max)(), "NONNEGATIVE")
Check for a non negative number.
std::string ignore_space(std::string item)
Helper function to allow checks to ignore spaces to be passed to IsMember or Transform.
Definition Validators.hpp:699
const Range PositiveNumber((std::numeric_limits< double >::min)(),(std::numeric_limits< double >::max)(), "POSITIVE")
Check for a positive valued number (val>0.0), <double>::min here is the smallest positive number.
const TypeValidator< double > Number("NUMBER")
Check for a number.
std::vector< std::pair< std::string, T > > TransformPairs
definition of the default transformation object
Definition Validators.hpp:554
T type
Definition TypeTools.hpp:80
T type
Definition TypeTools.hpp:97
Definition Validators.hpp:393
std::integral_constant< bool, value > type
Definition Validators.hpp:399
static auto test(int) -> decltype(std::declval< CC >().find(std::declval< VV >()), std::true_type())
static auto test(...) -> decltype(std::false_type())
Adaptor for set-like structure: This just wraps a normal container in a few utilities that do almost ...
Definition TypeTools.hpp:111
typename T::value_type value_type
Definition TypeTools.hpp:112
typename std::remove_const< value_type >::type first_type
Definition TypeTools.hpp:113