CLI11 2.3.2
Loading...
Searching...
No Matches
Validators.hpp
Go to the documentation of this file.
1// Copyright (c) 2017-2023, 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
230
233 public:
235};
236
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) {
274 auto val = DesiredType();
275 if(!lexical_cast(input_string, val)) {
276 return std::string("Failed parsing ") + input_string + " as a " + detail::type_name<DesiredType>();
277 }
278 return std::string();
279 }) {}
280 TypeValidator() : TypeValidator(detail::type_name<DesiredType>()) {}
281};
282
285
289 public:
290 explicit FileOnDefaultPath(std::string default_path, bool enableErrorReturn = true);
291};
292
294class Range : public Validator {
295 public:
300 template <typename T>
301 Range(T min_val, T max_val, const std::string &validator_name = std::string{}) : Validator(validator_name) {
302 if(validator_name.empty()) {
303 std::stringstream out;
304 out << detail::type_name<T>() << " in [" << min_val << " - " << max_val << "]";
305 description(out.str());
306 }
307
308 func_ = [min_val, max_val](std::string &input) {
310 T val;
311 bool converted = lexical_cast(input, val);
312 if((!converted) || (val < min_val || val > max_val)) {
313 std::stringstream out;
314 out << "Value " << input << " not in range [";
315 out << min_val << " - " << max_val << "]";
316 return out.str();
317 }
318 return std::string{};
319 };
320 }
321
323 template <typename T>
324 explicit Range(T max_val, const std::string &validator_name = std::string{})
325 : Range(static_cast<T>(0), max_val, validator_name) {}
326};
327
329const Range NonNegativeNumber((std::numeric_limits<double>::max)(), "NONNEGATIVE");
330
332const Range PositiveNumber((std::numeric_limits<double>::min)(), (std::numeric_limits<double>::max)(), "POSITIVE");
333
335class Bound : public Validator {
336 public:
341 template <typename T> Bound(T min_val, T max_val) {
342 std::stringstream out;
343 out << detail::type_name<T>() << " bounded to [" << min_val << " - " << max_val << "]";
344 description(out.str());
345
346 func_ = [min_val, max_val](std::string &input) {
348 T val;
349 bool converted = lexical_cast(input, val);
350 if(!converted) {
351 return std::string("Value ") + input + " could not be converted";
352 }
353 if(val < min_val)
354 input = detail::to_string(min_val);
355 else if(val > max_val)
356 input = detail::to_string(max_val);
357
358 return std::string{};
359 };
360 }
361
363 template <typename T> explicit Bound(T max_val) : Bound(static_cast<T>(0), max_val) {}
364};
365
366namespace detail {
367template <typename T,
368 enable_if_t<is_copyable_ptr<typename std::remove_reference<T>::type>::value, detail::enabler> = detail::dummy>
369auto smart_deref(T value) -> decltype(*value) {
370 return *value;
371}
372
373template <
374 typename T,
376typename std::remove_reference<T>::type &smart_deref(T &value) {
377 return value;
378}
380template <typename T> std::string generate_set(const T &set) {
381 using element_t = typename detail::element_type<T>::type;
382 using iteration_type_t = typename detail::pair_adaptor<element_t>::value_type; // the type of the object pair
383 std::string out(1, '{');
384 out.append(detail::join(
386 [](const iteration_type_t &v) { return detail::pair_adaptor<element_t>::first(v); },
387 ","));
388 out.push_back('}');
389 return out;
390}
391
393template <typename T> std::string generate_map(const T &map, bool key_only = false) {
394 using element_t = typename detail::element_type<T>::type;
395 using iteration_type_t = typename detail::pair_adaptor<element_t>::value_type; // the type of the object pair
396 std::string out(1, '{');
397 out.append(detail::join(
399 [key_only](const iteration_type_t &v) {
401
402 if(!key_only) {
403 res.append("->");
405 }
406 return res;
407 },
408 ","));
409 out.push_back('}');
410 return out;
411}
412
413template <typename C, typename V> struct has_find {
414 template <typename CC, typename VV>
415 static auto test(int) -> decltype(std::declval<CC>().find(std::declval<VV>()), std::true_type());
416 template <typename, typename> static auto test(...) -> decltype(std::false_type());
417
418 static const auto value = decltype(test<C, V>(0))::value;
419 using type = std::integral_constant<bool, value>;
420};
421
423template <typename T, typename V, enable_if_t<!has_find<T, V>::value, detail::enabler> = detail::dummy>
424auto search(const T &set, const V &val) -> std::pair<bool, decltype(std::begin(detail::smart_deref(set)))> {
425 using element_t = typename detail::element_type<T>::type;
426 auto &setref = detail::smart_deref(set);
427 auto it = std::find_if(std::begin(setref), std::end(setref), [&val](decltype(*std::begin(setref)) v) {
429 });
430 return {(it != std::end(setref)), it};
431}
432
434template <typename T, typename V, enable_if_t<has_find<T, V>::value, detail::enabler> = detail::dummy>
435auto search(const T &set, const V &val) -> std::pair<bool, decltype(std::begin(detail::smart_deref(set)))> {
436 auto &setref = detail::smart_deref(set);
437 auto it = setref.find(val);
438 return {(it != std::end(setref)), it};
439}
440
442template <typename T, typename V>
443auto search(const T &set, const V &val, const std::function<V(V)> &filter_function)
444 -> std::pair<bool, decltype(std::begin(detail::smart_deref(set)))> {
445 using element_t = typename detail::element_type<T>::type;
446 // do the potentially faster first search
447 auto res = search(set, val);
448 if((res.first) || (!(filter_function))) {
449 return res;
450 }
451 // if we haven't found it do the longer linear search with all the element translations
452 auto &setref = detail::smart_deref(set);
453 auto it = std::find_if(std::begin(setref), std::end(setref), [&](decltype(*std::begin(setref)) v) {
455 a = filter_function(a);
456 return (a == val);
457 });
458 return {(it != std::end(setref)), it};
459}
460
461// the following suggestion was made by Nikita Ofitserov(@himikof)
462// done in templates to prevent compiler warnings on negation of unsigned numbers
463
465template <typename T>
466inline typename std::enable_if<std::is_signed<T>::value, T>::type overflowCheck(const T &a, const T &b) {
467 if((a > 0) == (b > 0)) {
468 return ((std::numeric_limits<T>::max)() / (std::abs)(a) < (std::abs)(b));
469 }
470 return ((std::numeric_limits<T>::min)() / (std::abs)(a) > -(std::abs)(b));
471}
473template <typename T>
474inline typename std::enable_if<!std::is_signed<T>::value, T>::type overflowCheck(const T &a, const T &b) {
475 return ((std::numeric_limits<T>::max)() / a < b);
476}
477
479template <typename T> typename std::enable_if<std::is_integral<T>::value, bool>::type checked_multiply(T &a, T b) {
480 if(a == 0 || b == 0 || a == 1 || b == 1) {
481 a *= b;
482 return true;
483 }
484 if(a == (std::numeric_limits<T>::min)() || b == (std::numeric_limits<T>::min)()) {
485 return false;
486 }
487 if(overflowCheck(a, b)) {
488 return false;
489 }
490 a *= b;
491 return true;
492}
493
495template <typename T>
496typename std::enable_if<std::is_floating_point<T>::value, bool>::type checked_multiply(T &a, T b) {
497 T c = a * b;
498 if(std::isinf(c) && !std::isinf(a) && !std::isinf(b)) {
499 return false;
500 }
501 a = c;
502 return true;
503}
504
505} // namespace detail
507class IsMember : public Validator {
508 public:
509 using filter_fn_t = std::function<std::string(std::string)>;
510
512 template <typename T, typename... Args>
513 IsMember(std::initializer_list<T> values, Args &&...args)
514 : IsMember(std::vector<T>(values), std::forward<Args>(args)...) {}
515
517 template <typename T> explicit IsMember(T &&set) : IsMember(std::forward<T>(set), nullptr) {}
518
521 template <typename T, typename F> explicit IsMember(T set, F filter_function) {
522
523 // Get the type of the contained item - requires a container have ::value_type
524 // if the type does not have first_type and second_type, these are both value_type
525 using element_t = typename detail::element_type<T>::type; // Removes (smart) pointers if needed
526 using item_t = typename detail::pair_adaptor<element_t>::first_type; // Is value_type if not a map
527
528 using local_item_t = typename IsMemberType<item_t>::type; // This will convert bad types to good ones
529 // (const char * to std::string)
530
531 // Make a local copy of the filter function, using a std::function if not one already
532 std::function<local_item_t(local_item_t)> filter_fn = filter_function;
533
534 // This is the type name for help, it will take the current version of the set contents
535 desc_function_ = [set]() { return detail::generate_set(detail::smart_deref(set)); };
536
537 // This is the function that validates
538 // It stores a copy of the set pointer-like, so shared_ptr will stay alive
539 func_ = [set, filter_fn](std::string &input) {
541 local_item_t b;
542 if(!lexical_cast(input, b)) {
543 throw ValidationError(input); // name is added later
544 }
545 if(filter_fn) {
546 b = filter_fn(b);
547 }
548 auto res = detail::search(set, b, filter_fn);
549 if(res.first) {
550 // Make sure the version in the input string is identical to the one in the set
551 if(filter_fn) {
553 }
554
555 // Return empty error string (success)
556 return std::string{};
557 }
558
559 // If you reach this point, the result was not found
560 return input + " not in " + detail::generate_set(detail::smart_deref(set));
561 };
562 }
563
565 template <typename T, typename... Args>
566 IsMember(T &&set, filter_fn_t filter_fn_1, filter_fn_t filter_fn_2, Args &&...other)
567 : IsMember(
568 std::forward<T>(set),
569 [filter_fn_1, filter_fn_2](std::string a) { return filter_fn_2(filter_fn_1(a)); },
570 other...) {}
571};
572
574template <typename T> using TransformPairs = std::vector<std::pair<std::string, T>>;
575
577class Transformer : public Validator {
578 public:
579 using filter_fn_t = std::function<std::string(std::string)>;
580
582 template <typename... Args>
583 Transformer(std::initializer_list<std::pair<std::string, std::string>> values, Args &&...args)
584 : Transformer(TransformPairs<std::string>(values), std::forward<Args>(args)...) {}
585
587 template <typename T> explicit Transformer(T &&mapping) : Transformer(std::forward<T>(mapping), nullptr) {}
588
591 template <typename T, typename F> explicit Transformer(T mapping, F filter_function) {
592
594 "mapping must produce value pairs");
595 // Get the type of the contained item - requires a container have ::value_type
596 // if the type does not have first_type and second_type, these are both value_type
597 using element_t = typename detail::element_type<T>::type; // Removes (smart) pointers if needed
598 using item_t = typename detail::pair_adaptor<element_t>::first_type; // Is value_type if not a map
599 using local_item_t = typename IsMemberType<item_t>::type; // Will convert bad types to good ones
600 // (const char * to std::string)
601
602 // Make a local copy of the filter function, using a std::function if not one already
603 std::function<local_item_t(local_item_t)> filter_fn = filter_function;
604
605 // This is the type name for help, it will take the current version of the set contents
606 desc_function_ = [mapping]() { return detail::generate_map(detail::smart_deref(mapping)); };
607
608 func_ = [mapping, filter_fn](std::string &input) {
610 local_item_t b;
611 if(!lexical_cast(input, b)) {
612 return std::string();
613 // there is no possible way we can match anything in the mapping if we can't convert so just return
614 }
615 if(filter_fn) {
616 b = filter_fn(b);
617 }
618 auto res = detail::search(mapping, b, filter_fn);
619 if(res.first) {
621 }
622 return std::string{};
623 };
624 }
625
627 template <typename T, typename... Args>
628 Transformer(T &&mapping, filter_fn_t filter_fn_1, filter_fn_t filter_fn_2, Args &&...other)
629 : Transformer(
630 std::forward<T>(mapping),
631 [filter_fn_1, filter_fn_2](std::string a) { return filter_fn_2(filter_fn_1(a)); },
632 other...) {}
633};
634
637 public:
638 using filter_fn_t = std::function<std::string(std::string)>;
639
641 template <typename... Args>
642 CheckedTransformer(std::initializer_list<std::pair<std::string, std::string>> values, Args &&...args)
643 : CheckedTransformer(TransformPairs<std::string>(values), std::forward<Args>(args)...) {}
644
646 template <typename T> explicit CheckedTransformer(T mapping) : CheckedTransformer(std::move(mapping), nullptr) {}
647
650 template <typename T, typename F> explicit CheckedTransformer(T mapping, F filter_function) {
651
653 "mapping must produce value pairs");
654 // Get the type of the contained item - requires a container have ::value_type
655 // if the type does not have first_type and second_type, these are both value_type
656 using element_t = typename detail::element_type<T>::type; // Removes (smart) pointers if needed
657 using item_t = typename detail::pair_adaptor<element_t>::first_type; // Is value_type if not a map
658 using local_item_t = typename IsMemberType<item_t>::type; // Will convert bad types to good ones
659 // (const char * to std::string)
660 using iteration_type_t = typename detail::pair_adaptor<element_t>::value_type; // the type of the object pair
661
662 // Make a local copy of the filter function, using a std::function if not one already
663 std::function<local_item_t(local_item_t)> filter_fn = filter_function;
664
665 auto tfunc = [mapping]() {
666 std::string out("value in ");
667 out += detail::generate_map(detail::smart_deref(mapping)) + " OR {";
668 out += detail::join(
669 detail::smart_deref(mapping),
670 [](const iteration_type_t &v) { return detail::to_string(detail::pair_adaptor<element_t>::second(v)); },
671 ",");
672 out.push_back('}');
673 return out;
674 };
675
676 desc_function_ = tfunc;
677
678 func_ = [mapping, tfunc, filter_fn](std::string &input) {
680 local_item_t b;
681 bool converted = lexical_cast(input, b);
682 if(converted) {
683 if(filter_fn) {
684 b = filter_fn(b);
685 }
686 auto res = detail::search(mapping, b, filter_fn);
687 if(res.first) {
689 return std::string{};
690 }
691 }
692 for(const auto &v : detail::smart_deref(mapping)) {
694 if(output_string == input) {
695 return std::string();
696 }
697 }
698
699 return "Check " + input + " " + tfunc() + " FAILED";
700 };
701 }
702
704 template <typename T, typename... Args>
705 CheckedTransformer(T &&mapping, filter_fn_t filter_fn_1, filter_fn_t filter_fn_2, Args &&...other)
707 std::forward<T>(mapping),
708 [filter_fn_1, filter_fn_2](std::string a) { return filter_fn_2(filter_fn_1(a)); },
709 other...) {}
710};
711
713inline std::string ignore_case(std::string item) { return detail::to_lower(item); }
714
716inline std::string ignore_underscore(std::string item) { return detail::remove_underscore(item); }
717
719inline std::string ignore_space(std::string item) {
720 item.erase(std::remove(std::begin(item), std::end(item), ' '), std::end(item));
721 item.erase(std::remove(std::begin(item), std::end(item), '\t'), std::end(item));
722 return item;
723}
724
737 public:
749
750 template <typename Number>
751 explicit AsNumberWithUnit(std::map<std::string, Number> mapping,
752 Options opts = DEFAULT,
753 const std::string &unit_name = "UNIT") {
754 description(generate_description<Number>(unit_name, opts));
755 validate_mapping(mapping, opts);
756
757 // transform function
758 func_ = [mapping, opts](std::string &input) -> std::string {
759 Number num{};
760
761 detail::rtrim(input);
762 if(input.empty()) {
763 throw ValidationError("Input is empty");
764 }
765
766 // Find split position between number and prefix
767 auto unit_begin = input.end();
768 while(unit_begin > input.begin() && std::isalpha(*(unit_begin - 1), std::locale())) {
769 --unit_begin;
770 }
771
772 std::string unit{unit_begin, input.end()};
773 input.resize(static_cast<std::size_t>(std::distance(input.begin(), unit_begin)));
774 detail::trim(input);
775
776 if(opts & UNIT_REQUIRED && unit.empty()) {
777 throw ValidationError("Missing mandatory unit");
778 }
779 if(opts & CASE_INSENSITIVE) {
780 unit = detail::to_lower(unit);
781 }
782 if(unit.empty()) {
784 if(!lexical_cast(input, num)) {
785 throw ValidationError(std::string("Value ") + input + " could not be converted to " +
786 detail::type_name<Number>());
787 }
788 // No need to modify input if no unit passed
789 return {};
790 }
791
792 // find corresponding factor
793 auto it = mapping.find(unit);
794 if(it == mapping.end()) {
795 throw ValidationError(unit +
796 " unit not recognized. "
797 "Allowed values: " +
798 detail::generate_map(mapping, true));
799 }
800
801 if(!input.empty()) {
803 bool converted = lexical_cast(input, num);
804 if(!converted) {
805 throw ValidationError(std::string("Value ") + input + " could not be converted to " +
806 detail::type_name<Number>());
807 }
808 // perform safe multiplication
809 bool ok = detail::checked_multiply(num, it->second);
810 if(!ok) {
811 throw ValidationError(detail::to_string(num) + " multiplied by " + unit +
812 " factor would cause number overflow. Use smaller value.");
813 }
814 } else {
815 num = static_cast<Number>(it->second);
816 }
817
818 input = detail::to_string(num);
819
820 return {};
821 };
822 }
823
824 private:
827 template <typename Number> static void validate_mapping(std::map<std::string, Number> &mapping, Options opts) {
828 for(auto &kv : mapping) {
829 if(kv.first.empty()) {
830 throw ValidationError("Unit must not be empty.");
831 }
832 if(!detail::isalpha(kv.first)) {
833 throw ValidationError("Unit must contain only letters.");
834 }
835 }
836
837 // make all units lowercase if CASE_INSENSITIVE
838 if(opts & CASE_INSENSITIVE) {
839 std::map<std::string, Number> lower_mapping;
840 for(auto &kv : mapping) {
841 auto s = detail::to_lower(kv.first);
842 if(lower_mapping.count(s)) {
843 throw ValidationError(std::string("Several matching lowercase unit representations are found: ") +
844 s);
845 }
846 lower_mapping[detail::to_lower(kv.first)] = kv.second;
847 }
848 mapping = std::move(lower_mapping);
849 }
850 }
851
853 template <typename Number> static std::string generate_description(const std::string &name, Options opts) {
854 std::stringstream out;
855 out << detail::type_name<Number>() << ' ';
856 if(opts & UNIT_REQUIRED) {
857 out << name;
858 } else {
859 out << '[' << name << ']';
860 }
861 return out.str();
862 }
863};
864
866 return static_cast<AsNumberWithUnit::Options>(static_cast<int>(a) | static_cast<int>(b));
867}
868
881 public:
882 using result_t = std::uint64_t;
883
891 explicit AsSizeValue(bool kb_is_1000);
892
893 private:
895 static std::map<std::string, result_t> init_mapping(bool kb_is_1000);
896
898 static std::map<std::string, result_t> get_mapping(bool kb_is_1000);
899};
900
901namespace detail {
906CLI11_INLINE std::pair<std::string, std::string> split_program_name(std::string commandline);
907
908} // namespace detail
910
911// [CLI11:validators_hpp:end]
912} // namespace CLI
913
914#ifndef CLI11_COMPILE
915#include "impl/Validators_inl.hpp"
916#endif
#define CLI11_INLINE
Definition Macros.hpp:73
#define CLI11_NODISCARD
Definition Macros.hpp:47
Definition Validators.hpp:736
Options
Definition Validators.hpp:742
@ UNIT_OPTIONAL
Definition Validators.hpp:745
@ CASE_INSENSITIVE
Definition Validators.hpp:744
@ DEFAULT
Definition Validators.hpp:747
@ UNIT_REQUIRED
Definition Validators.hpp:746
@ CASE_SENSITIVE
Definition Validators.hpp:743
AsNumberWithUnit(std::map< std::string, Number > mapping, Options opts=DEFAULT, const std::string &unit_name="UNIT")
Definition Validators.hpp:751
Definition Validators.hpp:880
AsSizeValue(bool kb_is_1000)
std::uint64_t result_t
Definition Validators.hpp:882
Produce a bounded range (factory). Min and max are inclusive.
Definition Validators.hpp:335
Bound(T min_val, T max_val)
Definition Validators.hpp:341
Bound(T max_val)
Range of one value is 0 to value.
Definition Validators.hpp:363
translate named items to other or a value set
Definition Validators.hpp:636
CheckedTransformer(T mapping)
direct map of std::string to std::string
Definition Validators.hpp:646
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:705
std::function< std::string(std::string)> filter_fn_t
Definition Validators.hpp:638
CheckedTransformer(std::initializer_list< std::pair< std::string, std::string > > values, Args &&...args)
This allows in-place construction.
Definition Validators.hpp:642
CheckedTransformer(T mapping, F filter_function)
Definition Validators.hpp:650
Class wrapping some of the accessors of Validator.
Definition Validators.hpp:205
Definition Validators.hpp:288
FileOnDefaultPath(std::string default_path, bool enableErrorReturn=true)
Verify items are in a set.
Definition Validators.hpp:507
IsMember(T &&set)
This checks to see if an item is in a set (empty function)
Definition Validators.hpp:517
IsMember(T set, F filter_function)
Definition Validators.hpp:521
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:566
IsMember(std::initializer_list< T > values, Args &&...args)
This allows in-place construction using an initializer list.
Definition Validators.hpp:513
std::function< std::string(std::string)> filter_fn_t
Definition Validators.hpp:509
Produce a range (factory). Min and max are inclusive.
Definition Validators.hpp:294
Range(T min_val, T max_val, const std::string &validator_name=std::string{})
Definition Validators.hpp:301
Range(T max_val, const std::string &validator_name=std::string{})
Range of one value is 0 to value.
Definition Validators.hpp:324
Translate named items to other or a value set.
Definition Validators.hpp:577
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:628
Transformer(std::initializer_list< std::pair< std::string, std::string > > values, Args &&...args)
This allows in-place construction.
Definition Validators.hpp:583
std::function< std::string(std::string)> filter_fn_t
Definition Validators.hpp:579
Transformer(T &&mapping)
direct map of std::string to std::string
Definition Validators.hpp:587
Transformer(T mapping, F filter_function)
Definition Validators.hpp:591
Validate the input as a particular type.
Definition Validators.hpp:269
TypeValidator()
Definition Validators.hpp:280
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:35
auto smart_deref(T value) -> decltype(*value)
Definition Validators.hpp:369
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:281
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:393
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:466
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:479
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:380
std::string value_string(const T &value)
get a string as a convertible value for arithmetic types
Definition TypeTools.hpp:351
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:424
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
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:32
bool lexical_cast(const std::string &input, T &output)
Integer conversion.
Definition TypeTools.hpp:913
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:713
std::string ignore_underscore(std::string item)
Helper function to allow ignore_underscore to be passed to IsMember or Transform.
Definition Validators.hpp:716
typename std::enable_if< B, T >::type enable_if_t
Definition TypeTools.hpp:43
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:865
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:574
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:719
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:78
T type
Definition TypeTools.hpp:95
Definition Validators.hpp:413
static const auto value
Definition Validators.hpp:418
std::integral_constant< bool, value > type
Definition Validators.hpp:419
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:109
typename T::value_type value_type
Definition TypeTools.hpp:110
typename std::remove_const< value_type >::type first_type
Definition TypeTools.hpp:111
static auto first(Q &&pair_value) -> decltype(std::forward< Q >(pair_value))
Get the first value (really just the underlying value)
Definition TypeTools.hpp:115