CLI11  2.6.2
Validators.hpp
Go to the documentation of this file.
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 <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 
39 namespace CLI {
40 // [CLI11:validators_hpp:verbatim]
41 
42 class Option;
43 
45 
52 
54 class 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  }
150  Validator newval(*this);
151  newval.application_index_ = app_index;
152  return newval;
153  }
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 
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.
183 namespace detail {
184 
186 enum class path_type : std::uint8_t { nonexistent, file, directory };
187 
189 CLI11_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 
226 
229 
232 
235 
238 
241 class FileOnDefaultPath : public Validator {
242  public:
243  explicit FileOnDefaultPath(std::string default_path, bool enableErrorReturn = true);
244 };
245 
247 class 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) {
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 
282 CLI11_MODULE_INLINE const Range NonNegativeNumber((std::numeric_limits<double>::max)(), "NONNEGATIVE");
283 
286  Range PositiveNumber((std::numeric_limits<double>::min)(), (std::numeric_limits<double>::max)(), "POSITIVE");
287 
288 namespace detail {
289 // the following suggestion was made by Nikita Ofitserov(@himikof)
290 // done in templates to prevent compiler warnings on negation of unsigned numbers
291 
293 template <typename T>
294 inline typename std::enable_if<std::is_signed<T>::value, T>::type overflowCheck(const T &a, const T &b) {
295  if((a > 0) == (b > 0)) {
296  return ((std::numeric_limits<T>::max)() / (std::abs)(a) < (std::abs)(b));
297  }
298  return ((std::numeric_limits<T>::min)() / (std::abs)(a) > -(std::abs)(b));
299 }
301 template <typename T>
302 inline typename std::enable_if<!std::is_signed<T>::value, T>::type overflowCheck(const T &a, const T &b) {
303  return ((std::numeric_limits<T>::max)() / a < b);
304 }
305 
307 template <typename T> typename std::enable_if<std::is_integral<T>::value, bool>::type checked_multiply(T &a, T b) {
308  if(a == 0 || b == 0 || a == 1 || b == 1) {
309  a *= b;
310  return true;
311  }
312  if(a == (std::numeric_limits<T>::min)() || b == (std::numeric_limits<T>::min)()) {
313  return false;
314  }
315  if(overflowCheck(a, b)) {
316  return false;
317  }
318  a *= b;
319  return true;
320 }
321 
323 template <typename T>
324 typename std::enable_if<std::is_floating_point<T>::value, bool>::type checked_multiply(T &a, T b) {
325  T c = a * b;
326  if(std::isinf(c) && !std::isinf(a) && !std::isinf(b)) {
327  return false;
328  }
329  a = c;
330  return true;
331 }
336 CLI11_INLINE std::pair<std::string, std::string> split_program_name(std::string commandline);
337 
338 } // namespace detail
340 
341 // [CLI11:validators_hpp:end]
342 } // namespace CLI
343 
344 #ifndef CLI11_COMPILE
345 #include "impl/Validators_inl.hpp" // IWYU pragma: export
346 #endif
std::string name_
The name for search purposes of the Validator.
Definition: Validators.hpp:63
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:294
CLI11_MODULE_INLINE const Range NonNegativeNumber((std::numeric_limits< double >::max)(),"NONNEGATIVE")
Check for a non negative number.
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
std::string operator()(std::string &str) const
Definition: App.hpp:36
CLI11_MODULE_INLINE const detail::EscapedStringTransformer EscapedString
convert escaped characters into their associated values
Definition: Validators.hpp:237
Range(T max_val, const std::string &validator_name=std::string{})
Range of one value is 0 to value.
Definition: Validators.hpp:277
CLI11_NODISCARD Validator application_index(int app_index) const
Specify the application index of a validator.
Definition: Validators.hpp:149
Check for an existing directory (returns error message if check fails)
Definition: Validators.hpp:200
Validator(std::string validator_desc)
Construct a Validator with just the description string.
Definition: Validators.hpp:77
bool non_modifying_
specify that a validator should not modify the input
Definition: Validators.hpp:69
Validator operator&(const Validator &other) const
CLI11_NODISCARD const std::string & get_name() const
Get the name of the Validator.
Definition: Validators.hpp:125
CLI11_NODISCARD Validator active(bool active_val=true) const
Specify whether the Validator is active or not.
Definition: Validators.hpp:132
Definition: Validators.hpp:241
CLI11_MODULE_INLINE const detail::NonexistentPathValidator NonexistentPath
Check for an non-existing path.
Definition: Validators.hpp:234
CLI11_MODULE_INLINE const detail::ExistingPathValidator ExistingPath
Check for an existing path.
Definition: Validators.hpp:231
Check for an non-existing path.
Definition: Validators.hpp:212
std::function< std::string(std::string &)> func_
Definition: Validators.hpp:61
CLI11_NODISCARD bool get_active() const
Get a boolean if the validator is active.
Definition: Validators.hpp:157
bool lexical_cast(const std::string &input, T &output)
Integer conversion.
Definition: TypeTools.hpp:1123
int application_index_
A Validator will only apply to an indexed value (-1 is all elements)
Definition: Validators.hpp:65
FileOnDefaultPath(std::string default_path, bool enableErrorReturn=true)
CLI11_INLINE path_type check_path(const char *file) noexcept
get the type of the path from a file name
#define CLI11_INLINE
Definition: Macros.hpp:176
Produce a range (factory). Min and max are inclusive.
Definition: Validators.hpp:247
Check for an existing path.
Definition: Validators.hpp:206
Validator operator|(const Validator &other) const
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 & name(std::string validator_name)
Specify the type string.
Definition: Validators.hpp:114
#define CLI11_MODULE_INLINE
Definition: Macros.hpp:183
Validator & application_index(int app_index)
Specify the application index of a validator.
Definition: Validators.hpp:144
CLI11_INLINE std::pair< std::string, std::string > split_program_name(std::string commandline)
#define CLI11_NODISCARD
Definition: Macros.hpp:58
Some validators that are provided.
Definition: Validators.hpp:54
Validator(std::string validator_desc, std::function< std::string(std::string &)> func)
Definition: Validators.hpp:71
bool active_
Enable for Validator to allow it to be disabled if need be.
Definition: Validators.hpp:67
std::string operator()(const std::string &str) const
Definition: Validators.hpp:93
CLI11_NODISCARD std::string get_description() const
Generate type description information for the Validator.
Definition: Validators.hpp:107
CLI11_MODULE_INLINE const detail::ExistingDirectoryValidator ExistingDirectory
Check for an existing directory (returns error message if check fails)
Definition: Validators.hpp:228
CLI11_MODULE_INLINE const detail::ExistingFileValidator ExistingFile
Check for existing file (returns error message if check fails)
Definition: Validators.hpp:225
CLI11_NODISCARD Validator name(std::string validator_name) const
Specify the type string.
Definition: Validators.hpp:119
Check for an existing file (returns error message if check fails)
Definition: Validators.hpp:194
Validator & active(bool active_val=true)
Specify whether the Validator is active or not.
Definition: Validators.hpp:127
Definition: Validators.hpp:217
CLI11_NODISCARD int get_application_index() const
Get the current value of the application index.
Definition: Validators.hpp:155
Validator & operation(std::function< std::string(std::string &)> op)
Set the Validator operation function.
Definition: Validators.hpp:83
std::function< std::string()> desc_function_
This is the description function, if empty the description_ will be used.
Definition: Validators.hpp:57
path_type
CLI enumeration of different file types.
Definition: Validators.hpp:186
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:307
CLI11_MODULE_INLINE const Range PositiveNumber((std::numeric_limits< double >::min)(),(std::numeric_limits< double >::max)(),"POSITIVE")
Check for a positive valued number (val>0.0), ::min here is the smallest positive number...
Validator & non_modifying(bool no_modify=true)
Specify whether the Validator can be modifying or not.
Definition: Validators.hpp:139
Validator operator!() const
Create a validator that fails when a given validator succeeds.
Range(T min_val, T max_val, const std::string &validator_name=std::string{})
Definition: Validators.hpp:254
Validator()=default
Validator & description(std::string validator_desc)
Specify the type string.
Definition: Validators.hpp:99