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);
 
   97         inline void prepareStream(std::ostream &os, T 
const &
cell) {
 
   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_) {
 
  151             template <
typename... CellArgs>
 
  154                 std::ostringstream os;
 
  155                 prepareStream(os, c);
 
  157                 commonPostAdd(c.getHeader(), os.str());
 
  163             void commonPreAdd() {
 
  171             void commonPostAdd(std::string 
const &header,
 
  172                                std::string 
const &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>
 
  232         inline CSVRowProxy<Derived> &operator<<(CSVRowProxy<Derived> &row,
 
  233                                                 Cell<CellArgs...> 
const &
cell) {
 
  247     template <
typename Derived> 
class CSVBase : 
public detail::CSVCommonBase {
 
  249         friend class detail::CSVRowProxy<Derived>;
 
  250         using RowProxy = detail::CSVRowProxy<Derived>;
 
  255         RowProxy 
row() { 
return RowProxy(*
this); }
 
  273                               std::string 
const &data) {
 
  274             auto col = getColumn(heading);
 
  275             ensureLatestRowCanHoldColId(col);
 
  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) {
 
  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);
 
  360         friend class CSVBase<StreamCSV>;
 
  372             Base::outputHeaders(m_stream);
 
  380         std::ostream &m_stream;
 
  385         bool m_streaming = 
false;
 
  389         void finalizeLatestRow() {
 
  400     template <
typename T>
 
  406     template <
typename T>
 
  414 #endif // INCLUDED_CSV_h_GUID_30FA2504_8CCF_4B87_71C7_5974F968BC19 
CSVRowProxy & operator=(CSVRowProxy const &)=delete
non-assignable 
void moveLatestRowToData()
utility function for use in derived finalizeLatestRow() 
CSVRowProxy(CSVRowProxy &&other)
move constructible 
void output(std::ostream &os) const 
detail::size< coerce_list< Ts...>> size
Get the size of a list (number of elements.) 
static void prepareStream(std::ostream &)
StreamCSV(std::ostream &os)
void outputData(std::ostream &os) const 
Called by derived classes to output stored data rows. 
void outputRow(std::ostream &os, DataRow const &row) const 
void prepareForRow()
Called by CSVRowProxy life cycle, on row creation. 
void dataForLatestRow(std::string const &heading, std::string const &data)
Called by CSVRowProxy life cycle, on cell addition. 
std::size_t numRows() const 
std::size_t numDataRows() const 
void add(Cell< CellArgs...> const &c)
Truly shared base class for all CSV implementations. 
detail::Cell< T > cell(const char *header, T const &data)
Helper free function to make a CSV cell.