mirror of
https://git.lynn.is/Gwen/argparser.git
synced 2024-05-14 21:31:09 +02:00
85 lines
3.2 KiB
C
85 lines
3.2 KiB
C
|
#ifndef ARGPARSER_LIST_TYPE_H
|
||
|
#define ARGPARSER_LIST_TYPE_H
|
||
|
|
||
|
#include "errors.h"
|
||
|
#include "type.h"
|
||
|
#include <memory>
|
||
|
#include <string>
|
||
|
#include <vector>
|
||
|
|
||
|
namespace argparser {
|
||
|
|
||
|
template<typename T>
|
||
|
class list_type : public type_impl<std::vector<T>> {
|
||
|
public:
|
||
|
list_type(std::string name, type_handle_impl<T> element_type) : type_impl<std::vector<T>>(std::move(name)), element_type(element_type) {}
|
||
|
std::vector<T> parse(const char *begin, const char *end, const char *&parse_end, internal::parser_allow_undelimited allow_undelimited) override {
|
||
|
auto cur_pos = begin;
|
||
|
std::vector<T> values{};
|
||
|
bool is_delimited;
|
||
|
if (*cur_pos == '[') {
|
||
|
is_delimited = true;
|
||
|
cur_pos++;
|
||
|
} else {
|
||
|
if (!internal::enum_flag_contains(allow_undelimited, internal::parser_allow_undelimited::Comma)) {
|
||
|
throw errors::type_parsing_error(this->name, std::string(begin, end), cur_pos - begin, "expected '['");
|
||
|
} else {
|
||
|
is_delimited = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (cur_pos >= end) {
|
||
|
throw errors::type_parsing_error(this->name, std::string(begin, end), end - begin, "unexpected end of input");
|
||
|
}
|
||
|
|
||
|
internal::parser_allow_undelimited sub_parse_allow_undelimited = internal::parser_allow_undelimited::Parenthesis;
|
||
|
if (!is_delimited) {
|
||
|
sub_parse_allow_undelimited & allow_undelimited;
|
||
|
}
|
||
|
|
||
|
while (true) {
|
||
|
const char *this_parse_end;
|
||
|
auto val = element_type->parse(cur_pos, end, this_parse_end, sub_parse_allow_undelimited);
|
||
|
values.push_back(val);
|
||
|
cur_pos = this_parse_end;
|
||
|
while (std::isspace(*cur_pos) && cur_pos <= end)
|
||
|
cur_pos++;
|
||
|
if (cur_pos >= end) {
|
||
|
if (!is_delimited) {
|
||
|
break;
|
||
|
} else {
|
||
|
throw errors::type_parsing_error(this->name, std::string(begin, end), end - begin, "unexpected end of input");
|
||
|
}
|
||
|
}
|
||
|
if (*cur_pos == ',') {
|
||
|
cur_pos++;
|
||
|
auto s = std::string_view(cur_pos, end);
|
||
|
auto close_bracket_pos = s.find_first_of(']');
|
||
|
if (s.find_first_not_of(internal::whitespace) == close_bracket_pos) {
|
||
|
break;
|
||
|
}
|
||
|
} else if (!is_delimited || *cur_pos == ']') {
|
||
|
break;
|
||
|
} else {
|
||
|
throw errors::type_parsing_error(this->name, std::string(begin, end), end - begin, "expected , or ]");
|
||
|
}
|
||
|
}
|
||
|
if (is_delimited) {
|
||
|
if (*cur_pos != ']') {
|
||
|
throw errors::type_parsing_error(this->name, std::string(begin, end), end - begin, "unexpected end of input");
|
||
|
} else {
|
||
|
cur_pos++;
|
||
|
}
|
||
|
}
|
||
|
parse_end = cur_pos;
|
||
|
return values;
|
||
|
}
|
||
|
private:
|
||
|
|
||
|
|
||
|
type_handle_impl<T> element_type;
|
||
|
};
|
||
|
}// namespace argparser
|
||
|
|
||
|
#endif//ARGPARSER_LIST_TYPE_H
|