CLI11 2.7.2
C++11 Command Line Interface Parser
Loading...
Searching...
No Matches
Validators.hpp
1// Copyright (c) 2017-2026, 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// IWYU pragma: private, include "CLI/CLI.hpp"
10
11#include "Error.hpp"
12#include "Macros.hpp"
13#include "StringTools.hpp"
14#include "TypeTools.hpp"
15
16// [CLI11:public_includes:set]
17#include <cmath>
18#include <cstdint>
19#include <cstdlib>
20#include <functional>
21#include <iterator>
22#include <limits>
23#include <sstream>
24#include <string>
25#include <type_traits>
26#include <utility>
27// [CLI11:public_includes:end]
28
29// [CLI11:validators_hpp_filesystem:verbatim]
30
31#if defined CLI11_HAS_FILESYSTEM && CLI11_HAS_FILESYSTEM > 0
32#include <filesystem>
33#else
34#include <sys/stat.h>
35#include <sys/types.h>
36#endif
37
38// [CLI11:validators_hpp_filesystem:end]
39
40namespace CLI {
41// [CLI11:validators_hpp:verbatim]
42
43class Option;
44
46
53
55class Validator {
56 protected:
58 std::function<std::string()> desc_function_{[]() { return std::string{}; }};
59
62 std::function<std::string(std::string &)> func_{[](std::string &) { return std::string{}; }};
64 std::string name_{};
68 bool active_{true};
70 bool non_modifying_{false};
71
72 Validator(std::string validator_desc, std::function<std::string(std::string &)> func);
73
74 public:
75 Validator() = default;
77 explicit Validator(std::string validator_desc) : desc_function_([validator_desc]() { return validator_desc; }) {}
79 Validator(std::function<std::string(std::string &)> op,
80 std::string validator_desc,
81 std::string validator_name = "");
83 Validator &operation(std::function<std::string(std::string &)> op) {
84 func_ = std::move(op);
85 return *this;
86 }
87
89 std::string operator()(std::string &str) const;
90
93 std::string operator()(const std::string &str) const;
94
96 Validator &description(std::string validator_desc) {
97 desc_function_ = [validator_desc]() { return validator_desc; };
98 return *this;
99 }
100
101 CLI11_NODISCARD Validator description(std::string validator_desc) const;
102
104 CLI11_NODISCARD std::string get_description() const;
106 Validator &name(std::string validator_name) {
107 name_ = std::move(validator_name);
108 return *this;
109 }
110
111 CLI11_NODISCARD Validator name(std::string validator_name) const;
113 CLI11_NODISCARD const std::string &get_name() const { return name_; }
115 Validator &active(bool active_val = true) {
116 active_ = active_val;
117 return *this;
118 }
119
120 CLI11_NODISCARD Validator active(bool active_val = true) const;
121
123 Validator &non_modifying(bool no_modify = true) {
124 non_modifying_ = no_modify;
125 return *this;
126 }
127
128 Validator &application_index(int app_index) {
129 application_index_ = app_index;
130 return *this;
131 }
132
133 CLI11_NODISCARD Validator application_index(int app_index) const;
135 CLI11_NODISCARD int get_application_index() const { return application_index_; }
137 CLI11_NODISCARD bool get_active() const { return active_; }
138
140 CLI11_NODISCARD bool get_modifying() const { return !non_modifying_; }
141
144 Validator operator&(const Validator &other) const;
145
148 Validator operator|(const Validator &other) const;
149
151 Validator operator!() const;
152
153 private:
154 void _merge_description(const Validator &val1, const Validator &val2, const std::string &merger);
155};
156
158using CustomValidator = Validator;
159
160// The implementation of the built in validators is using the Validator class;
161// the user is only expected to use the const (static) versions (since there's no setup).
162// Therefore, this is in detail.
163namespace detail {
164
166enum class path_type : std::uint8_t { nonexistent, file, directory };
167
169CLI11_INLINE path_type check_path(const char *file) noexcept;
170
171// Static is not needed here, because global const implies static.
172
174class ExistingFileValidator : public Validator {
175 public:
176 ExistingFileValidator();
177};
178
180class ExistingDirectoryValidator : public Validator {
181 public:
182 ExistingDirectoryValidator();
183};
184
186class ExistingPathValidator : public Validator {
187 public:
188 ExistingPathValidator();
189};
190
192class NonexistentPathValidator : public Validator {
193 public:
194 NonexistentPathValidator();
195};
196
197class EscapedStringTransformer : public Validator {
198 public:
199 EscapedStringTransformer();
200};
201
202} // namespace detail
203
205CLI11_MODULE_INLINE const detail::ExistingFileValidator ExistingFile;
206
208CLI11_MODULE_INLINE const detail::ExistingDirectoryValidator ExistingDirectory;
209
211CLI11_MODULE_INLINE const detail::ExistingPathValidator ExistingPath;
212
214CLI11_MODULE_INLINE const detail::NonexistentPathValidator NonexistentPath;
215
217CLI11_MODULE_INLINE const detail::EscapedStringTransformer EscapedString;
218
221class FileOnDefaultPath : public Validator {
222 public:
223 explicit FileOnDefaultPath(std::string default_path, bool enableErrorReturn = true);
224};
225
227class Range : public Validator {
228 public:
233 template <typename T>
234 Range(T min_val, T max_val, const std::string &validator_name = std::string{}) : Validator(validator_name) {
235 if(validator_name.empty()) {
236 std::stringstream out;
237 out << detail::type_name<T>() << " in [" << min_val << " - " << max_val << "]";
238 description(out.str());
239 }
240
241 func_ = [min_val, max_val](std::string &input) {
242 using CLI::detail::lexical_cast;
243 T val;
244 bool converted = lexical_cast(input, val);
245 if((!converted) || (val < min_val || val > max_val)) {
246 std::stringstream out;
247 out << "Value " << input << " not in range [";
248 out << min_val << " - " << max_val << "]";
249 return out.str();
250 }
251 return std::string{};
252 };
253 }
254
256 template <typename T>
257 explicit Range(T max_val, const std::string &validator_name = std::string{})
258 : Range(static_cast<T>(0), max_val, validator_name) {}
259};
260
262CLI11_MODULE_INLINE const Range NonNegativeNumber((std::numeric_limits<double>::max)(), "NONNEGATIVE");
263
265CLI11_MODULE_INLINE const
266 Range PositiveNumber((std::numeric_limits<double>::denorm_min)(), (std::numeric_limits<double>::max)(), "POSITIVE");
267
268namespace detail {
269// the following suggestion was made by Nikita Ofitserov(@himikof)
270// done in templates to prevent compiler warnings on negation of unsigned numbers
271
273template <typename T>
274inline typename std::enable_if<std::is_signed<T>::value, bool>::type overflowCheck(const T &a, const T &b) {
275 if((a > 0) == (b > 0)) {
276 return ((std::numeric_limits<T>::max)() / (std::abs)(a) < (std::abs)(b));
277 }
278 return ((std::numeric_limits<T>::min)() / (std::abs)(a) > -(std::abs)(b));
279}
281template <typename T>
282inline typename std::enable_if<!std::is_signed<T>::value, bool>::type overflowCheck(const T &a, const T &b) {
283 return ((std::numeric_limits<T>::max)() / a < b);
284}
285
287template <typename T> typename std::enable_if<std::is_integral<T>::value, bool>::type checked_multiply(T &a, T b) {
288 if(a == 0 || b == 0 || a == 1 || b == 1) {
289 a *= b;
290 return true;
291 }
292 if(a == (std::numeric_limits<T>::min)() || b == (std::numeric_limits<T>::min)()) {
293 return false;
294 }
295 if(overflowCheck(a, b)) {
296 return false;
297 }
298 a *= b;
299 return true;
300}
301
303template <typename T>
304typename std::enable_if<std::is_floating_point<T>::value, bool>::type checked_multiply(T &a, T b) {
305 T c = a * b;
306 if(std::isinf(c) && !std::isinf(a) && !std::isinf(b)) {
307 return false;
308 }
309 a = c;
310 return true;
311}
316CLI11_INLINE std::pair<std::string, std::string> split_program_name(std::string commandline);
317
318} // namespace detail
320
321// [CLI11:validators_hpp:end]
322} // namespace CLI
323
324#ifndef CLI11_COMPILE
325#include "impl/Validators_inl.hpp" // IWYU pragma: export
326#endif
Definition Option.hpp:261
Produce a range (factory). Min and max are inclusive.
Definition Validators.hpp:227
Range(T min_val, T max_val, const std::string &validator_name=std::string{})
Definition Validators.hpp:234
Range(T max_val, const std::string &validator_name=std::string{})
Range of one value is 0 to value.
Definition Validators.hpp:257
Some validators that are provided.
Definition Validators.hpp:55
Validator operator&(const Validator &other) const
Definition Validators_inl.hpp:86
CLI11_NODISCARD int get_application_index() const
Get the current value of the application index.
Definition Validators.hpp:135
int application_index_
A Validator will only apply to an indexed value (-1 is all elements).
Definition Validators.hpp:66
Validator & non_modifying(bool no_modify=true)
Specify whether the Validator can be modifying or not.
Definition Validators.hpp:123
Validator & description(std::string validator_desc)
Specify the type string.
Definition Validators.hpp:96
Validator operator|(const Validator &other) const
Definition Validators_inl.hpp:108
CLI11_NODISCARD bool get_active() const
Get a boolean if the validator is active.
Definition Validators.hpp:137
bool active_
Enable for Validator to allow it to be disabled if need be.
Definition Validators.hpp:68
bool non_modifying_
specify that a validator should not modify the input
Definition Validators.hpp:70
Validator(std::string validator_desc)
Construct a Validator with just the description string.
Definition Validators.hpp:77
Validator & name(std::string validator_name)
Specify the type string.
Definition Validators.hpp:106
std::function< std::string()> desc_function_
This is the description function, if empty the description_ will be used.
Definition Validators.hpp:58
std::function< std::string(std::string &)> func_
Definition Validators.hpp:62
CLI11_NODISCARD std::string get_description() const
Generate type description information for the Validator.
Definition Validators_inl.hpp:61
CLI11_NODISCARD const std::string & get_name() const
Get the name of the Validator.
Definition Validators.hpp:113
Validator & active(bool active_val=true)
Specify whether the Validator is active or not.
Definition Validators.hpp:115
std::string name_
The name for search purposes of the Validator.
Definition Validators.hpp:64
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:140
Validator operator!() const
Create a validator that fails when a given validator succeeds.
Definition Validators_inl.hpp:130
std::string operator()(std::string &str) const
Definition Validators_inl.hpp:37
Validator & application_index(int app_index)
Specify the application index of a validator.
Definition Validators.hpp:128
Validator & operation(std::function< std::string(std::string &)> op)
Set the Validator operation function.
Definition Validators.hpp:83
Definition Validators.hpp:197
Check for an existing directory (returns error message if check fails).
Definition Validators.hpp:180
Check for an existing file (returns error message if check fails).
Definition Validators.hpp:174
Check for an existing path.
Definition Validators.hpp:186
Check for an non-existing path.
Definition Validators.hpp:192