mirror of
https://git.lynn.is/Gwen/argparser.git
synced 2024-05-08 02:31:09 +02:00
97 lines
3.3 KiB
C++
97 lines
3.3 KiB
C++
#ifndef ARGPARSER_REPEAT_OPT_H
|
|
#define ARGPARSER_REPEAT_OPT_H
|
|
|
|
#include <cassert>
|
|
#include <format>
|
|
#include <memory>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include "errors.h"
|
|
#include "option.h"
|
|
#include "parse-result.h"
|
|
#include "type.h"
|
|
|
|
namespace argparser {
|
|
|
|
template<typename T>
|
|
class repeatable_option_impl : public option, public std::enable_shared_from_this<repeatable_option_impl<T>> {
|
|
public:
|
|
repeatable_option_impl(std::string name, type_handle_impl<T> type) : option(std::move(name)), type(std::move(type)) {}
|
|
|
|
std::shared_ptr<repeatable_option_impl<T>> default_value(std::vector<T> val) {
|
|
this->default_value_ = std::make_optional(val);
|
|
return this->shared_from_this();
|
|
}
|
|
|
|
std::shared_ptr<repeatable_option_impl<T>> min(unsigned int min) {
|
|
this->min_ = min;
|
|
return this->shared_from_this();
|
|
}
|
|
|
|
std::shared_ptr<repeatable_option_impl<T>> max(unsigned int max) {
|
|
this->max_ = max;
|
|
return this->shared_from_this();
|
|
}
|
|
|
|
void validate(const parse_result &pr) const override {
|
|
unsigned int count = 0;
|
|
if (pr.has_opt(this->name)) {
|
|
count = get(pr).size();
|
|
}
|
|
if ((min_.has_value() && count < min_.value()) ||
|
|
(max_.has_value() && count > max_.value())) {
|
|
throw errors::wrong_option_count_error(this->name, min_, max_, count);
|
|
}
|
|
}
|
|
|
|
[[nodiscard]] bool consumes_value() const override {
|
|
return true;
|
|
}
|
|
|
|
[[nodiscard]] std::vector<T> get(const parse_result &pr) const {
|
|
auto v = pr.get_opt(name);
|
|
if (!v.has_value()) {
|
|
if (default_value_.has_value()) {
|
|
return default_value_.value();
|
|
}
|
|
throw std::runtime_error(std::format("option {} was not provided", name));
|
|
}
|
|
return std::any_cast<std::vector<T>>(v);
|
|
}
|
|
[[nodiscard]] bool has(const parse_result &pr) const {
|
|
return pr.has_opt(name);
|
|
}
|
|
|
|
private:
|
|
void do_parse(std::optional<std::string> arg, std::any &val) override {
|
|
assert(arg.has_value());
|
|
const char *parse_end;
|
|
auto begin = &*arg->begin();
|
|
auto end = &*arg->end();
|
|
auto single_val = this->type->parse(begin, end, parse_end, internal::parser_allow_undelimited::Any);
|
|
if (parse_end != end) {
|
|
throw errors::type_parsing_error(this->type->get_name(), std::string(begin, end), parse_end - begin, "unexpected input");
|
|
}
|
|
std::vector<T> val_vec{};
|
|
if (val.has_value()) {
|
|
val_vec = std::any_cast<std::vector<T>>(val);
|
|
}
|
|
val_vec.push_back(single_val);
|
|
val = std::make_any<std::vector<T>>(val_vec);
|
|
}
|
|
|
|
type_handle_impl<T> type;
|
|
|
|
std::optional<std::vector<T>> default_value_ = std::nullopt;
|
|
std::optional<unsigned int> min_ = std::nullopt;
|
|
std::optional<unsigned int> max_ = std::nullopt;
|
|
};
|
|
|
|
template<typename T>
|
|
using repeatable_option_handle_impl = std::shared_ptr<repeatable_option_impl<T>>;
|
|
|
|
}// namespace argparser
|
|
|
|
#endif//ARGPARSER_REPEAT_OPT_H
|