argparser/src/repeat-arg.h
2023-05-17 10:17:56 +02:00

96 lines
2.8 KiB
C++

#ifndef ARGPARSER_REPEAT_ARG_H
#define ARGPARSER_REPEAT_ARG_H
#include "argument.h"
#include "errors.h"
#include "parse-result.h"
#include "type.h"
#include <any>
#include <cassert>
#include <memory>
#include <optional>
#include <span>
#include <string>
#include <vector>
namespace argparser {
template<typename T>
class repeatable_arg : public arg, public std::enable_shared_from_this<repeatable_arg<T>> {
public:
repeatable_arg(std::string name, type_handle_impl<T> type) : arg(std::move(name)), type(type) {}
std::shared_ptr<repeatable_arg<T>> min(size_t min) {
min_ = min;
return this->shared_from_this();
}
std::shared_ptr<repeatable_arg<T>> max(size_t max) {
max_ = max;
return this->shared_from_this();
}
[[nodiscard]] std::vector<T> get(const parse_result &pr) const {
auto v = pr.get_arg(name);
if (!v.has_value()) {
return std::vector<T>{};
}
return std::any_cast<std::vector<T>>(v);
}
[[nodiscard]] bool has(const parse_result &pr) const {
return pr.has_arg(name);
}
private:
type_handle_impl<T> type;
std::optional<size_t> max_;
std::optional<size_t> min_;
void do_parse(std::string input, parse_result &pr) const override {
auto current_val = pr.get_arg(name);
std::vector<T> values;
if (current_val.has_value()) {
values = std::any_cast<std::vector<T>>(current_val);
}
assert(!max_.has_value() || values.size() < max_.value());
auto val = this->parse_single_value(input, type);
values.push_back(val);
pr.set_arg(name, std::make_any<std::vector<T>>(std::move(values)));
}
[[nodiscard]] bool get_can_parse_more(parse_result &pr) const override {
if (max_.has_value()) {
auto val = pr.get_arg(name);
if (!val.has_value()) {
return true;
}
return std::any_cast<std::vector<T>>(val).size() < max_.value();
} else {
return true;
}
}
[[nodiscard]] bool get_has_parsed_enough(parse_result &pr) const override {
if (min_.has_value() && min_.value() > 0) {
auto val = pr.get_arg(name);
if (!val.has_value()) {
return false;
}
auto val_ = std::any_cast<std::vector<T>>(val);
return val_.size() >= min_.value();
} else {
return true;
}
}
};
template<typename T>
using repeatable_arg_handle = std::shared_ptr<repeatable_arg<T>>;
}// namespace argparser
#endif//ARGPARSER_REPEAT_ARG_H