File indexing completed on 2026-09-11 09:07:22
0001
0002
0003
0004
0005
0006
0007 #pragma once
0008
0009
0010
0011 #include "Error.hpp"
0012 #include "Macros.hpp"
0013 #include "StringTools.hpp"
0014 #include "TypeTools.hpp"
0015
0016
0017 #include <cmath>
0018 #include <cstdint>
0019 #include <functional>
0020 #include <iostream>
0021 #include <limits>
0022 #include <memory>
0023 #include <string>
0024 #include <utility>
0025 #include <vector>
0026
0027
0028
0029
0030 #if defined CLI11_HAS_FILESYSTEM && CLI11_HAS_FILESYSTEM > 0
0031 #include <filesystem> // NOLINT(build/include)
0032 #else
0033 #include <sys/stat.h>
0034 #include <sys/types.h>
0035 #endif
0036
0037
0038
0039 namespace CLI {
0040
0041
0042 class Option;
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054 class Validator {
0055 protected:
0056
0057 std::function<std::string()> desc_function_{[]() { return std::string{}; }};
0058
0059
0060
0061 std::function<std::string(std::string &)> func_{[](std::string &) { return std::string{}; }};
0062
0063 std::string name_{};
0064
0065 int application_index_ = -1;
0066
0067 bool active_{true};
0068
0069 bool non_modifying_{false};
0070
0071 Validator(std::string validator_desc, std::function<std::string(std::string &)> func)
0072 : desc_function_([validator_desc]() { return validator_desc; }), func_(std::move(func)) {}
0073
0074 public:
0075 Validator() = default;
0076
0077 explicit Validator(std::string validator_desc) : desc_function_([validator_desc]() { return validator_desc; }) {}
0078
0079 Validator(std::function<std::string(std::string &)> op, std::string validator_desc, std::string validator_name = "")
0080 : desc_function_([validator_desc]() { return validator_desc; }), func_(std::move(op)),
0081 name_(std::move(validator_name)) {}
0082
0083 Validator &operation(std::function<std::string(std::string &)> op) {
0084 func_ = std::move(op);
0085 return *this;
0086 }
0087
0088
0089 std::string operator()(std::string &str) const;
0090
0091
0092
0093 std::string operator()(const std::string &str) const {
0094 std::string value = str;
0095 return (active_) ? func_(value) : std::string{};
0096 }
0097
0098
0099 Validator &description(std::string validator_desc) {
0100 desc_function_ = [validator_desc]() { return validator_desc; };
0101 return *this;
0102 }
0103
0104 CLI11_NODISCARD Validator description(std::string validator_desc) const;
0105
0106
0107 CLI11_NODISCARD std::string get_description() const {
0108 if(active_) {
0109 return desc_function_();
0110 }
0111 return std::string{};
0112 }
0113
0114 Validator &name(std::string validator_name) {
0115 name_ = std::move(validator_name);
0116 return *this;
0117 }
0118
0119 CLI11_NODISCARD Validator name(std::string validator_name) const {
0120 Validator newval(*this);
0121 newval.name_ = std::move(validator_name);
0122 return newval;
0123 }
0124
0125 CLI11_NODISCARD const std::string &get_name() const { return name_; }
0126
0127 Validator &active(bool active_val = true) {
0128 active_ = active_val;
0129 return *this;
0130 }
0131
0132 CLI11_NODISCARD Validator active(bool active_val = true) const {
0133 Validator newval(*this);
0134 newval.active_ = active_val;
0135 return newval;
0136 }
0137
0138
0139 Validator &non_modifying(bool no_modify = true) {
0140 non_modifying_ = no_modify;
0141 return *this;
0142 }
0143
0144 Validator &application_index(int app_index) {
0145 application_index_ = app_index;
0146 return *this;
0147 }
0148
0149 CLI11_NODISCARD Validator application_index(int app_index) const {
0150 Validator newval(*this);
0151 newval.application_index_ = app_index;
0152 return newval;
0153 }
0154
0155 CLI11_NODISCARD int get_application_index() const { return application_index_; }
0156
0157 CLI11_NODISCARD bool get_active() const { return active_; }
0158
0159
0160 CLI11_NODISCARD bool get_modifying() const { return !non_modifying_; }
0161
0162
0163
0164 Validator operator&(const Validator &other) const;
0165
0166
0167
0168 Validator operator|(const Validator &other) const;
0169
0170
0171 Validator operator!() const;
0172
0173 private:
0174 void _merge_description(const Validator &val1, const Validator &val2, const std::string &merger);
0175 };
0176
0177
0178 using CustomValidator = Validator;
0179
0180
0181
0182
0183 namespace detail {
0184
0185
0186 enum class path_type : std::uint8_t { nonexistent, file, directory };
0187
0188
0189 CLI11_INLINE path_type check_path(const char *file) noexcept;
0190
0191
0192
0193
0194 class ExistingFileValidator : public Validator {
0195 public:
0196 ExistingFileValidator();
0197 };
0198
0199
0200 class ExistingDirectoryValidator : public Validator {
0201 public:
0202 ExistingDirectoryValidator();
0203 };
0204
0205
0206 class ExistingPathValidator : public Validator {
0207 public:
0208 ExistingPathValidator();
0209 };
0210
0211
0212 class NonexistentPathValidator : public Validator {
0213 public:
0214 NonexistentPathValidator();
0215 };
0216
0217 class EscapedStringTransformer : public Validator {
0218 public:
0219 EscapedStringTransformer();
0220 };
0221
0222 }
0223
0224
0225 const detail::ExistingFileValidator ExistingFile;
0226
0227
0228 const detail::ExistingDirectoryValidator ExistingDirectory;
0229
0230
0231 const detail::ExistingPathValidator ExistingPath;
0232
0233
0234 const detail::NonexistentPathValidator NonexistentPath;
0235
0236
0237 const detail::EscapedStringTransformer EscapedString;
0238
0239
0240
0241 class FileOnDefaultPath : public Validator {
0242 public:
0243 explicit FileOnDefaultPath(std::string default_path, bool enableErrorReturn = true);
0244 };
0245
0246
0247 class Range : public Validator {
0248 public:
0249
0250
0251
0252
0253 template <typename T>
0254 Range(T min_val, T max_val, const std::string &validator_name = std::string{}) : Validator(validator_name) {
0255 if(validator_name.empty()) {
0256 std::stringstream out;
0257 out << detail::type_name<T>() << " in [" << min_val << " - " << max_val << "]";
0258 description(out.str());
0259 }
0260
0261 func_ = [min_val, max_val](std::string &input) {
0262 using CLI::detail::lexical_cast;
0263 T val;
0264 bool converted = lexical_cast(input, val);
0265 if((!converted) || (val < min_val || val > max_val)) {
0266 std::stringstream out;
0267 out << "Value " << input << " not in range [";
0268 out << min_val << " - " << max_val << "]";
0269 return out.str();
0270 }
0271 return std::string{};
0272 };
0273 }
0274
0275
0276 template <typename T>
0277 explicit Range(T max_val, const std::string &validator_name = std::string{})
0278 : Range(static_cast<T>(0), max_val, validator_name) {}
0279 };
0280
0281
0282 const Range NonNegativeNumber((std::numeric_limits<double>::max)(), "NONNEGATIVE");
0283
0284
0285 const Range PositiveNumber((std::numeric_limits<double>::min)(), (std::numeric_limits<double>::max)(), "POSITIVE");
0286
0287 namespace detail {
0288
0289
0290
0291
0292 template <typename T>
0293 inline typename std::enable_if<std::is_signed<T>::value, T>::type overflowCheck(const T &a, const T &b) {
0294 if((a > 0) == (b > 0)) {
0295 return ((std::numeric_limits<T>::max)() / (std::abs)(a) < (std::abs)(b));
0296 }
0297 return ((std::numeric_limits<T>::min)() / (std::abs)(a) > -(std::abs)(b));
0298 }
0299
0300 template <typename T>
0301 inline typename std::enable_if<!std::is_signed<T>::value, T>::type overflowCheck(const T &a, const T &b) {
0302 return ((std::numeric_limits<T>::max)() / a < b);
0303 }
0304
0305
0306 template <typename T> typename std::enable_if<std::is_integral<T>::value, bool>::type checked_multiply(T &a, T b) {
0307 if(a == 0 || b == 0 || a == 1 || b == 1) {
0308 a *= b;
0309 return true;
0310 }
0311 if(a == (std::numeric_limits<T>::min)() || b == (std::numeric_limits<T>::min)()) {
0312 return false;
0313 }
0314 if(overflowCheck(a, b)) {
0315 return false;
0316 }
0317 a *= b;
0318 return true;
0319 }
0320
0321
0322 template <typename T>
0323 typename std::enable_if<std::is_floating_point<T>::value, bool>::type checked_multiply(T &a, T b) {
0324 T c = a * b;
0325 if(std::isinf(c) && !std::isinf(a) && !std::isinf(b)) {
0326 return false;
0327 }
0328 a = c;
0329 return true;
0330 }
0331
0332
0333
0334
0335 CLI11_INLINE std::pair<std::string, std::string> split_program_name(std::string commandline);
0336
0337 }
0338
0339
0340
0341 }
0342
0343 #ifndef CLI11_COMPILE
0344 #include "impl/Validators_inl.hpp" // IWYU pragma: export
0345 #endif