Page MenuHomePhorge

No OneTemporary

Size
20 KB
Referenced Files
None
Subscribers
None
diff --git a/examples/CSVFiles/main.cpp b/examples/CSVFiles/main.cpp
index bd8b61b..f57c01c 100644
--- a/examples/CSVFiles/main.cpp
+++ b/examples/CSVFiles/main.cpp
@@ -1,345 +1,350 @@
//===-- examples/CSVFiles/main.cpp ------------------*- C++ -*-===//
//
// The RoSA Framework
//
//===----------------------------------------------------------------------===//
///
/// \file examples/basic-system/basic-system.cpp
///
/// \author Edwin Willegger (edwin.willegger@tuwien.ac.at)
///
/// \date 2019
///
/// \brief A simple example on the basic \c rosa::csv, \c rosa::iterator and
/// \c rosa::writer classes. Focus is on the tuple impementations.
///
//===----------------------------------------------------------------------===//
#include <cstdint>
#include <cstddef>
#include <iostream>
#include <istream>
#include <sstream>
#include <fstream>
#include <ostream>
#include <string>
#include <vector>
#include <typeinfo>
#include <map>
#include <algorithm>
#include <tuple>
#include <type_traits>
#include <unistd.h>
//includes for an complete example to read and write
//with sensors and agents.
#include "rosa/deluxe/DeluxeContext.hpp"
#include "rosa/config/version.h"
//includes to test the basic functionality
//to read and write tuples.
#include "rosa/support/csv/CSVReader.hpp"
#include "rosa/support/csv/CSVWriter.hpp"
#include "rosa/support/iterator/split_tuple_iterator.hpp"
#include "rosa/support/writer/split_tuple_writer.hpp"
/// the name of the example
const std::string ExampleName = "csvfiles";
/// How many cycles of simulation to perform.
const size_t NumberOfSimulationCycles = 10;
/// Paths for the CSV files for simulation.
/// input csv files
const std::string csvPath = "../examples/CSVFiles/";
const std::string csvFileWithHeader = csvPath + "HR-New.csv";
const std::string csvFileNoHeader = csvPath + "HR.csv";
const std::string csvFileHeaderSemi = csvPath + "HR-New-Semicolon.csv";
/// output csv files
const std::string csvFileWriteHea = csvPath + "csvwriter_noheader.csv";
const std::string csvFileWriteNoHeaSplit = csvPath + "csvSplitwriter_noheader.csv";
using namespace rosa;
///
/// This function tests the basic CSVIterator capablities, and shows you
/// how you could work with this class.
///
void testtupleCSVReader(void){
//different streams to get the csv data out of the files
//file contains header and valid data entries, delimter = ','
std::ifstream file_header_data(csvFileWithHeader);
//file contains header and valid data entries, delimter = ','
std::ifstream file_header_data_2(csvFileWithHeader);
//file contains header and valid data entries, delimter = ','
std::ifstream file_header_data_3(csvFileWithHeader);
//file contains header and valid data entries, delimter = ','
std::ifstream file_header_data_4(csvFileWithHeader);
//file contains header and valid data entries, delimter = ','
std::ifstream file_header_data_5(csvFileWithHeader);
//file contains header and valid data entries, delimter = ','
std::ifstream file_header_data_6(csvFileWithHeader);
//file contains no header an valid data entries, delimter = ','
std::ifstream file2(csvFileNoHeader);
//file contains header and valid data entries, delimter = ';'
std::ifstream file3(csvFileHeaderSemi);
csv::CSVIterator<int, std::string, std::string, int, int> it(file_header_data);
it.setDelimeter(',');
it++;
it++;
//if you iterate over the end of file, the last values
//of the file will remain in the data structure but no
//error occurs.
it++;
it++;
//-------------------------------------------------------------------
// a possiblity to get the data out of the iterator
std::tuple<int, std::string, std::string, int, int> value = *it;
//
// Show the value of one iterator
//
LOG_INFO( "Values are: ");
LOG_INFO(std::get<0>(value) );
LOG_INFO(std::get<1>(value) );
//--------------------------------------------------------------------
//testing differnet parameters to the constructor
//uncomment to see that it is not possible to iterate over an vector in the tuple.
//rosa::csv::CSVIterator<double, std::vector<int>> it2(file, 1);
//try to skip a valid number of lines after the header
csv::CSVIterator<double, float, int, int, float> it2_0(file_header_data_2, 1);
//try to skip a valid number of lines after the header, but you assume that the file has no header
//uncomment this line to crash the programm
//csv::CSVIterator<double, float, int, int, float> it2_1(file_header_data_3, 0, csv::HeaderInformation::HasNoHeader);
//try to skip a valid number of lines after the header, but you assume that the file has no header
//uncomment this line to crash the program
//csv::CSVIterator<double, float, int, int, float> it2_2(file_header_data_4, 1, csv::HeaderInformation::HasNoHeader);
//try to skip a valid number of lines of a file without header
csv::CSVIterator<double, float, int, int, float> it2_3(file2, 1, csv::HeaderInformation::HasNoHeader);
//try to skip a valid number of lines after the header, but with different delimeter
csv::CSVIterator<double, float, int, int, float> it2_4(file3, 2, csv::HeaderInformation::HasHeader, ';');
// if you skip more lines than valid, you generate an infinte loop
//csv::CSVIterator<double, float, int, int, float> it3(file_header_data_5, 500);
//if you don't need data from all columns just select the number of columns you
//need. You get the data back from the first column (index 0) to the fourth column
//all values from the fifth column are ignored.
csv::CSVIterator<double, float, int, float> it4(file_header_data_6);
}
///
/// This function tests the basic CSVTupleWriter capablities, and shows you
/// how you could work with this class.
///
void testtupleCSVWriter(void){
//
// Create output writer with an file
//
std::ofstream file_header_out(csvFileWriteHea);
csv::CSVTupleWriter<int, float, std::string> wri(file_header_out);
//
// Create test tuples
//
std::tuple<int, float, std::string> values(5, 8.3, "hallo");
std::tuple<int, float, std::string> values2(3, 8.3, "end");
//
// Create test header lines for the test tuples
//
std::array<std::string, 3> header {"zero column", "first column", "second column"};
std::array<std::string, 4> headerWrong {"zero column", "first column", "second column", "third column"};
std::array<std::string, 2> headerWrongShort {"zero column", "first column"};
+ //if you uncomment this line than it would be possible for you to write the header into the stream
+ //in the next line.
+ //wri.write(values);
wri.writeHeader(header);
wri.write(values);
wri.write(values);
+ // it is not possible to write an additional header into the stream.
+ wri.writeHeader(header);
wri.write(values);
wri << values;
wri << values2;
//uncomment this line to see, that you can't write a header with the too many elements.
//wri.writeHeader(headerWrong);
//uncomment this line to see, that you can't write a header with the too few elements.
//wri.writeHeader(headerWrongShort);
}
///
/// This function tests the basic splitTupleIterator capablities, and shows you
/// how you could work with this class, this class is used if you want to split
/// a CSVIterator in separate parts.
///
void testsplitTupleIterator(void)
{
//
// Create deluxe context
//
std::unique_ptr<rosa::deluxe::DeluxeContext> C =
deluxe::DeluxeContext::create(ExampleName);
//
// Create deluxe sensors.
//
LOG_INFO("Creating sensors.");
// All sensors are created without defining a normal generator function, but
// with the default value of the second argument. That, however, requires the
// data type to be explicitly defined. This is good for simulation only.
// Three different sensors were created, this is just a random number taken.
AgentHandle Elem0Sensor = C->createSensor<int>("Element1 Sensor");
AgentHandle Elem1Sensor = C->createSensor<float>("Element2 Sensor");
AgentHandle Elem2Sensor = C->createSensor<std::string>("Element3 Sensor");
//
// Initialize deluxe context for simulation.
//
C->initializeSimulation();
// Type aliases for iterators
using Iterator = rosa::csv::CSVIterator<int, float, std::string>;
using IteratorValue = std::tuple<int, float, std::string>;
static_assert (std::is_same<typename Iterator::value_type, IteratorValue>::value, "Iterator must provide tuples" );
//
// Open CSV file and register the columns to the corresponding sensors.
//
std::ifstream TestCSV(csvFileWithHeader);
//
// Test data looks like:
// Element1, Element2, Element3, Element4, Element5 -- is the header line
// 3, 5, 8, 9.5, 17 -- first line of values
// 100, -8, 30, 18.8, 29 -- other line of values were also in the file
// 5, 20, -100, -200.1, -30 -- if you have less number of values than simulation rounds all values
// -- beyond your last value will be zero.
//get element iterator ranges
auto [Elem0Range, Elem1Range, Elem2Range] = iterator::splitTupleIterator(Iterator(TestCSV), Iterator());
//dissect ranges into begin and end iterators by structred bindings
auto[Elem0Begin, Elem0End] = Elem0Range;
auto[Elem1Begin, Elem1End] = Elem1Range;
auto[Elem2Begin, Elem2End] = Elem2Range;
C->registerSensorValues(Elem0Sensor, std::move(Elem0Begin), Elem0End);
C->registerSensorValues(Elem1Sensor, std::move(Elem1Begin), Elem1End);
C->registerSensorValues(Elem2Sensor, std::move(Elem2Begin), Elem2End);
//
// Simulate.
//
C->simulate(NumberOfSimulationCycles);
}
///
/// This function tests the basic splitTupleWriter capablities, and shows you
/// how you could work with this class, this class is used if you want to split
/// a CSVWriter in separate parts.
///
void testsplitTupleWriter(void){
//
// Create output writer with an file
//
std::ofstream file_header_out(csvFileWriteNoHeaSplit);
csv::CSVTupleWriter<int, float, std::string> wri(file_header_out);
// if you omit, the type definition in the template, than auto generated types were used,
// and they may not fit to the used CSVTupleWriter.
wri << std::make_tuple<int, float, std::string>(1000, 50.6, "tuple_created");
auto [T0Writer, T1Writer, T2Writer] = writer::splitTupleWriter(std::move(wri),
writer::IncompleteTuplePolicy::Ignore);
//writing elements in sequential order into the writer classes, but you can write the values into the writers in
//a random order.
T0Writer << (500);
T1Writer << (3.0);
T2Writer << "splitted writter";
T2Writer << "splitting is cool";
T0Writer << (-30);
T1Writer << (-0.004);
// you can also write more often values into a writer and later into the other writers
// all data will be processed correctly into the right order.
T0Writer << (1);
T0Writer << (2);
T1Writer << (-0.4);
T0Writer << (3);
T2Writer << "again";
T0Writer << (4);
T1Writer << (-0.1);
T1Writer << (-0.2);
T2Writer << "and";
T1Writer << (-0.3);
T2Writer << "splitting";
T2Writer << "once again";
// again writing data of one tuple entry to the different writers in a random fashion.
T1Writer << (-0.004);
T2Writer << "splitting is cool";
T0Writer << (-30);
}
int main(void){
LOG_INFO_STREAM << library_string() << " -- " << terminal::Color::Red
<< ExampleName << " example" << terminal::Color::Default << '\n';
//
// Testing CSVWriter.
//
LOG_INFO("Testing CSVWriter CSVTupleItrator implementation: ");
testtupleCSVWriter();
//
// Testing CSVReader.
//
LOG_INFO("Testing CSVReader CSVTupleIterator implementation: ");
testtupleCSVReader();
//
// Testing SplitTupleIterator.
//
LOG_INFO("Testing SplitTupleIterator: ");
testsplitTupleIterator();
//
// Testing SplitTupleWriter.
//
LOG_INFO("Testing SplitTupleWriter: ");
testsplitTupleWriter();
//
// info that user knows programm has finished.
//
LOG_INFO( "All tests finished.");
return 0;
}
diff --git a/include/rosa/support/csv/CSVWriter.hpp b/include/rosa/support/csv/CSVWriter.hpp
index 3ee9b6d..8fc2eed 100755
--- a/include/rosa/support/csv/CSVWriter.hpp
+++ b/include/rosa/support/csv/CSVWriter.hpp
@@ -1,215 +1,218 @@
//===-- rosa/support/csv/CSVWriter.hpp --------------------------*- C++ -*-===//
//
// The RoSA Framework
//
//===----------------------------------------------------------------------===//
///
/// \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 <tuple>
#include <vector>
#include <array>
-#include "../log.h"
+#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 {
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;
}
/// 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;
/// 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) {}
+ : 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);
- std::string message = "";
- LOG_TRACE("Writing tuple values into file \n");
- message = " Tuple has " + std::to_string(size) + " elements. \n";
- LOG_TRACE(message);
+ LOG_TRACE_STREAM << "Writing tuple values into file \n";
+ LOG_TRACE_STREAM << " Tuple has " << std::to_string(size) << " elements. \n";
- message = " Value is ";
- LOG_TRACE(message);
- LOG_TRACE(std::get<i>(values));
+ 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.
///
/// \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.
- if(Str){
+ /// 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 delimeter, in this case ", " until
/// the last entry
if(index != header.size()){
*Str << *i << ", ";
/// write the last entry into the stream, without any delimeter
}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.
+ 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.
///
/// \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;
}
/// 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) {
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
Wed, Sep 10, 10:28 AM (4 h, 37 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
179327
Default Alt Text
(20 KB)

Event Timeline