28 #if defined CLI11_CPP17 && defined __has_include && !defined CLI11_HAS_FILESYSTEM
29 #if __has_include(<filesystem>)
31 #if defined __MAC_OS_X_VERSION_MIN_REQUIRED && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500
32 #define CLI11_HAS_FILESYSTEM 0
35 #if defined __cpp_lib_filesystem && __cpp_lib_filesystem >= 201703
36 #if defined _GLIBCXX_RELEASE && _GLIBCXX_RELEASE >= 9
37 #define CLI11_HAS_FILESYSTEM 1
38 #elif defined(__GLIBCXX__)
40 #define CLI11_HAS_FILESYSTEM 0
42 #define CLI11_HAS_FILESYSTEM 1
45 #define CLI11_HAS_FILESYSTEM 0
51 #if defined CLI11_HAS_FILESYSTEM && CLI11_HAS_FILESYSTEM > 0
55 #include <sys/types.h>
81 std::function<std::string(std::string &)>
func_{[](std::string &) {
return std::string{}; }};
96 Validator(std::function<std::string(std::string &)> op, std::string validator_desc, std::string validator_name =
"")
98 name_(std::move(validator_name)) {}
101 func_ = std::move(op);
107 std::string retstring;
110 std::string value = str;
111 retstring =
func_(value);
113 retstring =
func_(str);
122 std::string value = str;
134 newval.
desc_function_ = [validator_desc]() {
return validator_desc; };
142 return std::string{};
146 name_ = std::move(validator_name);
152 newval.
name_ = std::move(validator_name);
198 newval._merge_description(*
this, other,
" AND ");
201 const std::function<std::string(std::string & filename)> &f1 =
func_;
202 const std::function<std::string(std::string & filename)> &f2 = other.func_;
204 newval.
func_ = [f1, f2](std::string &input) {
205 std::string s1 = f1(input);
206 std::string s2 = f2(input);
207 if(!s1.empty() && !s2.empty())
208 return std::string(
"(") + s1 +
") AND (" + s2 +
")";
223 newval._merge_description(*
this, other,
" OR ");
226 const std::function<std::string(std::string &)> &f1 =
func_;
227 const std::function<std::string(std::string &)> &f2 = other.func_;
229 newval.
func_ = [f1, f2](std::string &input) {
230 std::string s1 = f1(input);
231 std::string s2 = f2(input);
232 if(s1.empty() || s2.empty())
233 return std::string();
235 return std::string(
"(") + s1 +
") OR (" + s2 +
")";
248 return (!str.empty()) ? std::string(
"NOT ") + str : std::string{};
251 const std::function<std::string(std::string & res)> &f1 =
func_;
253 newval.
func_ = [f1, dfunc1](std::string &test) -> std::string {
254 std::string s1 = f1(test);
256 return std::string(
"check ") + dfunc1() +
" succeeded improperly";
258 return std::string{};
266 void _merge_description(
const Validator &val1,
const Validator &val2,
const std::string &merger) {
272 std::string f1 = dfunc1();
273 std::string f2 = dfunc2();
274 if((f1.empty()) || (f2.empty())) {
277 return std::string(1,
'(') + f1 +
')' + merger +
'(' + f2 +
')';
294 #if defined CLI11_HAS_FILESYSTEM && CLI11_HAS_FILESYSTEM > 0
298 auto stat = std::filesystem::status(file, ec);
302 switch(stat.type()) {
303 case std::filesystem::file_type::none:
304 case std::filesystem::file_type::not_found:
306 case std::filesystem::file_type::directory:
308 case std::filesystem::file_type::symlink:
309 case std::filesystem::file_type::block:
310 case std::filesystem::file_type::character:
311 case std::filesystem::file_type::fifo:
312 case std::filesystem::file_type::socket:
313 case std::filesystem::file_type::regular:
314 case std::filesystem::file_type::unknown:
322 #if defined(_MSC_VER)
323 struct __stat64 buffer;
324 if(_stat64(
file, &buffer) == 0) {
329 if(stat(
file, &buffer) == 0) {
340 func_ = [](std::string &filename) {
341 auto path_result =
check_path(filename.c_str());
343 return "File does not exist: " + filename;
346 return "File is actually a directory: " + filename;
348 return std::string();
357 func_ = [](std::string &filename) {
358 auto path_result =
check_path(filename.c_str());
360 return "Directory does not exist: " + filename;
363 return "Directory is actually a file: " + filename;
365 return std::string();
374 func_ = [](std::string &filename) {
375 auto path_result =
check_path(filename.c_str());
377 return "Path does not exist: " + filename;
379 return std::string();
388 func_ = [](std::string &filename) {
389 auto path_result =
check_path(filename.c_str());
391 return "Path already exists: " + filename;
393 return std::string();
402 func_ = [](std::string &ip_addr) {
404 if(result.size() != 4) {
405 return std::string(
"Invalid IPV4 address must have four parts (") + ip_addr +
')';
408 for(
const auto &var : result) {
411 return std::string(
"Failed parsing number (") + var +
')';
413 if(num < 0 || num > 255) {
414 return std::string(
"Each IP number must be between 0 and 255 ") + var;
417 return std::string();
426 func_ = [](std::string &number_str) {
429 return std::string(
"Failed parsing number: (") + number_str +
')';
432 return std::string(
"Number less or equal to 0: (") + number_str +
')';
434 return std::string();
442 func_ = [](std::string &number_str) {
445 return std::string(
"Failed parsing number: (") + number_str +
')';
448 return std::string(
"Number less than 0: (") + number_str +
')';
450 return std::string();
459 func_ = [](std::string &number_str) {
462 return std::string(
"Failed parsing as a number (") + number_str +
')';
464 return std::string();
504 template <
typename T>
Range(T min, T max) {
505 std::stringstream out;
506 out << detail::type_name<T>() <<
" in [" << min <<
" - " << max <<
"]";
509 func_ = [min, max](std::string &input) {
512 if((!converted) || (val < min || val > max))
513 return std::string(
"Value ") + input +
" not in range " +
std::to_string(min) +
" to " +
516 return std::string();
521 template <
typename T>
explicit Range(T max) :
Range(static_cast<T>(0), max) {}
531 template <
typename T>
Bound(T min, T max) {
532 std::stringstream out;
533 out << detail::type_name<T>() <<
" bounded to [" << min <<
" - " << max <<
"]";
536 func_ = [min, max](std::string &input) {
540 return std::string(
"Value ") + input +
" could not be converted";
547 return std::string{};
552 template <
typename T>
explicit Bound(T max) :
Bound(static_cast<T>(0), max) {}
556 template <
typename T,
572 std::string out(1,
'{');
582 template <
typename T> std::string
generate_map(
const T &map,
bool key_only =
false) {
585 std::string out(1,
'{');
588 [key_only](
const iteration_type_t &v) {
602 template <
typename C,
typename V>
struct has_find {
603 template <
typename CC,
typename VV>
604 static auto test(
int) -> decltype(std::declval<CC>().find(std::declval<VV>()), std::true_type());
605 template <
typename,
typename>
static auto test(...) -> decltype(std::false_type());
608 using type = std::integral_constant<bool, value>;
616 auto it = std::find_if(std::begin(setref), std::end(setref), [&val](decltype(*std::begin(setref)) v) {
619 return {(it != std::end(setref)), it};
626 auto it = setref.find(val);
627 return {(it != std::end(setref)), it};
631 template <
typename T,
typename V>
632 auto search(
const T &set,
const V &val,
const std::function<V(V)> &filter_function)
636 auto res =
search(set, val);
637 if((res.first) || (!(filter_function))) {
642 auto it = std::find_if(std::begin(setref), std::end(setref), [&](decltype(*std::begin(setref)) v) {
644 a = filter_function(a);
647 return {(it != std::end(setref)), it};
654 template <
typename T>
655 inline typename std::enable_if<std::is_signed<T>::value, T>::type
overflowCheck(
const T &a,
const T &b) {
656 if((a > 0) == (b > 0)) {
657 return ((std::numeric_limits<T>::max)() / (std::abs)(a) < (std::abs)(b));
659 return ((std::numeric_limits<T>::min)() / (std::abs)(a) > -(std::abs)(b));
663 template <
typename T>
664 inline typename std::enable_if<!std::is_signed<T>::value, T>::type
overflowCheck(
const T &a,
const T &b) {
665 return ((std::numeric_limits<T>::max)() / a < b);
669 template <
typename T>
typename std::enable_if<std::is_integral<T>::value,
bool>::type
checked_multiply(T &a, T b) {
670 if(a == 0 || b == 0 || a == 1 || b == 1) {
674 if(a == (std::numeric_limits<T>::min)() || b == (std::numeric_limits<T>::min)()) {
685 template <
typename T>
686 typename std::enable_if<std::is_floating_point<T>::value,
bool>::type
checked_multiply(T &a, T b) {
688 if(std::isinf(c) && !std::isinf(a) && !std::isinf(b)) {
702 template <
typename T,
typename... Args>
703 IsMember(std::initializer_list<T> values, Args &&... args)
704 :
IsMember(std::vector<T>(values), std::forward<Args>(args)...) {}
707 template <
typename T>
explicit IsMember(T &&set) :
IsMember(std::forward<T>(set), nullptr) {}
711 template <
typename T,
typename F>
explicit IsMember(T set, F filter_function) {
722 std::function<local_item_t(local_item_t)> filter_fn = filter_function;
729 func_ = [set, filter_fn](std::string &input) {
745 return std::string{};
749 std::string out(
" not in ");
756 template <
typename T,
typename... Args>
759 std::forward<T>(set),
760 [filter_fn_1, filter_fn_2](std::string a) {
return filter_fn_2(filter_fn_1(a)); },
765 template <
typename T>
using TransformPairs = std::vector<std::pair<std::string, T>>;
773 template <
typename... Args>
774 Transformer(std::initializer_list<std::pair<std::string, std::string>> values, Args &&... args)
782 template <
typename T,
typename F>
explicit Transformer(T mapping, F filter_function) {
785 "mapping must produce value pairs");
794 std::function<local_item_t(local_item_t)> filter_fn = filter_function;
799 func_ = [mapping, filter_fn](std::string &input) {
802 return std::string();
812 return std::string{};
817 template <
typename T,
typename... Args>
820 std::forward<T>(mapping),
821 [filter_fn_1, filter_fn_2](std::string a) {
return filter_fn_2(filter_fn_1(a)); },
831 template <
typename... Args>
832 CheckedTransformer(std::initializer_list<std::pair<std::string, std::string>> values, Args &&... args)
843 "mapping must produce value pairs");
853 std::function<local_item_t(local_item_t)> filter_fn = filter_function;
855 auto tfunc = [mapping]() {
856 std::string out(
"value in ");
868 func_ = [mapping, tfunc, filter_fn](std::string &input) {
878 return std::string{};
883 if(output_string == input) {
884 return std::string();
888 return "Check " + input +
" " + tfunc() +
" FAILED";
893 template <
typename T,
typename... Args>
896 std::forward<T>(mapping),
897 [filter_fn_1, filter_fn_2](std::string a) {
return filter_fn_2(filter_fn_1(a)); },
909 item.erase(std::remove(std::begin(item), std::end(item),
' '), std::end(item));
910 item.erase(std::remove(std::begin(item), std::end(item),
'\t'), std::end(item));
939 template <
typename Number>
942 const std::string &unit_name =
"UNIT") {
943 description(generate_description<Number>(unit_name, opts));
944 validate_mapping(mapping, opts);
947 func_ = [mapping, opts](std::string &input) -> std::string {
956 auto unit_begin = input.end();
957 while(unit_begin > input.begin() &&
std::isalpha(*(unit_begin - 1), std::locale())) {
961 std::string unit{unit_begin, input.end()};
962 input.resize(
static_cast<std::size_t
>(std::distance(input.begin(), unit_begin)));
974 throw ValidationError(std::string(
"Value ") + input +
" could not be converted to " +
975 detail::type_name<Number>());
984 auto it = mapping.find(unit);
985 if(it == mapping.end()) {
987 " unit not recognized. "
996 " factor would cause number overflow. Use smaller value.");
1007 template <
typename Number>
static void validate_mapping(std::map<std::string, Number> &mapping,
Options opts) {
1008 for(
auto &kv : mapping) {
1009 if(kv.first.empty()) {
1013 throw ValidationError(
"Unit must contain only letters.");
1019 std::map<std::string, Number> lower_mapping;
1020 for(
auto &kv : mapping) {
1022 if(lower_mapping.count(s)) {
1023 throw ValidationError(std::string(
"Several matching lowercase unit representations are found: ") +
1028 mapping = std::move(lower_mapping);
1033 template <
typename Number>
static std::string generate_description(
const std::string &
name,
Options opts) {
1034 std::stringstream out;
1035 out << detail::type_name<Number>() <<
' ';
1039 out <<
'[' <<
name <<
']';
1069 description(
"SIZE [b, kb(=1000b), kib(=1024b), ...]");
1077 static std::map<std::string, result_t> init_mapping(
bool kb_is_1000) {
1078 std::map<std::string, result_t> m;
1079 result_t k_factor = kb_is_1000 ? 1000 : 1024;
1084 for(std::string p : {
"k",
"m",
"g",
"t",
"p",
"e"}) {
1096 static std::map<std::string, result_t> get_mapping(
bool kb_is_1000) {
1098 static auto m = init_mapping(
true);
1101 static auto m = init_mapping(
false);
1114 std::pair<std::string, std::string> vals;
1116 auto esp = commandline.find_first_of(
' ', 1);
1118 esp = commandline.find_first_of(
' ', esp + 1);
1119 if(esp == std::string::npos) {
1122 esp = commandline.find_first_of(
' ', 1);
1126 vals.first = commandline.substr(0, esp);
1129 vals.second = (esp != std::string::npos) ? commandline.substr(esp + 1) : std::string{};
Definition: Validators.hpp:925
Options
Definition: Validators.hpp:931
@ UNIT_OPTIONAL
Definition: Validators.hpp:934
@ CASE_INSENSITIVE
Definition: Validators.hpp:933
@ DEFAULT
Definition: Validators.hpp:936
@ UNIT_REQUIRED
Definition: Validators.hpp:935
@ CASE_SENSITIVE
Definition: Validators.hpp:932
AsNumberWithUnit(std::map< std::string, Number > mapping, Options opts=DEFAULT, const std::string &unit_name="UNIT")
Definition: Validators.hpp:940
Definition: Validators.hpp:1056
AsSizeValue(bool kb_is_1000)
Definition: Validators.hpp:1067
std::uint64_t result_t
Definition: Validators.hpp:1058
Produce a bounded range (factory). Min and max are inclusive.
Definition: Validators.hpp:525
Bound(T max)
Range of one value is 0 to value.
Definition: Validators.hpp:552
Bound(T min, T max)
Definition: Validators.hpp:531
Class wrapping some of the accessors of Validator.
Definition: Validators.hpp:283
Verify items are in a set.
Definition: Validators.hpp:697
IsMember(T &&set)
This checks to see if an item is in a set (empty function)
Definition: Validators.hpp:707
IsMember(T set, F filter_function)
Definition: Validators.hpp:711
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:757
IsMember(std::initializer_list< T > values, Args &&... args)
This allows in-place construction using an initializer list.
Definition: Validators.hpp:703
std::function< std::string(std::string)> filter_fn_t
Definition: Validators.hpp:699
Produce a range (factory). Min and max are inclusive.
Definition: Validators.hpp:498
Range(T max)
Range of one value is 0 to value.
Definition: Validators.hpp:521
Range(T min, T max)
Definition: Validators.hpp:504
Thrown when validation of results fails.
Definition: Error.hpp:202
Some validators that are provided.
Definition: Validators.hpp:74
bool get_active() const
Get a boolean if the validator is active.
Definition: Validators.hpp:188
Validator & description(std::string validator_desc)
Specify the type string.
Definition: Validators.hpp:127
int application_index_
A Validator will only apply to an indexed value (-1 is all elements)
Definition: Validators.hpp:85
std::string operator()(const std::string &str) const
Definition: Validators.hpp:121
Validator & operation(std::function< std::string(std::string &)> op)
Set the Validator operation function.
Definition: Validators.hpp:100
Validator operator&(const Validator &other) const
Definition: Validators.hpp:195
bool active_
Enable for Validator to allow it to be disabled if need be.
Definition: Validators.hpp:87
Validator name(std::string validator_name) const
Specify the type string.
Definition: Validators.hpp:150
Validator application_index(int app_index) const
Specify the application index of a validator.
Definition: Validators.hpp:180
bool non_modifying_
specify that a validator should not modify the input
Definition: Validators.hpp:89
Validator & name(std::string validator_name)
Specify the type string.
Definition: Validators.hpp:145
Validator(std::string validator_desc)
Construct a Validator with just the description string.
Definition: Validators.hpp:94
std::string get_description() const
Generate type description information for the Validator.
Definition: Validators.hpp:138
std::string operator()(std::string &str) const
Definition: Validators.hpp:106
Validator active(bool active_val=true) const
Specify whether the Validator is active or not.
Definition: Validators.hpp:163
std::function< std::string()> desc_function_
This is the description function, if empty the description_ will be used.
Definition: Validators.hpp:77
int get_application_index() const
Get the current value of the application index.
Definition: Validators.hpp:186
std::function< std::string(std::string &)> func_
Definition: Validators.hpp:81
Validator operator!() const
Create a validator that fails when a given validator succeeds.
Definition: Validators.hpp:243
const std::string & get_name() const
Get the name of the Validator.
Definition: Validators.hpp:156
Validator operator|(const Validator &other) const
Definition: Validators.hpp:220
std::string name_
The name for search purposes of the Validator.
Definition: Validators.hpp:83
Validator description(std::string validator_desc) const
Specify the type string.
Definition: Validators.hpp:132
Validator & active(bool active_val=true)
Specify whether the Validator is active or not.
Definition: Validators.hpp:158
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:191
Validator(std::function< std::string(std::string &)> op, std::string validator_desc, std::string validator_name="")
Construct Validator from basic information.
Definition: Validators.hpp:96
Validator & application_index(int app_index)
Specify the application index of a validator.
Definition: Validators.hpp:175
Validator & non_modifying(bool no_modify=true)
Specify whether the Validator can be modifying or not.
Definition: Validators.hpp:170
Check for an existing directory (returns error message if check fails)
Definition: Validators.hpp:354
ExistingDirectoryValidator()
Definition: Validators.hpp:356
Check for an existing file (returns error message if check fails)
Definition: Validators.hpp:337
ExistingFileValidator()
Definition: Validators.hpp:339
Check for an existing path.
Definition: Validators.hpp:371
ExistingPathValidator()
Definition: Validators.hpp:373
Validate the given string is a legal ipv4 address.
Definition: Validators.hpp:399
IPV4Validator()
Definition: Validators.hpp:401
Validate the argument is a number and greater than or equal to 0.
Definition: Validators.hpp:439
NonNegativeNumber()
Definition: Validators.hpp:441
Check for an non-existing path.
Definition: Validators.hpp:385
NonexistentPathValidator()
Definition: Validators.hpp:387
Validate the argument is a number.
Definition: Validators.hpp:456
Number()
Definition: Validators.hpp:458
Validate the argument is a number and greater than 0.
Definition: Validators.hpp:423
PositiveNumber()
Definition: Validators.hpp:425
constexpr enabler dummy
An instance to use in EnableIf.
Definition: TypeTools.hpp:29
auto smart_deref(T value) -> decltype(*value)
Definition: Validators.hpp:558
auto to_string(T &&value) -> decltype(std::forward< T >(value))
Convert an object to a string (directly forward if this can become a string)
Definition: TypeTools.hpp:226
path_type check_path(const char *file) noexcept
get the type of the path from a file name
Definition: Validators.hpp:321
path_type
CLI enumeration of different file types.
Definition: Validators.hpp:292
std::string generate_map(const T &map, bool key_only=false)
Generate a string representation of a map.
Definition: Validators.hpp:582
std::pair< std::string, std::string > split_program_name(std::string commandline)
Definition: Validators.hpp:1112
std::string remove_underscore(std::string str)
remove underscores from a string
Definition: StringTools.hpp:207
std::string generate_set(const T &set)
Generate a string representation of a set.
Definition: Validators.hpp:569
std::string value_string(const T &value)
get a string as a convertible value for arithmetic types
Definition: TypeTools.hpp:294
std::vector< std::string > split(const std::string &s, char delim)
Split a string by a delim.
Definition: StringTools.hpp:42
auto search(const T &set, const V &val) -> std::pair< bool, decltype(std::begin(detail::smart_deref(set)))>
A search function.
Definition: Validators.hpp:613
std::string join(const T &v, std::string delim=",")
Simple function to join a string.
Definition: StringTools.hpp:59
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:669
bool isalpha(const std::string &str)
Verify that str consists of letters only.
Definition: StringTools.hpp:194
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:655
std::string & ltrim(std::string &str)
Trim whitespace from left of string.
Definition: StringTools.hpp:101
std::string & trim(std::string &str)
Trim whitespace from string.
Definition: StringTools.hpp:130
std::string to_lower(std::string str)
Return a lower case version of a string.
Definition: StringTools.hpp:199
std::string & rtrim(std::string &str)
Trim whitespace from right of string.
Definition: StringTools.hpp:115
enabler
Simple empty scoped class.
Definition: TypeTools.hpp:26
bool lexical_cast(const std::string &input, T &output)
Signed integers.
Definition: TypeTools.hpp:609
std::string ignore_case(std::string item)
Helper function to allow ignore_case to be passed to IsMember or Transform.
Definition: Validators.hpp:902
std::string ignore_underscore(std::string item)
Helper function to allow ignore_underscore to be passed to IsMember or Transform.
Definition: Validators.hpp:905
typename std::enable_if< B, T >::type enable_if_t
Definition: TypeTools.hpp:37
const detail::ExistingDirectoryValidator ExistingDirectory
Check for an existing directory (returns error message if check fails)
Definition: Validators.hpp:477
const detail::NonNegativeNumber NonNegativeNumber
Check for a non-negative number.
Definition: Validators.hpp:492
const detail::Number Number
Check for a number.
Definition: Validators.hpp:495
const detail::NonexistentPathValidator NonexistentPath
Check for an non-existing path.
Definition: Validators.hpp:483
const detail::IPV4Validator ValidIPV4
Check for an IP4 address.
Definition: Validators.hpp:486
const detail::ExistingPathValidator ExistingPath
Check for an existing path.
Definition: Validators.hpp:480
std::vector< std::pair< std::string, T > > TransformPairs
definition of the default transformation object
Definition: Validators.hpp:765
const detail::ExistingFileValidator ExistingFile
Check for existing file (returns error message if check fails)
Definition: Validators.hpp:474
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:908
const detail::PositiveNumber PositiveNumber
Check for a positive number.
Definition: Validators.hpp:489
T type
Definition: TypeTools.hpp:78
T type
Definition: TypeTools.hpp:91
Definition: Validators.hpp:602
static const auto value
Definition: Validators.hpp:607
std::integral_constant< bool, value > type
Definition: Validators.hpp:608
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:102
typename T::value_type value_type
Definition: TypeTools.hpp:103
typename std::remove_const< value_type >::type first_type
Definition: TypeTools.hpp:104
static auto first(Q &&pair_value) -> decltype(std::forward< Q >(pair_value))
Get the first value (really just the underlying value)
Definition: TypeTools.hpp:108