From f76eabee7a77d19d908a4e0c6e8de112db1ae2ab Mon Sep 17 00:00:00 2001 From: yyc12345 Date: Sat, 6 Dec 2025 21:29:51 +0800 Subject: [PATCH] feat: add validator concept for clap --- src/CMakeLists.txt | 1 + src/yycc/carton/clap/application.hpp | 2 +- src/yycc/carton/clap/manual.hpp | 4 +- src/yycc/carton/clap/validator.hpp | 79 ++++++++++++++++++++++++++++ 4 files changed, 83 insertions(+), 3 deletions(-) create mode 100644 src/yycc/carton/clap/validator.hpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1ae4469..479f8d2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -96,6 +96,7 @@ FILES yycc/carton/clap/summary.hpp yycc/carton/clap/application.hpp yycc/carton/clap/manual.hpp + yycc/carton/clap/validator.hpp yycc/carton/fft.hpp ) # Setup header infomations diff --git a/src/yycc/carton/clap/application.hpp b/src/yycc/carton/clap/application.hpp index 3690e30..cddefc7 100644 --- a/src/yycc/carton/clap/application.hpp +++ b/src/yycc/carton/clap/application.hpp @@ -14,7 +14,7 @@ namespace yycc::carton::clap::application { NS_YYCC_CLAP::option::OptionCollection&& options, NS_YYCC_CLAP::variable::VariableCollection&& variables); ~Application(); - YYCC_DEFAULT_COPY_MOVE(Application); + YYCC_DEFAULT_COPY_MOVE(Application) public: const NS_YYCC_CLAP::summary::Summary& get_summary() const; diff --git a/src/yycc/carton/clap/manual.hpp b/src/yycc/carton/clap/manual.hpp index 416d18d..a629730 100644 --- a/src/yycc/carton/clap/manual.hpp +++ b/src/yycc/carton/clap/manual.hpp @@ -13,7 +13,7 @@ namespace yycc::carton::clap::manual { public: ManualTr(); ~ManualTr(); - YYCC_DEFAULT_COPY_MOVE(ManualTr); + YYCC_DEFAULT_COPY_MOVE(ManualTr) public: std::u8string author_and_version; @@ -25,7 +25,7 @@ namespace yycc::carton::clap::manual { public: Manual(const NS_YYCC_CLAP::application::Application& app, ManualTr&& trctx = ManualTr()); ~Manual(); - YYCC_DEFAULT_COPY_MOVE(Manual); + YYCC_DEFAULT_COPY_MOVE(Manual) private: void setup_table(); diff --git a/src/yycc/carton/clap/validator.hpp b/src/yycc/carton/clap/validator.hpp new file mode 100644 index 0000000..0946b14 --- /dev/null +++ b/src/yycc/carton/clap/validator.hpp @@ -0,0 +1,79 @@ +#pragma once +#include "../../num/parse.hpp" +#include +#include +#include +#include +#include + +#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 const std::string_view& as its only argument, + * and return std::optional 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 + 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>; + }; + + template::min(), auto TMax = std::numeric_limits::max()> + struct IntegralValidator { + static_assert(TMin <= TMax); + using ReturnType = T; + std::optional validate(const std::u8string_view& sv) { + auto rv = NS_YYCC_NUM_PARSE::parse(sv); + if (rv) { + auto value = rv.value(); + if (value > TMax || value < TMin) return std::nullopt; + else return value; + } else return std::nullopt; + } + }; + + template::lowest(), auto TMax = std::numeric_limits::max()> + struct FloatingPointValidator { + static_assert(std::isfinite(TMin)); + static_assert(std::isfinite(TMax)); + static_assert(TMin <= TMax); + using ReturnType = T; + std::optional validate(const std::u8string_view& sv) { + auto rv = NS_YYCC_NUM_PARSE::parse(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 validate(const std::u8string_view& sv) { + auto rv = NS_YYCC_NUM_PARSE::parse(sv); + if (rv) return rv.value(); + else return std::nullopt; + } + }; + + struct StringValidator { + using ReturnType = std::u8string; + std::optional validate(const std::u8string_view& sv) { return std::u8string(sv); } + }; + +} // namespace yycc::carton::clap::validator + +#undef NS_YYCC_NUM_PARSE