CLI11
C++11 Command Line Interface Parser
Loading...
Searching...
No Matches
Validators.hpp
1// Copyright (c) 2017-2025, 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 <functional>
20#include <iostream>
21#include <limits>
22#include <memory>
23#include <string>
24#include <utility>
25#include <vector>
26// [CLI11:public_includes:end]
27
28// [CLI11:validators_hpp_filesystem:verbatim]
29
30#if defined CLI11_HAS_FILESYSTEM && CLI11_HAS_FILESYSTEM > 0
31#include <filesystem> // NOLINT(build/include)
32#else
33#include <sys/stat.h>
34#include <sys/types.h>
35#endif
36
37// [CLI11:validators_hpp_filesystem:end]
38
39namespace CLI {
40// [CLI11:validators_hpp:verbatim]
41
42class Option;
43
45
52
54class Validator {
55 protected:
57 std::function<std::string()> desc_function_{[]() { return std::string{}; }};
58
61 std::function<std::string(std::string &)> func_{[](std::string &) { return std::string{}; }};
63 std::string name_{};
67 bool active_{true};
69 bool non_modifying_{false};
70
71 Validator(std::string validator_desc, std::function<std::string(std::string &)> func)
72 : desc_function_([validator_desc]() { return validator_desc; }), func_(std::move(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, std::string validator_desc, std::string validator_name = "")
80 : desc_function_([validator_desc]() { return validator_desc; }), func_(std::move(op)),
81 name_(std::move(validator_name)) {}
83 Validator &operation(std::function<std::string(std::string &)> op) {
84 func_ = std::move(op);
85 return *this;
86 }
89 std::string operator()(std::string &str) const;
90
93 std::string operator()(const std::string &str) const {
94 std::string value = str;
95 return (active_) ? func_(value) : std::string{};
96 }
97
99 Validator &description(std::string validator_desc) {
100 desc_function_ = [validator_desc]() { return validator_desc; };
101 return *this;
102 }
104 CLI11_NODISCARD Validator description(std::string validator_desc) const;
105
107 CLI11_NODISCARD std::string get_description() const {
108 if(active_) {
109 return desc_function_();
110 }
111 return std::string{};
112 }
114 Validator &name(std::string validator_name) {
115 name_ = std::move(validator_name);
116 return *this;
117 }
119 CLI11_NODISCARD Validator name(std::string validator_name) const {
120 Validator newval(*this);
121 newval.name_ = std::move(validator_name);
122 return newval;
123 }
125 CLI11_NODISCARD const std::string &get_name() const { return name_; }
127 Validator &active(bool active_val = true) {
128 active_ = active_val;
129 return *this;
130 }
132 CLI11_NODISCARD Validator active(bool active_val = true) const {
133 Validator newval(*this);
134 newval.active_ = active_val;
135 return newval;
136 }
137
139 Validator &non_modifying(bool no_modify = true) {
140 non_modifying_ = no_modify;
141 return *this;
142 }
144 Validator &application_index(int app_index) {
145 application_index_ = app_index;
146 return *this;
147 }
149 CLI11_NODISCARD Validator application_index(int app_index) const {
150 Validator newval(*this);
151 newval.application_index_ = app_index;
152 return newval;
153 }
155 CLI11_NODISCARD int get_application_index() const { return application_index_; }
157 CLI11_NODISCARD bool get_active() const { return active_; }
158
160 CLI11_NODISCARD bool get_modifying() const { return !non_modifying_; }
161
164 Validator operator&(const Validator &other) const;
165
168 Validator operator|(const Validator &other) const;
169
171 Validator operator!() const;
172
173 private:
174 void _merge_description(const Validator &val1, const Validator &val2, const std::string &merger);
175};
176
178using CustomValidator = Validator;
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
186enum class path_type : std::uint8_t { nonexistent, file, directory };
187
189CLI11_INLINE path_type check_path(const char *file) noexcept;
190
191// Static is not needed here, because global const implies static.
192
195 public:
197};
198
201 public:
203};
204
207 public:
209};
210
213 public:
215};
216
218 public:
220};
221
222} // namespace detail
223
225const detail::ExistingFileValidator ExistingFile;
226
228const detail::ExistingDirectoryValidator ExistingDirectory;
229
231const detail::ExistingPathValidator ExistingPath;
232
234const detail::NonexistentPathValidator NonexistentPath;
235
237const detail::EscapedStringTransformer EscapedString;
238
242 public:
243 explicit FileOnDefaultPath(std::string default_path, bool enableErrorReturn = true);
244};
245
247class Range : public Validator {
248 public:
253 template <typename T>
254 Range(T min_val, T max_val, const std::string &validator_name = std::string{}) : Validator(validator_name) {
255 if(validator_name.empty()) {
256 std::stringstream out;
257 out << detail::type_name<T>() << " in [" << min_val << " - " << max_val << "]";
258 description(out.str());
259 }
260
261 func_ = [min_val, max_val](std::string &input) {
262 using CLI::detail::lexical_cast;
263 T val;
264 bool converted = lexical_cast(input, val);
265 if((!converted) || (val < min_val || val > max_val)) {
266 std::stringstream out;
267 out << "Value " << input << " not in range [";
268 out << min_val << " - " << max_val << "]";
269 return out.str();
270 }
271 return std::string{};
272 };
273 }
274
276 template <typename T>
277 explicit Range(T max_val, const std::string &validator_name = std::string{})
278 : Range(static_cast<T>(0), max_val, validator_name) {}
279};
280
282const Range NonNegativeNumber((std::numeric_limits<double>::max)(), "NONNEGATIVE");
283
285const Range PositiveNumber((std::numeric_limits<double>::min)(), (std::numeric_limits<double>::max)(), "POSITIVE");
286
287namespace detail {
288// the following suggestion was made by Nikita Ofitserov(@himikof)
289// done in templates to prevent compiler warnings on negation of unsigned numbers
290
292template <typename T>
293inline typename std::enable_if<std::is_signed<T>::value, T>::type overflowCheck(const T &a, const T &b) {
294 if((a > 0) == (b > 0)) {
295 return ((std::numeric_limits<T>::max)() / (std::abs)(a) < (std::abs)(b));
296 }
297 return ((std::numeric_limits<T>::min)() / (std::abs)(a) > -(std::abs)(b));
298}
300template <typename T>
301inline typename std::enable_if<!std::is_signed<T>::value, T>::type overflowCheck(const T &a, const T &b) {
302 return ((std::numeric_limits<T>::max)() / a < b);
303}
304
306template <typename T> typename std::enable_if<std::is_integral<T>::value, bool>::type checked_multiply(T &a, T b) {
307 if(a == 0 || b == 0 || a == 1 || b == 1) {
308 a *= b;
309 return true;
310 }
311 if(a == (std::numeric_limits<T>::min)() || b == (std::numeric_limits<T>::min)()) {
312 return false;
313 }
314 if(overflowCheck(a, b)) {
315 return false;
316 }
317 a *= b;
318 return true;
319}
320
322template <typename T>
323typename std::enable_if<std::is_floating_point<T>::value, bool>::type checked_multiply(T &a, T b) {
324 T c = a * b;
325 if(std::isinf(c) && !std::isinf(a) && !std::isinf(b)) {
326 return false;
327 }
328 a = c;
329 return true;
330}
335CLI11_INLINE std::pair<std::string, std::string> split_program_name(std::string commandline);
336
337} // namespace detail
339
340// [CLI11:validators_hpp:end]
341} // namespace CLI
342
343#ifndef CLI11_COMPILE
344#include "impl/Validators_inl.hpp" // IWYU pragma: export
345#endif
Definition Validators.hpp:241
Produce a range (factory). Min and max are inclusive.
Definition Validators.hpp:247
Range(T min_val, T max_val, const std::string &validator_name=std::string{})
Definition Validators.hpp:254
Range(T max_val, const std::string &validator_name=std::string{})
Range of one value is 0 to value.
Definition Validators.hpp:277
Some validators that are provided.
Definition Validators.hpp:54
Validator operator&(const Validator &other) const
Definition Validators_inl.hpp:45
CLI11_NODISCARD int get_application_index() const
Get the current value of the application index.
Definition Validators.hpp:155
int application_index_
A Validator will only apply to an indexed value (-1 is all elements)
Definition Validators.hpp:65
Validator & non_modifying(bool no_modify=true)
Specify whether the Validator can be modifying or not.
Definition Validators.hpp:139
Validator & description(std::string validator_desc)
Specify the type string.
Definition Validators.hpp:99
std::string operator()(const std::string &str) const
Definition Validators.hpp:93
CLI11_NODISCARD Validator application_index(int app_index) const
Specify the application index of a validator.
Definition Validators.hpp:149
Validator operator|(const Validator &other) const
Definition Validators_inl.hpp:67
CLI11_NODISCARD bool get_active() const
Get a boolean if the validator is active.
Definition Validators.hpp:157
bool active_
Enable for Validator to allow it to be disabled if need be.
Definition Validators.hpp:67
bool non_modifying_
specify that a validator should not modify the input
Definition Validators.hpp:69
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:114
std::function< std::string()> desc_function_
This is the description function, if empty the description_ will be used.
Definition Validators.hpp:57
std::function< std::string(std::string &)> func_
Definition Validators.hpp:61
CLI11_NODISCARD std::string get_description() const
Generate type description information for the Validator.
Definition Validators.hpp:107
CLI11_NODISCARD Validator active(bool active_val=true) const
Specify whether the Validator is active or not.
Definition Validators.hpp:132
CLI11_NODISCARD const std::string & get_name() const
Get the name of the Validator.
Definition Validators.hpp:125
Validator & active(bool active_val=true)
Specify whether the Validator is active or not.
Definition Validators.hpp:127
std::string name_
The name for search purposes of the Validator.
Definition Validators.hpp:63
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:160
CLI11_NODISCARD Validator name(std::string validator_name) const
Specify the type string.
Definition Validators.hpp:119
Validator operator!() const
Create a validator that fails when a given validator succeeds.
Definition Validators_inl.hpp:89
std::string operator()(std::string &str) const
Definition Validators_inl.hpp:26
Validator & application_index(int app_index)
Specify the application index of a validator.
Definition Validators.hpp:144
Validator(std::function< std::string(std::string &)> op, std::string validator_desc, std::string validator_name="")
Construct Validator from basic information.
Definition Validators.hpp:79
Validator & operation(std::function< std::string(std::string &)> op)
Set the Validator operation function.
Definition Validators.hpp:83
Definition Validators.hpp:217
Check for an existing directory (returns error message if check fails)
Definition Validators.hpp:200
Check for an existing file (returns error message if check fails)
Definition Validators.hpp:194
Check for an existing path.
Definition Validators.hpp:206
Check for an non-existing path.
Definition Validators.hpp:212