CLI11 2.3.1
Loading...
Searching...
No Matches
Validators.hpp
Go to the documentation of this file.
1// Copyright (c) 2017-2022, University of Cincinnati, developed by Henry Schreiner
2// under NSF AWARD 1414736 and by the respective contributors.
3// All rights reserved.
4//
5// SPDX-License-Identifier: BSD-3-Clause
6
7#pragma once
8
9#include "Error.hpp"
10#include "Macros.hpp"
11#include "StringTools.hpp"
12#include "TypeTools.hpp"
13
14// [CLI11:public_includes:set]
15#include <cmath>
16#include <cstdint>
17#include <functional>
18#include <iostream>
19#include <limits>
20#include <map>
21#include <memory>
22#include <string>
23#include <utility>
24#include <vector>
25// [CLI11:public_includes:end]
26
27// [CLI11:validators_hpp_filesystem:verbatim]
28
29// C standard library
30// Only needed for existence checking
31#if defined CLI11_CPP17 && defined __has_include && !defined CLI11_HAS_FILESYSTEM
32#if __has_include(<filesystem>)
33// Filesystem cannot be used if targeting macOS < 10.15
34#if defined __MAC_OS_X_VERSION_MIN_REQUIRED && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500
35#define CLI11_HAS_FILESYSTEM 0
36#elif defined(__wasi__)
37// As of wasi-sdk-14, filesystem is not implemented
38#define CLI11_HAS_FILESYSTEM 0
39#else
40#include <filesystem>
41#if defined __cpp_lib_filesystem && __cpp_lib_filesystem >= 201703
42#if defined _GLIBCXX_RELEASE && _GLIBCXX_RELEASE >= 9
43#define CLI11_HAS_FILESYSTEM 1
44#elif defined(__GLIBCXX__)
45// if we are using gcc and Version <9 default to no filesystem
46#define CLI11_HAS_FILESYSTEM 0
47#else
48#define CLI11_HAS_FILESYSTEM 1
49#endif
50#else
51#define CLI11_HAS_FILESYSTEM 0
52#endif
53#endif
54#endif
55#endif
56
57#if defined CLI11_HAS_FILESYSTEM && CLI11_HAS_FILESYSTEM > 0
58#include <filesystem> // NOLINT(build/include)
59#else
60#include <sys/stat.h>
61#include <sys/types.h>
62#endif
63
64// [CLI11:validators_hpp_filesystem:end]
65
66namespace CLI {
67// [CLI11:validators_hpp:verbatim]
68
69class Option;
70
72
79
81class Validator {
82 protected:
84 std::function<std::string()> desc_function_{[]() { return std::string{}; }};
85
88 std::function<std::string(std::string &)> func_{[](std::string &) { return std::string{}; }};
90 std::string name_{};
94 bool active_{true};
96 bool non_modifying_{false};
97
98 Validator(std::string validator_desc, std::function<std::string(std::string &)> func)
99 : desc_function_([validator_desc]() { return validator_desc; }), func_(std::move(func)) {}
100
101 public:
102 Validator() = default;
104 explicit Validator(std::string validator_desc) : desc_function_([validator_desc]() { return validator_desc; }) {}
106 Validator(std::function<std::string(std::string &)> op, std::string validator_desc, std::string validator_name = "")
107 : desc_function_([validator_desc]() { return validator_desc; }), func_(std::move(op)),
108 name_(std::move(validator_name)) {}
110 Validator &operation(std::function<std::string(std::string &)> op) {
111 func_ = std::move(op);
112 return *this;
113 }
116 std::string operator()(std::string &str) const;
117
120 std::string operator()(const std::string &str) const {
121 std::string value = str;
122 return (active_) ? func_(value) : std::string{};
123 }
124
126 Validator &description(std::string validator_desc) {
127 desc_function_ = [validator_desc]() { return validator_desc; };
128 return *this;
129 }
131 CLI11_NODISCARD Validator description(std::string validator_desc) const;
132
134 CLI11_NODISCARD std::string get_description() const {
135 if(active_) {
136 return desc_function_();
137 }
138 return std::string{};
139 }
141 Validator &name(std::string validator_name) {
142 name_ = std::move(validator_name);
143 return *this;
144 }
146 CLI11_NODISCARD Validator name(std::string validator_name) const {
147 Validator newval(*this);
148 newval.name_ = std::move(validator_name);
149 return newval;
150 }
152 CLI11_NODISCARD const std::string &get_name() const { return name_; }
154 Validator &active(bool active_val = true) {
155 active_ = active_val;
156 return *this;
157 }
159 CLI11_NODISCARD Validator active(bool active_val = true) const {
160 Validator newval(*this);
161 newval.active_ = active_val;
162 return newval;
163 }
164
166 Validator &non_modifying(bool no_modify = true) {
167 non_modifying_ = no_modify;
168 return *this;
169 }
171 Validator &application_index(int app_index) {
172 application_index_ = app_index;
173 return *this;
174 }
177 Validator newval(*this);
178 newval.application_index_ = app_index;
179 return newval;
180 }
184 CLI11_NODISCARD bool get_active() const { return active_; }
185
188
191 Validator operator&(const Validator &other) const;
192
195 Validator operator|(const Validator &other) const;
196
199
200 private:
201 void _merge_description(const Validator &val1, const Validator &val2, const std::string &merger);
202};
203
206 public:
207};
208// The implementation of the built in validators is using the Validator class;
209// the user is only expected to use the const (static) versions (since there's no setup).
210// Therefore, this is in detail.
211namespace detail {
212
215
217CLI11_INLINE path_type check_path(const char *file) noexcept;
218
221 public:
223};
224
227 public:
229};
230
233 public:
235};
236
239 public:
241};
242
244class IPV4Validator : public Validator {
245 public:
247};
248
249} // namespace detail
250
251// Static is not needed here, because global const implies static.
252
255
258
261
264
267
269template <typename DesiredType> class TypeValidator : public Validator {
270 public:
271 explicit TypeValidator(const std::string &validator_name)
272 : Validator(validator_name, [](std::string &input_string) {
273 auto val = DesiredType();
274 if(!detail::lexical_cast(input_string, val)) {
275 return std::string("Failed parsing ") + input_string + " as a " + detail::type_name<DesiredType>();
276 }
277 return std::string();
278 }) {}
279 TypeValidator() : TypeValidator(detail::type_name<DesiredType>()) {}
280};
281
284
288 public:
289 explicit FileOnDefaultPath(std::string default_path, bool enableErrorReturn = true);
290};
291
293class Range : public Validator {
294 public:
299 template <typename T>
300 Range(T min_val, T max_val, const std::string &validator_name = std::string{}) : Validator(validator_name) {
301 if(validator_name.empty()) {
302 std::stringstream out;
303 out << detail::type_name<T>() << " in [" << min_val << " - " << max_val << "]";
304 description(out.str());
305 }
306
307 func_ = [min_val, max_val](std::string &input) {
308 T val;
309 bool converted = detail::lexical_cast(input, val);
310 if((!converted) || (val < min_val || val > max_val)) {
311 std::stringstream out;
312 out << "Value " << input << " not in range [";
313 out << min_val << " - " << max_val << "]";
314 return out.str();
315 }
316 return std::string{};
317 };
318 }
319
321 template <typename T>
322 explicit Range(T max_val, const std::string &validator_name = std::string{})
323 : Range(static_cast<T>(0), max_val, validator_name) {}
324};
325
327const Range NonNegativeNumber((std::numeric_limits<double>::max)(), "NONNEGATIVE");
328
330const Range PositiveNumber((std::numeric_limits<double>::min)(), (std::numeric_limits<double>::max)(), "POSITIVE");
331
333class Bound : public Validator {
334 public:
339 template <typename T> Bound(T min_val, T max_val) {
340 std::stringstream out;
341 out << detail::type_name<T>() << " bounded to [" << min_val << " - " << max_val << "]";
342 description(out.str());
343
344 func_ = [min_val, max_val](std::string &input) {
345 T val;
346 bool converted = detail::lexical_cast(input, val);
347 if(!converted) {
348 return std::string("Value ") + input + " could not be converted";
349 }
350 if(val < min_val)
351 input = detail::to_string(min_val);
352 else if(val > max_val)
353 input = detail::to_string(max_val);
354
355 return std::string{};
356 };
357 }
358
360 template <typename T> explicit Bound(T max_val) : Bound(static_cast<T>(0), max_val) {}
361};
362
363namespace detail {
364template <typename T,
365 enable_if_t<is_copyable_ptr<typename std::remove_reference<T>::type>::value, detail::enabler> = detail::dummy>
366auto smart_deref(T value) -> decltype(*value) {
367 return *value;
368}
369
370template <
371 typename T,
373typename std::remove_reference<T>::type &smart_deref(T &value) {
374 return value;
375}
377template <typename T> std::string generate_set(const T &set) {
378 using element_t = typename detail::element_type<T>::type;
379 using iteration_type_t = typename detail::pair_adaptor<element_t>::value_type; // the type of the object pair
380 std::string out(1, '{');
381 out.append(detail::join(
383 [](const iteration_type_t &v) { return detail::pair_adaptor<element_t>::first(v); },
384 ","));
385 out.push_back('}');
386 return out;
387}
388
390template <typename T> std::string generate_map(const T &map, bool key_only = false) {
391 using element_t = typename detail::element_type<T>::type;
392 using iteration_type_t = typename detail::pair_adaptor<element_t>::value_type; // the type of the object pair
393 std::string out(1, '{');
394 out.append(detail::join(
396 [key_only](const iteration_type_t &v) {
398
399 if(!key_only) {
400 res.append("->");
402 }
403 return res;
404 },
405 ","));
406 out.push_back('}');
407 return out;
408}
409
410template <typename C, typename V> struct has_find {
411 template <typename CC, typename VV>
412 static auto test(int) -> decltype(std::declval<CC>().find(std::declval<VV>()), std::true_type());
413 template <typename, typename> static auto test(...) -> decltype(std::false_type());
414
415 static const auto value = decltype(test<C, V>(0))::value;
416 using type = std::integral_constant<bool, value>;
417};
418
420template <typename T, typename V, enable_if_t<!has_find<T, V>::value, detail::enabler> = detail::dummy>
421auto search(const T &set, const V &val) -> std::pair<bool, decltype(std::begin(detail::smart_deref(set)))> {
422 using element_t = typename detail::element_type<T>::type;
423 auto &setref = detail::smart_deref(set);
424 auto it = std::find_if(std::begin(setref), std::end(setref), [&val](decltype(*std::begin(setref)) v) {
426 });
427 return {(it != std::end(setref)), it};
428}
429
431template <typename T, typename V, enable_if_t<has_find<T, V>::value, detail::enabler> = detail::dummy>
432auto search(const T &set, const V &val) -> std::pair<bool, decltype(std::begin(detail::smart_deref(set)))> {
433 auto &setref = detail::smart_deref(set);
434 auto it = setref.find(val);
435 return {(it != std::end(setref)), it};
436}
437
439template <typename T, typename V>
440auto search(const T &set, const V &val, const std::function<V(V)> &filter_function)
441 -> std::pair<bool, decltype(std::begin(detail::smart_deref(set)))> {
442 using element_t = typename detail::element_type<T>::type;
443 // do the potentially faster first search
444 auto res = search(set, val);
445 if((res.first) || (!(filter_function))) {
446 return res;
447 }
448 // if we haven't found it do the longer linear search with all the element translations
449 auto &setref = detail::smart_deref(set);
450 auto it = std::find_if(std::begin(setref), std::end(setref), [&](decltype(*std::begin(setref)) v) {
452 a = filter_function(a);
453 return (a == val);
454 });
455 return {(it != std::end(setref)), it};
456}
457
458// the following suggestion was made by Nikita Ofitserov(@himikof)
459// done in templates to prevent compiler warnings on negation of unsigned numbers
460
462template <typename T>
463inline typename std::enable_if<std::is_signed<T>::value, T>::type overflowCheck(const T &a, const T &b) {
464 if((a > 0) == (b > 0)) {
465 return ((std::numeric_limits<T>::max)() / (std::abs)(a) < (std::abs)(b));
466 }
467 return ((std::numeric_limits<T>::min)() / (std::abs)(a) > -(std::abs)(b));
468}
470template <typename T>
471inline typename std::enable_if<!std::is_signed<T>::value, T>::type overflowCheck(const T &a, const T &b) {
472 return ((std::numeric_limits<T>::max)() / a < b);
473}
474
476template <typename T> typename std::enable_if<std::is_integral<T>::value, bool>::type checked_multiply(T &a, T b) {
477 if(a == 0 || b == 0 || a == 1 || b == 1) {
478 a *= b;
479 return true;
480 }
481 if(a == (std::numeric_limits<T>::min)() || b == (std::numeric_limits<T>::min)()) {
482 return false;
483 }
484 if(overflowCheck(a, b)) {
485 return false;
486 }
487 a *= b;
488 return true;
489}
490
492template <typename T>
493typename std::enable_if<std::is_floating_point<T>::value, bool>::type checked_multiply(T &a, T b) {
494 T c = a * b;
495 if(std::isinf(c) && !std::isinf(a) && !std::isinf(b)) {
496 return false;
497 }
498 a = c;
499 return true;
500}
501
502} // namespace detail
504class IsMember : public Validator {
505 public:
506 using filter_fn_t = std::function<std::string(std::string)>;
507
509 template <typename T, typename... Args>
510 IsMember(std::initializer_list<T> values, Args &&...args)
511 : IsMember(std::vector<T>(values), std::forward<Args>(args)...) {}
512
514 template <typename T> explicit IsMember(T &&set) : IsMember(std::forward<T>(set), nullptr) {}
515
518 template <typename T, typename F> explicit IsMember(T set, F filter_function) {
519
520 // Get the type of the contained item - requires a container have ::value_type
521 // if the type does not have first_type and second_type, these are both value_type
522 using element_t = typename detail::element_type<T>::type; // Removes (smart) pointers if needed
523 using item_t = typename detail::pair_adaptor<element_t>::first_type; // Is value_type if not a map
524
525 using local_item_t = typename IsMemberType<item_t>::type; // This will convert bad types to good ones
526 // (const char * to std::string)
527
528 // Make a local copy of the filter function, using a std::function if not one already
529 std::function<local_item_t(local_item_t)> filter_fn = filter_function;
530
531 // This is the type name for help, it will take the current version of the set contents
532 desc_function_ = [set]() { return detail::generate_set(detail::smart_deref(set)); };
533
534 // This is the function that validates
535 // It stores a copy of the set pointer-like, so shared_ptr will stay alive
536 func_ = [set, filter_fn](std::string &input) {
537 local_item_t b;
538 if(!detail::lexical_cast(input, b)) {
539 throw ValidationError(input); // name is added later
540 }
541 if(filter_fn) {
542 b = filter_fn(b);
543 }
544 auto res = detail::search(set, b, filter_fn);
545 if(res.first) {
546 // Make sure the version in the input string is identical to the one in the set
547 if(filter_fn) {
549 }
550
551 // Return empty error string (success)
552 return std::string{};
553 }
554
555 // If you reach this point, the result was not found
556 return input + " not in " + detail::generate_set(detail::smart_deref(set));
557 };
558 }
559
561 template <typename T, typename... Args>
562 IsMember(T &&set, filter_fn_t filter_fn_1, filter_fn_t filter_fn_2, Args &&...other)
563 : IsMember(
564 std::forward<T>(set),
565 [filter_fn_1, filter_fn_2](std::string a) { return filter_fn_2(filter_fn_1(a)); },
566 other...) {}
567};
568
570template <typename T> using TransformPairs = std::vector<std::pair<std::string, T>>;
571
573class Transformer : public Validator {
574 public:
575 using filter_fn_t = std::function<std::string(std::string)>;
576
578 template <typename... Args>
579 Transformer(std::initializer_list<std::pair<std::string, std::string>> values, Args &&...args)
580 : Transformer(TransformPairs<std::string>(values), std::forward<Args>(args)...) {}
581
583 template <typename T> explicit Transformer(T &&mapping) : Transformer(std::forward<T>(mapping), nullptr) {}
584
587 template <typename T, typename F> explicit Transformer(T mapping, F filter_function) {
588
590 "mapping must produce value pairs");
591 // Get the type of the contained item - requires a container have ::value_type
592 // if the type does not have first_type and second_type, these are both value_type
593 using element_t = typename detail::element_type<T>::type; // Removes (smart) pointers if needed
594 using item_t = typename detail::pair_adaptor<element_t>::first_type; // Is value_type if not a map
595 using local_item_t = typename IsMemberType<item_t>::type; // Will convert bad types to good ones
596 // (const char * to std::string)
597
598 // Make a local copy of the filter function, using a std::function if not one already
599 std::function<local_item_t(local_item_t)> filter_fn = filter_function;
600
601 // This is the type name for help, it will take the current version of the set contents
602 desc_function_ = [mapping]() { return detail::generate_map(detail::smart_deref(mapping)); };
603
604 func_ = [mapping, filter_fn](std::string &input) {
605 local_item_t b;
606 if(!detail::lexical_cast(input, b)) {
607 return std::string();
608 // there is no possible way we can match anything in the mapping if we can't convert so just return
609 }
610 if(filter_fn) {
611 b = filter_fn(b);
612 }
613 auto res = detail::search(mapping, b, filter_fn);
614 if(res.first) {
616 }
617 return std::string{};
618 };
619 }
620
622 template <typename T, typename... Args>
623 Transformer(T &&mapping, filter_fn_t filter_fn_1, filter_fn_t filter_fn_2, Args &&...other)
624 : Transformer(
625 std::forward<T>(mapping),
626 [filter_fn_1, filter_fn_2](std::string a) { return filter_fn_2(filter_fn_1(a)); },
627 other...) {}
628};
629
632 public:
633 using filter_fn_t = std::function<std::string(std::string)>;
634
636 template <typename... Args>
637 CheckedTransformer(std::initializer_list<std::pair<std::string, std::string>> values, Args &&...args)
638 : CheckedTransformer(TransformPairs<std::string>(values), std::forward<Args>(args)...) {}
639
641 template <typename T> explicit CheckedTransformer(T mapping) : CheckedTransformer(std::move(mapping), nullptr) {}
642
645 template <typename T, typename F> explicit CheckedTransformer(T mapping, F filter_function) {
646
648 "mapping must produce value pairs");
649 // Get the type of the contained item - requires a container have ::value_type
650 // if the type does not have first_type and second_type, these are both value_type
651 using element_t = typename detail::element_type<T>::type; // Removes (smart) pointers if needed
652 using item_t = typename detail::pair_adaptor<element_t>::first_type; // Is value_type if not a map
653 using local_item_t = typename IsMemberType<item_t>::type; // Will convert bad types to good ones
654 // (const char * to std::string)
655 using iteration_type_t = typename detail::pair_adaptor<element_t>::value_type; // the type of the object pair
656
657 // Make a local copy of the filter function, using a std::function if not one already
658 std::function<local_item_t(local_item_t)> filter_fn = filter_function;
659
660 auto tfunc = [mapping]() {
661 std::string out("value in ");
662 out += detail::generate_map(detail::smart_deref(mapping)) + " OR {";
663 out += detail::join(
664 detail::smart_deref(mapping),
665 [](const iteration_type_t &v) { return detail::to_string(detail::pair_adaptor<element_t>::second(v)); },
666 ",");
667 out.push_back('}');
668 return out;
669 };
670
671 desc_function_ = tfunc;
672
673 func_ = [mapping, tfunc, filter_fn](std::string &input) {
674 local_item_t b;
675 bool converted = detail::lexical_cast(input, b);
676 if(converted) {
677 if(filter_fn) {
678 b = filter_fn(b);
679 }
680 auto res = detail::search(mapping, b, filter_fn);
681 if(res.first) {
683 return std::string{};
684 }
685 }
686 for(const auto &v : detail::smart_deref(mapping)) {
688 if(output_string == input) {
689 return std::string();
690 }
691 }
692
693 return "Check " + input + " " + tfunc() + " FAILED";
694 };
695 }
696
698 template <typename T, typename... Args>
699 CheckedTransformer(T &&mapping, filter_fn_t filter_fn_1, filter_fn_t filter_fn_2, Args &&...other)
701 std::forward<T>(mapping),
702 [filter_fn_1, filter_fn_2](std::string a) { return filter_fn_2(filter_fn_1(a)); },
703 other...) {}
704};
705
707inline std::string ignore_case(std::string item) { return detail::to_lower(item); }
708
710inline std::string ignore_underscore(std::string item) { return detail::remove_underscore(item); }
711
713inline std::string ignore_space(std::string item) {
714 item.erase(std::remove(std::begin(item), std::end(item), ' '), std::end(item));
715 item.erase(std::remove(std::begin(item), std::end(item), '\t'), std::end(item));
716 return item;
717}
718
731 public:
736 enum Options {
742 };
743
744 template <typename Number>
745 explicit AsNumberWithUnit(std::map<std::string, Number> mapping,
746 Options opts = DEFAULT,
747 const std::string &unit_name = "UNIT") {
748 description(generate_description<Number>(unit_name, opts));
749 validate_mapping(mapping, opts);
750
751 // transform function
752 func_ = [mapping, opts](std::string &input) -> std::string {
753 Number num{};
754
755 detail::rtrim(input);
756 if(input.empty()) {
757 throw ValidationError("Input is empty");
758 }
759
760 // Find split position between number and prefix
761 auto unit_begin = input.end();
762 while(unit_begin > input.begin() && std::isalpha(*(unit_begin - 1), std::locale())) {
763 --unit_begin;
764 }
765
766 std::string unit{unit_begin, input.end()};
767 input.resize(static_cast<std::size_t>(std::distance(input.begin(), unit_begin)));
768 detail::trim(input);
769
770 if(opts & UNIT_REQUIRED && unit.empty()) {
771 throw ValidationError("Missing mandatory unit");
772 }
773 if(opts & CASE_INSENSITIVE) {
774 unit = detail::to_lower(unit);
775 }
776 if(unit.empty()) {
777 if(!detail::lexical_cast(input, num)) {
778 throw ValidationError(std::string("Value ") + input + " could not be converted to " +
779 detail::type_name<Number>());
780 }
781 // No need to modify input if no unit passed
782 return {};
783 }
784
785 // find corresponding factor
786 auto it = mapping.find(unit);
787 if(it == mapping.end()) {
788 throw ValidationError(unit +
789 " unit not recognized. "
790 "Allowed values: " +
791 detail::generate_map(mapping, true));
792 }
793
794 if(!input.empty()) {
795 bool converted = detail::lexical_cast(input, num);
796 if(!converted) {
797 throw ValidationError(std::string("Value ") + input + " could not be converted to " +
798 detail::type_name<Number>());
799 }
800 // perform safe multiplication
801 bool ok = detail::checked_multiply(num, it->second);
802 if(!ok) {
803 throw ValidationError(detail::to_string(num) + " multiplied by " + unit +
804 " factor would cause number overflow. Use smaller value.");
805 }
806 } else {
807 num = static_cast<Number>(it->second);
808 }
809
810 input = detail::to_string(num);
811
812 return {};
813 };
814 }
815
816 private:
819 template <typename Number> static void validate_mapping(std::map<std::string, Number> &mapping, Options opts) {
820 for(auto &kv : mapping) {
821 if(kv.first.empty()) {
822 throw ValidationError("Unit must not be empty.");
823 }
824 if(!detail::isalpha(kv.first)) {
825 throw ValidationError("Unit must contain only letters.");
826 }
827 }
828
829 // make all units lowercase if CASE_INSENSITIVE
830 if(opts & CASE_INSENSITIVE) {
831 std::map<std::string, Number> lower_mapping;
832 for(auto &kv : mapping) {
833 auto s = detail::to_lower(kv.first);
834 if(lower_mapping.count(s)) {
835 throw ValidationError(std::string("Several matching lowercase unit representations are found: ") +
836 s);
837 }
838 lower_mapping[detail::to_lower(kv.first)] = kv.second;
839 }
840 mapping = std::move(lower_mapping);
841 }
842 }
843
845 template <typename Number> static std::string generate_description(const std::string &name, Options opts) {
846 std::stringstream out;
847 out << detail::type_name<Number>() << ' ';
848 if(opts & UNIT_REQUIRED) {
849 out << name;
850 } else {
851 out << '[' << name << ']';
852 }
853 return out.str();
854 }
855};
856
858 return static_cast<AsNumberWithUnit::Options>(static_cast<int>(a) | static_cast<int>(b));
859}
860
873 public:
874 using result_t = std::uint64_t;
875
883 explicit AsSizeValue(bool kb_is_1000);
884
885 private:
887 static std::map<std::string, result_t> init_mapping(bool kb_is_1000);
888
890 static std::map<std::string, result_t> get_mapping(bool kb_is_1000);
891};
892
893namespace detail {
898CLI11_INLINE std::pair<std::string, std::string> split_program_name(std::string commandline);
899
900} // namespace detail
902
903// [CLI11:validators_hpp:end]
904} // namespace CLI
905
906#ifndef CLI11_COMPILE
907#include "impl/Validators_inl.hpp"
908#endif
#define CLI11_INLINE
Definition: Macros.hpp:73
#define CLI11_NODISCARD
Definition: Macros.hpp:47
Definition: Validators.hpp:730
Options
Definition: Validators.hpp:736
@ UNIT_OPTIONAL
Definition: Validators.hpp:739
@ CASE_INSENSITIVE
Definition: Validators.hpp:738
@ DEFAULT
Definition: Validators.hpp:741
@ UNIT_REQUIRED
Definition: Validators.hpp:740
@ CASE_SENSITIVE
Definition: Validators.hpp:737
AsNumberWithUnit(std::map< std::string, Number > mapping, Options opts=DEFAULT, const std::string &unit_name="UNIT")
Definition: Validators.hpp:745
Definition: Validators.hpp:872
AsSizeValue(bool kb_is_1000)
std::uint64_t result_t
Definition: Validators.hpp:874
Produce a bounded range (factory). Min and max are inclusive.
Definition: Validators.hpp:333
Bound(T min_val, T max_val)
Definition: Validators.hpp:339
Bound(T max_val)
Range of one value is 0 to value.
Definition: Validators.hpp:360
translate named items to other or a value set
Definition: Validators.hpp:631
CheckedTransformer(T mapping)
direct map of std::string to std::string
Definition: Validators.hpp:641
CheckedTransformer(T &&mapping, 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.
Definition: Validators.hpp:699
std::function< std::string(std::string)> filter_fn_t
Definition: Validators.hpp:633
CheckedTransformer(std::initializer_list< std::pair< std::string, std::string > > values, Args &&...args)
This allows in-place construction.
Definition: Validators.hpp:637
CheckedTransformer(T mapping, F filter_function)
Definition: Validators.hpp:645
Class wrapping some of the accessors of Validator.
Definition: Validators.hpp:205
Definition: Validators.hpp:287
FileOnDefaultPath(std::string default_path, bool enableErrorReturn=true)
Verify items are in a set.
Definition: Validators.hpp:504
IsMember(T &&set)
This checks to see if an item is in a set (empty function)
Definition: Validators.hpp:514
IsMember(T set, F filter_function)
Definition: Validators.hpp:518
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:562
IsMember(std::initializer_list< T > values, Args &&...args)
This allows in-place construction using an initializer list.
Definition: Validators.hpp:510
std::function< std::string(std::string)> filter_fn_t
Definition: Validators.hpp:506
Produce a range (factory). Min and max are inclusive.
Definition: Validators.hpp:293
Range(T min_val, T max_val, const std::string &validator_name=std::string{})
Definition: Validators.hpp:300
Range(T max_val, const std::string &validator_name=std::string{})
Range of one value is 0 to value.
Definition: Validators.hpp:322
Translate named items to other or a value set.
Definition: Validators.hpp:573
Transformer(T &&mapping, 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.
Definition: Validators.hpp:623
Transformer(std::initializer_list< std::pair< std::string, std::string > > values, Args &&...args)
This allows in-place construction.
Definition: Validators.hpp:579
std::function< std::string(std::string)> filter_fn_t
Definition: Validators.hpp:575
Transformer(T &&mapping)
direct map of std::string to std::string
Definition: Validators.hpp:583
Transformer(T mapping, F filter_function)
Definition: Validators.hpp:587
Validate the input as a particular type.
Definition: Validators.hpp:269
TypeValidator()
Definition: Validators.hpp:279
TypeValidator(const std::string &validator_name)
Definition: Validators.hpp:271
Thrown when validation of results fails.
Definition: Error.hpp:213
Some validators that are provided.
Definition: Validators.hpp:81
CLI11_NODISCARD int get_application_index() const
Get the current value of the application index.
Definition: Validators.hpp:182
int application_index_
A Validator will only apply to an indexed value (-1 is all elements)
Definition: Validators.hpp:92
Validator & non_modifying(bool no_modify=true)
Specify whether the Validator can be modifying or not.
Definition: Validators.hpp:166
Validator & description(std::string validator_desc)
Specify the type string.
Definition: Validators.hpp:126
std::string operator()(const std::string &str) const
Definition: Validators.hpp:120
CLI11_NODISCARD Validator application_index(int app_index) const
Specify the application index of a validator.
Definition: Validators.hpp:176
CLI11_NODISCARD bool get_active() const
Get a boolean if the validator is active.
Definition: Validators.hpp:184
Validator operator&(const Validator &other) const
bool active_
Enable for Validator to allow it to be disabled if need be.
Definition: Validators.hpp:94
bool non_modifying_
specify that a validator should not modify the input
Definition: Validators.hpp:96
Validator(std::string validator_desc)
Construct a Validator with just the description string.
Definition: Validators.hpp:104
Validator(std::string validator_desc, std::function< std::string(std::string &)> func)
Definition: Validators.hpp:98
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:141
Validator()=default
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:84
std::function< std::string(std::string &)> func_
Definition: Validators.hpp:88
CLI11_NODISCARD std::string get_description() const
Generate type description information for the Validator.
Definition: Validators.hpp:134
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:159
CLI11_NODISCARD const std::string & get_name() const
Get the name of the Validator.
Definition: Validators.hpp:152
Validator operator|(const Validator &other) const
Validator & active(bool active_val=true)
Specify whether the Validator is active or not.
Definition: Validators.hpp:154
std::string name_
The name for search purposes of the Validator.
Definition: Validators.hpp:90
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:187
CLI11_NODISCARD Validator name(std::string validator_name) const
Specify the type string.
Definition: Validators.hpp:146
Validator & application_index(int app_index)
Specify the application index of a validator.
Definition: Validators.hpp:171
Validator(std::function< std::string(std::string &)> op, std::string validator_desc, std::string validator_name="")
Construct Validator from basic information.
Definition: Validators.hpp:106
Validator & operation(std::function< std::string(std::string &)> op)
Set the Validator operation function.
Definition: Validators.hpp:110
Check for an existing directory (returns error message if check fails)
Definition: Validators.hpp:226
Check for an existing file (returns error message if check fails)
Definition: Validators.hpp:220
Check for an existing path.
Definition: Validators.hpp:232
Validate the given string is a legal ipv4 address.
Definition: Validators.hpp:244
Check for an non-existing path.
Definition: Validators.hpp:238
constexpr enabler dummy
An instance to use in EnableIf.
Definition: TypeTools.hpp:34
auto smart_deref(T value) -> decltype(*value)
Definition: Validators.hpp:366
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:270
path_type
CLI enumeration of different file types.
Definition: Validators.hpp:214
std::string generate_map(const T &map, bool key_only=false)
Generate a string representation of a map.
Definition: Validators.hpp:390
std::string remove_underscore(std::string str)
remove underscores from a string
Definition: StringTools.hpp:182
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:463
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:476
std::string & trim(std::string &str)
Trim whitespace from string.
Definition: StringTools.hpp:109
std::string generate_set(const T &set)
Generate a string representation of a set.
Definition: Validators.hpp:377
std::string value_string(const T &value)
get a string as a convertible value for arithmetic types
Definition: TypeTools.hpp:340
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:421
std::string join(const T &v, std::string delim=",")
Simple function to join a string.
Definition: StringTools.hpp:51
bool isalpha(const std::string &str)
Verify that str consists of letters only.
Definition: StringTools.hpp:169
CLI11_INLINE std::pair< std::string, std::string > split_program_name(std::string commandline)
std::string to_lower(std::string str)
Return a lower case version of a string.
Definition: StringTools.hpp:174
CLI11_INLINE std::string & rtrim(std::string &str)
Trim whitespace from right of string.
enabler
Simple empty scoped class.
Definition: TypeTools.hpp:31
bool lexical_cast(const std::string &input, T &output)
Integer conversion.
Definition: TypeTools.hpp:884
Definition: App.hpp:34
std::string ignore_case(std::string item)
Helper function to allow ignore_case to be passed to IsMember or Transform.
Definition: Validators.hpp:707
std::string ignore_underscore(std::string item)
Helper function to allow ignore_underscore to be passed to IsMember or Transform.
Definition: Validators.hpp:710
typename std::enable_if< B, T >::type enable_if_t
Definition: TypeTools.hpp:42
const detail::ExistingDirectoryValidator ExistingDirectory
Check for an existing directory (returns error message if check fails)
Definition: Validators.hpp:257
AsNumberWithUnit::Options operator|(const AsNumberWithUnit::Options &a, const AsNumberWithUnit::Options &b)
Definition: Validators.hpp:857
const detail::NonexistentPathValidator NonexistentPath
Check for an non-existing path.
Definition: Validators.hpp:263
const detail::IPV4Validator ValidIPV4
Check for an IP4 address.
Definition: Validators.hpp:266
const detail::ExistingPathValidator ExistingPath
Check for an existing path.
Definition: Validators.hpp:260
std::vector< std::pair< std::string, T > > TransformPairs
definition of the default transformation object
Definition: Validators.hpp:570
const detail::ExistingFileValidator ExistingFile
Check for existing file (returns error message if check fails)
Definition: Validators.hpp:254
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:713
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.
T type
Definition: TypeTools.hpp:74
T type
Definition: TypeTools.hpp:87
Definition: Validators.hpp:410
static const auto value
Definition: Validators.hpp:415
std::integral_constant< bool, value > type
Definition: Validators.hpp:416
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:98
typename T::value_type value_type
Definition: TypeTools.hpp:99
typename std::remove_const< value_type >::type first_type
Definition: TypeTools.hpp:100
static auto first(Q &&pair_value) -> decltype(std::forward< Q >(pair_value))
Get the first value (really just the underlying value)
Definition: TypeTools.hpp:104