diff --git a/include/ss/parser.hpp b/include/ss/parser.hpp index 2a95301..e286e7c 100644 --- a/include/ss/parser.hpp +++ b/include/ss/parser.hpp @@ -38,10 +38,6 @@ public: : file_name_{file_name}, reader_{file_name_, delim} { if (reader_.file_) { read_line(); - if (eof_) { - handle_error_eof_reached(); - return; - } if constexpr (ignore_header) { ignore_next(); } else { diff --git a/test/test_parser.cpp b/test/test_parser.cpp index de1be8c..1e3bc23 100644 --- a/test/test_parser.cpp +++ b/test/test_parser.cpp @@ -9,9 +9,6 @@ #include #include -// TODO remove -#include - namespace { [[maybe_unused]] void replace_all(std::string& s, const std::string& from, const std::string& to) { @@ -51,13 +48,13 @@ void update_if_crlf(std::string& s) { struct X { constexpr static auto delim = ","; - constexpr static auto make_empty = "_EMPTY_"; + constexpr static auto empty = "_EMPTY_"; int i; double d; std::string s; std::string to_string() const { - if (s == make_empty) { + if (s == empty) { return ""; } @@ -1050,17 +1047,18 @@ static inline void check_size(size_t size1, size_t size2) { CHECK_EQ(size1, size2); } -template -static void test_fields(const std::string file_name, const std::vector& data, - const std::vector& fields) { +template +static void test_fields_impl(const std::string file_name, + const std::vector& data, + const std::vector& fields) { using CaseType = std::tuple; - ss::parser p{file_name, ","}; + ss::parser p{file_name, ","}; CHECK_FALSE(p.field_exists("Unknown")); p.use_fields(fields); std::vector i; - for (const auto& a : p.iterate()) { + for (const auto& a : p.template iterate()) { i.push_back(a); } @@ -1078,6 +1076,16 @@ static void test_fields(const std::string file_name, const std::vector& data, } } +template +static void test_fields(const std::string file_name, const std::vector& data, + const std::vector& fields) { + test_fields_impl, Ts...>(file_name, data, fields); + test_fields_impl, Ts...>(file_name, data, + fields); + test_fields_impl, Ts...>(file_name, data, + fields); +} + TEST_CASE("parser test various cases with header") { unique_file_name f{"test_parser"}; constexpr static auto Int = "Int"; @@ -1280,22 +1288,23 @@ TEST_CASE("parser test invalid header fields usage") { {"Int", "String", "Double"}); } -static inline void test_ignore_empty(const std::vector& data) { +template +void test_ignore_empty_impl(const std::vector& data) { unique_file_name f{"test_parser"}; make_and_write(f.name, data); std::vector expected; for (const auto& d : data) { - if (d.s != X::make_empty) { + if (d.s != X::empty) { expected.push_back(d); } } { - ss::parser p{f.name, ","}; + ss::parser p{f.name, ","}; std::vector i; - for (const auto& a : p.iterate()) { + for (const auto& a : p.template iterate()) { i.push_back(a); } @@ -1303,71 +1312,70 @@ static inline void test_ignore_empty(const std::vector& data) { } { - ss::parser p{f.name, ","}; + ss::parser p{f.name, ","}; std::vector i; size_t n = 0; - for (const auto& a : p.iterate()) { - if (data.at(n).s == X::make_empty) { - CHECK_FALSE(p.valid()); + while (!p.eof()) { + try { + ++n; + const auto& a = p.template get_next(); + if (data.at(n - 1).s == X::empty) { + CHECK_FALSE(p.valid()); + continue; + } + i.push_back(a); + } catch (...) { + CHECK_EQ(data.at(n - 1).s, X::empty); } - i.push_back(a); - ++n; } - if (data != expected) { - CHECK_NE(i, expected); - } + CHECK_EQ(i, expected); } } +template +void test_ignore_empty(const std::vector& data) { + test_ignore_empty_impl(data); + test_ignore_empty_impl(data); + test_ignore_empty_impl(data); +} + TEST_CASE("parser test various cases with empty lines") { test_ignore_empty({{1, 2, "x"}, {3, 4, "y"}, {9, 10, "v"}, {11, 12, "w"}}); test_ignore_empty( - {{1, 2, X::make_empty}, {3, 4, "y"}, {9, 10, "v"}, {11, 12, "w"}}); + {{1, 2, X::empty}, {3, 4, "y"}, {9, 10, "v"}, {11, 12, "w"}}); test_ignore_empty( - {{1, 2, "x"}, {3, 4, "y"}, {9, 10, "v"}, {11, 12, X::make_empty}}); + {{1, 2, "x"}, {3, 4, "y"}, {9, 10, "v"}, {11, 12, X::empty}}); test_ignore_empty( - {{1, 2, "x"}, {5, 6, X::make_empty}, {9, 10, "v"}, {11, 12, "w"}}); + {{1, 2, "x"}, {5, 6, X::empty}, {9, 10, "v"}, {11, 12, "w"}}); - test_ignore_empty({{1, 2, X::make_empty}, - {5, 6, X::make_empty}, - {9, 10, "v"}, - {11, 12, "w"}}); + test_ignore_empty( + {{1, 2, X::empty}, {5, 6, X::empty}, {9, 10, "v"}, {11, 12, "w"}}); - test_ignore_empty({{1, 2, X::make_empty}, - {3, 4, "y"}, - {9, 10, "v"}, - {11, 12, X::make_empty}}); + test_ignore_empty( + {{1, 2, X::empty}, {3, 4, "y"}, {9, 10, "v"}, {11, 12, X::empty}}); - test_ignore_empty({{1, 2, "x"}, - {3, 4, "y"}, - {9, 10, X::make_empty}, - {11, 12, X::make_empty}}); + test_ignore_empty( + {{1, 2, "x"}, {3, 4, "y"}, {9, 10, X::empty}, {11, 12, X::empty}}); - test_ignore_empty({{1, 2, X::make_empty}, - {3, 4, "y"}, - {9, 10, X::make_empty}, - {11, 12, X::make_empty}}); + test_ignore_empty( + {{1, 2, X::empty}, {3, 4, "y"}, {9, 10, X::empty}, {11, 12, X::empty}}); - test_ignore_empty({{1, 2, X::make_empty}, - {3, 4, X::make_empty}, - {9, 10, X::make_empty}, - {11, 12, X::make_empty}}); + test_ignore_empty({{1, 2, X::empty}, + {3, 4, X::empty}, + {9, 10, X::empty}, + {11, 12, X::empty}}); - test_ignore_empty({{1, 2, "x"}, - {3, 4, X::make_empty}, - {9, 10, X::make_empty}, - {11, 12, X::make_empty}}); + test_ignore_empty( + {{1, 2, "x"}, {3, 4, X::empty}, {9, 10, X::empty}, {11, 12, X::empty}}); - test_ignore_empty({{1, 2, X::make_empty}, - {3, 4, X::make_empty}, - {9, 10, X::make_empty}, - {11, 12, "w"}}); + test_ignore_empty( + {{1, 2, X::empty}, {3, 4, X::empty}, {9, 10, X::empty}, {11, 12, "w"}}); - test_ignore_empty({{11, 12, X::make_empty}}); + test_ignore_empty({{11, 12, X::empty}}); test_ignore_empty({}); }