Skip to content

Commit

Permalink
Fix CSVReader ignoring the last line
Browse files Browse the repository at this point in the history
`in.good()` was tested too early which made the CSVReader drop the last
line of any file. This would affect TMC location databases that are not
newline-terminated.
  • Loading branch information
windytan committed Aug 6, 2024
1 parent 6436165 commit dcec5c5
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 10 deletions.
2 changes: 2 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## HEAD

* Bug fixes:
* Fix the CSVReader (used in the TMC decoder) ignoring the last line of any file
* Build system fixes:
* macOS: ask Homebrew about liquid-dsp location instead of hardcoding it
* Set default installation prefix to /usr/local (all platforms)
Expand Down
12 changes: 2 additions & 10 deletions src/tmc/csv.cc
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,7 @@ std::vector<std::vector<std::string>> readCSV(const std::string& filename, char
if (!in.is_open())
return lines;

for (std::string line; std::getline(in, line);) {
if (!in.good())
break;

for (std::string line; std::getline(in, line); in.good()) {
line.erase(std::remove(line.begin(), line.end(), '\r'), line.end());
line.erase(std::remove(line.begin(), line.end(), '\n'), line.end());

Expand All @@ -46,10 +43,7 @@ CSVTable readCSVWithTitles(const std::string& filename, char delimiter) {

std::ifstream in(filename);
if (in.is_open()) {
for (std::string line; std::getline(in, line);) {
if (!in.good())
break;

for (std::string line; std::getline(in, line); in.good()) {
lines.push_back(line);
}

Expand All @@ -63,12 +57,10 @@ std::string get_string(const CSVTable& table, const CSVRow& row, const std::stri
return row.at(table.titles.at(title));
}

// @throws exceptions from std::stoi
int get_int(const CSVTable& table, const CSVRow& row, const std::string& title) {
return std::stoi(row.at(table.titles.at(title)));
}

// @throws exceptions from std::stoi
uint16_t get_uint16(const CSVTable& table, const CSVRow& row, const std::string& title) {
return static_cast<uint16_t>(get_int(table, row, title));
}
Expand Down
2 changes: 2 additions & 0 deletions src/tmc/csv.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,11 @@ CSVTable readCSVContainerWithTitles(const Container& csvdata, char delimiter) {
std::string get_string(const CSVTable& table, const CSVRow& row, const std::string& title);

// Find an element by its title and return it as int.
// @throws exceptions from std::stoi
int get_int(const CSVTable& table, const CSVRow& row, const std::string& title);

// Find an element by its title and return it as uint16_t.
// @throws exceptions from std::stoi
uint16_t get_uint16(const CSVTable& table, const CSVRow& row, const std::string& title);

// Find an element by its title and return it as bool.
Expand Down
28 changes: 28 additions & 0 deletions test/unit.cc
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include <fstream>
#include <sstream>
#include <vector>

Expand All @@ -9,6 +10,7 @@
#include "../src/common.h"
#include "../src/groups.h"
#include "../src/options.h"
#include "../src/tmc/csv.h"
#include "test_helpers.h"

TEST_CASE("Bitfield extraction") {
Expand Down Expand Up @@ -492,3 +494,29 @@ TEST_CASE("Invalid data") {
}, options, 0xE24D));
}
}

TEST_CASE("CSV reader") {
const std::string testfilename{"testfile.csv"};

std::ofstream out(testfilename);
out << "num;a;b;c\n0;-16;+8;7\nzero;minus 16;plus 8;seitsemän";
out.close();

SECTION("Simple read without titles") {
auto csv = redsea::readCSV(testfilename, ';');

CHECK(csv.size() == 3);
CHECK(csv.at(1).at(3) == "7");
}

SECTION("Get values by column title") {
auto csv = redsea::readCSVWithTitles(testfilename, ';');

CHECK(csv.rows.size() == 2);
CHECK(redsea::get_int(csv, csv.rows.at(0), "a") == -16);
CHECK(redsea::get_int(csv, csv.rows.at(0), "b") == 8);
CHECK(redsea::get_uint16(csv, csv.rows.at(0), "c") == 7);

CHECK(redsea::get_string(csv, csv.rows.at(1), "c") == "seitsemän");
}
}

0 comments on commit dcec5c5

Please sign in to comment.