Page MenuHomePhorge

No OneTemporary

Size
34 KB
Referenced Files
None
Subscribers
None
diff --git a/include/rosa/support/csv/CSVReader.hpp b/include/rosa/support/csv/CSVReader.hpp
index 98970ed..6d5cd25 100755
--- a/include/rosa/support/csv/CSVReader.hpp
+++ b/include/rosa/support/csv/CSVReader.hpp
@@ -1,494 +1,479 @@
//===-- rosa/support/csv/CSVReader.hpp --------------------------*- C++ -*-===//
//
// The RoSA Framework
//
// Distributed under the terms and conditions of the Boost Software License 1.0.
// See accompanying file LICENSE.
//
// If you did not receive a copy of the license file, see
// http://www.boost.org/LICENSE_1_0.txt.
//
//===----------------------------------------------------------------------===//
///
/// \file rosa/support/csv/CSVReader.hpp
///
-/// \authors David Juhasz (david.juhasz@tuwien.ac.at), Edwin Willegger (edwin.willegger@tuwien.ac.at)
+/// \authors David Juhasz (david.juhasz@tuwien.ac.at),
+/// Edwin Willegger (edwin.willegger@tuwien.ac.at)
///
/// \date 2017-2019
///
/// \brief Facitilities to read CSV files.
///
/// \note The implementation is based on the solution at
/// https://stackoverflow.com/a/1120224
///
//===----------------------------------------------------------------------===//
#ifndef ROSA_SUPPORT_CSV_CSVREADER_HPP
#define ROSA_SUPPORT_CSV_CSVREADER_HPP
#include "rosa/support/debug.hpp"
#include "rosa/support/sequence.hpp"
+#include <algorithm>
#include <istream>
-#include <sstream>
-#include <vector>
#include <map>
-#include <algorithm>
#include <set>
+#include <sstream>
+#include <vector>
namespace rosa {
namespace csv {
/// Indicating it the CSV file contains any header or not
-enum class HeaderInformation {
- HasHeader,
- HasNoHeader
-};
+enum class HeaderInformation { HasHeader, HasNoHeader };
/// Anonymous namespace providing implementation details for
/// \c rosa::csv::CSVIterator, consider it private.
namespace {
/// Provides facility for parsing one value from a string.
///
/// \tparam T type of value to parse
/// \tparam IsSignedInt if \p T is a signed integral type, always use default
/// \tparam IsUnsignedInt if \p T is an unsigned integral type, always use
/// default
/// \tparam IsFloat if \p T is a floating-point type, always use default
/// \tparam IsString if \p T is \c std::string, always use default
///
/// \note Specializations of this struct are provided for arithmentic types
/// and \c std::string.
template <typename T,
bool IsSignedInt =
(std::is_integral<T>::value && std::is_signed<T>::value),
bool IsUnsignedInt =
(std::is_integral<T>::value && std::is_unsigned<T>::value),
bool IsFloat = std::is_floating_point<T>::value,
bool IsString = std::is_same<T, std::string>::value>
struct ValueParser {
///
///
/// \param Cell the \c std::string to parse
///
/// \return the parsed value
///
/// \note The function silently fails if cannot parse \p Cell for type \p T.
static T parse(const std::string &Cell) noexcept;
};
-template <typename T>
-struct ValueParser<T, true, false, false, false> {
+template <typename T> struct ValueParser<T, true, false, false, false> {
STATIC_ASSERT((std::is_integral<T>::value && std::is_signed<T>::value),
"wrong type"); // Sanity check.
static T parse(const std::string &Cell) noexcept {
return static_cast<T>(std::stoll(Cell));
}
};
-template <typename T>
-struct ValueParser<T, false, true, false, false> {
+template <typename T> struct ValueParser<T, false, true, false, false> {
STATIC_ASSERT((std::is_integral<T>::value && std::is_unsigned<T>::value),
"wrong type"); // Sanity check.
static T parse(const std::string &Cell) noexcept {
return static_cast<T>(std::stoull(Cell));
}
};
-template <typename T>
-struct ValueParser<T, false, false, true, false> {
+template <typename T> struct ValueParser<T, false, false, true, false> {
STATIC_ASSERT((std::is_floating_point<T>::value),
"wrong type"); // Sanity check.
static T parse(const std::string &Cell) noexcept {
return static_cast<T>(std::stold(Cell));
}
};
-template <typename T>
-struct ValueParser<T, false, false, false, true> {
+template <typename T> struct ValueParser<T, false, false, false, true> {
STATIC_ASSERT((std::is_same<T, std::string>::value),
"wrong type"); // Sanity check.
static T parse(const std::string &Cell) noexcept { return Cell; }
};
/// Parses and stores entries from a row of CSV data.
///
/// \tparam Ts types of values to parse and store, i.e. entries in the row
///
/// \note The implementation relies on \c rosa::csv::CSVRowParser, which is
/// implemented only for `arithmetic` types -- signed and unsigned integral
/// and floating-point types -- and for \c std::string. Those are the valid
/// values for \p Ts.
template <typename... Ts> class CSVRow {
private:
/// Parses a given row of CSV data into \c CSVRow::Data.
///
/// \ CSVRow::Data is filled with values parsed from \p LineStream. Entries
/// in the line are to be separated by commas, the character `,`.
///
/// \note Parsed values are silently converted to types \p Ts.
///
/// \note Parsing silently fails if values do not match \p Ts.
///
/// \tparam S0 indices to access tuple elements.
///
/// \param [in,out] LineStream the line to parse
///
/// \note The last argument is used only to get \p S0, the actual value of
/// the parameter is ignored.
template <size_t... S0>
void parseRow(std::stringstream &LineStream, char Delimiter, Seq<S0...>) {
STATIC_ASSERT(sizeof...(Ts) == sizeof...(S0),
"Not matching template arguments.");
std::string Cell;
// Get fields and parse the values into the proper element of the tuple
// one by one in a fold expression.
((std::getline(LineStream, Cell, Delimiter),
std::get<S0>(Data) = ValueParser<Ts>::parse(Cell)),
...);
-
}
public:
-
/// Constructor with all possible parameters
///
- /// The function creates an instance of an CSVRow object and sets the attributes of the
- /// object to the values of the parameters.
+ /// The function creates an instance of an CSVRow object and sets the
+ /// attributes of the object to the values of the parameters.
///
- /// \param SkipRows the number of data rows to skip, not taking header into account.
- /// \param HeaderInfo is the first line of the file a header row or not.
- /// \param Delimiter to seperate between the data entries within one row.
+ /// \param SkipRows the number of data rows to skip, not taking header into
+ /// account. \param HeaderInfo is the first line of the file a header row or
+ /// not. \param Delimiter to seperate between the data entries within one row.
CSVRow(const size_t SkipRows = 0,
const HeaderInformation HeaderInfo = HeaderInformation::HasHeader,
- const char Delimiter = ',') :
- SkipRows(SkipRows), HeaderInfo(HeaderInfo), Delimiter(Delimiter),
- RowNumber(0), IsHeaderRead(false) {
- }
-
-
+ const char Delimiter = ',')
+ : SkipRows(SkipRows), HeaderInfo(HeaderInfo), Delimiter(Delimiter),
+ RowNumber(0), IsHeaderRead(false) {}
/// Parses and stores one row of CSV data.
///
/// The function reads one line from \p Str and parses it into
/// \c rosa::csv::CSVRow::Data using \c rosa::csv::CSVRowParser.
///
/// \param [in,out] Str input stream of a CSV file
void readNextRow(std::istream &Str) noexcept {
std::string Line;
std::getline(Str, Line);
- if(Line.size() > 0){
- std::stringstream LineStream(Line);
- parseRow(LineStream, Delimiter, seq_t<sizeof...(Ts)>());
+ if (Line.size() > 0) {
+ std::stringstream LineStream(Line);
+ parseRow(LineStream, Delimiter, seq_t<sizeof...(Ts)>());
- RowNumber = RowNumber + 1;
+ RowNumber = RowNumber + 1;
}
-
}
/// Read header row and stores it as \p std::string.
///
/// The function reads the first line of the csv file and stores the entries
/// in a vector.
///
/// \param [in,out] Str input stream of a CSV file
void readHeader(std::istream &Str) noexcept {
- std::string Line;
- std::getline(Str, Line);
- std::stringstream LineStream(Line);
- std::string Value;
+ std::string Line;
+ std::getline(Str, Line);
+ std::stringstream LineStream(Line);
+ std::string Value;
- while( getline(LineStream, Value, Delimiter) ){
- Header.push_back(Value);
- }
+ while (getline(LineStream, Value, Delimiter)) {
+ Header.push_back(Value);
+ }
- IsHeaderRead = true;
+ IsHeaderRead = true;
}
/// The number of rows to skip once.
///
/// This function returns the number of data rows to skip
/// at the beginning of the file.
///
/// \return The number of rows to skip at the beginning of a csv file.
- inline size_t SkipNumRows() const noexcept {
- return this->SkipRows;
- }
+ inline size_t SkipNumRows() const noexcept { return this->SkipRows; }
/// The current row number within the csv file.
///
/// This function returns the current row number. The header
/// row is not counted as a row.
///
/// \returns the current row number within the csv file.
- inline size_t CurRow() const noexcept {
- return this->RowNumber;
- }
+ inline size_t CurRow() const noexcept { return this->RowNumber; }
/// Indiciates if the header was already read.
///
/// This function returns true, if the header of a csv file which contains
/// a header file is already read.
/// The user has to pass in the attribute HeaderInfo the information if the
/// file has in the first row the header row or not.
///
/// \return if the header of a file is already read.
- inline bool IsHeaderReadDone() const noexcept{
- return this->IsHeaderRead;
- }
-
+ inline bool IsHeaderReadDone() const noexcept { return this->IsHeaderRead; }
/// Indicates if the file contains a header row in the first row.
///
/// This function returns if the file contains a header row.
- /// The information if the file contains a header row or not, has to be passed by the user.
- /// The standard value is HeaderInformation::HasHeader
+ /// The information if the file contains a header row or not, has to be passed
+ /// by the user. The standard value is HeaderInformation::HasHeader
///
- /// \return if the csv file contains a header row in the first line of the file.
+ /// \return if the csv file contains a header row in the first line of the
+ /// file.
inline HeaderInformation HasFileHeader() const noexcept {
- return this->HeaderInfo;
+ return this->HeaderInfo;
}
/// Set the number of rows to skip.
///
/// This function sets the number of rows to skip at the beginning of
/// the reading of the file.
///
- /// \param SkipRowsBeginning the number of rows you want to skip at the beginning of the file.
+ /// \param SkipRowsBeginning the number of rows you want to skip at the
+ /// beginning of the file.
inline void SetSkipRows(const size_t SkipRowsBeginning) noexcept {
- this->SkipRows = SkipRowsBeginning;
+ this->SkipRows = SkipRowsBeginning;
}
/// Is the first row a header row or not.
///
/// This function sets the information, if the first row of the csv file
/// is a header line or not.
///
/// \param HeaderInf if the first row is a header row or not.
inline void SetHeaderInfo(const HeaderInformation HeaderInf) noexcept {
- this->HeaderInfo = HeaderInf;
+ this->HeaderInfo = HeaderInf;
}
/// Set the seperator between data entries.
///
- /// This funcction sets the separator between the data entries of the csv file.
+ /// This funcction sets the separator between the data entries of the csv
+ /// file.
///
/// \param separator the character that separates the data values.
- inline void SetDelimiter(char separator) {
- this->Delimiter = separator;
- }
-
-
-
+ inline void SetDelimiter(char separator) { this->Delimiter = separator; }
/// Gives a constant references for the \c std::tuple containing the values
/// read by \p this object.
///
/// \return \c CSVRow::Data
const std::tuple<Ts...> &tuple(void) const noexcept { return Data; }
private:
- std::tuple<Ts...> Data; ///< Stores parsed entries
- size_t SkipRows; ///< The number of rows to skip at the very beginning of the file.
- ///< This number only applies on the number of data rows.
- ///< If your file contains a header row and data rows, the skiping
- ///< of the header row is not taken into account.
- HeaderInformation HeaderInfo; ///< If the file contains a header row or not.
- char Delimiter; ///< The seperator between the data entries.
- size_t RowNumber; ///< Current row number, counts all row numbers including the header row.
- bool IsHeaderRead; ///< Was the header read or not.
- std::vector<std::string> Header; ///< The content of the header row.
-
+ std::tuple<Ts...> Data; ///< Stores parsed entries
+ size_t SkipRows; ///< The number of rows to skip at the very beginning of the
+ ///< file. This number only applies on the number of data
+ ///< rows. If your file contains a header row and data rows,
+ ///< the skiping of the header row is not taken into account.
+ HeaderInformation HeaderInfo; ///< If the file contains a header row or not.
+ char Delimiter; ///< The seperator between the data entries.
+ size_t RowNumber; ///< Current row number, counts all row numbers including
+ ///< the header row.
+ bool IsHeaderRead; ///< Was the header read or not.
+ std::vector<std::string> Header; ///< The content of the header row.
};
/// Reads a row of CSV data into \c rosa::csv::CSVRow.
///
/// The next line is read from \p Str by calling
/// \c rosa::csv::CSVRow::readNextRow on \p Data until all lines are
/// skipped.
///
/// If the function is called for the first time and the file contains
/// a header than is the header and the first data row read in after the
/// number of rows that the user wants to skip.
///
/// \tparam Ts type of values to read from the row
///
/// \note The CSV file should contain a line with fields matching \p Ts...
///
/// \param [in,out] Str input stream of a CSV file
/// \param [in,out] Data object to read the next line into
///
/// \return \p Str after reading one line from it
template <typename... Ts>
std::istream &operator>>(std::istream &Str, CSVRow<Ts...> &Data) {
- if( Data.HasFileHeader() == HeaderInformation::HasHeader && !Data.IsHeaderReadDone() ) {
+ if (Data.HasFileHeader() == HeaderInformation::HasHeader &&
+ !Data.IsHeaderReadDone()) {
Data.readHeader(Str);
}
- while(Data.CurRow() < (Data.SkipNumRows())){
+ while (Data.CurRow() < (Data.SkipNumRows())) {
Data.readNextRow(Str);
}
- //read the lines after you skipped the number of rows you want to skip
+ // read the lines after you skipped the number of rows you want to skip
Data.readNextRow(Str);
return Str;
}
} // End namespace
/// Provides `InputIterator` features for iterating over a CSV file.
///
/// The iterator parses rows into `std::tuple` values and iterates over the
/// file row by row.
///
/// \tparam Ts types of values stored in one row of the CSV file
///
/// \note The iterator expects each row to consists of fields matching \p Ts.
///
/// \note The implementation relies on \c rosa::csv::CSVRow, which in turn
/// relies on \c rosa::csv::CSVRowParser, which is implemented only for
/// `arithmetic` types -- signed and unsigned integral types and floating-point
/// types -- and for \c std::string. Those are the valid values for \p Ts
template <typename... Ts> class CSVIterator {
public:
/// \defgroup CSVIteratorTypedefs Typedefs of rosa::csv::CSVIterator
///
/// Standard `typedef`s for iterators.
///
///@{
typedef std::input_iterator_tag
iterator_category; ///< Category of the iterator.
typedef std::tuple<Ts...> value_type; ///< Type of values iterated over.
typedef std::size_t difference_type; ///< Type to identify distance.
typedef std::tuple<Ts...> *pointer; ///< Pointer to the type iterated over.
typedef std::tuple<Ts...>
&reference; ///< Reference to the type iterated over.
///@}
/// Creates a new instance.
///
/// \param [in,out] S input stream to iterate over
- /// \param SkipRows the number of rows you want to skip only once at the beginning of the file.
- /// If you have an header in the file, it is supposed to be the first row, and it will be always read out.
- /// But after this header the next number of Rows will be skipped.
- /// \param HeaderInfo is used to know wheter the file contains an header row or not.
+ /// \param SkipRows the number of rows you want to skip only once at
+ /// the beginning of the file.
+ /// If you have an header in the file, it is supposed to be
+ /// the first row, and it will be always read out. But after
+ /// this header the next number of Rows will be skipped.
+ /// \param HeaderInfo is used to know wheter the file contains an
+ /// header row or not.
/// The header has to be in the first row.
- /// \param Delimiter is the separator between the differnt values of the csv file.
+ /// \param Delimiter is the separator between the differnt values of
+ /// the csv file.
CSVIterator(std::istream &S, const size_t SkipRows = 0,
const HeaderInformation HeaderInfo = HeaderInformation::HasHeader,
- const char Delimiter = ',') : Str(S.good() ? &S : nullptr),
- SkipRows(SkipRows), HeaderInfo(HeaderInfo), Delimiter(Delimiter), Row(){
+ const char Delimiter = ',')
+ : Str(S.good() ? &S : nullptr), SkipRows(SkipRows),
+ HeaderInfo(HeaderInfo), Delimiter(Delimiter), Row() {
Row.SetSkipRows(SkipRows);
Row.SetHeaderInfo(HeaderInfo);
Row.SetDelimiter(Delimiter);
// \c rosa::csv::CSVIterator::Row is initialized empty so the first
// incrementation here will read the first row.
++(*this);
}
/// Creates an empty new instance.
CSVIterator(void) noexcept
: Str(nullptr), SkipRows(0), HeaderInfo(HeaderInformation::HasHeader),
Delimiter(','), Row() {}
/// Pre-increment operator.
///
/// The implementation reads the next row. If the end of the input stream is
/// reached, the operator becomes empty and has no further effect.
///
/// \return \p this object after incrementing it.
CSVIterator &operator++() {
if (Str) {
if (!((*Str) >> Row)) {
Str = nullptr;
}
}
return *this;
}
/// Post-increment operator.
///
/// The implementation uses the pre-increment operator and returns a copy of
/// the original state of \p this object.
///
/// \return \p this object before incrementing it.
CSVIterator operator++(int) {
CSVIterator Tmp(*this);
++(*this);
return Tmp;
}
/// Returns a constant reference to the current entry.
///
/// \note Should not dereference the iterator when it is empty.
///
/// \return constant reference to the current entry.
const std::tuple<Ts...> &operator*(void)const noexcept { return Row.tuple(); }
/// Returns a constant pointer to the current entry.
///
/// \note Should not dereference the iterator when it is empty.
///
/// \return constant pointer to the current entry.
const std::tuple<Ts...> *operator->(void)const noexcept {
return &Row.tuple();
}
/// Tells if \p this object is equal to another one.
///
/// Two \c rosa::csv::CSVReader instances are equal if and only if they are
/// the same or both are empty.
///
/// \param RHS other object to compare to
///
/// \return whether \p this object is equal with \p RHS
bool operator==(const CSVIterator &RHS) const noexcept {
return ((this == &RHS) || ((this->Str == nullptr) && (RHS.Str == nullptr)));
}
/// Tells if \p this object is not equal to another one.
///
/// \see rosa::csv::CSVReader::operator==
///
/// \param RHS other object to compare to
///
/// \return whether \p this object is not equal with \p RHS.
bool operator!=(const CSVIterator &RHS) const noexcept {
return !((*this) == RHS);
}
/// Set the delimiter used in the csv file.
/// \param Separator the character which separates the values in the csv file.
inline void setDelimiter(char Separator) noexcept {
- this->Delimiter = Separator;
+ this->Delimiter = Separator;
}
/// get the delimiter currently set to separate the values in the csv file.
- /// \return the current character, which is used to separte teh values in the csv file.
- inline char getDelimiter() const noexcept {
- return this->Delimiter;
- }
+ /// \return the current character, which is used to separte teh values in the
+ /// csv file.
+ inline char getDelimiter() const noexcept { return this->Delimiter; }
private:
- std::istream *Str; ///< Input stream of a CSV file to iterate over.
- size_t SkipRows; ///< Number of Rows to skip only once at the beginning of the file.
- HeaderInformation HeaderInfo; ///< does the csv file contain a header or not, if this information is
- ///< not given correclty, the reading of the header would result in
- ///< in an error.
- char Delimiter; ///< Delimiter between the entries in the csv file.
- CSVRow<Ts...> Row; ///< Content of the current row
-
+ std::istream *Str; ///< Input stream of a CSV file to iterate over.
+ size_t SkipRows; ///< Number of Rows to skip only once at the beginning of the
+ ///< file.
+ HeaderInformation
+ HeaderInfo; ///< does the csv file contain a header or not, if this
+ ///< information is not given correclty, the reading of the
+ ///< header would result in in an error.
+ char Delimiter; ///< Delimiter between the entries in the csv file.
+ CSVRow<Ts...> Row; ///< Content of the current row
};
} // End namespace csv
} // End namespace rosa
#endif // ROSA_SUPPORT_CSV_CSVREADER_HPP
diff --git a/include/rosa/support/csv/CSVWriter.hpp b/include/rosa/support/csv/CSVWriter.hpp
index f621cbd..c3766ef 100755
--- a/include/rosa/support/csv/CSVWriter.hpp
+++ b/include/rosa/support/csv/CSVWriter.hpp
@@ -1,227 +1,229 @@
//===-- rosa/support/csv/CSVWriter.hpp --------------------------*- C++ -*-===//
//
// The RoSA Framework
//
// Distributed under the terms and conditions of the Boost Software License 1.0.
// See accompanying file LICENSE.
//
// If you did not receive a copy of the license file, see
// http://www.boost.org/LICENSE_1_0.txt.
//
//===----------------------------------------------------------------------===//
///
/// \file rosa/support/csv/CSVWriter.hpp
///
/// \authors David Juhasz (david.juhasz@tuwien.ac.at)
/// Edwin Willegger (edwin.willegger@tuwien.ac.at)
///
/// \date 2017-2019
///
/// \brief Facitilities to write CSV files.
///
//===----------------------------------------------------------------------===//
#ifndef ROSA_SUPPORT_CSV_CSVWRITER_HPP
#define ROSA_SUPPORT_CSV_CSVWRITER_HPP
#include <iostream>
#include <ostream>
+#include <array>
#include <tuple>
#include <vector>
-#include <array>
#include "rosa/support/log.h"
namespace rosa {
namespace csv {
/// Provides facilities to write values into a CSV file.
///
/// The writer emits a comma, the character `,`, between each written values.
/// The resulted stream is a flat CSV file as it consists of onlyone row, no new
/// line is emitted.
///
/// \tparam T type of values to write
-template <typename T>
-class CSVWriter {
+template <typename T> class CSVWriter {
public:
/// Creates a new instance.
///
/// \param [in,out] S output stream to write to
///
/// \note The writer operates on non-binary outputs as long as \p S is in
/// good state.
CSVWriter(std::ostream &S)
: Str(S.good() && !(S.flags() & std::ios::binary) ? &S : nullptr),
IsFirst(true) {}
/// Tells if the last operation was successful.
///
/// \return if the last operation was successful
- bool good(void) const noexcept {
- return Str != nullptr;
- }
+ bool good(void) const noexcept { return Str != nullptr; }
/// Writes an entry to the output stream.
///
/// The implementation does anything only if the last operation was
/// successful. If so, \p V is written to \c rosa::csv::CSVWriter::Str.
/// The emitted value is preceded with a comma if the actual call is not the
/// first one for \p this object. Success of the operation is checked at the
/// end.
///
/// \param V value to write
void write(const T &V) {
if (Str) {
if (!IsFirst) {
*Str << ',';
} else {
IsFirst = false;
}
*Str << V;
if (!Str->good()) {
Str = nullptr;
}
}
}
private:
std::ostream *Str; ///< Output stream to write to.
bool IsFirst; ///< Denotes if the next write would be the first one.
};
/// Writes a tuple of values into a CSV file
///
/// \tparam Ts types of values to write
template <typename... Ts> class CSVTupleWriter {
public:
+ // typedef <Ts...> value_type ; ///< Type of values written.
+ typedef std::tuple<Ts...> value_type;
-// typedef <Ts...> value_type ; ///< Type of values written.
- typedef std::tuple<Ts...> value_type;
-
- /// Creates a new instance.
- ///
- /// \param [in,out] S output stream to write to
- ///
- /// \note The writer operates on non-binary outputs as long as \p S is in
- /// good state.
- CSVTupleWriter(std::ostream &S)
- : Str(S.good() && !(S.flags() & std::ios::binary) ? &S : nullptr),
- IsHeaderWritten(false), IsDataWritten(false) {}
-
- /// Tells if the last operation was successful.
- ///
- /// \return if the last operation was successful
- bool good(void) const noexcept {
- return Str != nullptr;
- }
+ /// Creates a new instance.
+ ///
+ /// \param [in,out] S output stream to write to
+ ///
+ /// \note The writer operates on non-binary outputs as long as \p S is in
+ /// good state.
+ CSVTupleWriter(std::ostream &S)
+ : Str(S.good() && !(S.flags() & std::ios::binary) ? &S : nullptr),
+ IsHeaderWritten(false), IsDataWritten(false) {}
+ /// Tells if the last operation was successful.
+ ///
+ /// \return if the last operation was successful
+ bool good(void) const noexcept { return Str != nullptr; }
- /// Write the values of a tuple to a CSV file with \c rosa::csv::CSVTupleWriter.
- ///
- /// \see rosa::csv::CSVTupleWriter
- ///
- ///
- /// \param [in,out] values tuple, which values are written in a recusive fashion into a stream.
- template<size_t i = 0>
- void write(const std::tuple<Ts...> &values) {
- constexpr size_t size = sizeof...(Ts);
-
- LOG_TRACE_STREAM << "Writing tuple values into file \n";
- LOG_TRACE_STREAM << " Tuple has " << std::to_string(size) << " elements. \n";
-
- LOG_TRACE_STREAM << " Value is " << std::get<i>(values);
-
- if(Str){
- /// Write the current element of the tuple into the stream and add a separtor after it,
- /// and call the function for the next element in the tuple.
- if constexpr(i+1 != sizeof...(Ts)){
- *Str << std::get<i>(values) << ", ";
- write<i+1>(values);
- /// If the last element is written into the stream than begin a new line.
- }else if constexpr(i + 1 == sizeof...(Ts)){
- *Str << std::get<i>(values) << '\n';
- /// every time the last data value of a line is written, the flag indicates that data was already written into the file.
- IsDataWritten = true;
- }
- }
+ /// Write the values of a tuple to a CSV file with \c
+ /// rosa::csv::CSVTupleWriter.
+ ///
+ /// \see rosa::csv::CSVTupleWriter
+ ///
+ ///
+ /// \param [in,out] values tuple, which values are written in a recusive
+ /// fashion into a stream.
+ template <size_t i = 0> void write(const std::tuple<Ts...> &values) {
+ constexpr size_t size = sizeof...(Ts);
+
+ LOG_TRACE_STREAM << "Writing tuple values into file \n";
+ LOG_TRACE_STREAM << " Tuple has " << std::to_string(size)
+ << " elements. \n";
+
+ LOG_TRACE_STREAM << " Value is " << std::get<i>(values);
+
+ if (Str) {
+ /// Write the current element of the tuple into the stream and add a
+ /// separtor after it, and call the function for the next element in the
+ /// tuple.
+ if constexpr (i + 1 != sizeof...(Ts)) {
+ *Str << std::get<i>(values) << ", ";
+ write<i + 1>(values);
+ /// If the last element is written into the stream than begin a new
+ /// line.
+ } else if constexpr (i + 1 == sizeof...(Ts)) {
+ *Str << std::get<i>(values) << '\n';
+ /// every time the last data value of a line is written, the flag
+ /// indicates that data was already written into the file.
+ IsDataWritten = true;
+ }
}
+ }
- /// Write the header values to a CSV file with \c rosa::csv::CSVTupleWriter.
- ///
- /// \note The function has no effect if anything has already been written
- /// to the output stream either by \c
- /// rosa::csv::CSVTupleWriter::writeHeader() or \c
- /// rosa::csv::CSVTupleWriter::write().
- ///
- /// \see rosa::csv::CSVTupleWriter
- ///
- /// \param header the content of the header line.
- void writeHeader(const std::array<std::string, sizeof...(Ts)> &header){
- size_t index = 0;
- /// write into the stream only, if it is not a nullptr, and if no data and no header was already written into it.
- if(Str && IsDataWritten == false && IsHeaderWritten == false){
- index = 0;
- for (auto i = header.begin(); i != header.end(); ++i){
- index = index + 1;
- /// write into the stream every entry with a delimiter, in this case ", " until
- /// the last entry
- if(index != header.size()){
- *Str << *i << ", ";
- /// write the last entry into the stream, without any delimiter
- }else {
- *Str << *i;
- }
- }
- /// finish the header line and start a new line.
- *Str << '\n';
- /// now it is not possible to write additional header lines.
- IsHeaderWritten = true;
+ /// Write the header values to a CSV file with \c rosa::csv::CSVTupleWriter.
+ ///
+ /// \note The function has no effect if anything has already been written
+ /// to the output stream either by \c
+ /// rosa::csv::CSVTupleWriter::writeHeader() or \c
+ /// rosa::csv::CSVTupleWriter::write().
+ ///
+ /// \see rosa::csv::CSVTupleWriter
+ ///
+ /// \param header the content of the header line.
+ void writeHeader(const std::array<std::string, sizeof...(Ts)> &header) {
+ size_t index = 0;
+ /// write into the stream only, if it is not a nullptr, and if no data and
+ /// no header was already written into it.
+ if (Str && IsDataWritten == false && IsHeaderWritten == false) {
+ index = 0;
+ for (auto i = header.begin(); i != header.end(); ++i) {
+ index = index + 1;
+ /// write into the stream every entry with a delimiter, in this case ",
+ /// " until the last entry
+ if (index != header.size()) {
+ *Str << *i << ", ";
+ /// write the last entry into the stream, without any delimiter
+ } else {
+ *Str << *i;
}
+ }
+ /// finish the header line and start a new line.
+ *Str << '\n';
+ /// now it is not possible to write additional header lines.
+ IsHeaderWritten = true;
}
+ }
private:
- std::ostream *Str; ///< Output stream to write to.
- bool IsHeaderWritten; ///< If an header line was already written into the stream. If set than no additional header could be written.
- bool IsDataWritten; ///< If one line of data has already been written into the stream, than no headerline could be added.
+ std::ostream *Str; ///< Output stream to write to.
+ bool IsHeaderWritten; ///< If an header line was already written into the
+ ///< stream. If set than no additional header could be
+ ///< written.
+ bool IsDataWritten; ///< If one line of data has already been written into the
+ ///< stream, than no headerline could be added.
};
-/// Writes all values of a tuple to a CSV file with \c rosa::csv::CSVTupleWriter.
+/// Writes all values of a tuple to a CSV file with \c
+/// rosa::csv::CSVTupleWriter.
///
/// \see rosa::csv::CSVTupleWriter
///
/// \tparam Ts types of values to write
///
/// \param [in,out] W object to write with
/// \param V values to write
///
/// \return \p W after writing \p V with it
template <typename... Ts>
-CSVTupleWriter<Ts...> &operator<<(CSVTupleWriter<Ts...> &W, const std::tuple<Ts...> &V)
-{
- W.write(V);
- return W;
+CSVTupleWriter<Ts...> &operator<<(CSVTupleWriter<Ts...> &W,
+ const std::tuple<Ts...> &V) {
+ W.write(V);
+ return W;
}
/// Writes a value to a CSV file with \c rosa::csv::CSVWriter.
///
/// \see rosa::csv::CSVWriter
///
/// \tparam T type of value to write
///
/// \param [in,out] W object to write with
/// \param V value to write
///
/// \return \p W after writing \p V with it
-template <typename T>
-CSVWriter<T> &operator<<(CSVWriter<T> &W, const T& V) {
+template <typename T> CSVWriter<T> &operator<<(CSVWriter<T> &W, const T &V) {
W.write(V);
return W;
}
} // End namespace csv
} // End namespace rosa
#endif // ROSA_SUPPORT_CSV_CSVWRITER_HPP

File Metadata

Mime Type
text/x-diff
Expires
Tue, Jul 1, 9:01 PM (2 h, 31 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
157091
Default Alt Text
(34 KB)

Event Timeline