CLI11 2.4.1
Loading...
Searching...
No Matches
Validators.hpp
Go to the documentation of this file.
1// Copyright (c) 2017-2024, 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#if defined CLI11_HAS_FILESYSTEM && CLI11_HAS_FILESYSTEM > 0
30#include <filesystem> // NOLINT(build/include)
31#else
32#include <sys/stat.h>
33#include <sys/types.h>
34#endif
35
36// [CLI11:validators_hpp_filesystem:end]
37
38namespace CLI {
39// [CLI11:validators_hpp:verbatim]
40
41class Option;
42
44
51
53class Validator {
54 protected:
56 std::function<std::string()> desc_function_{[]() { return std::string{}; }};
57
60 std::function<std::string(std::string &)> func_{[](std::string &) { return std::string{}; }};
62 std::string name_{};
66 bool active_{true};
68 bool non_modifying_{false};
69
70 Validator(std::string validator_desc, std::function<std::string(std::string &)> func)
71 : desc_function_([validator_desc]() { return validator_desc; }), func_(std::move(func)) {}
72
73 public:
74 Validator() = default;
76 explicit Validator(std::string validator_desc) : desc_function_([validator_desc]() { return validator_desc; }) {}
78 Validator(std::function<std::string(std::string &)> op, std::string validator_desc, std::string validator_name = "")
79 : desc_function_([validator_desc]() { return validator_desc; }), func_(std::move(op)),
80 name_(std::move(validator_name)) {}
82 Validator &operation(std::function<std::string(std::string &)> op) {
83 func_ = std::move(op);
84 return *this;
85 }
88 std::string operator()(std::string &str) const;
89
92 std::string operator()(const std::string &str) const {
93 std::string value = str;
94 return (active_) ? func_(value) : std::string{};
95 }
96
98 Validator &description(std::string validator_desc) {
99 desc_function_ = [validator_desc]() { return validator_desc; };
100 return *this;
101 }
103 CLI11_NODISCARD Validator description(std::string validator_desc) const;
104
106 CLI11_NODISCARD std::string get_description() const {
107 if(active_) {
108 return desc_function_();
109 }
110 return std::string{};
111 }
113 Validator &name(std::string validator_name) {
114 name_ = std::move(validator_name);
115 return *this;
116 }
118 CLI11_NODISCARD Validator name(std::string validator_name) const {
119 Validator newval(*this);
120 newval.name_ = std::move(validator_name);
121 return newval;
122 }
124 CLI11_NODISCARD const std::string &get_name() const { return name_; }
126 Validator &active(bool active_val = true) {
127 active_ = active_val;
128 return *this;
129 }
131 CLI11_NODISCARD Validator active(bool active_val = true) const {
132 Validator newval(*this);
133 newval.active_ = active_val;
134 return newval;
135 }
136
138 Validator &non_modifying(bool no_modify = true) {
139 non_modifying_ = no_modify;
140 return *this;
141 }
143 Validator &application_index(int app_index) {
144 application_index_ = app_index;
145 return *this;
146 }
149 Validator newval(*this);
150 newval.application_index_ = app_index;
151 return newval;
152 }
156 CLI11_NODISCARD bool get_active() const { return active_; }
157
160
163 Validator operator&(const Validator &other) const;
164
167 Validator operator|(const Validator &other) const;
168
171
172 private:
173 void _merge_description(const Validator &val1, const Validator &val2, const std::string &merger);
174};
175
178 public:
179};
180// The implementation of the built in validators is using the Validator class;
181// the user is only expected to use the const (static) versions (since there's no setup).
182// Therefore, this is in detail.
183namespace detail {
184
187
189CLI11_INLINE path_type check_path(const char *file) noexcept;
190
193 public:
195};
196
199 public:
201};
202
205 public:
207};
208
211 public:
213};
214
216class IPV4Validator : public Validator {
217 public:
219};
220
222 public:
224};
225
226} // namespace detail
227
228// Static is not needed here, because global const implies static.
229
232
235
238
241
244
247
249template <typename DesiredType> class TypeValidator : public Validator {
250 public:
251 explicit TypeValidator(const std::string &validator_name)
252 : Validator(validator_name, [](std::string &input_string) {
254 auto val = DesiredType();
255 if(!lexical_cast(input_string, val)) {
256 return std::string("Failed parsing ") + input_string + " as a " + detail::type_name<DesiredType>();
257 }
258 return std::string();
259 }) {}
260 TypeValidator() : TypeValidator(detail::type_name<DesiredType>()) {}
261};
262
265
269 public:
270 explicit FileOnDefaultPath(std::string default_path, bool enableErrorReturn = true);
271};
272
274class Range : public Validator {
275 public:
280 template <typename T>
281 Range(T min_val, T max_val, const std::string &validator_name = std::string{}) : Validator(validator_name) {
282 if(validator_name.empty()) {
283 std::stringstream out;
284 out << detail::type_name<T>() << " in [" << min_val << " - " << max_val << "]";
285 description(out.str());
286 }
287
288 func_ = [min_val, max_val](std::string &input) {
290 T val;
291 bool converted = lexical_cast(input, val);
292 if((!converted) || (val < min_val || val > max_val)) {
293 std::stringstream out;
294 out << "Value " << input << " not in range [";
295 out << min_val << " - " << max_val << "]";
296 return out.str();
297 }
298 return std::string{};
299 };
300 }
301
303 template <typename T>
304 explicit Range(T max_val, const std::string &validator_name = std::string{})
305 : Range(static_cast<T>(0), max_val, validator_name) {}
306};
307
309const Range NonNegativeNumber((std::numeric_limits<double>::max)(), "NONNEGATIVE");
310
312const Range PositiveNumber((std::numeric_limits<double>::min)(), (std::numeric_limits<double>::max)(), "POSITIVE");
313
315class Bound : public Validator {
316 public:
321 template <typename T> Bound(T min_val, T max_val) {
322 std::stringstream out;
323 out << detail::type_name<T>() << " bounded to [" << min_val << " - " << max_val << "]";
324 description(out.str());
325
326 func_ = [min_val, max_val](std::string &input) {
328 T val;
329 bool converted = lexical_cast(input, val);
330 if(!converted) {
331 return std::string("Value ") + input + " could not be converted";
332 }
333 if(val < min_val)
334 input = detail::to_string(min_val);
335 else if(val > max_val)
336 input = detail::to_string(max_val);
337
338 return std::string{};
339 };
340 }
341
343 template <typename T> explicit Bound(T max_val) : Bound(static_cast<T>(0), max_val) {}
344};
345
346namespace detail {
347template <typename T,
348 enable_if_t<is_copyable_ptr<typename std::remove_reference<T>::type>::value, detail::enabler> = detail::dummy>
349auto smart_deref(T value) -> decltype(*value) {
350 return *value;
351}
352
353template <
354 typename T,
356typename std::remove_reference<T>::type &smart_deref(T &value) {
357 return value;
358}
360template <typename T> std::string generate_set(const T &set) {
361 using element_t = typename detail::element_type<T>::type;
362 using iteration_type_t = typename detail::pair_adaptor<element_t>::value_type; // the type of the object pair
363 std::string out(1, '{');
364 out.append(detail::join(
366 [](const iteration_type_t &v) { return detail::pair_adaptor<element_t>::first(v); },
367 ","));
368 out.push_back('}');
369 return out;
370}
371
373template <typename T> std::string generate_map(const T &map, bool key_only = false) {
374 using element_t = typename detail::element_type<T>::type;
375 using iteration_type_t = typename detail::pair_adaptor<element_t>::value_type; // the type of the object pair
376 std::string out(1, '{');
377 out.append(detail::join(
379 [key_only](const iteration_type_t &v) {
381
382 if(!key_only) {
383 res.append("->");
385 }
386 return res;
387 },
388 ","));
389 out.push_back('}');
390 return out;
391}
392
393template <typename C, typename V> struct has_find {
394 template <typename CC, typename VV>
395 static auto test(int) -> decltype(std::declval<CC>().find(std::declval<VV>()), std::true_type());
396 template <typename, typename> static auto test(...) -> decltype(std::false_type());
397
398 static const auto value = decltype(test<C, V>(0))::value;
399 using type = std::integral_constant<bool, value>;
400};
401
403template <typename T, typename V, enable_if_t<!has_find<T, V>::value, detail::enabler> = detail::dummy>
404auto search(const T &set, const V &val) -> std::pair<bool, decltype(std::begin(detail::smart_deref(set)))> {
405 using element_t = typename detail::element_type<T>::type;
406 auto &setref = detail::smart_deref(set);
407 auto it = std::find_if(std::begin(setref), std::end(setref), [&val](decltype(*std::begin(setref)) v) {
409 });
410 return {(it != std::end(setref)), it};
411}
412
414template <typename T, typename V, enable_if_t<has_find<T, V>::value, detail::enabler> = detail::dummy>
415auto search(const T &set, const V &val) -> std::pair<bool, decltype(std::begin(detail::smart_deref(set)))> {
416 auto &setref = detail::smart_deref(set);
417 auto it = setref.find(val);
418 return {(it != std::end(setref)), it};
419}
420
422template <typename T, typename V>
423auto search(const T &set, const V &val, const std::function<V(V)> &filter_function)
424 -> std::pair<bool, decltype(std::begin(detail::smart_deref(set)))> {
425 using element_t = typename detail::element_type<T>::type;
426 // do the potentially faster first search
427 auto res = search(set, val);
428 if((res.first) || (!(filter_function))) {
429 return res;
430 }
431 // if we haven't found it do the longer linear search with all the element translations
432 auto &setref = detail::smart_deref(set);
433 auto it = std::find_if(std::begin(setref), std::end(setref), [&](decltype(*std::begin(setref)) v) {
435 a = filter_function(a);
436 return (a == val);
437 });
438 return {(it != std::end(setref)), it};
439}
440
441// the following suggestion was made by Nikita Ofitserov(@himikof)
442// done in templates to prevent compiler warnings on negation of unsigned numbers
443
445template <typename T>
446inline typename std::enable_if<std::is_signed<T>::value, T>::type overflowCheck(const T &a, const T &b) {
447 if((a > 0) == (b > 0)) {
448 return ((std::numeric_limits<T>::max)() / (std::abs)(a) < (std::abs)(b));
449 }
450 return ((std::numeric_limits<T>::min)() / (std::abs)(a) > -(std::abs)(b));
451}
453template <typename T>
454inline typename std::enable_if<!std::is_signed<T>::value, T>::type overflowCheck(const T &a, const T &b) {
455 return ((std::numeric_limits<T>::max)() / a < b);
456}
457
459template <typename T> typename std::enable_if<std::is_integral<T>::value, bool>::type checked_multiply(T &a, T b) {
460 if(a == 0 || b == 0 || a == 1 || b == 1) {
461 a *= b;
462 return true;
463 }
464 if(a == (std::numeric_limits<T>::min)() || b == (std::numeric_limits<T>::min)()) {
465 return false;
466 }
467 if(overflowCheck(a, b)) {
468 return false;
469 }
470 a *= b;
471 return true;
472}
473
475template <typename T>
476typename std::enable_if<std::is_floating_point<T>::value, bool>::type checked_multiply(T &a, T b) {
477 T c = a * b;
478 if(std::isinf(c) && !std::isinf(a) && !std::isinf(b)) {
479 return false;
480 }
481 a = c;
482 return true;
483}
484
485} // namespace detail
487class IsMember : public Validator {
488 public:
489 using filter_fn_t = std::function<std::string(std::string)>;
490
492 template <typename T, typename... Args>
493 IsMember(std::initializer_list<T> values, Args &&...args)
494 : IsMember(std::vector<T>(values), std::forward<Args>(args)...) {}
495
497 template <typename T> explicit IsMember(T &&set) : IsMember(std::forward<T>(set), nullptr) {}
498
501 template <typename T, typename F> explicit IsMember(T set, F filter_function) {
502
503 // Get the type of the contained item - requires a container have ::value_type
504 // if the type does not have first_type and second_type, these are both value_type
505 using element_t = typename detail::element_type<T>::type; // Removes (smart) pointers if needed
506 using item_t = typename detail::pair_adaptor<element_t>::first_type; // Is value_type if not a map
507
508 using local_item_t = typename IsMemberType<item_t>::type; // This will convert bad types to good ones
509 // (const char * to std::string)
510
511 // Make a local copy of the filter function, using a std::function if not one already
512 std::function<local_item_t(local_item_t)> filter_fn = filter_function;
513
514 // This is the type name for help, it will take the current version of the set contents
515 desc_function_ = [set]() { return detail::generate_set(detail::smart_deref(set)); };
516
517 // This is the function that validates
518 // It stores a copy of the set pointer-like, so shared_ptr will stay alive
519 func_ = [set, filter_fn](std::string &input) {
521 local_item_t b;
522 if(!lexical_cast(input, b)) {
523 throw ValidationError(input); // name is added later
524 }
525 if(filter_fn) {
526 b = filter_fn(b);
527 }
528 auto res = detail::search(set, b, filter_fn);
529 if(res.first) {
530 // Make sure the version in the input string is identical to the one in the set
531 if(filter_fn) {
533 }
534
535 // Return empty error string (success)
536 return std::string{};
537 }
538
539 // If you reach this point, the result was not found
540 return input + " not in " + detail::generate_set(detail::smart_deref(set));
541 };
542 }
543
545 template <typename T, typename... Args>
546 IsMember(T &&set, filter_fn_t filter_fn_1, filter_fn_t filter_fn_2, Args &&...other)
547 : IsMember(
548 std::forward<T>(set),
549 [filter_fn_1, filter_fn_2](std::string a) { return filter_fn_2(filter_fn_1(a)); },
550 other...) {}
551};
552
554template <typename T> using TransformPairs = std::vector<std::pair<std::string, T>>;
555
557class Transformer : public Validator {
558 public:
559 using filter_fn_t = std::function<std::string(std::string)>;
560
562 template <typename... Args>
563 Transformer(std::initializer_list<std::pair<std::string, std::string>> values, Args &&...args)
564 : Transformer(TransformPairs<std::string>(values), std::forward<Args>(args)...) {}
565
567 template <typename T> explicit Transformer(T &&mapping) : Transformer(std::forward<T>(mapping), nullptr) {}
568
571 template <typename T, typename F> explicit Transformer(T mapping, F filter_function) {
572
574 "mapping must produce value pairs");
575 // Get the type of the contained item - requires a container have ::value_type
576 // if the type does not have first_type and second_type, these are both value_type
577 using element_t = typename detail::element_type<T>::type; // Removes (smart) pointers if needed
578 using item_t = typename detail::pair_adaptor<element_t>::first_type; // Is value_type if not a map
579 using local_item_t = typename IsMemberType<item_t>::type; // Will convert bad types to good ones
580 // (const char * to std::string)
581
582 // Make a local copy of the filter function, using a std::function if not one already
583 std::function<local_item_t(local_item_t)> filter_fn = filter_function;
584
585 // This is the type name for help, it will take the current version of the set contents
586 desc_function_ = [mapping]() { return detail::generate_map(detail::smart_deref(mapping)); };
587
588 func_ = [mapping, filter_fn](std::string &input) {
590 local_item_t b;
591 if(!lexical_cast(input, b)) {
592 return std::string();
593 // there is no possible way we can match anything in the mapping if we can't convert so just return
594 }
595 if(filter_fn) {
596 b = filter_fn(b);
597 }
598 auto res = detail::search(mapping, b, filter_fn);
599 if(res.first) {
601 }
602 return std::string{};
603 };
604 }
605
607 template <typename T, typename... Args>
608 Transformer(T &&mapping, filter_fn_t filter_fn_1, filter_fn_t filter_fn_2, Args &&...other)
609 : Transformer(
610 std::forward<T>(mapping),
611 [filter_fn_1, filter_fn_2](std::string a) { return filter_fn_2(filter_fn_1(a)); },
612 other...) {}
613};
614
617 public:
618 using filter_fn_t = std::function<std::string(std::string)>;
619
621 template <typename... Args>
622 CheckedTransformer(std::initializer_list<std::pair<std::string, std::string>> values, Args &&...args)
623 : CheckedTransformer(TransformPairs<std::string>(values), std::forward<Args>(args)...) {}
624
626 template <typename T> explicit CheckedTransformer(T mapping) : CheckedTransformer(std::move(mapping), nullptr) {}
627
630 template <typename T, typename F> explicit CheckedTransformer(T mapping, F filter_function) {
631
633 "mapping must produce value pairs");
634 // Get the type of the contained item - requires a container have ::value_type
635 // if the type does not have first_type and second_type, these are both value_type
636 using element_t = typename detail::element_type<T>::type; // Removes (smart) pointers if needed
637 using item_t = typename detail::pair_adaptor<element_t>::first_type; // Is value_type if not a map
638 using local_item_t = typename IsMemberType<item_t>::type; // Will convert bad types to good ones
639 // (const char * to std::string)
640 using iteration_type_t = typename detail::pair_adaptor<element_t>::value_type; // the type of the object pair
641
642 // Make a local copy of the filter function, using a std::function if not one already
643 std::function<local_item_t(local_item_t)> filter_fn = filter_function;
644
645 auto tfunc = [mapping]() {
646 std::string out("value in ");
647 out += detail::generate_map(detail::smart_deref(mapping)) + " OR {";
648 out += detail::join(
649 detail::smart_deref(mapping),
650 [](const iteration_type_t &v) { return detail::to_string(detail::pair_adaptor<element_t>::second(v)); },
651 ",");
652 out.push_back('}');
653 return out;
654 };
655
656 desc_function_ = tfunc;
657
658 func_ = [mapping, tfunc, filter_fn](std::string &input) {
660 local_item_t b;
661 bool converted = lexical_cast(input, b);
662 if(converted) {
663 if(filter_fn) {
664 b = filter_fn(b);
665 }
666 auto res = detail::search(mapping, b, filter_fn);
667 if(res.first) {
669 return std::string{};
670 }
671 }
672 for(const auto &v : detail::smart_deref(mapping)) {
674 if(output_string == input) {
675 return std::string();
676 }
677 }
678
679 return "Check " + input + " " + tfunc() + " FAILED";
680 };
681 }
682
684 template <typename T, typename... Args>
685 CheckedTransformer(T &&mapping, filter_fn_t filter_fn_1, filter_fn_t filter_fn_2, Args &&...other)
687 std::forward<T>(mapping),
688 [filter_fn_1, filter_fn_2](std::string a) { return filter_fn_2(filter_fn_1(a)); },
689 other...) {}
690};
691
693inline std::string ignore_case(std::string item) { return detail::to_lower(item); }
694
696inline std::string ignore_underscore(std::string item) { return detail::remove_underscore(item); }
697
699inline std::string ignore_space(std::string item) {
700 item.erase(std::remove(std::begin(item), std::end(item), ' '), std::end(item));
701 item.erase(std::remove(std::begin(item), std::end(item), '\t'), std::end(item));
702 return item;
703}
704
717 public:
722 enum Options {
728 };
729
730 template <typename Number>
731 explicit AsNumberWithUnit(std::map<std::string, Number> mapping,
732 Options opts = DEFAULT,
733 const std::string &unit_name = "UNIT") {
734 description(generate_description<Number>(unit_name, opts));
735 validate_mapping(mapping, opts);
736
737 // transform function
738 func_ = [mapping, opts](std::string &input) -> std::string {
739 Number num{};
740
741 detail::rtrim(input);
742 if(input.empty()) {
743 throw ValidationError("Input is empty");
744 }
745
746 // Find split position between number and prefix
747 auto unit_begin = input.end();
748 while(unit_begin > input.begin() && std::isalpha(*(unit_begin - 1), std::locale())) {
749 --unit_begin;
750 }
751
752 std::string unit{unit_begin, input.end()};
753 input.resize(static_cast<std::size_t>(std::distance(input.begin(), unit_begin)));
754 detail::trim(input);
755
756 if(opts & UNIT_REQUIRED && unit.empty()) {
757 throw ValidationError("Missing mandatory unit");
758 }
759 if(opts & CASE_INSENSITIVE) {
760 unit = detail::to_lower(unit);
761 }
762 if(unit.empty()) {
764 if(!lexical_cast(input, num)) {
765 throw ValidationError(std::string("Value ") + input + " could not be converted to " +
766 detail::type_name<Number>());
767 }
768 // No need to modify input if no unit passed
769 return {};
770 }
771
772 // find corresponding factor
773 auto it = mapping.find(unit);
774 if(it == mapping.end()) {
775 throw ValidationError(unit +
776 " unit not recognized. "
777 "Allowed values: " +
778 detail::generate_map(mapping, true));
779 }
780
781 if(!input.empty()) {
783 bool converted = lexical_cast(input, num);
784 if(!converted) {
785 throw ValidationError(std::string("Value ") + input + " could not be converted to " +
786 detail::type_name<Number>());
787 }
788 // perform safe multiplication
789 bool ok = detail::checked_multiply(num, it->second);
790 if(!ok) {
791 throw ValidationError(detail::to_string(num) + " multiplied by " + unit +
792 " factor would cause number overflow. Use smaller value.");
793 }
794 } else {
795 num = static_cast<Number>(it->second);
796 }
797
798 input = detail::to_string(num);
799
800 return {};
801 };
802 }
803
804 private:
807 template <typename Number> static void validate_mapping(std::map<std::string, Number> &mapping, Options opts) {
808 for(auto &kv : mapping) {
809 if(kv.first.empty()) {
810 throw ValidationError("Unit must not be empty.");
811 }
812 if(!detail::isalpha(kv.first)) {
813 throw ValidationError("Unit must contain only letters.");
814 }
815 }
816
817 // make all units lowercase if CASE_INSENSITIVE
818 if(opts & CASE_INSENSITIVE) {
819 std::map<std::string, Number> lower_mapping;
820 for(auto &kv : mapping) {
821 auto s = detail::to_lower(kv.first);
822 if(lower_mapping.count(s)) {
823 throw ValidationError(std::string("Several matching lowercase unit representations are found: ") +
824 s);
825 }
826 lower_mapping[detail::to_lower(kv.first)] = kv.second;
827 }
828 mapping = std::move(lower_mapping);
829 }
830 }
831
833 template <typename Number> static std::string generate_description(const std::string &name, Options opts) {
834 std::stringstream out;
835 out << detail::type_name<Number>() << ' ';
836 if(opts & UNIT_REQUIRED) {
837 out << name;
838 } else {
839 out << '[' << name << ']';
840 }
841 return out.str();
842 }
843};
844
846 return static_cast<AsNumberWithUnit::Options>(static_cast<int>(a) | static_cast<int>(b));
847}
848
861 public:
862 using result_t = std::uint64_t;
863
871 explicit AsSizeValue(bool kb_is_1000);
872
873 private:
875 static std::map<std::string, result_t> init_mapping(bool kb_is_1000);
876
878 static std::map<std::string, result_t> get_mapping(bool kb_is_1000);
879};
880
881namespace detail {
886CLI11_INLINE std::pair<std::string, std::string> split_program_name(std::string commandline);
887
888} // namespace detail
890
891// [CLI11:validators_hpp:end]
892} // namespace CLI
893
894#ifndef CLI11_COMPILE
895#include "impl/Validators_inl.hpp"
896#endif
#define CLI11_INLINE
Definition: Macros.hpp:129
#define CLI11_NODISCARD
Definition: Macros.hpp:47
Definition: Validators.hpp:716
Options
Definition: Validators.hpp:722
@ UNIT_OPTIONAL
Definition: Validators.hpp:725
@ CASE_INSENSITIVE
Definition: Validators.hpp:724
@ DEFAULT
Definition: Validators.hpp:727
@ UNIT_REQUIRED
Definition: Validators.hpp:726
@ CASE_SENSITIVE
Definition: Validators.hpp:723
AsNumberWithUnit(std::map< std::string, Number > mapping, Options opts=DEFAULT, const std::string &unit_name="UNIT")
Definition: Validators.hpp:731
Definition: Validators.hpp:860
AsSizeValue(bool kb_is_1000)
std::uint64_t result_t
Definition: Validators.hpp:862
Produce a bounded range (factory). Min and max are inclusive.
Definition: Validators.hpp:315
Bound(T min_val, T max_val)
Definition: Validators.hpp:321
Bound(T max_val)
Range of one value is 0 to value.
Definition: Validators.hpp:343
translate named items to other or a value set
Definition: Validators.hpp:616
CheckedTransformer(T mapping)
direct map of std::string to std::string
Definition: Validators.hpp:626
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:685
std::function< std::string(std::string)> filter_fn_t
Definition: Validators.hpp:618
CheckedTransformer(std::initializer_list< std::pair< std::string, std::string > > values, Args &&...args)
This allows in-place construction.
Definition: Validators.hpp:622
CheckedTransformer(T mapping, F filter_function)
Definition: Validators.hpp:630
Class wrapping some of the accessors of Validator.
Definition: Validators.hpp:177
Definition: Validators.hpp:268
FileOnDefaultPath(std::string default_path, bool enableErrorReturn=true)
Verify items are in a set.
Definition: Validators.hpp:487
IsMember(T &&set)
This checks to see if an item is in a set (empty function)
Definition: Validators.hpp:497
IsMember(T set, F filter_function)
Definition: Validators.hpp:501
IsMember(T &&set, filter_fn_t filter_fn_1, filter_fn_t filter_fn_2, Args &&...other)
You can pass in as many filter functions as you like, they nest (string only currently)
Definition: Validators.hpp:546
IsMember(std::initializer_list< T > values, Args &&...args)
This allows in-place construction using an initializer list.
Definition: Validators.hpp:493
std::function< std::string(std::string)> filter_fn_t
Definition: Validators.hpp:489
Produce a range (factory). Min and max are inclusive.
Definition: Validators.hpp:274
Range(T min_val, T max_val, const std::string &validator_name=std::string{})
Definition: Validators.hpp:281
Range(T max_val, const std::string &validator_name=std::string{})
Range of one value is 0 to value.
Definition: Validators.hpp:304
Translate named items to other or a value set.
Definition: Validators.hpp:557
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:608
Transformer(std::initializer_list< std::pair< std::string, std::string > > values, Args &&...args)
This allows in-place construction.
Definition: Validators.hpp:563
std::function< std::string(std::string)> filter_fn_t
Definition: Validators.hpp:559
Transformer(T &&mapping)
direct map of std::string to std::string
Definition: Validators.hpp:567
Transformer(T mapping, F filter_function)
Definition: Validators.hpp:571
Validate the input as a particular type.
Definition: Validators.hpp:249
TypeValidator()
Definition: Validators.hpp:260
TypeValidator(const std::string &validator_name)
Definition: Validators.hpp:251
Thrown when validation of results fails.
Definition: Error.hpp:219
Some validators that are provided.
Definition: Validators.hpp:53
CLI11_NODISCARD int get_application_index() const
Get the current value of the application index.
Definition: Validators.hpp:154
int application_index_
A Validator will only apply to an indexed value (-1 is all elements)
Definition: Validators.hpp:64
Validator & non_modifying(bool no_modify=true)
Specify whether the Validator can be modifying or not.
Definition: Validators.hpp:138
Validator & description(std::string validator_desc)
Specify the type string.
Definition: Validators.hpp:98
std::string operator()(const std::string &str) const
Definition: Validators.hpp:92
CLI11_NODISCARD Validator application_index(int app_index) const
Specify the application index of a validator.
Definition: Validators.hpp:148
CLI11_NODISCARD bool get_active() const
Get a boolean if the validator is active.
Definition: Validators.hpp:156
Validator operator&(const Validator &other) const
bool active_
Enable for Validator to allow it to be disabled if need be.
Definition: Validators.hpp:66
bool non_modifying_
specify that a validator should not modify the input
Definition: Validators.hpp:68
Validator(std::string validator_desc)
Construct a Validator with just the description string.
Definition: Validators.hpp:76
Validator(std::string validator_desc, std::function< std::string(std::string &)> func)
Definition: Validators.hpp:70
CLI11_NODISCARD Validator description(std::string validator_desc) const
Specify the type string.
Validator & name(std::string validator_name)
Specify the type string.
Definition: Validators.hpp:113
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:56
std::function< std::string(std::string &)> func_
Definition: Validators.hpp:60
CLI11_NODISCARD std::string get_description() const
Generate type description information for the Validator.
Definition: Validators.hpp:106
Validator operator!() const
Create a validator that fails when a given validator succeeds.
CLI11_NODISCARD Validator active(bool active_val=true) const
Specify whether the Validator is active or not.
Definition: Validators.hpp:131
CLI11_NODISCARD const std::string & get_name() const
Get the name of the Validator.
Definition: Validators.hpp:124
Validator operator|(const Validator &other) const
Validator & active(bool active_val=true)
Specify whether the Validator is active or not.
Definition: Validators.hpp:126
std::string name_
The name for search purposes of the Validator.
Definition: Validators.hpp:62
CLI11_NODISCARD bool get_modifying() const
Get a boolean if the validator is allowed to modify the input returns true if it can modify the input...
Definition: Validators.hpp:159
CLI11_NODISCARD Validator name(std::string validator_name) const
Specify the type string.
Definition: Validators.hpp:118
Validator & application_index(int app_index)
Specify the application index of a validator.
Definition: Validators.hpp:143
Validator(std::function< std::string(std::string &)> op, std::string validator_desc, std::string validator_name="")
Construct Validator from basic information.
Definition: Validators.hpp:78
Validator & operation(std::function< std::string(std::string &)> op)
Set the Validator operation function.
Definition: Validators.hpp:82
Definition: Validators.hpp:221
Check for an existing directory (returns error message if check fails)
Definition: Validators.hpp:198
Check for an existing file (returns error message if check fails)
Definition: Validators.hpp:192
Check for an existing path.
Definition: Validators.hpp:204
Validate the given string is a legal ipv4 address.
Definition: Validators.hpp:216
Check for an non-existing path.
Definition: Validators.hpp:210
constexpr enabler dummy
An instance to use in EnableIf.
Definition: TypeTools.hpp:37
auto smart_deref(T value) -> decltype(*value)
Definition: Validators.hpp:349
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:293
path_type
CLI enumeration of different file types.
Definition: Validators.hpp:186
std::string generate_map(const T &map, bool key_only=false)
Generate a string representation of a map.
Definition: Validators.hpp:373
std::string remove_underscore(std::string str)
remove underscores from a string
Definition: StringTools.hpp:187
std::enable_if< std::is_signed< T >::value, T >::type overflowCheck(const T &a, const T &b)
Do a check for overflow on signed numbers.
Definition: Validators.hpp:446
std::enable_if< std::is_integral< T >::value, bool >::type checked_multiply(T &a, T b)
Performs a *= b; if it doesn't cause integer overflow. Returns false otherwise.
Definition: Validators.hpp:459
std::string & 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:360
std::string value_string(const T &value)
get a string as a convertible value for arithmetic types
Definition: TypeTools.hpp:363
CLI11_INLINE path_type check_path(const char *file) noexcept
get the type of the path from a file name
auto search(const T &set, const V &val) -> std::pair< bool, decltype(std::begin(detail::smart_deref(set)))>
A search function.
Definition: Validators.hpp:404
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:174
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:179
CLI11_INLINE std::string & rtrim(std::string &str)
Trim whitespace from right of string.
enabler
Simple empty scoped class.
Definition: TypeTools.hpp:34
bool lexical_cast(const std::string &input, T &output)
Integer conversion.
Definition: TypeTools.hpp:1015
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:693
std::string ignore_underscore(std::string item)
Helper function to allow ignore_underscore to be passed to IsMember or Transform.
Definition: Validators.hpp:696
typename std::enable_if< B, T >::type enable_if_t
Definition: TypeTools.hpp:45
const detail::ExistingDirectoryValidator ExistingDirectory
Check for an existing directory (returns error message if check fails)
Definition: Validators.hpp:234
AsNumberWithUnit::Options operator|(const AsNumberWithUnit::Options &a, const AsNumberWithUnit::Options &b)
Definition: Validators.hpp:845
const detail::EscapedStringTransformer EscapedString
convert escaped characters into their associated values
Definition: Validators.hpp:246
const detail::NonexistentPathValidator NonexistentPath
Check for an non-existing path.
Definition: Validators.hpp:240
const detail::IPV4Validator ValidIPV4
Check for an IP4 address.
Definition: Validators.hpp:243
const detail::ExistingPathValidator ExistingPath
Check for an existing path.
Definition: Validators.hpp:237
std::vector< std::pair< std::string, T > > TransformPairs
definition of the default transformation object
Definition: Validators.hpp:554
const detail::ExistingFileValidator ExistingFile
Check for existing file (returns error message if check fails)
Definition: Validators.hpp:231
const Range NonNegativeNumber((std::numeric_limits< double >::max)(), "NONNEGATIVE")
Check for a non negative number.
std::string ignore_space(std::string item)
Helper function to allow checks to ignore spaces to be passed to IsMember or Transform.
Definition: Validators.hpp:699
const Range PositiveNumber((std::numeric_limits< double >::min)(),(std::numeric_limits< double >::max)(), "POSITIVE")
Check for a positive valued number (val>0.0), <double>::min here is the smallest positive number.
const TypeValidator< double > Number("NUMBER")
Check for a number.
T type
Definition: TypeTools.hpp:80
T type
Definition: TypeTools.hpp:97
Definition: Validators.hpp:393
static const auto value
Definition: Validators.hpp:398
std::integral_constant< bool, value > type
Definition: Validators.hpp:399
static auto test(int) -> decltype(std::declval< CC >().find(std::declval< VV >()), std::true_type())
static auto test(...) -> decltype(std::false_type())
Adaptor for set-like structure: This just wraps a normal container in a few utilities that do almost ...
Definition: TypeTools.hpp:111
typename T::value_type value_type
Definition: TypeTools.hpp:112
typename std::remove_const< value_type >::type first_type
Definition: TypeTools.hpp:113
static auto first(Q &&pair_value) -> decltype(std::forward< Q >(pair_value))
Get the first value (really just the underlying value)
Definition: TypeTools.hpp:117