fixes
This commit is contained in:
87
include/util/line_parser.hpp
Normal file
87
include/util/line_parser.hpp
Normal 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{};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user