1
0
Files
YYCCommonplace/src/yycc/carton/clap/validator.hpp

80 lines
3.0 KiB
C++

#pragma once
#include "../../num/parse.hpp"
#include <optional>
#include <string_view>
#include <limits>
#include <concepts>
#include <cmath>
#define NS_YYCC_NUM_PARSE ::yycc::num::parse
namespace yycc::carton::clap::validator {
/**
* @brief The concept for checking whether given type is a valid command line argument validator.
* @details
* A valid command line argument validator must have a type name or alias called "ReturnType"
* indicating the return value of this validator.
*
* And, it also should have an member function called "validate"
* which receive <TT>const std::string_view&</TT> as its only argument,
* and return <TT>std::optional<ReturnType></TT> as result.
* If this \t std::optional is empty, it means that there is some error occurs when validating,
* otherwise, it is the validated value.
*/
template<typename T>
concept Validator = requires(const T& t, const std::u8string_view& sv) {
// Check whether there is T::ReturnType type
typename T::ReturnType;
// Check whether there is "validate" member function and it has correct signature.
{ t.validate(sv) } -> std::same_as<std::optional<typename T::ReturnType>>;
};
template<std::integral T, auto TMin = std::numeric_limits<T>::min(), auto TMax = std::numeric_limits<T>::max()>
struct IntegralValidator {
static_assert(TMin <= TMax);
using ReturnType = T;
std::optional<ReturnType> validate(const std::u8string_view& sv) {
auto rv = NS_YYCC_NUM_PARSE::parse<ReturnType>(sv);
if (rv) {
auto value = rv.value();
if (value > TMax || value < TMin) return std::nullopt;
else return value;
} else return std::nullopt;
}
};
template<std::floating_point T, auto TMin = std::numeric_limits<T>::lowest(), auto TMax = std::numeric_limits<T>::max()>
struct FloatingPointValidator {
static_assert(std::isfinite(TMin));
static_assert(std::isfinite(TMax));
static_assert(TMin <= TMax);
using ReturnType = T;
std::optional<ReturnType> validate(const std::u8string_view& sv) {
auto rv = NS_YYCC_NUM_PARSE::parse<ReturnType>(sv);
if (rv) {
auto value = rv.value();
if (value > TMax || value < TMin) return std::nullopt;
else return value;
} else return std::nullopt;
}
};
struct BoolValidator {
using ReturnType = bool;
std::optional<ReturnType> validate(const std::u8string_view& sv) {
auto rv = NS_YYCC_NUM_PARSE::parse<ReturnType>(sv);
if (rv) return rv.value();
else return std::nullopt;
}
};
struct StringValidator {
using ReturnType = std::u8string;
std::optional<ReturnType> validate(const std::u8string_view& sv) { return std::u8string(sv); }
};
} // namespace yycc::carton::clap::validator
#undef NS_YYCC_NUM_PARSE