This commit is contained in:
ZY4N
2024-12-22 16:58:40 +01:00
parent 2704814de2
commit db8db8f9d7
161 changed files with 17102 additions and 0 deletions

View File

@@ -0,0 +1,87 @@
#pragma once
#include <string>
#include <string_view>
#include <istream>
#include "util/for_each.hpp"
namespace ztu
{
template<bool Repeating, typename F>
struct prefixed_line_parser {
const std::string_view prefix;
F parse;
};
template<bool Repeating>
struct line_repeating_type {};
static constexpr auto is_repeating = line_repeating_type<true>{};
static constexpr auto is_not_repeating = line_repeating_type<false>{};
template<bool Repeating, typename F>
prefixed_line_parser<Repeating, F> make_line_parser(std::string_view prefix, line_repeating_type<Repeating>, F&& f)
{
return { prefix, std::forward<F>(f) };
}
template<typename E, bool... Rs, class... Fs>
E parse_lines(std::istream& in, const bool pedantic, prefixed_line_parser<Rs, Fs>&&... parsers)
{
auto ec = E{};
std::string line;
while (std::getline(in, line)) [[likely]]
{
parse_current_line:
auto line_updated = false;
for_each::argument(
[&]<bool R, typename F>(prefixed_line_parser<R, F>&& parser) -> bool
{
if (line.starts_with(parser.prefix))
{
const auto prefix_length = parser.prefix.length();
ec = parser.parse(line.substr(prefix_length));
if constexpr (R)
{
while (std::getline(in, line))
{
if (line.starts_with(parser.prefix)) [[likely]]
{
ec = parser.parse(line.substr(prefix_length));
}
else [[unlikely]]
{
line_updated = true;
break;
}
}
}
return true;
}
return false;
},
std::forward<prefixed_line_parser<Rs, Fs>>(parsers)...
);
if (pedantic) {
if (ec != E{}) [[unlikely]] {
return ec;
}
}
if (line_updated)
{
goto parse_current_line;
}
}
return E{};
}
}