Skip to content

Instantly share code, notes, and snippets.

@willir
Created December 6, 2015 16:41
Show Gist options
  • Save willir/a25afcd73891f08fb575 to your computer and use it in GitHub Desktop.
Save willir/a25afcd73891f08fb575 to your computer and use it in GitHub Desktop.
#include "CsvReader.h"
#include <stdexcept>
using namespace std;
CsvReader::CsvReader(const char *filePath, size_t bufSize) :
mBufSize(bufSize),
mBuf(new char[bufSize]) {
mFile = fopen(filePath, "rt");
if(!mFile) {
throw invalid_argument(string("can't open file ") + filePath);
}
}
CsvReader::~CsvReader() {
delete []mBuf;
if(mFile) {
fclose(mFile);
}
}
std::vector<std::vector<std::string>> &CsvReader::parse() {
size_t readRes = 0;
do {
readRes = fread(mBuf, 1, mBufSize, mFile);
parseNextBuf(mBuf, readRes);
} while(readRes == mBufSize);
finish();
return mRes;
}
void CsvReader::parseNextBuf(const char *buf, size_t len) {
const char *aChar = buf;
while (aChar != buf + len) {
switch (*aChar) {
case '"':
if(mLastCharWasQuote) { // Double quote is just one quote
mFieldInProgress.push_back(*aChar);
mLastCharWasQuote = false;
} else {
mLastCharWasQuote = true;
}
mNewLine = false;
mInQuote = !mInQuote;
break;
case ',':
mNewLine = false;
if (mInQuote) {
mFieldInProgress += *aChar;
} else {
mLineInProgress.push_back(std::move(mFieldInProgress));
mFieldInProgress.clear();
}
break;
case '\n':
case '\r':
if (mInQuote) {
mFieldInProgress += *aChar;
} else {
if (!mNewLine) {
mLineInProgress.push_back(std::move(mFieldInProgress));
mRes.push_back(std::move(mLineInProgress));
mFieldInProgress.clear();
mLineInProgress.clear();
mNewLine = true;
}
}
break;
default:
mNewLine = false;
mFieldInProgress.push_back(*aChar);
break;
}
if(*aChar != '"') {
mLastCharWasQuote = false;
}
++aChar;
}
}
void CsvReader::finish() {
if (!mFieldInProgress.empty())
mLineInProgress.push_back(std::move(mFieldInProgress));
if (!mLineInProgress.empty())
mRes.push_back(std::move(mLineInProgress));
}
#pragma once
#include <stdio.h>
#include <vector>
#include <string>
class CsvReader {
public:
CsvReader(const char *filePath, size_t bufSize = 8192);
~CsvReader();
std::vector<std::vector<std::string>> &parse();
private:
void parseNextBuf(const char *buf, size_t len);
void finish();
size_t mBufSize = 0;
char *mBuf = nullptr;
FILE *mFile = nullptr;
std::string mFieldInProgress;
std::vector<std::string> mLineInProgress;
std::vector<std::vector<std::string>> mRes;
bool mInQuote = false;
bool mLastCharWasQuote = false;
bool mNewLine = false;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment