portingtools/src/csv.cpp
2022-11-08 21:59:56 +01:00

74 lines
1.6 KiB
C++

#include "csv.hpp"
#include <istream>
#include <string>
#include <vector>
namespace csv {
enum class CSVState { UnquotedField, QuotedField, QuotedQuote };
// this function has been made in collaboration with
// StackOverflow https://stackoverflow.com/a/30338543
void readCSVRow(const std::string &row, std::vector<std::string> &fields) {
fields.push_back("");
CSVState state = CSVState::UnquotedField;
size_t i = 0; // index of the current field
for (char c : row) {
switch (state) {
case CSVState::UnquotedField:
switch (c) {
case ',': // end of field
fields.push_back("");
i++;
break;
case '"':
state = CSVState::QuotedField;
break;
default:
fields[i].push_back(c);
break;
}
break;
case CSVState::QuotedField:
switch (c) {
case '"':
state = CSVState::QuotedQuote;
break;
default:
fields[i].push_back(c);
break;
}
break;
case CSVState::QuotedQuote:
switch (c) {
case ',': // , after closing quote
fields.push_back("");
i++;
state = CSVState::UnquotedField;
break;
case '"': // "" -> "
fields[i].push_back('"');
state = CSVState::QuotedField;
break;
default: // end of quote
state = CSVState::UnquotedField;
break;
}
break;
}
}
}
bool CsvReader::operator>>(std::vector<std::string> &line) {
line.clear();
if (!m_stream) {
return false;
}
std::string row;
std::getline(m_stream, row);
readCSVRow(row, line);
return !!m_stream;
}
} // namespace csv