From fd39b5eef2534b5dedbd0464a96f7e6149780530 Mon Sep 17 00:00:00 2001 From: ado Date: Sat, 29 Jul 2023 00:38:27 +0200 Subject: [PATCH 01/22] Try msvc ci --- .github/workflows/win-msvc.yaml | 48 +++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 .github/workflows/win-msvc.yaml diff --git a/.github/workflows/win-msvc.yaml b/.github/workflows/win-msvc.yaml new file mode 100644 index 0000000..308cdc8 --- /dev/null +++ b/.github/workflows/win-msvc.yaml @@ -0,0 +1,48 @@ +name: msvc-ci + +on: + push: + branches: + - master + - feature/** + - improvement/** + - bugfix/** + + pull_request: + branches: + - master + - feature/** + - improvement/** + - bugfix/** + +jobs: + ci: + defaults: + run: + shell: bash + runs-on: ${{matrix.config.os}} + strategy: + fail-fast: false + matrix: + config: + - { os: windows-2019, vs: "Visual Studio 2020" } + build: [Debug, Release] + platform: [Win32, x64] + + name: "${{matrix.config.vs}}:${{matrix.platform}}:${{matrix.build}}" + steps: + - name: checkout + uses: actions/checkout@v2 + + - name: Install dependencies + run: script/ci_install_deps.sh + + - name: Configure + run: cmake -S test -B build -D CMAKE_BUILD_TYPE=Debug + + - name: Build + run: cmake --build build -j ${{ steps.cores.outputs.count }} + + - name: Run + working-directory: build + run: ctest --output-on-failure -j ${{ steps.cores.outputs.count }} From 515ddad997133fa2a219bed066d4992b4e5bdf05 Mon Sep 17 00:00:00 2001 From: ado Date: Sat, 29 Jul 2023 00:45:33 +0200 Subject: [PATCH 02/22] Add _CRT_SECURE_NO_WARNINGS define to remove msvc warnings --- include/ss/common.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/ss/common.hpp b/include/ss/common.hpp index f8563dc..7546d16 100644 --- a/include/ss/common.hpp +++ b/include/ss/common.hpp @@ -4,6 +4,8 @@ #include #include +#define _CRT_SECURE_NO_WARNINGS + namespace ss { struct none {}; From 7b1f49d30477effbd93f896b31ee025d2eb567ff Mon Sep 17 00:00:00 2001 From: ado Date: Sat, 29 Jul 2023 00:49:06 +0200 Subject: [PATCH 03/22] Add _CRT_SECURE_NO_WARNINGS define to remove msvc warnings --- include/ss/common.hpp | 2 -- include/ss/type_traits.hpp | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/ss/common.hpp b/include/ss/common.hpp index 7546d16..f8563dc 100644 --- a/include/ss/common.hpp +++ b/include/ss/common.hpp @@ -4,8 +4,6 @@ #include #include -#define _CRT_SECURE_NO_WARNINGS - namespace ss { struct none {}; diff --git a/include/ss/type_traits.hpp b/include/ss/type_traits.hpp index 294b8bb..f973781 100644 --- a/include/ss/type_traits.hpp +++ b/include/ss/type_traits.hpp @@ -1,5 +1,7 @@ #pragma once +#define _CRT_SECURE_NO_WARNINGS + #include #include From 6baeb2d598588738bc67424a998c34fe141df8a9 Mon Sep 17 00:00:00 2001 From: ado Date: Sat, 29 Jul 2023 00:53:04 +0200 Subject: [PATCH 04/22] Add _CRT_SECURE_NO_WARNINGS define to remove msvc warnings --- include/ss/parser.hpp | 2 ++ include/ss/type_traits.hpp | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/ss/parser.hpp b/include/ss/parser.hpp index 4ad4df4..74967cf 100644 --- a/include/ss/parser.hpp +++ b/include/ss/parser.hpp @@ -1,5 +1,7 @@ #pragma once +#define _CRT_SECURE_NO_WARNINGS + #include "common.hpp" #include "converter.hpp" #include "extract.hpp" diff --git a/include/ss/type_traits.hpp b/include/ss/type_traits.hpp index f973781..294b8bb 100644 --- a/include/ss/type_traits.hpp +++ b/include/ss/type_traits.hpp @@ -1,7 +1,5 @@ #pragma once -#define _CRT_SECURE_NO_WARNINGS - #include #include From 75f5ee2a55c0d858c53f49461528a34bd632b4b7 Mon Sep 17 00:00:00 2001 From: ado Date: Sat, 29 Jul 2023 00:56:08 +0200 Subject: [PATCH 05/22] Add _CRT_SECURE_NO_WARNINGS define to remove msvc warnings --- test/test_helpers.hpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/test_helpers.hpp b/test/test_helpers.hpp index 06ea703..1da01f5 100644 --- a/test/test_helpers.hpp +++ b/test/test_helpers.hpp @@ -1,4 +1,7 @@ #pragma once + +#define _CRT_SECURE_NO_WARNINGS + #include #include From 705ce422f0162edae21b2923051f7f1b6afeaa17 Mon Sep 17 00:00:00 2001 From: ado Date: Sat, 29 Jul 2023 01:11:29 +0200 Subject: [PATCH 06/22] Add constexpr values to lambda to handle msvc issue with respect to captured constexpr values --- test/test_parser.cpp | 1738 +++++++++++++++++++++--------------------- 1 file changed, 858 insertions(+), 880 deletions(-) diff --git a/test/test_parser.cpp b/test/test_parser.cpp index 9c8db9a..a554949 100644 --- a/test/test_parser.cpp +++ b/test/test_parser.cpp @@ -7,1131 +7,1109 @@ #include std::string time_now_rand() { - std::stringstream ss; - auto t = std::time(nullptr); - auto tm = *std::localtime(&t); - ss << std::put_time(&tm, "%d%m%Y%H%M%S"); - srand(time(nullptr)); - return ss.str() + std::to_string(rand()); + std::stringstream ss; + auto t = std::time(nullptr); + auto tm = *std::localtime(&t); + ss << std::put_time(&tm, "%d%m%Y%H%M%S"); + srand(time(nullptr)); + return ss.str() + std::to_string(rand()); } inline int i = 0; struct unique_file_name { - const std::string name; + const std::string name; - unique_file_name() - : name{"random_" + std::to_string(i++) + time_now_rand() + - "_file.csv"} { - } + unique_file_name() + : name{"random_" + std::to_string(i++) + time_now_rand() + "_file.csv"} {} - ~unique_file_name() { - std::filesystem::remove(name); - } + ~unique_file_name() { std::filesystem::remove(name); } }; -void replace_all(std::string& s, const std::string& from, - const std::string& to) { - if (from.empty()) return; - size_t start_pos = 0; - while ((start_pos = s.find(from, start_pos)) != std::string::npos) { - s.replace(start_pos, from.length(), to); - start_pos += to.length(); - } +void replace_all(std::string &s, const std::string &from, + const std::string &to) { + if (from.empty()) + return; + size_t start_pos = 0; + while ((start_pos = s.find(from, start_pos)) != std::string::npos) { + s.replace(start_pos, from.length(), to); + start_pos += to.length(); + } } -void update_if_crlf(std::string& s) { +void update_if_crlf(std::string &s) { #ifdef _WIN32 - replace_all(s, "\r\n", "\n"); + replace_all(s, "\r\n", "\n"); #else - (void)(s); + (void)(s); #endif } struct X { - constexpr static auto delim = ","; - constexpr static auto make_empty = "_EMPTY_"; - int i; - double d; - std::string s; + constexpr static auto delim = ","; + constexpr static auto make_empty = "_EMPTY_"; + int i; + double d; + std::string s; - std::string to_string() const { - if (s == make_empty) { - return ""; - } + std::string to_string() const { + if (s == make_empty) { + return ""; + } - return std::to_string(i) - .append(delim) - .append(std::to_string(d)) - .append(delim) - .append(s); - } - auto tied() const { - return std::tie(i, d, s); - } + return std::to_string(i) + .append(delim) + .append(std::to_string(d)) + .append(delim) + .append(s); + } + auto tied() const { return std::tie(i, d, s); } }; template -std::enable_if_t, bool> operator==(const T& lhs, - const T& rhs) { - return lhs.tied() == rhs.tied(); +std::enable_if_t, bool> operator==(const T &lhs, + const T &rhs) { + return lhs.tied() == rhs.tied(); } template -static void make_and_write(const std::string& file_name, - const std::vector& data, - const std::vector& header = {}) { - std::ofstream out{file_name}; +static void make_and_write(const std::string &file_name, + const std::vector &data, + const std::vector &header = {}) { + std::ofstream out{file_name}; #ifdef _WIN32 - std::vector new_lines = {"\n"}; + std::vector new_lines = {"\n"}; #else - std::vector new_lines = {"\n", "\r\n"}; + std::vector new_lines = {"\n", "\r\n"}; #endif - for (const auto& i : header) { - if (&i != &header.front()) { - out << T::delim; - } - out << i; + for (const auto &i : header) { + if (&i != &header.front()) { + out << T::delim; } + out << i; + } - if (!header.empty()) { - out << new_lines.front(); - } + if (!header.empty()) { + out << new_lines.front(); + } - for (size_t i = 0; i < data.size(); ++i) { - out << data[i].to_string() << new_lines[i % new_lines.size()]; - } + for (size_t i = 0; i < data.size(); ++i) { + out << data[i].to_string() << new_lines[i % new_lines.size()]; + } } #include TEST_CASE("parser test various cases") { - unique_file_name f; - std::vector data = {{1, 2, "x"}, {3, 4, "y"}, {5, 6, "z"}, - {7, 8, "u"}, {9, 10, "v"}, {11, 12, "w"}}; - make_and_write(f.name, data); - { - ss::parser p{f.name, ","}; - ss::parser p0{std::move(p)}; - p = std::move(p0); - std::vector i; + unique_file_name f; + std::vector data = {{1, 2, "x"}, {3, 4, "y"}, {5, 6, "z"}, + {7, 8, "u"}, {9, 10, "v"}, {11, 12, "w"}}; + make_and_write(f.name, data); + { + ss::parser p{f.name, ","}; + ss::parser p0{std::move(p)}; + p = std::move(p0); + std::vector i; - ss::parser p2{f.name, ","}; - std::vector i2; + ss::parser p2{f.name, ","}; + std::vector i2; - while (!p.eof()) { - auto a = p.get_next(); - i.emplace_back(ss::to_object(a)); - } - - for (const auto& a : p2.iterate()) { - i2.emplace_back(ss::to_object(a)); - } - - CHECK_EQ(i, data); - CHECK_EQ(i2, data); + while (!p.eof()) { + auto a = p.get_next(); + i.emplace_back(ss::to_object(a)); } - { - ss::parser p{f.name, ","}; - std::vector i; - - ss::parser p2{f.name, ","}; - std::vector i2; - - ss::parser p3{f.name, ","}; - std::vector i3; - - std::vector expected = {std::begin(data) + 1, std::end(data)}; - using tup = std::tuple; - - p.ignore_next(); - while (!p.eof()) { - auto a = p.get_next(); - i.emplace_back(ss::to_object(a)); - } - - p2.ignore_next(); - for (const auto& a : p2.iterate()) { - i2.emplace_back(ss::to_object(a)); - } - - p3.ignore_next(); - for (auto it = p3.iterate().begin(); it != p3.iterate().end(); - ++it) { - i3.emplace_back(ss::to_object(*it)); - } - - CHECK_EQ(i, expected); - CHECK_EQ(i2, expected); - CHECK_EQ(i3, expected); + for (const auto &a : p2.iterate()) { + i2.emplace_back(ss::to_object(a)); } - { - ss::parser p{f.name, ","}; - std::vector i; - ss::parser p2{f.name, ","}; - std::vector i2; + CHECK_EQ(i, data); + CHECK_EQ(i2, data); + } - while (!p.eof()) { - i.push_back(p.get_object()); - } + { + ss::parser p{f.name, ","}; + std::vector i; - for (auto&& a : p2.iterate_object()) { - i2.push_back(std::move(a)); - } + ss::parser p2{f.name, ","}; + std::vector i2; - CHECK_EQ(i, data); - CHECK_EQ(i2, data); + ss::parser p3{f.name, ","}; + std::vector i3; + + std::vector expected = {std::begin(data) + 1, std::end(data)}; + using tup = std::tuple; + + p.ignore_next(); + while (!p.eof()) { + auto a = p.get_next(); + i.emplace_back(ss::to_object(a)); } - { - ss::parser p{f.name, ","}; - std::vector i; - - for (auto&& a : p.iterate_object()) { - i.push_back(std::move(a)); - } - - CHECK_EQ(i, data); + p2.ignore_next(); + for (const auto &a : p2.iterate()) { + i2.emplace_back(ss::to_object(a)); } - { - ss::parser p{f.name, ","}; - std::vector i; - - ss::parser p2{f.name, ","}; - std::vector i2; - - using tup = std::tuple; - while (!p.eof()) { - i.push_back(p.get_object()); - } - - for (auto it = p2.iterate_object().begin(); - it != p2.iterate_object().end(); it++) { - i2.push_back({it->i, it->d, it->s}); - } - - CHECK_EQ(i, data); - CHECK_EQ(i2, data); + p3.ignore_next(); + for (auto it = p3.iterate().begin(); it != p3.iterate().end(); + ++it) { + i3.emplace_back(ss::to_object(*it)); } - { - ss::parser p{f.name, ","}; - std::vector i; + CHECK_EQ(i, expected); + CHECK_EQ(i2, expected); + CHECK_EQ(i3, expected); + } - using tup = std::tuple; - for (auto&& a : p.iterate_object()) { - i.push_back(std::move(a)); - } + { + ss::parser p{f.name, ","}; + std::vector i; + ss::parser p2{f.name, ","}; + std::vector i2; - CHECK_EQ(i, data); + while (!p.eof()) { + i.push_back(p.get_object()); } - { - ss::parser p{f.name, ","}; - std::vector i; - - while (!p.eof()) { - i.push_back(p.get_next()); - } - - CHECK_EQ(i, data); + for (auto &&a : p2.iterate_object()) { + i2.push_back(std::move(a)); } - { - ss::parser p{f.name, ","}; - std::vector i; + CHECK_EQ(i, data); + CHECK_EQ(i2, data); + } - for (auto&& a : p.iterate()) { - i.push_back(std::move(a)); - } + { + ss::parser p{f.name, ","}; + std::vector i; - CHECK_EQ(i, data); + for (auto &&a : p.iterate_object()) { + i.push_back(std::move(a)); } - { - constexpr int excluded = 3; - ss::parser p{f.name, ","}; - std::vector i; + CHECK_EQ(i, data); + } - ss::parser p2{f.name, ","}; - std::vector i2; + { + ss::parser p{f.name, ","}; + std::vector i; - while (!p.eof()) { - auto a = - p.get_object, double, std::string>(); - if (p.valid()) { - i.push_back(a); - } - } + ss::parser p2{f.name, ","}; + std::vector i2; - for (auto&& a : p2.iterate_object, double, - std::string>()) { - if (p2.valid()) { - i2.push_back(std::move(a)); - } - } - - std::vector expected; - for (auto& x : data) { - if (x.i != excluded) { - expected.push_back(x); - } - } - - std::copy_if(data.begin(), data.end(), expected.begin(), - [](const X& x) { return x.i != excluded; }); - CHECK_EQ(i, expected); - CHECK_EQ(i2, expected); + using tup = std::tuple; + while (!p.eof()) { + i.push_back(p.get_object()); } - { - ss::parser p{f.name, ","}; - std::vector i; - - ss::parser p2{f.name, ","}; - std::vector i2; - - while (!p.eof()) { - auto a = p.get_object, double, std::string>(); - if (p.valid()) { - i.push_back(a); - } - } - - for (auto&& a : - p2.iterate_object, double, std::string>()) { - if (p2.valid()) { - i2.push_back(std::move(a)); - } - } - - std::vector expected = {{3, 4, "y"}}; - CHECK_EQ(i, expected); - CHECK_EQ(i2, expected); + for (auto it = p2.iterate_object().begin(); + it != p2.iterate_object().end(); it++) { + i2.push_back({it->i, it->d, it->s}); } - { - unique_file_name empty_f; - std::vector empty_data = {}; + CHECK_EQ(i, data); + CHECK_EQ(i2, data); + } - make_and_write(empty_f.name, empty_data); + { + ss::parser p{f.name, ","}; + std::vector i; - ss::parser p{empty_f.name, ","}; - std::vector i; - - ss::parser p2{empty_f.name, ","}; - std::vector i2; - - while (!p.eof()) { - i.push_back(p.get_next()); - } - - for (auto&& a : p2.iterate()) { - i2.push_back(std::move(a)); - } - - CHECK(i.empty()); - CHECK(i2.empty()); + using tup = std::tuple; + for (auto &&a : p.iterate_object()) { + i.push_back(std::move(a)); } + + CHECK_EQ(i, data); + } + + { + ss::parser p{f.name, ","}; + std::vector i; + + while (!p.eof()) { + i.push_back(p.get_next()); + } + + CHECK_EQ(i, data); + } + + { + ss::parser p{f.name, ","}; + std::vector i; + + for (auto &&a : p.iterate()) { + i.push_back(std::move(a)); + } + + CHECK_EQ(i, data); + } + + { + constexpr int excluded = 3; + ss::parser p{f.name, ","}; + std::vector i; + + ss::parser p2{f.name, ","}; + std::vector i2; + + while (!p.eof()) { + auto a = p.get_object, double, std::string>(); + if (p.valid()) { + i.push_back(a); + } + } + + for (auto &&a : + p2.iterate_object, double, std::string>()) { + if (p2.valid()) { + i2.push_back(std::move(a)); + } + } + + std::vector expected; + for (auto &x : data) { + if (x.i != excluded) { + expected.push_back(x); + } + } + + std::copy_if(data.begin(), data.end(), expected.begin(), + [&](const X &x) { return x.i != excluded; }); + CHECK_EQ(i, expected); + CHECK_EQ(i2, expected); + } + + { + ss::parser p{f.name, ","}; + std::vector i; + + ss::parser p2{f.name, ","}; + std::vector i2; + + while (!p.eof()) { + auto a = p.get_object, double, std::string>(); + if (p.valid()) { + i.push_back(a); + } + } + + for (auto &&a : + p2.iterate_object, double, std::string>()) { + if (p2.valid()) { + i2.push_back(std::move(a)); + } + } + + std::vector expected = {{3, 4, "y"}}; + CHECK_EQ(i, expected); + CHECK_EQ(i2, expected); + } + + { + unique_file_name empty_f; + std::vector empty_data = {}; + + make_and_write(empty_f.name, empty_data); + + ss::parser p{empty_f.name, ","}; + std::vector i; + + ss::parser p2{empty_f.name, ","}; + std::vector i2; + + while (!p.eof()) { + i.push_back(p.get_next()); + } + + for (auto &&a : p2.iterate()) { + i2.push_back(std::move(a)); + } + + CHECK(i.empty()); + CHECK(i2.empty()); + } } using test_tuple = std::tuple; struct test_struct { - int i; - double d; - char c; - auto tied() { - return std::tie(i, d, c); - } + int i; + double d; + char c; + auto tied() { return std::tie(i, d, c); } }; -void expect_test_struct(const test_struct&) { -} +void expect_test_struct(const test_struct &) {} // various scenarios TEST_CASE("parser test composite conversion") { - unique_file_name f; - { - std::ofstream out{f.name}; - for (auto& i : - {"10,a,11.1", "10,20,11.1", "junk", "10,11.1", "1,11.1,a", "junk", - "10,junk", "11,junk", "10,11.1,c", "10,20", "10,22.2,f"}) { - out << i << std::endl; - } + unique_file_name f; + { + std::ofstream out{f.name}; + for (auto &i : + {"10,a,11.1", "10,20,11.1", "junk", "10,11.1", "1,11.1,a", "junk", + "10,junk", "11,junk", "10,11.1,c", "10,20", "10,22.2,f"}) { + out << i << std::endl; } + } - ss::parser p{f.name, ","}; - auto fail = [] { FAIL(""); }; - auto expect_error = [](auto error) { CHECK(!error.empty()); }; + ss::parser p{f.name, ","}; + auto fail = [] { FAIL(""); }; + auto expect_error = [](auto error) { CHECK(!error.empty()); }; + + REQUIRE(p.valid()); + REQUIRE_FALSE(p.eof()); + + { + constexpr static auto expectedData = std::tuple{10, 'a', 11.1}; + + auto [d1, d2, d3, d4] = p.try_next(fail) + .or_else(fail) + .or_else([&](auto &&data) { + CHECK_EQ(data, expectedData); + }) + .on_error(fail) + .or_else(fail) + .values(); REQUIRE(p.valid()); + REQUIRE_FALSE(d1); + REQUIRE_FALSE(d2); + REQUIRE(d3); + REQUIRE_FALSE(d4); + CHECK_EQ(*d3, expectedData); + } + + { + REQUIRE(!p.eof()); + constexpr static auto expectedData = std::tuple{10, 20, 11.1}; + + auto [d1, d2, d3, d4] = + p.try_next([&](auto &i1, auto i2, double d) { + CHECK_EQ(std::tie(i1, i2, d), expectedData); + }) + .on_error(fail) + .or_object(fail) + .on_error(fail) + .or_else(fail) + .on_error(fail) + .or_else(fail) + .values(); + + REQUIRE(p.valid()); + REQUIRE(d1); + REQUIRE_FALSE(d2); + REQUIRE_FALSE(d3); + REQUIRE_FALSE(d4); + CHECK_EQ(*d1, expectedData); + } + + { + REQUIRE(!p.eof()); + + auto [d1, d2, d3, d4, d5] = + p.try_object(fail) + .on_error(expect_error) + .or_else(fail) + .or_else(fail) + .or_else(fail) + .or_else(fail) + .values(); + + REQUIRE_FALSE(p.valid()); + REQUIRE_FALSE(d1); + REQUIRE_FALSE(d2); + REQUIRE_FALSE(d3); + REQUIRE_FALSE(d4); + REQUIRE_FALSE(d5); + } + + { + REQUIRE(!p.eof()); + + auto [d1, d2] = p.try_next([](auto &i, auto &d) { + REQUIRE_EQ(std::tie(i, d), std::tuple{10, 11.1}); + }) + .or_else([](auto &, auto &) { FAIL(""); }) + .values(); + + REQUIRE(p.valid()); + REQUIRE(d1); + REQUIRE_FALSE(d2); + } + + { + REQUIRE(!p.eof()); + + auto [d1, d2] = p.try_next([](auto &, auto &) { FAIL(""); }) + .or_else(expect_test_struct) + .values(); + + REQUIRE(p.valid()); + REQUIRE_FALSE(d1); + REQUIRE(d2); + CHECK_EQ(d2->tied(), std::tuple{1, 11.1, 'a'}); + } + + { + REQUIRE(!p.eof()); + + auto [d1, d2, d3, d4, d5] = p.try_next(fail) + .or_object() + .or_else(expect_test_struct) + .or_else(fail) + .or_else>(fail) + .on_error(expect_error) + .values(); + + REQUIRE_FALSE(p.valid()); + REQUIRE_FALSE(d1); + REQUIRE_FALSE(d2); + REQUIRE_FALSE(d3); + REQUIRE_FALSE(d4); + REQUIRE_FALSE(d5); + } + + { + REQUIRE(!p.eof()); + + auto [d1, d2] = p.try_next>() + .on_error(fail) + .or_else>(fail) + .on_error(fail) + .values(); + + REQUIRE(p.valid()); + REQUIRE(d1); + REQUIRE_FALSE(d2); + CHECK_EQ(*d1, std::tuple{10, std::nullopt}); + } + + { REQUIRE_FALSE(p.eof()); - { - constexpr static auto expectedData = std::tuple{10, 'a', 11.1}; + auto [d1, d2] = p.try_next>() + .on_error(fail) + .or_else>(fail) + .on_error(fail) + .values(); - auto [d1, d2, d3, d4] = - p.try_next(fail) - .or_else(fail) - .or_else( - [](auto&& data) { CHECK_EQ(data, expectedData); }) - .on_error(fail) - .or_else(fail) - .values(); + REQUIRE(p.valid()); + REQUIRE(d1); + REQUIRE_FALSE(d2); + CHECK_EQ(*d1, std::tuple{11, std::variant{"junk"}}); + } - REQUIRE(p.valid()); - REQUIRE_FALSE(d1); - REQUIRE_FALSE(d2); - REQUIRE(d3); - REQUIRE_FALSE(d4); - CHECK_EQ(*d3, expectedData); - } + { + REQUIRE(!p.eof()); - { - REQUIRE(!p.eof()); - constexpr static auto expectedData = std::tuple{10, 20, 11.1}; + auto [d1, d2] = p.try_object() + .or_else(fail) + .values(); + REQUIRE(p.valid()); + REQUIRE(d1); + REQUIRE_FALSE(d2); + CHECK_EQ(d1->tied(), std::tuple{10, 11.1, 'c'}); + } - auto [d1, d2, d3, d4] = - p.try_next([](auto& i1, auto i2, double d) { - CHECK_EQ(std::tie(i1, i2, d), expectedData); - }) - .on_error(fail) - .or_object(fail) - .on_error(fail) - .or_else(fail) - .on_error(fail) - .or_else(fail) - .values(); + { + REQUIRE_FALSE(p.eof()); - REQUIRE(p.valid()); - REQUIRE(d1); - REQUIRE_FALSE(d2); - REQUIRE_FALSE(d3); - REQUIRE_FALSE(d4); - CHECK_EQ(*d1, expectedData); - } + auto [d1, d2, d3, d4] = + p.try_next([] { return false; }) + .or_else([](auto &) { return false; }) + .or_else() + .or_else(fail) + .values(); - { - REQUIRE(!p.eof()); + REQUIRE(p.valid()); + REQUIRE_FALSE(d1); + REQUIRE_FALSE(d2); + REQUIRE(d3); + REQUIRE_FALSE(d4); + CHECK_EQ(d3.value(), std::tuple{10, 20}); + } - auto [d1, d2, d3, d4, d5] = - p.try_object(fail) - .on_error(expect_error) - .or_else(fail) - .or_else(fail) - .or_else(fail) - .or_else(fail) - .values(); + { + REQUIRE(!p.eof()); - REQUIRE_FALSE(p.valid()); - REQUIRE_FALSE(d1); - REQUIRE_FALSE(d2); - REQUIRE_FALSE(d3); - REQUIRE_FALSE(d4); - REQUIRE_FALSE(d5); - } + auto [d1, d2, d3, d4] = + p.try_object([] { return false; }) + .or_else([](auto &) { return false; }) + .or_object() + .or_else(fail) + .values(); - { - REQUIRE(!p.eof()); + REQUIRE(p.valid()); + REQUIRE_FALSE(d1); + REQUIRE_FALSE(d2); + REQUIRE(d3); + REQUIRE_FALSE(d4); + CHECK_EQ(d3->tied(), std::tuple{10, 22.2, 'f'}); + } - auto [d1, d2] = - p.try_next([](auto& i, auto& d) { - REQUIRE_EQ(std::tie(i, d), std::tuple{10, 11.1}); - }) - .or_else([](auto&, auto&) { FAIL(""); }) - .values(); - - REQUIRE(p.valid()); - REQUIRE(d1); - REQUIRE_FALSE(d2); - } - - { - REQUIRE(!p.eof()); - - auto [d1, d2] = p.try_next([](auto&, auto&) { FAIL(""); }) - .or_else(expect_test_struct) - .values(); - - REQUIRE(p.valid()); - REQUIRE_FALSE(d1); - REQUIRE(d2); - CHECK_EQ(d2->tied(), std::tuple{1, 11.1, 'a'}); - } - - { - REQUIRE(!p.eof()); - - auto [d1, d2, d3, d4, d5] = - p.try_next(fail) - .or_object() - .or_else(expect_test_struct) - .or_else(fail) - .or_else>(fail) - .on_error(expect_error) - .values(); - - REQUIRE_FALSE(p.valid()); - REQUIRE_FALSE(d1); - REQUIRE_FALSE(d2); - REQUIRE_FALSE(d3); - REQUIRE_FALSE(d4); - REQUIRE_FALSE(d5); - } - - { - REQUIRE(!p.eof()); - - auto [d1, d2] = p.try_next>() - .on_error(fail) - .or_else>(fail) - .on_error(fail) - .values(); - - REQUIRE(p.valid()); - REQUIRE(d1); - REQUIRE_FALSE(d2); - CHECK_EQ(*d1, std::tuple{10, std::nullopt}); - } - - { - REQUIRE_FALSE(p.eof()); - - auto [d1, d2] = p.try_next>() - .on_error(fail) - .or_else>(fail) - .on_error(fail) - .values(); - - REQUIRE(p.valid()); - REQUIRE(d1); - REQUIRE_FALSE(d2); - CHECK_EQ(*d1, std::tuple{11, std::variant{"junk"}}); - } - - { - REQUIRE(!p.eof()); - - auto [d1, d2] = p.try_object() - .or_else(fail) - .values(); - REQUIRE(p.valid()); - REQUIRE(d1); - REQUIRE_FALSE(d2); - CHECK_EQ(d1->tied(), std::tuple{10, 11.1, 'c'}); - } - - { - REQUIRE_FALSE(p.eof()); - - auto [d1, d2, d3, d4] = - p.try_next([] { return false; }) - .or_else([](auto&) { return false; }) - .or_else() - .or_else(fail) - .values(); - - REQUIRE(p.valid()); - REQUIRE_FALSE(d1); - REQUIRE_FALSE(d2); - REQUIRE(d3); - REQUIRE_FALSE(d4); - CHECK_EQ(d3.value(), std::tuple{10, 20}); - } - - { - REQUIRE(!p.eof()); - - auto [d1, d2, d3, d4] = - p.try_object([] { return false; }) - .or_else([](auto&) { return false; }) - .or_object() - .or_else(fail) - .values(); - - REQUIRE(p.valid()); - REQUIRE_FALSE(d1); - REQUIRE_FALSE(d2); - REQUIRE(d3); - REQUIRE_FALSE(d4); - CHECK_EQ(d3->tied(), std::tuple{10, 22.2, 'f'}); - } - - CHECK(p.eof()); + CHECK(p.eof()); } size_t move_called = 0; struct my_string { - char* data{nullptr}; + char *data{nullptr}; - my_string() = default; + my_string() = default; - ~my_string() { - delete[] data; - } + ~my_string() { delete[] data; } - // make sure no object is copied - my_string(const my_string&) = delete; - my_string& operator=(const my_string&) = delete; + // make sure no object is copied + my_string(const my_string &) = delete; + my_string &operator=(const my_string &) = delete; - my_string(my_string&& other) : data{other.data} { - move_called++; - other.data = nullptr; - } + my_string(my_string &&other) : data{other.data} { + move_called++; + other.data = nullptr; + } - my_string& operator=(my_string&& other) { - move_called++; - data = other.data; - return *this; - } + my_string &operator=(my_string &&other) { + move_called++; + data = other.data; + return *this; + } }; template <> -inline bool ss::extract(const char* begin, const char* end, my_string& s) { - size_t size = end - begin; - s.data = new char[size + 1]; - strncpy(s.data, begin, size); - s.data[size] = '\0'; - return true; +inline bool ss::extract(const char *begin, const char *end, my_string &s) { + size_t size = end - begin; + s.data = new char[size + 1]; + strncpy(s.data, begin, size); + s.data[size] = '\0'; + return true; } struct xyz { - my_string x; - my_string y; - my_string z; - auto tied() { - return std::tie(x, y, z); - } + my_string x; + my_string y; + my_string z; + auto tied() { return std::tie(x, y, z); } }; TEST_CASE("parser test the moving of parsed values") { - { - unique_file_name f; - { - std::ofstream out{f.name}; - out << "x" << std::endl; - } - - ss::parser p{f.name, ","}; - auto x = p.get_next(); - CHECK_LE(move_called, 1); - move_called = 0; - } - + { unique_file_name f; { - std::ofstream out{f.name}; - out << "a,b,c" << std::endl; + std::ofstream out{f.name}; + out << "x" << std::endl; } - { + ss::parser p{f.name, ","}; + auto x = p.get_next(); + CHECK_LE(move_called, 1); + move_called = 0; + } - ss::parser p{f.name, ","}; - auto x = p.get_next(); - CHECK_LE(move_called, 3); - move_called = 0; - } + unique_file_name f; + { + std::ofstream out{f.name}; + out << "a,b,c" << std::endl; + } - { - ss::parser p{f.name, ","}; - auto x = p.get_object(); - CHECK_LE(move_called, 6); - move_called = 0; - } + { - { - ss::parser p{f.name, ","}; - auto x = p.get_next(); - CHECK_LE(move_called, 6); - move_called = 0; - } + ss::parser p{f.name, ","}; + auto x = p.get_next(); + CHECK_LE(move_called, 3); + move_called = 0; + } + + { + ss::parser p{f.name, ","}; + auto x = p.get_object(); + CHECK_LE(move_called, 6); + move_called = 0; + } + + { + ss::parser p{f.name, ","}; + auto x = p.get_next(); + CHECK_LE(move_called, 6); + move_called = 0; + } } TEST_CASE("parser test the moving of parsed composite values") { - // to compile is enough - return; - ss::parser p{"", ""}; - p.try_next() - .or_else([](auto&&) {}) - .or_else([](auto&) {}) - .or_else([](auto&&) {}) - .or_object([](auto&&) {}) - .or_else>( - [](auto&, auto&, auto&) {}); + // to compile is enough + return; + ss::parser p{"", ""}; + p.try_next() + .or_else([](auto &&) {}) + .or_else([](auto &) {}) + .or_else([](auto &&) {}) + .or_object([](auto &&) {}) + .or_else>( + [](auto &, auto &, auto &) {}); } TEST_CASE("parser test error mode") { - unique_file_name f; - { - std::ofstream out{f.name}; - out << "junk" << std::endl; - out << "junk" << std::endl; - } + unique_file_name f; + { + std::ofstream out{f.name}; + out << "junk" << std::endl; + out << "junk" << std::endl; + } - ss::parser p(f.name, ","); + ss::parser p(f.name, ","); - REQUIRE_FALSE(p.eof()); - p.get_next(); - CHECK_FALSE(p.valid()); - CHECK_FALSE(p.error_msg().empty()); + REQUIRE_FALSE(p.eof()); + p.get_next(); + CHECK_FALSE(p.valid()); + CHECK_FALSE(p.error_msg().empty()); } -std::string no_quote(const std::string& s) { - if (!s.empty() && s[0] == '"') { - return {std::next(begin(s)), std::prev(end(s))}; - } - return s; +std::string no_quote(const std::string &s) { + if (!s.empty() && s[0] == '"') { + return {std::next(begin(s)), std::prev(end(s))}; + } + return s; } TEST_CASE("parser test csv on multiple lines with quotes") { - unique_file_name f; - std::vector data = {{1, 2, "\"x\r\nx\nx\""}, - {3, 4, "\"y\ny\r\ny\""}, - {5, 6, "\"z\nz\""}, - {7, 8, "\"u\"\"\""}, - {9, 10, "v"}, - {11, 12, "\"w\n\""}}; - for (auto& [_, __, s] : data) { - update_if_crlf(s); - } + unique_file_name f; + std::vector data = {{1, 2, "\"x\r\nx\nx\""}, + {3, 4, "\"y\ny\r\ny\""}, + {5, 6, "\"z\nz\""}, + {7, 8, "\"u\"\"\""}, + {9, 10, "v"}, + {11, 12, "\"w\n\""}}; + for (auto &[_, __, s] : data) { + update_if_crlf(s); + } - make_and_write(f.name, data); - for (auto& [_, __, s] : data) { - s = no_quote(s); - if (s[0] == 'u') { - s = "u\""; - } + make_and_write(f.name, data); + for (auto &[_, __, s] : data) { + s = no_quote(s); + if (s[0] == 'u') { + s = "u\""; } + } - ss::parser> p{f.name, ","}; - std::vector i; + ss::parser> p{f.name, ","}; + std::vector i; - while (!p.eof()) { - auto a = p.get_next(); - i.emplace_back(ss::to_object(a)); - } + while (!p.eof()) { + auto a = p.get_next(); + i.emplace_back(ss::to_object(a)); + } - for (auto& [_, __, s] : i) { - update_if_crlf(s); - } - CHECK_EQ(i, data); + for (auto &[_, __, s] : i) { + update_if_crlf(s); + } + CHECK_EQ(i, data); - ss::parser> p_no_multiline{f.name, ","}; - while (!p.eof()) { - auto a = p_no_multiline.get_next(); - CHECK(!p.valid()); - } + ss::parser> p_no_multiline{f.name, ","}; + while (!p.eof()) { + auto a = p_no_multiline.get_next(); + CHECK(!p.valid()); + } } -std::string no_escape(std::string& s) { - s.erase(std::remove(begin(s), end(s), '\\'), end(s)); - return s; +std::string no_escape(std::string &s) { + s.erase(std::remove(begin(s), end(s), '\\'), end(s)); + return s; } TEST_CASE("parser test csv on multiple lines with escapes") { - unique_file_name f; - std::vector data = {{1, 2, "x\\\nx\\\r\nx"}, - {5, 6, "z\\\nz\\\nz"}, - {7, 8, "u"}, - {3, 4, "y\\\ny\\\ny"}, - {9, 10, "v\\\\"}, - {11, 12, "w\\\n"}}; - for (auto& [_, __, s] : data) { - update_if_crlf(s); - } + unique_file_name f; + std::vector data = { + {1, 2, "x\\\nx\\\r\nx"}, {5, 6, "z\\\nz\\\nz"}, {7, 8, "u"}, + {3, 4, "y\\\ny\\\ny"}, {9, 10, "v\\\\"}, {11, 12, "w\\\n"}}; + for (auto &[_, __, s] : data) { + update_if_crlf(s); + } - make_and_write(f.name, data); - for (auto& [_, __, s] : data) { - s = no_escape(s); - if (s == "v") { - s = "v\\"; - } + make_and_write(f.name, data); + for (auto &[_, __, s] : data) { + s = no_escape(s); + if (s == "v") { + s = "v\\"; } + } - ss::parser> p{f.name, ","}; - std::vector i; + ss::parser> p{f.name, ","}; + std::vector i; - while (!p.eof()) { - auto a = p.get_next(); - i.emplace_back(ss::to_object(a)); - } + while (!p.eof()) { + auto a = p.get_next(); + i.emplace_back(ss::to_object(a)); + } - for (auto& [_, __, s] : i) { - update_if_crlf(s); - } - CHECK_EQ(i, data); + for (auto &[_, __, s] : i) { + update_if_crlf(s); + } + CHECK_EQ(i, data); - ss::parser> p_no_multiline{f.name, ","}; - while (!p.eof()) { - auto a = p_no_multiline.get_next(); - CHECK_FALSE(p.valid()); - } + ss::parser> p_no_multiline{f.name, ","}; + while (!p.eof()) { + auto a = p_no_multiline.get_next(); + CHECK_FALSE(p.valid()); + } } TEST_CASE("parser test csv on multiple lines with quotes and escapes") { - unique_file_name f; - { - std::ofstream out{f.name}; - out << "1,2,\"just\\\n\nstrings\"" << std::endl; + unique_file_name f; + { + std::ofstream out{f.name}; + out << "1,2,\"just\\\n\nstrings\"" << std::endl; #ifndef _WIN32 - out << "3,4,\"just\r\nsome\\\r\n\n\\\nstrings\"" << std::endl; - out << "5,6,\"just\\\n\\\r\n\r\n\nstrings" << std::endl; + out << "3,4,\"just\r\nsome\\\r\n\n\\\nstrings\"" << std::endl; + out << "5,6,\"just\\\n\\\r\n\r\n\nstrings" << std::endl; #else - out << "3,4,\"just\nsome\\\n\n\\\nstrings\"" << std::endl; - out << "5,6,\"just\\\n\\\n\n\nstrings" << std::endl; + out << "3,4,\"just\nsome\\\n\n\\\nstrings\"" << std::endl; + out << "5,6,\"just\\\n\\\n\n\nstrings" << std::endl; #endif - out << "7,8,\"just strings\"" << std::endl; - out << "9,10,just strings" << std::endl; + out << "7,8,\"just strings\"" << std::endl; + out << "9,10,just strings" << std::endl; + } + + ss::parser, ss::quote<'"'>> p{f.name}; + std::vector i; + + while (!p.eof()) { + auto a = p.get_next(); + if (p.valid()) { + i.emplace_back(ss::to_object(a)); } + } - ss::parser, ss::quote<'"'>> p{f.name}; - std::vector i; - - while (!p.eof()) { - auto a = p.get_next(); - if (p.valid()) { - i.emplace_back(ss::to_object(a)); - } - } - - std::vector data = {{1, 2, "just\n\nstrings"}, + std::vector data = {{1, 2, "just\n\nstrings"}, #ifndef _WIN32 - {3, 4, "just\r\nsome\r\n\n\nstrings"}, + {3, 4, "just\r\nsome\r\n\n\nstrings"}, #else - {3, 4, "just\nsome\n\n\nstrings"}, + {3, 4, "just\nsome\n\n\nstrings"}, #endif - {9, 10, "just strings"}}; + {9, 10, "just strings"}}; - for (auto& [_, __, s] : i) { - update_if_crlf(s); - } - CHECK_EQ(i, data); + for (auto &[_, __, s] : i) { + update_if_crlf(s); + } + CHECK_EQ(i, data); } TEST_CASE("parser test multiline restricted") { - unique_file_name f; - { - std::ofstream out{f.name}; - out << "1,2,\"just\n\nstrings\"" << std::endl; + unique_file_name f; + { + std::ofstream out{f.name}; + out << "1,2,\"just\n\nstrings\"" << std::endl; #ifndef _WIN32 - out << "3,4,\"ju\n\r\n\nnk\"" << std::endl; - out << "5,6,just\\\n\\\r\nstrings" << std::endl; + out << "3,4,\"ju\n\r\n\nnk\"" << std::endl; + out << "5,6,just\\\n\\\r\nstrings" << std::endl; #else - out << "3,4,\"ju\n\n\nnk\"" << std::endl; - out << "5,6,just\\\n\\\nstrings" << std::endl; + out << "3,4,\"ju\n\n\nnk\"" << std::endl; + out << "5,6,just\\\n\\\nstrings" << std::endl; #endif - out << "7,8,ju\\\n\\\n\\\nnk" << std::endl; - out << "9,10,\"just\\\n\nstrings\"" << std::endl; - out << "11,12,\"ju\\\n|\n\n\n\n\nk\"" << std::endl; - out << "13,14,\"ju\\\n\\\n15,16\"\\\n\\\\\n\nnk\"" << std::endl; - out << "17,18,\"ju\\\n\\\n\\\n\\\\\n\nnk\"" << std::endl; - out << "19,20,just strings" << std::endl; + out << "7,8,ju\\\n\\\n\\\nnk" << std::endl; + out << "9,10,\"just\\\n\nstrings\"" << std::endl; + out << "11,12,\"ju\\\n|\n\n\n\n\nk\"" << std::endl; + out << "13,14,\"ju\\\n\\\n15,16\"\\\n\\\\\n\nnk\"" << std::endl; + out << "17,18,\"ju\\\n\\\n\\\n\\\\\n\nnk\"" << std::endl; + out << "19,20,just strings" << std::endl; + } + + ss::parser, ss::quote<'"'>, ss::escape<'\\'>> p{ + f.name, ","}; + std::vector i; + + while (!p.eof()) { + auto a = p.get_next(); + if (p.valid()) { + i.emplace_back(ss::to_object(a)); } + } - ss::parser, ss::quote<'"'>, ss::escape<'\\'>> - p{f.name, ","}; - std::vector i; - - while (!p.eof()) { - auto a = p.get_next(); - if (p.valid()) { - i.emplace_back(ss::to_object(a)); - } - } - - std::vector data = {{1, 2, "just\n\nstrings"}, + std::vector data = {{1, 2, "just\n\nstrings"}, #ifndef _WIN32 - {5, 6, "just\n\r\nstrings"}, + {5, 6, "just\n\r\nstrings"}, #else - {5, 6, "just\n\nstrings"}, + {5, 6, "just\n\nstrings"}, #endif - {9, 10, "just\n\nstrings"}, - {19, 20, "just strings"}}; + {9, 10, "just\n\nstrings"}, + {19, 20, "just strings"}}; - for (auto& [_, __, s] : i) { - update_if_crlf(s); - } - CHECK_EQ(i, data); + for (auto &[_, __, s] : i) { + update_if_crlf(s); + } + CHECK_EQ(i, data); } -template -struct has_type; +template struct has_type; template struct has_type> : std::disjunction...> {}; -void checkSize(size_t size1, size_t size2) { - CHECK_EQ(size1, size2); -} +void checkSize(size_t size1, size_t size2) { CHECK_EQ(size1, size2); } template -void testFields(const std::string file_name, const std::vector& data, - const std::vector& fields) { - using CaseType = std::tuple; +void testFields(const std::string file_name, const std::vector &data, + const std::vector &fields) { + using CaseType = std::tuple; - ss::parser p{file_name, ","}; - CHECK_FALSE(p.field_exists("Unknown")); - p.use_fields(fields); - std::vector i; + ss::parser p{file_name, ","}; + CHECK_FALSE(p.field_exists("Unknown")); + p.use_fields(fields); + std::vector i; - for (const auto& a : p.iterate()) { - i.push_back(a); + for (const auto &a : p.iterate()) { + i.push_back(a); + } + + checkSize(i.size(), data.size()); + for (size_t j = 0; j < i.size(); ++j) { + if constexpr (has_type::value) { + CHECK_EQ(std::get(i[j]), data[j].i); } - - checkSize(i.size(), data.size()); - for (size_t j = 0; j < i.size(); ++j) { - if constexpr (has_type::value) { - CHECK_EQ(std::get(i[j]), data[j].i); - } - if constexpr (has_type::value) { - CHECK_EQ(std::get(i[j]), data[j].d); - } - if constexpr (has_type::value) { - CHECK_EQ(std::get(i[j]), data[j].s); - } + if constexpr (has_type::value) { + CHECK_EQ(std::get(i[j]), data[j].d); } + if constexpr (has_type::value) { + CHECK_EQ(std::get(i[j]), data[j].s); + } + } } TEST_CASE("parser test various cases with header") { - unique_file_name f; - constexpr static auto Int = "Int"; - constexpr static auto Dbl = "Double"; - constexpr static auto Str = "String"; - using str = std::string; + unique_file_name f; + constexpr static auto Int = "Int"; + constexpr static auto Dbl = "Double"; + constexpr static auto Str = "String"; + using str = std::string; - std::vector header{Int, Dbl, Str}; + std::vector header{Int, Dbl, Str}; - std::vector data = {{1, 2, "x"}, {3, 4, "y"}, {5, 6, "z"}, - {7, 8, "u"}, {9, 10, "v"}, {11, 12, "w"}}; + std::vector data = {{1, 2, "x"}, {3, 4, "y"}, {5, 6, "z"}, + {7, 8, "u"}, {9, 10, "v"}, {11, 12, "w"}}; - make_and_write(f.name, data, header); - const auto& o = f.name; - const auto& d = data; + make_and_write(f.name, data, header); + const auto &o = f.name; + const auto &d = data; - { - ss::parser p{f.name, ","}; - std::vector i; + { + ss::parser p{f.name, ","}; + std::vector i; - for (const auto& a : p.iterate()) { - i.emplace_back(ss::to_object(a)); - } - - CHECK_NE(i, data); + for (const auto &a : p.iterate()) { + i.emplace_back(ss::to_object(a)); } - { - ss::parser p{f.name, ","}; - std::vector i; + CHECK_NE(i, data); + } - p.ignore_next(); - for (const auto& a : p.iterate()) { - i.emplace_back(ss::to_object(a)); - } + { + ss::parser p{f.name, ","}; + std::vector i; - CHECK_EQ(i, data); + p.ignore_next(); + for (const auto &a : p.iterate()) { + i.emplace_back(ss::to_object(a)); } - { - ss::parser p{f.name, ","}; - std::vector i; + CHECK_EQ(i, data); + } - for (const auto& a : p.iterate()) { - i.emplace_back(ss::to_object(a)); - } + { + ss::parser p{f.name, ","}; + std::vector i; - CHECK_EQ(i, data); + for (const auto &a : p.iterate()) { + i.emplace_back(ss::to_object(a)); } - { - ss::parser p{f.name, ","}; - p.use_fields(Int, Dbl, Str); - CHECK_FALSE(p.valid()); - } + CHECK_EQ(i, data); + } + + { + ss::parser p{f.name, ","}; + p.use_fields(Int, Dbl, Str); + CHECK_FALSE(p.valid()); + } + + { + ss::parser p{f.name, ","}; + CHECK_FALSE(p.field_exists("Unknown")); + + p.use_fields(Int, "Unknown"); + CHECK_FALSE(p.valid()); + } + + { + ss::parser p{f.name, ","}; + p.use_fields(Int, Int); + CHECK_FALSE(p.valid()); + } + + { + ss::parser p{f.name, ","}; + p.use_fields(Int, Dbl); { - ss::parser p{f.name, ","}; - CHECK_FALSE(p.field_exists("Unknown")); - - p.use_fields(Int, "Unknown"); - CHECK_FALSE(p.valid()); + auto [int_, double_] = p.get_next(); + CHECK_EQ(int_, data[0].i); + CHECK_EQ(double_, data[0].d); } + p.use_fields(Dbl, Int); + { - ss::parser p{f.name, ","}; - p.use_fields(Int, Int); - CHECK_FALSE(p.valid()); + auto [double_, int_] = p.get_next(); + CHECK_EQ(int_, data[1].i); + CHECK_EQ(double_, data[1].d); } + p.use_fields(Str); + { - ss::parser p{f.name, ","}; - p.use_fields(Int, Dbl); - - { - auto [int_, double_] = p.get_next(); - CHECK_EQ(int_, data[0].i); - CHECK_EQ(double_, data[0].d); - } - - p.use_fields(Dbl, Int); - - { - auto [double_, int_] = p.get_next(); - CHECK_EQ(int_, data[1].i); - CHECK_EQ(double_, data[1].d); - } - - p.use_fields(Str); - - { - auto string_ = p.get_next(); - CHECK_EQ(string_, data[2].s); - } - - p.use_fields(Str, Int, Dbl); - - { - auto [string_, int_, double_] = - p.get_next(); - CHECK_EQ(double_, data[3].d); - CHECK_EQ(int_, data[3].i); - CHECK_EQ(string_, data[3].s); - } + auto string_ = p.get_next(); + CHECK_EQ(string_, data[2].s); } - /* python used to generate permutations - import itertools + p.use_fields(Str, Int, Dbl); - header = {'str': 'Str', - 'double': 'Dbl', - 'int': 'Int'} + { + auto [string_, int_, double_] = p.get_next(); + CHECK_EQ(double_, data[3].d); + CHECK_EQ(int_, data[3].i); + CHECK_EQ(string_, data[3].s); + } + } - keys = ['str', 'int', 'double'] + /* python used to generate permutations + import itertools - for r in range (1, 3): - combinations = list(itertools.permutations(keys, r = r)) + header = {'str': 'Str', + 'double': 'Dbl', + 'int': 'Int'} - for combination in combinations: - template_params = [] - arg_params = [] - for type in combination: - template_params.append(type) - arg_params.append(header[type]) - call = 'testFields<' + ', '.join(template_params) + \ - '>(o, d, {' + ', '.join(arg_params) + '});' - print(call) - */ + keys = ['str', 'int', 'double'] - testFields(o, d, {Str}); - testFields(o, d, {Int}); - testFields(o, d, {Dbl}); - testFields(o, d, {Str, Int}); - testFields(o, d, {Str, Dbl}); - testFields(o, d, {Int, Str}); - testFields(o, d, {Int, Dbl}); - testFields(o, d, {Dbl, Str}); - testFields(o, d, {Dbl, Int}); - testFields(o, d, {Str, Int, Dbl}); - testFields(o, d, {Str, Dbl, Int}); - testFields(o, d, {Int, Str, Dbl}); - testFields(o, d, {Int, Dbl, Str}); - testFields(o, d, {Dbl, Str, Int}); - testFields(o, d, {Dbl, Int, Str}); + for r in range (1, 3): + combinations = list(itertools.permutations(keys, r = r)) + + for combination in combinations: + template_params = [] + arg_params = [] + for type in combination: + template_params.append(type) + arg_params.append(header[type]) + call = 'testFields<' + ', '.join(template_params) + \ + '>(o, d, {' + ', '.join(arg_params) + '});' + print(call) + */ + + testFields(o, d, {Str}); + testFields(o, d, {Int}); + testFields(o, d, {Dbl}); + testFields(o, d, {Str, Int}); + testFields(o, d, {Str, Dbl}); + testFields(o, d, {Int, Str}); + testFields(o, d, {Int, Dbl}); + testFields(o, d, {Dbl, Str}); + testFields(o, d, {Dbl, Int}); + testFields(o, d, {Str, Int, Dbl}); + testFields(o, d, {Str, Dbl, Int}); + testFields(o, d, {Int, Str, Dbl}); + testFields(o, d, {Int, Dbl, Str}); + testFields(o, d, {Dbl, Str, Int}); + testFields(o, d, {Dbl, Int, Str}); } -void testIgnoreEmpty(const std::vector& data) { - unique_file_name f; - make_and_write(f.name, data); +void testIgnoreEmpty(const std::vector &data) { + unique_file_name f; + make_and_write(f.name, data); - std::vector expected; - for (const auto& d : data) { - if (d.s != X::make_empty) { - expected.push_back(d); - } + std::vector expected; + for (const auto &d : data) { + if (d.s != X::make_empty) { + expected.push_back(d); + } + } + + { + ss::parser p{f.name, ","}; + + std::vector i; + for (const auto &a : p.iterate()) { + i.push_back(a); } - { - ss::parser p{f.name, ","}; + CHECK_EQ(i, expected); + } - std::vector i; - for (const auto& a : p.iterate()) { - i.push_back(a); - } - - CHECK_EQ(i, expected); + { + 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()); + } + i.push_back(a); + ++n; } - { - 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()); - } - i.push_back(a); - ++n; - } - - if (data != expected) { - CHECK_NE(i, expected); - } + if (data != expected) { + CHECK_NE(i, expected); } + } } TEST_CASE("parser test various cases with empty lines") { - testIgnoreEmpty({{1, 2, "x"}, {3, 4, "y"}, {9, 10, "v"}, {11, 12, "w"}}); + testIgnoreEmpty({{1, 2, "x"}, {3, 4, "y"}, {9, 10, "v"}, {11, 12, "w"}}); - testIgnoreEmpty( - {{1, 2, X::make_empty}, {3, 4, "y"}, {9, 10, "v"}, {11, 12, "w"}}); + testIgnoreEmpty( + {{1, 2, X::make_empty}, {3, 4, "y"}, {9, 10, "v"}, {11, 12, "w"}}); - testIgnoreEmpty( - {{1, 2, "x"}, {3, 4, "y"}, {9, 10, "v"}, {11, 12, X::make_empty}}); + testIgnoreEmpty( + {{1, 2, "x"}, {3, 4, "y"}, {9, 10, "v"}, {11, 12, X::make_empty}}); - testIgnoreEmpty( - {{1, 2, "x"}, {5, 6, X::make_empty}, {9, 10, "v"}, {11, 12, "w"}}); + testIgnoreEmpty( + {{1, 2, "x"}, {5, 6, X::make_empty}, {9, 10, "v"}, {11, 12, "w"}}); - testIgnoreEmpty({{1, 2, X::make_empty}, - {5, 6, X::make_empty}, - {9, 10, "v"}, - {11, 12, "w"}}); + testIgnoreEmpty({{1, 2, X::make_empty}, + {5, 6, X::make_empty}, + {9, 10, "v"}, + {11, 12, "w"}}); - testIgnoreEmpty({{1, 2, X::make_empty}, - {3, 4, "y"}, - {9, 10, "v"}, - {11, 12, X::make_empty}}); + testIgnoreEmpty({{1, 2, X::make_empty}, + {3, 4, "y"}, + {9, 10, "v"}, + {11, 12, X::make_empty}}); - testIgnoreEmpty({{1, 2, "x"}, - {3, 4, "y"}, - {9, 10, X::make_empty}, - {11, 12, X::make_empty}}); + testIgnoreEmpty({{1, 2, "x"}, + {3, 4, "y"}, + {9, 10, X::make_empty}, + {11, 12, X::make_empty}}); - testIgnoreEmpty({{1, 2, X::make_empty}, - {3, 4, "y"}, - {9, 10, X::make_empty}, - {11, 12, X::make_empty}}); + testIgnoreEmpty({{1, 2, X::make_empty}, + {3, 4, "y"}, + {9, 10, X::make_empty}, + {11, 12, X::make_empty}}); - testIgnoreEmpty({{1, 2, X::make_empty}, - {3, 4, X::make_empty}, - {9, 10, X::make_empty}, - {11, 12, X::make_empty}}); + testIgnoreEmpty({{1, 2, X::make_empty}, + {3, 4, X::make_empty}, + {9, 10, X::make_empty}, + {11, 12, X::make_empty}}); - testIgnoreEmpty({{1, 2, "x"}, - {3, 4, X::make_empty}, - {9, 10, X::make_empty}, - {11, 12, X::make_empty}}); + testIgnoreEmpty({{1, 2, "x"}, + {3, 4, X::make_empty}, + {9, 10, X::make_empty}, + {11, 12, X::make_empty}}); - testIgnoreEmpty({{1, 2, X::make_empty}, - {3, 4, X::make_empty}, - {9, 10, X::make_empty}, - {11, 12, "w"}}); + testIgnoreEmpty({{1, 2, X::make_empty}, + {3, 4, X::make_empty}, + {9, 10, X::make_empty}, + {11, 12, "w"}}); - testIgnoreEmpty({{11, 12, X::make_empty}}); + testIgnoreEmpty({{11, 12, X::make_empty}}); - testIgnoreEmpty({}); + testIgnoreEmpty({}); } From e6a7e099752d1ef97e7106cfc5143dc3c2689164 Mon Sep 17 00:00:00 2001 From: ado Date: Sat, 29 Jul 2023 01:18:01 +0200 Subject: [PATCH 07/22] Add config option for ctest within win-msvc.yml --- .github/workflows/win-msvc.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/win-msvc.yaml b/.github/workflows/win-msvc.yaml index 308cdc8..95a22f8 100644 --- a/.github/workflows/win-msvc.yaml +++ b/.github/workflows/win-msvc.yaml @@ -45,4 +45,4 @@ jobs: - name: Run working-directory: build - run: ctest --output-on-failure -j ${{ steps.cores.outputs.count }} + run: ctest -C Debug --output-on-failure -j ${{ steps.cores.outputs.count }} From 58857fff2d1dc99afe50b606bf47056121442b8f Mon Sep 17 00:00:00 2001 From: ado Date: Sat, 29 Jul 2023 01:18:11 +0200 Subject: [PATCH 08/22] Add config option for ctest within win-msvc.yml --- .github/workflows/win-msvc.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/win-msvc.yaml b/.github/workflows/win-msvc.yaml index 95a22f8..4308542 100644 --- a/.github/workflows/win-msvc.yaml +++ b/.github/workflows/win-msvc.yaml @@ -1,4 +1,4 @@ -name: msvc-ci +name: win-msvc-ci on: push: From 5d6c2c4af5f7cd4520046fb5f85e5982aa01d6d7 Mon Sep 17 00:00:00 2001 From: ado Date: Sat, 29 Jul 2023 01:44:19 +0200 Subject: [PATCH 09/22] Remove move count unit test from parser tests --- test/test_parser.cpp | 47 -------------------------------------------- 1 file changed, 47 deletions(-) diff --git a/test/test_parser.cpp b/test/test_parser.cpp index a554949..bae9aab 100644 --- a/test/test_parser.cpp +++ b/test/test_parser.cpp @@ -553,8 +553,6 @@ TEST_CASE("parser test composite conversion") { CHECK(p.eof()); } -size_t move_called = 0; - struct my_string { char *data{nullptr}; @@ -567,12 +565,10 @@ struct my_string { my_string &operator=(const my_string &) = delete; my_string(my_string &&other) : data{other.data} { - move_called++; other.data = nullptr; } my_string &operator=(my_string &&other) { - move_called++; data = other.data; return *this; } @@ -594,49 +590,6 @@ struct xyz { auto tied() { return std::tie(x, y, z); } }; -TEST_CASE("parser test the moving of parsed values") { - { - unique_file_name f; - { - std::ofstream out{f.name}; - out << "x" << std::endl; - } - - ss::parser p{f.name, ","}; - auto x = p.get_next(); - CHECK_LE(move_called, 1); - move_called = 0; - } - - unique_file_name f; - { - std::ofstream out{f.name}; - out << "a,b,c" << std::endl; - } - - { - - ss::parser p{f.name, ","}; - auto x = p.get_next(); - CHECK_LE(move_called, 3); - move_called = 0; - } - - { - ss::parser p{f.name, ","}; - auto x = p.get_object(); - CHECK_LE(move_called, 6); - move_called = 0; - } - - { - ss::parser p{f.name, ","}; - auto x = p.get_next(); - CHECK_LE(move_called, 6); - move_called = 0; - } -} - TEST_CASE("parser test the moving of parsed composite values") { // to compile is enough return; From a98742945b5accb9b6216bf72d25fb2e9fbb73de Mon Sep 17 00:00:00 2001 From: ado Date: Sat, 29 Jul 2023 13:56:00 +0200 Subject: [PATCH 10/22] Update test helpers --- include/ss/parser.hpp | 2 - test/test_helpers.hpp | 99 +++++++++++++++++-------------------------- 2 files changed, 39 insertions(+), 62 deletions(-) diff --git a/include/ss/parser.hpp b/include/ss/parser.hpp index 74967cf..4ad4df4 100644 --- a/include/ss/parser.hpp +++ b/include/ss/parser.hpp @@ -1,7 +1,5 @@ #pragma once -#define _CRT_SECURE_NO_WARNINGS - #include "common.hpp" #include "converter.hpp" #include "extract.hpp" diff --git a/test/test_helpers.hpp b/test/test_helpers.hpp index 1da01f5..e99852a 100644 --- a/test/test_helpers.hpp +++ b/test/test_helpers.hpp @@ -1,9 +1,6 @@ #pragma once -#define _CRT_SECURE_NO_WARNINGS - -#include -#include +#include #ifdef CMAKE_GITHUB_CI #include @@ -12,73 +9,55 @@ #endif struct buffer { - char* data_{nullptr}; + std::string data_; - char* operator()(const char* data) { - if (data_) { - delete[] data_; - } - data_ = new char[strlen(data) + 1]; - strcpy(data_, data); - return data_; - } + char *operator()(const std::string &data) { + data_ = data; + return data_.data(); + } - char* append(const char* data) { - if (data_) { - char* new_data_ = new char[strlen(data_) + strlen(data) + 1]; - strcpy(new_data_, data_); - strcat(new_data_, data); - delete[] data_; - data_ = new_data_; - return data_; - } else { - return operator()(data); - } - } + char *append(const std::string &data) { + data_ += data; + return data_.data(); + } - char* append_overwrite_last(const char* data, size_t size) { - data_[strlen(data_) - size] = '\0'; - return append(data); - } - - ~buffer() { - if (data_) { - delete[] data_; - } - } + char *append_overwrite_last(const std::string &data, size_t size) { + data_.resize(data_.size() - size); + return append(data); + } }; [[maybe_unused]] inline buffer buff; #define CHECK_FLOATING_CONVERSION(input, type) \ - { \ - auto eps = std::numeric_limits::min(); \ - std::string s = #input; \ - auto t = ss::to_num(s.c_str(), s.c_str() + s.size()); \ - REQUIRE(t.has_value()); \ - CHECK_LT(std::abs(t.value() - type(input)), eps); \ - } \ - { \ - /* check negative too */ \ - auto eps = std::numeric_limits::min(); \ - auto s = std::string("-") + #input; \ - auto t = ss::to_num(s.c_str(), s.c_str() + s.size()); \ - REQUIRE(t.has_value()); \ - CHECK_LT(std::abs(t.value() - type(-input)), eps); \ - } + { \ + auto eps = std::numeric_limits::min(); \ + std::string s = #input; \ + auto t = ss::to_num(s.c_str(), s.c_str() + s.size()); \ + REQUIRE(t.has_value()); \ + CHECK_LT(std::abs(t.value() - type(input)), eps); \ + } \ + { \ + /* check negative too */ \ + auto eps = std::numeric_limits::min(); \ + auto s = std::string("-") + #input; \ + auto t = ss::to_num(s.c_str(), s.c_str() + s.size()); \ + REQUIRE(t.has_value()); \ + CHECK_LT(std::abs(t.value() - type(-input)), eps); \ + } #define CHECK_INVALID_CONVERSION(input, type) \ - { \ - std::string s = input; \ - auto t = ss::to_num(s.c_str(), s.c_str() + s.size()); \ - CHECK_FALSE(t.has_value()); \ - } + { \ + std::string s = input; \ + auto t = ss::to_num(s.c_str(), s.c_str() + s.size()); \ + CHECK_FALSE(t.has_value()); \ + } #define REQUIRE_VARIANT(var, el, type) \ - { \ - auto ptr = std::get_if(&var); \ - REQUIRE(ptr); \ - REQUIRE_EQ(el, *ptr); \ - } + { \ + auto ptr = std::get_if(&var); \ + REQUIRE(ptr); \ + REQUIRE_EQ(el, *ptr); \ + } #define CHECK_NOT_VARIANT(var, type) CHECK(!std::holds_alternative(var)); From e4d9e10ac3628feca69f6f1309ed56f4e092e06a Mon Sep 17 00:00:00 2001 From: ado Date: Sat, 29 Jul 2023 14:14:02 +0200 Subject: [PATCH 11/22] Update msvc ci --- .../workflows/{win-msvc.yaml => win-latest-msvc.yaml} | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) rename .github/workflows/{win-msvc.yaml => win-latest-msvc.yaml} (80%) diff --git a/.github/workflows/win-msvc.yaml b/.github/workflows/win-latest-msvc.yaml similarity index 80% rename from .github/workflows/win-msvc.yaml rename to .github/workflows/win-latest-msvc.yaml index 4308542..aec9871 100644 --- a/.github/workflows/win-msvc.yaml +++ b/.github/workflows/win-latest-msvc.yaml @@ -1,4 +1,4 @@ -name: win-msvc-ci +name: win-latest-msvc-ci on: push: @@ -20,16 +20,15 @@ jobs: defaults: run: shell: bash - runs-on: ${{matrix.config.os}} + runs-on: windows-latest strategy: fail-fast: false matrix: - config: - - { os: windows-2019, vs: "Visual Studio 2020" } + vs: ["Visual Studio 2020"] build: [Debug, Release] platform: [Win32, x64] - name: "${{matrix.config.vs}}:${{matrix.platform}}:${{matrix.build}}" + name: "${{matrix.vs}}:${{matrix.platform}}:${{matrix.build}}" steps: - name: checkout uses: actions/checkout@v2 From 3dcb2ce2ef4d4bf2d9d416f52204edc11b85b733 Mon Sep 17 00:00:00 2001 From: ado Date: Sat, 29 Jul 2023 14:22:41 +0200 Subject: [PATCH 12/22] Add vs16 for msvc ci --- .github/workflows/win-latest-msvc.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/win-latest-msvc.yaml b/.github/workflows/win-latest-msvc.yaml index aec9871..c422bcf 100644 --- a/.github/workflows/win-latest-msvc.yaml +++ b/.github/workflows/win-latest-msvc.yaml @@ -24,7 +24,7 @@ jobs: strategy: fail-fast: false matrix: - vs: ["Visual Studio 2020"] + vs: [vs17, vs16] build: [Debug, Release] platform: [Win32, x64] From 739077a8db480f5c3a064750f3ea824f622c003c Mon Sep 17 00:00:00 2001 From: ado Date: Sat, 29 Jul 2023 14:54:25 +0200 Subject: [PATCH 13/22] Fix msvc ci vs version names --- .github/workflows/win-latest-msvc.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/win-latest-msvc.yaml b/.github/workflows/win-latest-msvc.yaml index c422bcf..d28e5fb 100644 --- a/.github/workflows/win-latest-msvc.yaml +++ b/.github/workflows/win-latest-msvc.yaml @@ -24,7 +24,7 @@ jobs: strategy: fail-fast: false matrix: - vs: [vs17, vs16] + vs: ["Visual Studio 16 2019", "Visual Studio 17 2022"] build: [Debug, Release] platform: [Win32, x64] @@ -37,7 +37,7 @@ jobs: run: script/ci_install_deps.sh - name: Configure - run: cmake -S test -B build -D CMAKE_BUILD_TYPE=Debug + run: cmake -S test -B build -D CMAKE_BUILD_TYPE=${{ matrix.build }} - name: Build run: cmake --build build -j ${{ steps.cores.outputs.count }} From f762736da24f4332b09e730153d7e9c185125c91 Mon Sep 17 00:00:00 2001 From: ado Date: Sat, 29 Jul 2023 14:59:49 +0200 Subject: [PATCH 14/22] Fix msvc ci configure step --- .github/workflows/win-latest-msvc.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/win-latest-msvc.yaml b/.github/workflows/win-latest-msvc.yaml index d28e5fb..9607fe0 100644 --- a/.github/workflows/win-latest-msvc.yaml +++ b/.github/workflows/win-latest-msvc.yaml @@ -37,7 +37,7 @@ jobs: run: script/ci_install_deps.sh - name: Configure - run: cmake -S test -B build -D CMAKE_BUILD_TYPE=${{ matrix.build }} + run: cmake -S test -B build -G ${{ matrix.vs }} -A ${{ matrix.platform }} -D CMAKE_BUILD_TYPE=${{ matrix.build }} - name: Build run: cmake --build build -j ${{ steps.cores.outputs.count }} From d6bc8086b2b93332150744af2379a5c2a725dddd Mon Sep 17 00:00:00 2001 From: ado Date: Sat, 29 Jul 2023 15:03:25 +0200 Subject: [PATCH 15/22] Fix msvc ci configure step --- .github/workflows/win-latest-msvc.yaml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/.github/workflows/win-latest-msvc.yaml b/.github/workflows/win-latest-msvc.yaml index 9607fe0..91de658 100644 --- a/.github/workflows/win-latest-msvc.yaml +++ b/.github/workflows/win-latest-msvc.yaml @@ -17,10 +17,16 @@ on: jobs: ci: + if: >- + ! contains(toJSON(github.event.commits.*.message), '[skip ci]') && + ! contains(toJSON(github.event.commits.*.message), '[skip github]') + defaults: run: shell: bash + runs-on: windows-latest + strategy: fail-fast: false matrix: @@ -29,6 +35,7 @@ jobs: platform: [Win32, x64] name: "${{matrix.vs}}:${{matrix.platform}}:${{matrix.build}}" + steps: - name: checkout uses: actions/checkout@v2 @@ -37,7 +44,7 @@ jobs: run: script/ci_install_deps.sh - name: Configure - run: cmake -S test -B build -G ${{ matrix.vs }} -A ${{ matrix.platform }} -D CMAKE_BUILD_TYPE=${{ matrix.build }} + run: cmake -S test -B build -G "${{ matrix.vs }}" -A ${{ matrix.platform }} -D CMAKE_BUILD_TYPE=${{ matrix.build }} - name: Build run: cmake --build build -j ${{ steps.cores.outputs.count }} From bdfd8968614d5187be7baa580b30295bd4c42b04 Mon Sep 17 00:00:00 2001 From: ado Date: Sat, 29 Jul 2023 15:17:39 +0200 Subject: [PATCH 16/22] Fix msvc vs 16 ci --- .../{win-latest-msvc.yaml => win-msvc.yml} | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) rename .github/workflows/{win-latest-msvc.yaml => win-msvc.yml} (70%) diff --git a/.github/workflows/win-latest-msvc.yaml b/.github/workflows/win-msvc.yml similarity index 70% rename from .github/workflows/win-latest-msvc.yaml rename to .github/workflows/win-msvc.yml index 91de658..62405fa 100644 --- a/.github/workflows/win-latest-msvc.yaml +++ b/.github/workflows/win-msvc.yml @@ -1,4 +1,4 @@ -name: win-latest-msvc-ci +name: win-msvc-ci on: push: @@ -25,16 +25,22 @@ jobs: run: shell: bash - runs-on: windows-latest + runs-on: {{ matrix.config.os }} strategy: fail-fast: false matrix: - vs: ["Visual Studio 16 2019", "Visual Studio 17 2022"] + config: + - os: windows-2019 + vs: "Visual Studio 16 2019" + + - os: windows-latest + vs: "Visual Studio 17 2022" + build: [Debug, Release] platform: [Win32, x64] - name: "${{matrix.vs}}:${{matrix.platform}}:${{matrix.build}}" + name: "${{matrix.config.vs}}:${{matrix.platform}}:${{matrix.build}}" steps: - name: checkout @@ -44,7 +50,7 @@ jobs: run: script/ci_install_deps.sh - name: Configure - run: cmake -S test -B build -G "${{ matrix.vs }}" -A ${{ matrix.platform }} -D CMAKE_BUILD_TYPE=${{ matrix.build }} + run: cmake -S test -B build -G "${{ matrix.config.vs }}" -A ${{ matrix.platform }} --config ${{ matrix.build }} - name: Build run: cmake --build build -j ${{ steps.cores.outputs.count }} From b7f6009eb9e32cf98ed8b89d0f471b1aefb52e6f Mon Sep 17 00:00:00 2001 From: ado Date: Sat, 29 Jul 2023 15:30:05 +0200 Subject: [PATCH 17/22] Fix msvc ci yaml issues --- .github/workflows/win-msvc.yml | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/.github/workflows/win-msvc.yml b/.github/workflows/win-msvc.yml index 62405fa..7d9e520 100644 --- a/.github/workflows/win-msvc.yml +++ b/.github/workflows/win-msvc.yml @@ -25,17 +25,17 @@ jobs: run: shell: bash - runs-on: {{ matrix.config.os }} + runs-on: ${{ matrix.config.os }} strategy: fail-fast: false matrix: config: - - os: windows-2019 - vs: "Visual Studio 16 2019" + - os: windows-2019 + vs: "Visual Studio 16 2019" - - os: windows-latest - vs: "Visual Studio 17 2022" + - os: windows-latest + vs: "Visual Studio 17 2022" build: [Debug, Release] platform: [Win32, x64] @@ -50,11 +50,14 @@ jobs: run: script/ci_install_deps.sh - name: Configure - run: cmake -S test -B build -G "${{ matrix.config.vs }}" -A ${{ matrix.platform }} --config ${{ matrix.build }} + run: >- + cmake -S test -B build -G "${{matrix.config.vs}}" + -A ${{matrix.platform}} --config ${{matrix.build}} - name: Build - run: cmake --build build -j ${{ steps.cores.outputs.count }} + run: cmake --build build -j ${{steps.cores.outputs.count}} - name: Run working-directory: build - run: ctest -C Debug --output-on-failure -j ${{ steps.cores.outputs.count }} + run: >- + ctest -C Debug --output-on-failure -j ${{steps.cores.outputs.count}} From 72b74a3b6458c014f84cc45f022d178245c3f17f Mon Sep 17 00:00:00 2001 From: ado Date: Sat, 29 Jul 2023 15:35:29 +0200 Subject: [PATCH 18/22] Fix msvc ci configure step --- .github/workflows/win-msvc.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/win-msvc.yml b/.github/workflows/win-msvc.yml index 7d9e520..767d026 100644 --- a/.github/workflows/win-msvc.yml +++ b/.github/workflows/win-msvc.yml @@ -51,8 +51,8 @@ jobs: - name: Configure run: >- - cmake -S test -B build -G "${{matrix.config.vs}}" - -A ${{matrix.platform}} --config ${{matrix.build}} + cmake -S test -B build --config ${{matrix.build} + -G "${{matrix.config.vs}}" -A ${{matrix.platform}} - name: Build run: cmake --build build -j ${{steps.cores.outputs.count}} From 21d1096edf2f504c5a157968d676c845ab33fa7e Mon Sep 17 00:00:00 2001 From: ado Date: Sat, 29 Jul 2023 15:37:53 +0200 Subject: [PATCH 19/22] Fix msvc ci yaml issues --- .github/workflows/win-msvc.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/win-msvc.yml b/.github/workflows/win-msvc.yml index 767d026..cd2105a 100644 --- a/.github/workflows/win-msvc.yml +++ b/.github/workflows/win-msvc.yml @@ -51,7 +51,7 @@ jobs: - name: Configure run: >- - cmake -S test -B build --config ${{matrix.build} + cmake -S test -B build --config ${{matrix.build}} -G "${{matrix.config.vs}}" -A ${{matrix.platform}} - name: Build From e70fc056460aaf199f6c4d71a19b4b6b5b5396ba Mon Sep 17 00:00:00 2001 From: ado Date: Sat, 29 Jul 2023 15:39:51 +0200 Subject: [PATCH 20/22] Fix msvc ci configure step --- .github/workflows/win-msvc.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/win-msvc.yml b/.github/workflows/win-msvc.yml index cd2105a..5311925 100644 --- a/.github/workflows/win-msvc.yml +++ b/.github/workflows/win-msvc.yml @@ -51,7 +51,7 @@ jobs: - name: Configure run: >- - cmake -S test -B build --config ${{matrix.build}} + cmake -S test -B build -D CMAKE_BUILD_TYPE=${{matrix.build}} -G "${{matrix.config.vs}}" -A ${{matrix.platform}} - name: Build From d99cba274ed4f398e45fd99e77f1b27131cfc9b5 Mon Sep 17 00:00:00 2001 From: ado Date: Sat, 29 Jul 2023 16:08:33 +0200 Subject: [PATCH 21/22] Add win-msvc ci badge --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 8f4e1b4..6b01cfa 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ [![ubuntu-latest-icc](https://github.com/red0124/ssp/workflows/ubuntu-latest-icc-ci/badge.svg)](https://github.com/red0124/ssp/actions/workflows/ubuntu-latest-icc.yml) [![windows-msys2-gcc](https://github.com/red0124/ssp/workflows/win-msys2-gcc-ci/badge.svg)](https://github.com/red0124/ssp/actions/workflows/win-msys2-gcc.yml) [![windows-msys2-clang](https://github.com/red0124/ssp/workflows/win-msys2-clang-ci/badge.svg)](https://github.com/red0124/ssp/actions/workflows/win-msys2-clang.yml) +[![win-msvc-ci](https://github.com/red0124/ssp/workflows/win-msvc.yml/badge.svg)](https://github.com/red0124/ssp/actions/workflows/win-msvc.yml) A header only "csv" parser which is fast and versatile with modern C++ api. Requires compiler with C++17 support. [Can also be used to convert strings to specific types.](#The-converter) From 76091263f26ac27b59f1d93abb29fbabde699687 Mon Sep 17 00:00:00 2001 From: ado Date: Sat, 29 Jul 2023 16:11:27 +0200 Subject: [PATCH 22/22] Fix win-msvc ci badge --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6b01cfa..656c5c3 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ [![ubuntu-latest-icc](https://github.com/red0124/ssp/workflows/ubuntu-latest-icc-ci/badge.svg)](https://github.com/red0124/ssp/actions/workflows/ubuntu-latest-icc.yml) [![windows-msys2-gcc](https://github.com/red0124/ssp/workflows/win-msys2-gcc-ci/badge.svg)](https://github.com/red0124/ssp/actions/workflows/win-msys2-gcc.yml) [![windows-msys2-clang](https://github.com/red0124/ssp/workflows/win-msys2-clang-ci/badge.svg)](https://github.com/red0124/ssp/actions/workflows/win-msys2-clang.yml) -[![win-msvc-ci](https://github.com/red0124/ssp/workflows/win-msvc.yml/badge.svg)](https://github.com/red0124/ssp/actions/workflows/win-msvc.yml) +[![win-msvc-ci](https://github.com/red0124/ssp/workflows/win-msvc-ci/badge.svg)](https://github.com/red0124/ssp/actions/workflows/win-msvc.yml) A header only "csv" parser which is fast and versatile with modern C++ api. Requires compiler with C++17 support. [Can also be used to convert strings to specific types.](#The-converter)