2017-10-10 21:57:38 +00:00
|
|
|
#include "csv.hpp"
|
|
|
|
|
2017-10-10 22:06:12 +00:00
|
|
|
std::vector<std::string> csv_split(const char *s) {
|
2017-10-10 21:57:38 +00:00
|
|
|
std::vector<std::string> ret;
|
|
|
|
|
|
|
|
while (*s && *s != '\n' && *s != '\r') {
|
2017-10-10 22:06:12 +00:00
|
|
|
const char *start = s;
|
2017-10-10 21:57:38 +00:00
|
|
|
int within = 0;
|
|
|
|
|
|
|
|
for (; *s && *s != '\n' && *s != '\r'; s++) {
|
|
|
|
if (*s == '"') {
|
|
|
|
within = !within;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*s == ',' && !within) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string v = std::string(start, s - start);
|
|
|
|
ret.push_back(v);
|
|
|
|
|
|
|
|
if (*s == ',') {
|
|
|
|
s++;
|
|
|
|
|
|
|
|
while (*s && isspace(*s)) {
|
|
|
|
s++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string csv_dequote(std::string s) {
|
|
|
|
std::string out;
|
|
|
|
for (size_t i = 0; i < s.size(); i++) {
|
|
|
|
if (s[i] == '"') {
|
|
|
|
if (i + 1 < s.size() && s[i + 1] == '"') {
|
|
|
|
out.push_back('"');
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
out.push_back(s[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
2017-10-10 23:12:40 +00:00
|
|
|
std::string csv_getline(FILE *f) {
|
2017-10-10 22:06:12 +00:00
|
|
|
std::string out;
|
|
|
|
int c;
|
|
|
|
while ((c = getc(f)) != EOF) {
|
|
|
|
out.push_back(c);
|
|
|
|
if (c == '\n') {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
2017-10-10 23:12:40 +00:00
|
|
|
void readcsv(const char *fn, std::vector<std::string> &header, std::map<std::string, std::vector<std::string>> &mapping) {
|
2017-10-10 21:57:38 +00:00
|
|
|
FILE *f = fopen(fn, "r");
|
|
|
|
if (f == NULL) {
|
|
|
|
perror(fn);
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
|
2017-10-10 22:06:12 +00:00
|
|
|
std::string s;
|
2017-10-10 23:12:40 +00:00
|
|
|
if ((s = csv_getline(f)).size() > 0) {
|
2017-10-10 22:06:12 +00:00
|
|
|
header = csv_split(s.c_str());
|
2017-10-10 21:57:38 +00:00
|
|
|
|
|
|
|
for (size_t i = 0; i < header.size(); i++) {
|
|
|
|
header[i] = csv_dequote(header[i]);
|
|
|
|
}
|
|
|
|
}
|
2017-10-10 23:12:40 +00:00
|
|
|
while ((s = csv_getline(f)).size() > 0) {
|
2017-10-10 22:06:12 +00:00
|
|
|
std::vector<std::string> line = csv_split(s.c_str());
|
2017-10-10 21:57:38 +00:00
|
|
|
if (line.size() > 0) {
|
|
|
|
line[0] = csv_dequote(line[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (size_t i = 0; i < line.size() && i < header.size(); i++) {
|
|
|
|
// printf("putting %s\n", line[0].c_str());
|
|
|
|
mapping.insert(std::pair<std::string, std::vector<std::string>>(line[0], line));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fclose(f) != 0) {
|
|
|
|
perror("fclose");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
}
|
2017-10-10 23:22:21 +00:00
|
|
|
|
|
|
|
// Follow JSON rules for what looks like a number
|
|
|
|
bool is_number(std::string const &s) {
|
|
|
|
const char *cp = s.c_str();
|
|
|
|
char c = *(cp++);
|
|
|
|
|
|
|
|
if (c == '-' || (c >= '0' && c <= '9')) {
|
|
|
|
if (c == '-') {
|
|
|
|
c = *(cp++);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (c == '0') {
|
|
|
|
;
|
|
|
|
} else if (c >= '1' && c <= '9') {
|
|
|
|
c = *cp;
|
|
|
|
|
|
|
|
while (c >= '0' && c <= '9') {
|
|
|
|
cp++;
|
|
|
|
c = *cp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*cp == '.') {
|
|
|
|
cp++;
|
|
|
|
|
|
|
|
c = *cp;
|
|
|
|
if (c < '0' || c > '9') {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
while (c >= '0' && c <= '9') {
|
|
|
|
cp++;
|
|
|
|
c = *cp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
c = *cp;
|
|
|
|
if (c == 'e' || c == 'E') {
|
|
|
|
cp++;
|
|
|
|
|
|
|
|
c = *cp;
|
|
|
|
if (c == '+' || c == '-') {
|
|
|
|
cp++;
|
|
|
|
}
|
|
|
|
|
|
|
|
c = *cp;
|
|
|
|
if (c < '0' || c > '9') {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
while (c >= '0' && c <= '9') {
|
|
|
|
cp++;
|
|
|
|
c = *cp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|