#include "resolver.hpp" #include "types.hpp" #include "../../env.hpp" #include #include #define TYPES ::yycc::carton::clap::types #define APPLICATION ::yycc::carton::clap::application #define ENV ::yycc::env namespace yycc::carton::clap::resolver { #pragma region Core /// @brief Core capture function template static TYPES::ClapResult>> capture(const APPLICATION::Application& app, V&& vars) { std::map> values; const auto& variables = app.get_variables(); // Iterate variable list and process them one by one. for (const auto& [name, value] : vars) { // Check whether capture this variable. auto opt_token = variables.find_name(name); if (!opt_token.has_value()) continue; auto token = opt_token.value(); // Check whether it is captured. // If it is already captured, report error, // because environment variable can not be duplicated. if (values.contains(token)) { throw std::runtime_error("impossible duplicated environment variable name."); } // Finally check whether it care value, and insert data. if (variables.get_variable(token).is_care_value()) { values.emplace(token, value); } else { values.emplace(token, std::nullopt); } } return values; } #pragma endregion #pragma region Resolver Class TYPES::ClapResult Resolver::from_user(const APPLICATION::Application& app, const std::vector>& vars) { auto rv = capture(app, std::views::all(vars)); if (rv.has_value()) return Resolver(std::move(rv.value())); else return std::unexpected(rv.error()); } TYPES::ClapResult Resolver::from_system(const APPLICATION::Application& app) { auto vars = ENV::get_vars(); auto rv = capture(app, vars | std::views::transform([](const auto& p) { return std::make_pair(p.first, p.second); })); if (rv.has_value()) return Resolver(std::move(rv.value())); else return std::unexpected(rv.error()); } Resolver::Resolver(decltype(Resolver::values)&& values) : values(std::move(values)) {} Resolver::~Resolver() {} bool Resolver::has_variable(TYPES::Token token) const { return this->values.contains(token); } TYPES::ClapResult Resolver::get_flag_variable(TYPES::Token token) const { auto finder = this->values.find(token); if (finder == this->values.end()) { // Not found. return false; } else { // Found. auto val = finder->second; if (val.has_value()) throw std::logic_error("get flag variable as value variable."); else return true; } } TYPES::ClapResult Resolver::get_raw_value_variable(TYPES::Token token) const { auto finder = this->values.find(token); if (finder == this->values.end()) { // Not found. return std::unexpected(TYPES::ClapError::NotCaptured); } else { // Found. auto val = finder->second; if (val.has_value()) return std::u8string_view(val.value()); else throw std::logic_error("get value variable as flag variable."); } } #pragma endregion } // namespace yycc::carton::clap::resolver