25 #ifndef INCLUDED_CSV_h_GUID_30FA2504_8CCF_4B87_71C7_5974F968BC19 26 #define INCLUDED_CSV_h_GUID_30FA2504_8CCF_4B87_71C7_5974F968BC19 40 #include <type_traits> 41 #include <unordered_map> 46 template <
typename Derived>
class CSVBase;
50 explicit CellBase(
T const &data) : data_(data) {}
53 T const &getData()
const {
return data_; }
62 template <
typename T,
typename HeaderType = std::
string>
class Cell;
66 Cell(std::string
const &header,
T const &data)
67 :
Base(data), header_(header) {}
69 Cell(
const char *header,
T const &data)
70 :
Base(data), header_(header) {}
71 Cell(std::string &&header,
T const &data)
72 :
Base(data), header_(std::move(header)) {}
74 std::string
const &getHeader()
const {
return header_; }
88 std::is_floating_point<T>::value>::type> {
91 os << std::setprecision(std::numeric_limits<T>::digits10 + 1);
98 using DataValueConstType =
99 typename std::remove_reference<decltype(cell.getData())>::type;
100 using DataValueType =
101 typename std::remove_const<DataValueConstType>::type;
103 PrepType::prepareStream(os);
130 : csv_(other.csv_), preparedRow_(other.preparedRow_),
131 active_(other.active_) {
134 other.active_ =
false;
142 if (active_ && preparedRow_) {
143 csv_.finalizeLatestRow();
151 template <
typename... CellArgs>
154 std::ostringstream os;
157 commonPostAdd(c.getHeader(), os.str());
163 void commonPreAdd() {
165 csv_.prepareForRow();
171 void commonPostAdd(std::string
const &header,
172 std::string
const &value) {
173 csv_.dataForLatestRow(header, value);
177 bool preparedRow_ =
false;
182 static const char COMMA[] =
",";
183 static const char DOUBLEQUOTE[] =
"\"";
184 static const char DOUBLEQUOTE_COMMA[] =
"\",";
185 static const char NEWLINE[] =
"\n";
191 using DataRow = std::vector<std::string>;
192 using column_id = std::size_t;
193 column_id getColumn(std::string
const &heading) {
194 auto it = columnsMap_.find(heading);
196 column_id ret = columns_.size();
197 if (end(columnsMap_) != it) {
203 columns_.push_back(heading);
204 columnsMap_.insert(std::make_pair(heading, ret));
207 column_id numColumns()
const {
return columns_.size(); }
210 void outputHeaders(std::ostream &os)
const {
211 for (
auto &colName : columns_) {
212 os << csv::DOUBLEQUOTE << colName << csv::DOUBLEQUOTE_COMMA;
218 std::vector<std::string> columns_;
219 std::unordered_map<std::string, column_id> columnsMap_;
223 template <
typename Derived,
typename... CellArgs>
225 operator<<(CSVRowProxy<Derived> &&row,
Cell<CellArgs...>
const &
cell) {
227 return std::move(row);
231 template <
typename Derived,
typename... CellArgs>
255 RowProxy
row() {
return RowProxy(*
this); }
273 std::string
const &data) {
274 auto col = getColumn(heading);
275 ensureLatestRowCanHoldColId(col);
276 latestRow()[col] = data;
283 derived().finalizeLatestRow();
292 void outputRow(std::ostream &os, DataRow
const &row)
const {
293 for (
auto &
cell : row) {
294 os <<
cell << detail::csv::COMMA;
296 os << detail::csv::NEWLINE;
301 for (
auto &row : data_) {
308 data_.emplace_back(std::move(latestRow()));
313 void ensureLatestRowCanHoldColId(column_id
id) {
314 if (
id >= latestRow().
size()) {
315 latestRow().resize(
id + 1);
320 Derived
const &derived()
const {
321 return *
static_cast<Derived
const *
>(
this);
324 Derived &derived() {
return *
static_cast<Derived *
>(
this); }
325 std::size_t rows_ = 0;
326 std::vector<DataRow> data_;
341 Base::outputHeaders(os);
342 Base::outputData(os);
347 void finalizeLatestRow() { Base::moveLatestRowToData(); }
360 friend class CSVBase<StreamCSV>;
372 Base::outputHeaders(m_stream);
373 outputData(m_stream);
380 std::ostream &m_stream;
385 bool m_streaming =
false;
389 void finalizeLatestRow() {
392 Base::outputRow(m_stream, Base::latestRow());
394 Base::moveLatestRowToData();
400 template <
typename T>
406 template <
typename T>
414 #endif // INCLUDED_CSV_h_GUID_30FA2504_8CCF_4B87_71C7_5974F968BC19 std::size_t numDataRows() const
Gets the number of rows in the internal data storage.
Definition: CSV.h:261
std::size_t numRows() const
Gets the total number of rows that have been streamed/added to this CSV object, whether or not they'r...
Definition: CSV.h:266
Definition: RunLoopManager.h:42
CSVRowProxy(CSVRowProxy &&other)
move constructible
Definition: CSV.h:129
void prepareStream(std::ostream &os, T const &cell)
Invokes the trait to prepare a stream for a data type.
Definition: CSV.h:97
The main namespace for all C++ elements of the framework, internal and external.
Definition: namespace_osvr.dox:3
Definition: TypeSafeIdHash.h:44
Returned by calls to .row() on a CSV object (you'll never need instantiate manually), and only really interacted with using the operator<< and cell() calls.
Definition: CSV.h:112
void dataForLatestRow(std::string const &heading, std::string const &data)
Called by CSVRowProxy life cycle, on cell addition.
Definition: CSV.h:272
RowProxy row()
Main call for the CSV object: returns a proxy object that you can redirect "cells" into...
Definition: CSV.h:255
void finalizeLatestRow()
Called by CSVRowProxy life cycle, on destruction of active row proxy.
Definition: CSV.h:281
detail::size< coerce_list< Ts... >> size
Get the size of a list (number of elements.)
Definition: Size.h:56
static void prepareStream(std::ostream &)
Definition: CSV.h:81
StreamCSV(std::ostream &os)
Constructor.
Definition: CSV.h:366
Utility class used in conjunction with osvr::util::CSV, to store a single table cell's column header ...
Definition: CSV.h:62
Definition: newuoa.h:1888
void output(std::ostream &os) const
Outputs all the stored rows and columns, with the union of all headers in the first row...
Definition: CSV.h:340
void outputRow(std::ostream &os, DataRow const &row) const
Called by outputData() and by derived classes to format individual rows.
Definition: CSV.h:292
(Base) Class for easily outputting CSV files.
Definition: CSV.h:46
void startOutput()
Outputs all the stored rows and columns, with the union of all headers in the first row...
Definition: CSV.h:371
The "traditional" CSV class: get all your data set up ahead of time.
Definition: CSV.h:333
void add(Cell< CellArgs... > const &c)
Main function, used by the operator<< to add your cell to the row in progress.
Definition: CSV.h:152
void prepareForRow()
Called by CSVRowProxy life cycle, on row creation.
Definition: CSV.h:270
~CSVRowProxy()
Destructor - finalizes the row in the CSV object if we've got some data and haven't been moved-from...
Definition: CSV.h:139
DataRow & latestRow()
Called internally and potentially by derived classes for access to the "latest row" temporary storage...
Definition: CSV.h:288
void moveLatestRowToData()
utility function for use in derived finalizeLatestRow()
Definition: CSV.h:307
Truly shared base class for all CSV implementations.
Definition: CSV.h:189
void outputData(std::ostream &os) const
Called by derived classes to output stored data rows.
Definition: CSV.h:300
detail::Cell< T > cell(const char *header, T const &data)
Helper free function to make a CSV cell.
Definition: CSV.h:401
A CSV object taking a reference to an ostream that should remain valid throughout the entire lifetime...
Definition: CSV.h:358