Loading...
Searching...
No Matches
Validators.hpp
Go to the documentation of this file.
// Copyright (c) 2017-2025, University of Cincinnati, developed by Henry Schreiner
// under NSF AWARD 1414736 and by the respective contributors.
// All rights reserved.
//
// SPDX-License-Identifier: BSD-3-Clause
#pragma once
// IWYU pragma: private, include "CLI/CLI.hpp"
#include "Error.hpp"
#include "Macros.hpp"
#include "StringTools.hpp"
#include "TypeTools.hpp"
// [CLI11:public_includes:set]
#include <cmath>
#include <cstdint>
#include <functional>
#include <iostream>
#include <limits>
#include <memory>
#include <string>
#include <utility>
#include <vector>
// [CLI11:public_includes:end]
// [CLI11:validators_hpp_filesystem:verbatim]
#if defined CLI11_HAS_FILESYSTEM && CLI11_HAS_FILESYSTEM > 0
#include <filesystem> // NOLINT(build/include)
#else
#include <sys/stat.h>
#include <sys/types.h>
#endif
// [CLI11:validators_hpp_filesystem:end]
namespace CLI {
// [CLI11:validators_hpp:verbatim]
class Option;
class Validator {
protected:
std::function<std::string()> desc_function_{[]() { return std::string{}; }};
std::function<std::string(std::string &)> func_{[](std::string &) { return std::string{}; }};
std::string name_{};
int application_index_ = -1;
bool active_{true};
bool non_modifying_{false};
Validator(std::string validator_desc, std::function<std::string(std::string &)> func)
: desc_function_([validator_desc]() { return validator_desc; }), func_(std::move(func)) {}
public:
Validator() = default;
explicit Validator(std::string validator_desc) : desc_function_([validator_desc]() { return validator_desc; }) {}
Validator(std::function<std::string(std::string &)> op, std::string validator_desc, std::string validator_name = "")
: desc_function_([validator_desc]() { return validator_desc; }), func_(std::move(op)),
name_(std::move(validator_name)) {}
Validator &operation(std::function<std::string(std::string &)> op) {
func_ = std::move(op);
return *this;
}
std::string operator()(std::string &str) const;
std::string operator()(const std::string &str) const {
std::string value = str;
return (active_) ? func_(value) : std::string{};
}
Validator &description(std::string validator_desc) {
desc_function_ = [validator_desc]() { return validator_desc; };
return *this;
}
CLI11_NODISCARD Validator description(std::string validator_desc) const;
CLI11_NODISCARD std::string get_description() const {
if(active_) {
return desc_function_();
}
return std::string{};
}
Validator &name(std::string validator_name) {
name_ = std::move(validator_name);
return *this;
}
CLI11_NODISCARD Validator name(std::string validator_name) const {
Validator newval(*this);
newval.name_ = std::move(validator_name);
return newval;
}
CLI11_NODISCARD const std::string &get_name() const { return name_; }
Validator &active(bool active_val = true) {
active_ = active_val;
return *this;
}
CLI11_NODISCARD Validator active(bool active_val = true) const {
Validator newval(*this);
newval.active_ = active_val;
return newval;
}
Validator &non_modifying(bool no_modify = true) {
non_modifying_ = no_modify;
return *this;
}
Validator &application_index(int app_index) {
application_index_ = app_index;
return *this;
}
CLI11_NODISCARD Validator application_index(int app_index) const {
Validator newval(*this);
newval.application_index_ = app_index;
return newval;
}
CLI11_NODISCARD int get_application_index() const { return application_index_; }
CLI11_NODISCARD bool get_active() const { return active_; }
CLI11_NODISCARD bool get_modifying() const { return !non_modifying_; }
Validator operator&(const Validator &other) const;
Validator operator|(const Validator &other) const;
Validator operator!() const;
private:
void _merge_description(const Validator &val1, const Validator &val2, const std::string &merger);
};
using CustomValidator = Validator;
// The implementation of the built in validators is using the Validator class;
// the user is only expected to use the const (static) versions (since there's no setup).
// Therefore, this is in detail.
namespace detail {
enum class path_type : std::uint8_t { nonexistent, file, directory };
CLI11_INLINE path_type check_path(const char *file) noexcept;
// Static is not needed here, because global const implies static.
class ExistingFileValidator : public Validator {
public:
ExistingFileValidator();
};
class ExistingDirectoryValidator : public Validator {
public:
ExistingDirectoryValidator();
};
class ExistingPathValidator : public Validator {
public:
ExistingPathValidator();
};
class NonexistentPathValidator : public Validator {
public:
NonexistentPathValidator();
};
class EscapedStringTransformer : public Validator {
public:
EscapedStringTransformer();
};
} // namespace detail
const detail::ExistingFileValidator ExistingFile;
const detail::ExistingDirectoryValidator ExistingDirectory;
const detail::ExistingPathValidator ExistingPath;
const detail::NonexistentPathValidator NonexistentPath;
const detail::EscapedStringTransformer EscapedString;
class FileOnDefaultPath : public Validator {
public:
explicit FileOnDefaultPath(std::string default_path, bool enableErrorReturn = true);
};
class Range : public Validator {
public:
template <typename T>
Range(T min_val, T max_val, const std::string &validator_name = std::string{}) : Validator(validator_name) {
if(validator_name.empty()) {
std::stringstream out;
out << detail::type_name<T>() << " in [" << min_val << " - " << max_val << "]";
description(out.str());
}
func_ = [min_val, max_val](std::string &input) {
using CLI::detail::lexical_cast;
T val;
bool converted = lexical_cast(input, val);
if((!converted) || (val < min_val || val > max_val)) {
std::stringstream out;
out << "Value " << input << " not in range [";
out << min_val << " - " << max_val << "]";
return out.str();
}
return std::string{};
};
}
template <typename T>
explicit Range(T max_val, const std::string &validator_name = std::string{})
: Range(static_cast<T>(0), max_val, validator_name) {}
};
const Range NonNegativeNumber((std::numeric_limits<double>::max)(), "NONNEGATIVE");
const Range PositiveNumber((std::numeric_limits<double>::min)(), (std::numeric_limits<double>::max)(), "POSITIVE");
namespace detail {
// the following suggestion was made by Nikita Ofitserov(@himikof)
// done in templates to prevent compiler warnings on negation of unsigned numbers
template <typename T>
inline typename std::enable_if<std::is_signed<T>::value, T>::type overflowCheck(const T &a, const T &b) {
if((a > 0) == (b > 0)) {
return ((std::numeric_limits<T>::max)() / (std::abs)(a) < (std::abs)(b));
}
return ((std::numeric_limits<T>::min)() / (std::abs)(a) > -(std::abs)(b));
}
template <typename T>
inline typename std::enable_if<!std::is_signed<T>::value, T>::type overflowCheck(const T &a, const T &b) {
return ((std::numeric_limits<T>::max)() / a < b);
}
template <typename T> typename std::enable_if<std::is_integral<T>::value, bool>::type checked_multiply(T &a, T b) {
if(a == 0 || b == 0 || a == 1 || b == 1) {
a *= b;
return true;
}
if(a == (std::numeric_limits<T>::min)() || b == (std::numeric_limits<T>::min)()) {
return false;
}
if(overflowCheck(a, b)) {
return false;
}
a *= b;
return true;
}
template <typename T>
typename std::enable_if<std::is_floating_point<T>::value, bool>::type checked_multiply(T &a, T b) {
T c = a * b;
if(std::isinf(c) && !std::isinf(a) && !std::isinf(b)) {
return false;
}
a = c;
return true;
}
CLI11_INLINE std::pair<std::string, std::string> split_program_name(std::string commandline);
} // namespace detail
// [CLI11:validators_hpp:end]
} // namespace CLI
#ifndef CLI11_COMPILE
#include "impl/Validators_inl.hpp" // IWYU pragma: export
#endif
Error.hpp
Macros.hpp
CLI11_INLINE
#define CLI11_INLINE
Definition Macros.hpp:176
CLI11_NODISCARD
#define CLI11_NODISCARD
Definition Macros.hpp:58
StringTools.hpp
TypeTools.hpp
CLI::FileOnDefaultPath::FileOnDefaultPath
FileOnDefaultPath(std::string default_path, bool enableErrorReturn=true)
CLI::Option
Definition Option.hpp:259
CLI::Range
Produce a range (factory). Min and max are inclusive.
Definition Validators.hpp:247
CLI::Range::Range
Range(T min_val, T max_val, const std::string &validator_name=std::string{})
Definition Validators.hpp:254
CLI::Range::Range
Range(T max_val, const std::string &validator_name=std::string{})
Range of one value is 0 to value.
Definition Validators.hpp:277
CLI::Validator
Some validators that are provided.
Definition Validators.hpp:54
CLI::Validator::get_application_index
CLI11_NODISCARD int get_application_index() const
Get the current value of the application index.
Definition Validators.hpp:155
CLI::Validator::application_index_
int application_index_
A Validator will only apply to an indexed value (-1 is all elements).
Definition Validators.hpp:65
CLI::Validator::non_modifying
Validator & non_modifying(bool no_modify=true)
Specify whether the Validator can be modifying or not.
Definition Validators.hpp:139
CLI::Validator::description
Validator & description(std::string validator_desc)
Specify the type string.
Definition Validators.hpp:99
CLI::Validator::operator()
std::string operator()(const std::string &str) const
Definition Validators.hpp:93
CLI::Validator::application_index
CLI11_NODISCARD Validator application_index(int app_index) const
Specify the application index of a validator.
Definition Validators.hpp:149
CLI::Validator::get_active
CLI11_NODISCARD bool get_active() const
Get a boolean if the validator is active.
Definition Validators.hpp:157
CLI::Validator::operator&
Validator operator&(const Validator &other) const
CLI::Validator::active_
bool active_
Enable for Validator to allow it to be disabled if need be.
Definition Validators.hpp:67
CLI::Validator::non_modifying_
bool non_modifying_
specify that a validator should not modify the input
Definition Validators.hpp:69
CLI::Validator::Validator
Validator(std::string validator_desc)
Construct a Validator with just the description string.
Definition Validators.hpp:77
CLI::Validator::Validator
Validator(std::string validator_desc, std::function< std::string(std::string &)> func)
Definition Validators.hpp:71
CLI::Validator::description
CLI11_NODISCARD Validator description(std::string validator_desc) const
Specify the type string.
CLI::Validator::name
Validator & name(std::string validator_name)
Specify the type string.
Definition Validators.hpp:114
CLI::Validator::Validator
Validator()=default
CLI::Validator::operator()
std::string operator()(std::string &str) const
CLI::Validator::desc_function_
std::function< std::string()> desc_function_
This is the description function, if empty the description_ will be used.
Definition Validators.hpp:57
CLI::Validator::func_
std::function< std::string(std::string &)> func_
Definition Validators.hpp:61
CLI::Validator::get_description
CLI11_NODISCARD std::string get_description() const
Generate type description information for the Validator.
Definition Validators.hpp:107
CLI::Validator::operator!
Validator operator!() const
Create a validator that fails when a given validator succeeds.
CLI::Validator::active
CLI11_NODISCARD Validator active(bool active_val=true) const
Specify whether the Validator is active or not.
Definition Validators.hpp:132
CLI::Validator::get_name
CLI11_NODISCARD const std::string & get_name() const
Get the name of the Validator.
Definition Validators.hpp:125
CLI::Validator::operator|
Validator operator|(const Validator &other) const
CLI::Validator::active
Validator & active(bool active_val=true)
Specify whether the Validator is active or not.
Definition Validators.hpp:127
CLI::Validator::name_
std::string name_
The name for search purposes of the Validator.
Definition Validators.hpp:63
CLI::Validator::get_modifying
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
CLI::Validator::name
CLI11_NODISCARD Validator name(std::string validator_name) const
Specify the type string.
Definition Validators.hpp:119
CLI::Validator::application_index
Validator & application_index(int app_index)
Specify the application index of a validator.
Definition Validators.hpp:144
CLI::Validator::Validator
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
CLI::Validator::operation
Validator & operation(std::function< std::string(std::string &)> op)
Set the Validator operation function.
Definition Validators.hpp:83
CLI::detail::EscapedStringTransformer
Definition Validators.hpp:217
CLI::detail::EscapedStringTransformer::EscapedStringTransformer
EscapedStringTransformer()
CLI::detail::ExistingDirectoryValidator
Check for an existing directory (returns error message if check fails).
Definition Validators.hpp:200
CLI::detail::ExistingDirectoryValidator::ExistingDirectoryValidator
ExistingDirectoryValidator()
CLI::detail::ExistingFileValidator
Check for an existing file (returns error message if check fails).
Definition Validators.hpp:194
CLI::detail::ExistingFileValidator::ExistingFileValidator
ExistingFileValidator()
CLI::detail::ExistingPathValidator
Check for an existing path.
Definition Validators.hpp:206
CLI::detail::ExistingPathValidator::ExistingPathValidator
ExistingPathValidator()
CLI::detail::NonexistentPathValidator
Check for an non-existing path.
Definition Validators.hpp:212
CLI::detail::NonexistentPathValidator::NonexistentPathValidator
NonexistentPathValidator()
CLI::detail
Definition App.hpp:48
CLI::detail::overflowCheck
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:293
CLI::detail::checked_multiply
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:306
CLI::detail::check_path
CLI11_INLINE path_type check_path(const char *file) noexcept
get the type of the path from a file name
CLI::detail::split_program_name
CLI11_INLINE std::pair< std::string, std::string > split_program_name(std::string commandline)
CLI::detail::path_type
path_type
CLI enumeration of different file types.
Definition Validators.hpp:186
CLI::detail::path_type::nonexistent
@ nonexistent
Definition Validators.hpp:186
CLI::detail::path_type::directory
@ directory
Definition Validators.hpp:186
CLI::detail::path_type::file
@ file
Definition Validators.hpp:186
CLI
Definition App.hpp:36
CLI::ExistingDirectory
const detail::ExistingDirectoryValidator ExistingDirectory
Check for an existing directory (returns error message if check fails).
Definition Validators.hpp:228
CLI::EscapedString
const detail::EscapedStringTransformer EscapedString
convert escaped characters into their associated values
Definition Validators.hpp:237
CLI::NonexistentPath
const detail::NonexistentPathValidator NonexistentPath
Check for an non-existing path.
Definition Validators.hpp:234
CLI::CustomValidator
Validator CustomValidator
Alias for Validator for custom Validator for clarity.
Definition Validators.hpp:178
CLI::ExistingPath
const detail::ExistingPathValidator ExistingPath
Check for an existing path.
Definition Validators.hpp:231
CLI::ExistingFile
const detail::ExistingFileValidator ExistingFile
Check for existing file (returns error message if check fails).
Definition Validators.hpp:225
CLI::NonNegativeNumber
const Range NonNegativeNumber((std::numeric_limits< double >::max)(), "NONNEGATIVE")
Check for a non negative number.
CLI::PositiveNumber
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.