74 lines
1.6 KiB
C++
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
|