-
Notifications
You must be signed in to change notification settings - Fork 0
/
CSVLogger.cpp
89 lines (73 loc) · 2 KB
/
CSVLogger.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#include "CSVLogger.h"
#include "DataLog.h"
//Some code similar to https://github.com/p-ranav/csv2/blob/master/include/csv2/writer.hpp
using namespace std;
CSVLogger::CSVLogger(std::string filename) : columns(), out_(std::ofstream(filename))
{
columns["timestamp"] = 0;
csvLogThread = std::thread(&CSVLogger::run, this);
}
CSVLogger::~CSVLogger()
{
csvLogThread.join();
out_.close();
}
void CSVLogger::writeHeader() {
streampos pos = out_.tellp();
out_.seekp(0, ios::beg);
vector<string> strings = std::vector<string>(columns.size());
for (const auto& [column, index] : columns) {
strings[index] = column;
}
const auto delimiter_string = std::string(1, ',');
std::copy(strings.begin(), strings.end() - 1,
std::ostream_iterator<std::string>(out_, delimiter_string.c_str()));
out_ << strings.back() << "\n";
out_.seekp(0, ios::end);
}
void CSVLogger::writeRow(DataRow row) {
vector<string> strings = std::vector<string>(columns.size() + row.data.size()+1);
strings[0] = to_string(row.timestamp);
int lastIndex = 0;
bool newColumn = false;
//loop through row.data
for (const auto& [column, value] : row.data) {
if (auto it = columns.find(column); it != columns.end()) {
strings[it->second] = to_string(value);
if (it->second > lastIndex) {
lastIndex = it->second;
}
}
else {
int index = columns.size();
columns[column] = index;
strings[index] = to_string(value);
lastIndex = index;
newColumn = true;
}
}
if (newColumn) {
writeHeader();
}
const auto delimiter_string = std::string(1, ',');
std::copy(strings.begin(), strings.begin() + lastIndex+1,
std::ostream_iterator<std::string>(out_, delimiter_string.c_str()));
out_ << strings.back() << "\n";
if (numRowsBuffered++ > FLUSH_EVERY) {
out_.flush();
numRowsBuffered = 0;
}
}
void CSVLogger::addRow(DataRow row)
{
dataQueue.emplace(row);
}
void CSVLogger::run()
{
while (!DataLog::isDone()) {
DataRow currentRow;
while (this->dataQueue.try_dequeue(currentRow)) {
this->writeRow(currentRow);
}
}
}