portingtools/src/csv.cpp

92 lines
2.5 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;
}
}