Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F432971
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Size
20 KB
Referenced Files
None
Subscribers
None
View Options
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
Details
Attached
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)
Attached To
Mode
R20 SoC_Rosa_repo
Attached
Detach File
Event Timeline
Log In to Comment