diff --git a/CMakeLists.txt b/CMakeLists.txt index 2a72d8f..8176a7c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -181,6 +181,7 @@ if(RAPIDCSV_BUILD_TESTS) add_unit_test(test095) add_unit_test(test096) add_unit_test(test097) + add_unit_test(test098) # perf tests add_perf_test(ptest001) diff --git a/make.sh b/make.sh index b7c157b..0c78965 100755 --- a/make.sh +++ b/make.sh @@ -2,7 +2,7 @@ # make.sh # -# Copyright (C) 2020-2021 Kristofer Berggren +# Copyright (C) 2020-2024 Kristofer Berggren # All rights reserved. # # See LICENSE for redistribution information. @@ -168,7 +168,11 @@ if [[ "${INSTALL}" == "1" ]]; then if [ "${OS}" == "Linux" ]; then cd build-release && sudo make install && cd .. || exiterr "install failed (linux), exiting." elif [ "${OS}" == "Darwin" ]; then - cd build-release && make install && cd .. || exiterr "install failed (mac), exiting." + GHSUDO="" + if [[ "${GITHUB_ACTIONS}" == "true" ]]; then + GHSUDO="sudo" + fi + cd build-release && ${GHSUDO} make install && cd .. || exiterr "install failed (mac), exiting." else exiterr "install failed (unsupported os ${OS}), exiting." fi diff --git a/src/rapidcsv.h b/src/rapidcsv.h index 280aba3..cad4cf8 100644 --- a/src/rapidcsv.h +++ b/src/rapidcsv.h @@ -2,7 +2,7 @@ * rapidcsv.h * * URL: https://github.com/d99kris/rapidcsv - * Version: 8.83 + * Version: 8.84 * * Copyright (C) 2017-2024 Kristofer Berggren * All rights reserved. @@ -1351,7 +1351,7 @@ namespace rapidcsv SetCell(static_cast(columnIdx), pRowIdx, pCell); } - + /** * @brief Get column name * @param pColumnIdx zero-based column index. @@ -1663,16 +1663,15 @@ namespace rapidcsv p_FileLength -= readLength; } - // Handle last cell without linebreak - if (!cell.empty()) + // Handle last row / cell without linebreak + if (row.empty() && cell.empty()) { - row.push_back(Unquote(Trim(cell))); - cell.clear(); + // skip empty trailing line } - - // Handle last line without linebreak - if (!row.empty()) + else { + row.push_back(Unquote(Trim(cell))); + if (mLineReaderParams.mSkipCommentLines && !row.at(0).empty() && (row.at(0)[0] == mLineReaderParams.mCommentPrefix)) { @@ -1683,7 +1682,9 @@ namespace rapidcsv mData.push_back(row); } + cell.clear(); row.clear(); + quoted = false; } // Assume CR/LF if at least half the linebreaks have CR diff --git a/tests/test098.cpp b/tests/test098.cpp new file mode 100644 index 0000000..d37e6dc --- /dev/null +++ b/tests/test098.cpp @@ -0,0 +1,57 @@ +// test098.cpp - empty cells + +#include +#include "unittest.h" + +int main() +{ + int rv = 0; + + try + { + // empty cells without trailing linebreak on last line + { + std::string csv = + ",\n" + ",\n" + "," + ; + + std::istringstream sstream(csv); + rapidcsv::Document doc(sstream, rapidcsv::LabelParams(-1, -1)); + unittest::ExpectEqual(size_t, doc.GetRowCount(), 3); + unittest::ExpectEqual(size_t, doc.GetRow(0).size(), 2); + unittest::ExpectEqual(size_t, doc.GetRow(1).size(), 2); + unittest::ExpectEqual(size_t, doc.GetRow(2).size(), 2); + unittest::ExpectEqual(std::string, doc.GetCell(1 /* col */, 0 /* row */), ""); + unittest::ExpectEqual(std::string, doc.GetCell(1 /* col */, 1 /* row */), ""); + unittest::ExpectEqual(std::string, doc.GetCell(1 /* col */, 2 /* row */), ""); + } + + // empty cells with trailing linebreak on last line + { + std::string csv = + ",\n" + ",\n" + ",\n" + ; + + std::istringstream sstream(csv); + rapidcsv::Document doc(sstream, rapidcsv::LabelParams(-1, -1)); + unittest::ExpectEqual(size_t, doc.GetRowCount(), 3); + unittest::ExpectEqual(size_t, doc.GetRow(0).size(), 2); + unittest::ExpectEqual(size_t, doc.GetRow(1).size(), 2); + unittest::ExpectEqual(size_t, doc.GetRow(2).size(), 2); + unittest::ExpectEqual(std::string, doc.GetCell(0 /* col */, 0 /* row */), ""); + unittest::ExpectEqual(std::string, doc.GetCell(0 /* col */, 1 /* row */), ""); + unittest::ExpectEqual(std::string, doc.GetCell(0 /* col */, 2 /* row */), ""); + } + } + catch (const std::exception& ex) + { + std::cout << ex.what() << std::endl; + rv = 1; + } + + return rv; +}