Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F332136
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Size
36 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/docs/Issues.rst b/docs/Issues.rst
index 1e5a920..3f2a4b9 100755
--- a/docs/Issues.rst
+++ b/docs/Issues.rst
@@ -1,45 +1,54 @@
==================================================================
Known Issues with the Current Implementation of the RoSA Framework
==================================================================
.. contents::
:local:
TODO
====
* Project logo - `docs/_themes/rosa-theme/static/logo.png`
* License?
* Packaging with
`CPack <https://cmake.org/cmake/help/latest/module/CPack.html>`_.
* What about design documentation on the basics of RoSA?
* What about testing the framework?
Known Issues
============
* CMake
* VS2017 generates intermediate files for the `ZERO_CHECK` project out of the
build directory, see `CMake issue #16458`_.
* C++
* Mangled names of function pointers with non-throwing exception specification
in function signature will change in C++17. That renders binaries generated
with C++14 and C++17 incompatible (for linking).
* Since version 4.0.0, Clang warns about this compatibility issue as part
of `-Wc++1z-compat`. That warning is turned off in the build scripts.
* The langauge standard for building RoSA libraries and applications needs
to be lockstepped: now use C++14 only and step to C++17 later when it is
properly supported by all major compilers.
* Doxygen
* There are some strange warnings reported by doxygen when generating
documentation.
* There are some entities for which no or partial documentation is generated,
but no indication of any problem is reported by doxygen.
+* clang-tidy
+
+ * Clang-tidy reports warnings about `noexcept` marking for the move
+ constructor and move assignment operator of `rosa::Optional` in some
+ situations when the template with the non-specialized argument list is used
+ -- for example, in the file `example/deluxe-interface/deluxe-interface.cpp`.
+ However, the condition for the `noexcept` marking should be met and the
+ warning is pointless.
+
.. _CMake issue #16458: https://gitlab.kitware.com/cmake/cmake/issues/16458
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
index f39a687..276f940 100644
--- a/examples/CMakeLists.txt
+++ b/examples/CMakeLists.txt
@@ -1,7 +1,8 @@
# Add the different subdirectories
add_subdirectory(basic-system)
add_subdirectory(type-facilities)
add_subdirectory(messaging)
add_subdirectory(messaging-system)
add_subdirectory(agent-modules)
+add_subdirectory(deluxe-interface)
diff --git a/examples/deluxe-interface/CMakeLists.txt b/examples/deluxe-interface/CMakeLists.txt
new file mode 100755
index 0000000..7b5017b
--- /dev/null
+++ b/examples/deluxe-interface/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_executable(deluxe-interface deluxe-interface.cpp)
+ROSA_add_library_dependencies(deluxe-interface ROSAConfig)
+ROSA_add_library_dependencies(deluxe-interface ROSADeluxe)
+
diff --git a/examples/deluxe-interface/deluxe-interface.cpp b/examples/deluxe-interface/deluxe-interface.cpp
new file mode 100755
index 0000000..6f3b8e2
--- /dev/null
+++ b/examples/deluxe-interface/deluxe-interface.cpp
@@ -0,0 +1,312 @@
+//===-- examples/deluxe-interface/deluxe-interface.cpp ----------*- C++ -*-===//
+//
+// The RoSA Framework
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file examples/deluxe-interface/deluxe-interface.cpp
+///
+/// \author David Juhasz (david.juhasz@tuwien.ac.at)
+///
+/// \date 2017
+///
+/// \brief A simple example on the \c rosa::deluxe::DeluxeContext and related
+/// classes.
+//===----------------------------------------------------------------------===//
+
+#include "rosa/agent/Abstraction.hpp"
+#include "rosa/agent/Confidence.hpp"
+
+#include "rosa/config/version.h"
+
+#include "rosa/deluxe/DeluxeContext.hpp"
+
+#include "rosa/support/csv/CSVReader.hpp"
+#include "rosa/support/csv/CSVWriter.hpp"
+
+#include <fstream>
+
+using namespace rosa;
+using namespace rosa::agent;
+using namespace rosa::deluxe;
+using namespace rosa::terminal;
+
+/// Paths for the CSV files for simulation.
+///
+///@{
+const std::string HRCSVPath = "HR.csv";
+const std::string BRCSVPath = "BR.csv";
+const std::string SpO2CSVPath = "SpO2.csv";
+const std::string BPSysCSVPath = "BPSys.csv";
+const std::string BodyTempCSVPath = "BodyTemp.csv";
+const std::string ScoreCSVPath = "Score.csv";
+///@}
+
+/// How many cycles of simulation to perform.
+const size_t NumberOfSimulationCycles = 16;
+
+/// Warning levels for abstraction.
+enum WarningScore { No = 0, Low = 1, High = 2, Emergency = 3 };
+
+/// Helper function creating a deluxe agent for pre-processing sensory values.
+///
+/// Received values are first validated for confidence. Values which the
+/// validator does not mark confident are ignored. Confident values are
+/// abstracted into a \c WarningScore value, which is the result of the
+/// processing function.
+///
+/// \note The result, \c WarningScore, is returned as \c uint32_t because
+/// enumeration types are not integrated into built-in types. Hence, a master
+/// to these agents receives its input as \c uint32_t values, and may cast them
+/// to \c WarningScore explicitly.
+///
+/// \tparam T type of values to receive from the sensor
+///
+/// \param C the deluxe context to create the agent in
+/// \param Name name of the new agent
+/// \param CC confidence validator to use
+/// \param A abstraction to use
+///
+/// \return handle for the new agent
+template <typename T>
+AgentHandle createLowLevelAgent(std::unique_ptr<DeluxeContext> &C,
+ const std::string &Name,
+ const Confidence<T> &CC,
+ const Abstraction<T, WarningScore> &A) {
+ using handler = DeluxeAgent::D<uint32_t, T>;
+ using result = Optional<uint32_t>;
+ return C->createAgent(
+ Name, handler([&, Name](std::pair<T, bool> I) -> result {
+ LOG_INFO_STREAM << "\n******\n"
+ << Name << " " << (I.second ? "<New>" : "<Old>")
+ << " value: " << I.first << "\n******\n";
+ return (I.second && CC(I.first)) ? result(A(I.first)) : result();
+ }));
+}
+
+int main(void) {
+ LOG_INFO_STREAM
+ << '\n'
+ << library_string() << " -- " << Color::Red << "deluxe-interface example"
+ << Color::Default << '\n'
+ << Color::Yellow
+ << "CSV files are read from and written to the current working directory."
+ << Color::Default << '\n';
+
+ std::unique_ptr<DeluxeContext> C = DeluxeContext::create("Deluxe");
+
+ //
+ // 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.
+ AgentHandle HRSensor = C->createSensor<int32_t>("HR Sensor");
+ AgentHandle BRSensor = C->createSensor<int32_t>("BR Sensor");
+ AgentHandle SpO2Sensor = C->createSensor<int32_t>("SpO2 Sensor");
+ AgentHandle BPSysSensor = C->createSensor<int32_t>("BPSys Sensor");
+ AgentHandle BodyTempSensor = C->createSensor<float>("BodyTemp Sensor");
+
+ //
+ // Create functionalities.
+ //
+ LOG_INFO("Creating Functionalities for Agents.");
+
+ //
+ // Define confidence validators.
+ //
+ // Lower bounds are inclusive and upper bounds are exclusive.
+
+ Confidence<int32_t> HRConfidence(0, 501);
+ Confidence<int32_t> BRConfidence(0, 301);
+ Confidence<int32_t> SpO2Confidence(0, 101);
+ Confidence<int32_t> BPSysConfidence(0,501);
+ Confidence<float> BodyTempConfidence(-60,
+ nextRepresentableFloatingPoint(50.0f));
+
+ //
+ // Define abstractions.
+ //
+
+ RangeAbstraction<int32_t, WarningScore> HRAbstraction(
+ {{{0, 40}, Emergency},
+ {{40, 51}, High},
+ {{51, 60}, Low},
+ {{60, 100}, No},
+ {{100, 110}, Low},
+ {{110, 129}, High},
+ {{129, 200}, Emergency}},
+ Emergency);
+
+ RangeAbstraction<int32_t, WarningScore> BRAbstraction({{{0, 9}, High},
+ {{9, 14}, No},
+ {{14, 20}, Low},
+ {{20, 29}, High},
+ {{29, 50}, Emergency}},
+ Emergency);
+
+ RangeAbstraction<int32_t, WarningScore> SpO2Abstraction({{{1, 85}, Emergency},
+ {{85, 90}, High},
+ {{90, 95}, Low},
+ {{95, 100}, No}},
+ Emergency);
+
+ RangeAbstraction<int32_t, WarningScore> BPSysAbstraction(
+ {{{0, 70}, Emergency},
+ {{70, 81}, High},
+ {{81, 101}, Low},
+ {{101, 149}, No},
+ {{149, 169}, Low},
+ {{169, 179}, High},
+ {{179, 200}, Emergency}},
+ Emergency);
+
+ RangeAbstraction<float, WarningScore> BodyTempAbstraction(
+ {{{0, 28}, Emergency},
+ {{28, 32}, High},
+ {{32, 35}, Low},
+ {{35, 38}, No},
+ {{38, 39.5}, High},
+ {{39.5, 100}, Emergency}},
+ Emergency);
+
+ //
+ // Create low-level deluxe agents with \c createLowLevelAgent.
+ //
+ LOG_INFO("Creating low-level agents.");
+
+ AgentHandle HRAgent =
+ createLowLevelAgent(C, "HR Agent", HRConfidence, HRAbstraction);
+ AgentHandle BRAgent =
+ createLowLevelAgent(C, "BR Agent", BRConfidence, BRAbstraction);
+ AgentHandle SpO2Agent =
+ createLowLevelAgent(C, "SpO2 Agent", SpO2Confidence, SpO2Abstraction);
+ AgentHandle BPSysAgent =
+ createLowLevelAgent(C, "BPSys Agent", BPSysConfidence, BPSysAbstraction);
+ AgentHandle BodyTempAgent = createLowLevelAgent(
+ C, "BodyTemp Agent", BodyTempConfidence, BodyTempAbstraction);
+
+ //
+ // Connect sensors to low-level agents.
+ //
+ LOG_INFO("Connect sensors to their corresponding low-level agents.");
+
+ C->connectSensor(HRAgent, 0, HRSensor, "HR Sensor Channel");
+ C->connectSensor(BRAgent, 0, BRSensor, "BR Sensor Channel");
+ C->connectSensor(SpO2Agent, 0, SpO2Sensor, "SpO2 Sensor Channel");
+ C->connectSensor(BPSysAgent, 0, BPSysSensor, "BPSys Sensor Channel");
+ C->connectSensor(BodyTempAgent, 0, BodyTempSensor, "BodyTemp Sensor Channel");
+
+ //
+ // Create a high-level deluxe agent.
+ //
+ LOG_INFO("Create high-level agent.");
+
+ // The new agent logs its input values and results in the the sum of them.
+ AgentHandle BodyAgent = C->createAgent(
+ "Body Agent",
+ DeluxeAgent::D<uint32_t, uint32_t, uint32_t, uint32_t, uint32_t,
+ uint32_t>(
+ [](std::pair<uint32_t, bool> HR, std::pair<uint32_t, bool> BR,
+ std::pair<uint32_t, bool> SpO2, std::pair<uint32_t, bool> BPSys,
+ std::pair<uint32_t, bool> BodyTemp) -> Optional<uint32_t> {
+ LOG_INFO_STREAM << "\n*******\nBody Agent trigged with values:\n"
+ << (HR.second ? "<New>" : "<Old>")
+ << " HR warning score: " << HR.first << "\n"
+ << (BR.second ? "<New>" : "<Old>")
+ << " BR warning score: " << BR.first << "\n"
+ << (SpO2.second ? "<New>" : "<Old>")
+ << " SpO2 warning score: " << SpO2.first << "\n"
+ << (BPSys.second ? "<New>" : "<Old>")
+ << " BPSys warning score: " << BPSys.first << "\n"
+ << (BodyTemp.second ? "<New>" : "<Old>")
+ << " BodyTemp warning score: " << BodyTemp.first
+ << "\n******\n";
+ return {HR.first + BR.first + SpO2.first + BPSys.first +
+ BodyTemp.first};
+ }));
+
+ //
+ // Connect low-level agents to the high-level agent.
+ //
+ LOG_INFO("Connect low-level agents to the high-level agent.");
+
+ C->connectAgents(BodyAgent, 0, HRAgent, "HR Agent Channel");
+ C->connectAgents(BodyAgent, 1, BRAgent, "BR Agent Channel");
+ C->connectAgents(BodyAgent, 2, SpO2Agent, "SpO2 Agent Channel");
+ C->connectAgents(BodyAgent, 3, BPSysAgent, "BPSys Agent Channel");
+ C->connectAgents(BodyAgent, 4, BodyTempAgent, "BodyTemp Agent Channel");
+
+ //
+ // For simulation output, create a logger agent writing the output of the
+ // high-level agent into a CSV file.
+ //
+ LOG_INFO("Create a logger agent.");
+
+ // Create CSV writer.
+ std::ofstream ScoreCSV(ScoreCSVPath);
+ csv::CSVWriter<uint32_t> ScoreWriter(ScoreCSV);
+
+ // The agent writes each new input value into a CSV file and produces nothing.
+ AgentHandle LoggerAgent = C->createAgent(
+ "Logger Agent",
+ DeluxeAgent::D<unit_t, uint32_t>(
+ [&ScoreWriter](std::pair<uint32_t, bool> Score) -> Optional<unit_t> {
+ if (Score.second) {
+ // The state of \p ScoreWriter is not checked, expecting good.
+ ScoreWriter << Score.first;
+ }
+ return {};
+ }));
+
+ //
+ // Connect the high-level agent to the logger agent.
+ //
+ LOG_INFO("Connect the high-level agent to the logger agent.");
+
+ C->connectAgents(LoggerAgent, 0, BodyAgent, "Body Agent Channel");
+
+ //
+ // Do simulation.
+ //
+ LOG_INFO("Setting up and performing simulation.");
+
+ //
+ // Initialize deluxe context for simulation.
+ //
+
+ C->initializeSimulation();
+
+ //
+ // Open CSV files and register them for their corresponding sensors.
+ //
+
+ // Type aliases for iterators.
+ using CSVInt = csv::CSVFlatIterator<int32_t>;
+ using CSVFloat = csv::CSVFlatIterator<float>;
+
+ std::ifstream HRCSV(HRCSVPath);
+ C->registerSensorValues(HRSensor, CSVInt(HRCSV), CSVInt());
+
+ std::ifstream BRCSV(BRCSVPath);
+ C->registerSensorValues(BRSensor, CSVInt(BRCSV), CSVInt());
+
+ std::ifstream SpO2CSV(SpO2CSVPath);
+ C->registerSensorValues(SpO2Sensor, CSVInt(SpO2CSV), CSVInt());
+
+ std::ifstream BPSysCSV(BPSysCSVPath);
+ C->registerSensorValues(BPSysSensor, CSVInt(BPSysCSV), CSVInt());
+
+ std::ifstream BodyTempCSV(BodyTempCSVPath);
+ C->registerSensorValues(BodyTempSensor, CSVFloat(BodyTempCSV), CSVFloat());
+
+ //
+ // Simulate.
+ //
+
+ C->simulate(NumberOfSimulationCycles);
+
+ return 0;
+}
diff --git a/include/rosa/support/csv/CSVReader.hpp b/include/rosa/support/csv/CSVReader.hpp
new file mode 100755
index 0000000..cd625b4
--- /dev/null
+++ b/include/rosa/support/csv/CSVReader.hpp
@@ -0,0 +1,373 @@
+//===-- rosa/support/csv/CSVReader.hpp --------------------------*- C++ -*-===//
+//
+// The RoSA Framework
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file rosa/support/csv/CSVReader.hpp
+///
+/// \author David Juhasz (david.juhasz@tuwien.ac.at)
+///
+/// \date 2017
+///
+/// \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 <istream>
+#include <sstream>
+#include <vector>
+
+namespace rosa {
+namespace csv {
+
+/// Anonymous namespace providing implementation details for
+/// \c rosa::csv::CSVIterator, consider it private.
+namespace {
+
+/// Provides facility for parsing values from one row CSV data.
+///
+/// \tparam T type of values to parse from the line
+/// \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 CSVRowParser;
+
+/// Specialization for signed integral types.
+///
+/// \tparam T type of values to parse from the line
+///
+/// \pre \p T is a signed integral type:\code
+/// std::is_integral<T>::value && std::is_signed<T>::value
+/// \code
+template <typename T> struct CSVRowParser<T, true, false, false, false> {
+ STATIC_ASSERT((std::is_integral<T>::value && std::is_signed<T>::value),
+ "wrong type"); // Sanity check.
+
+ /// Parses a given row of CSV data into a given container.
+ ///
+ /// \p Data is cleared and then filled with values parsed from \p LineStream.
+ /// Entries in the line are to be separated by commas, the character `,`. A
+ /// trailing comma results in an empty entry at the end of the line. No empty
+ /// entry should be present otherwise.
+ ///
+ /// \param [in,out] LineStream the line to parse
+ /// \param [in,out] Data the container to store the parsed values
+ static void parse(std::stringstream &LineStream, std::vector<T> &Data) {
+ std::string Cell;
+ Data.clear();
+ while (std::getline(LineStream, Cell, ',')) {
+ Data.push_back(std::stoll(Cell));
+ }
+ // This checks for a trailing comma with no data after it.
+ if (!LineStream && Cell.empty()) {
+ // If there was a trailing comma then add an empty element.
+ Data.push_back(0);
+ }
+ }
+};
+
+/// Specialization for unsigned integral types.
+///
+/// \tparam T type of values to parse from the line
+///
+/// \pre \p T is an unsigned integral type:\code
+/// std::is_integral<T>::value && std::is_unsigned<T>::value
+/// \code
+template <typename T> struct CSVRowParser<T, false, true, false, false> {
+ STATIC_ASSERT((std::is_integral<T>::value && std::is_unsigned<T>::value),
+ "wrong type"); // Sanity check.
+
+ /// Parses a given row of CSV data into a given container.
+ ///
+ /// \p Data is cleared and then filled with values parsed from \p LineStream.
+ /// Entries in the line are to be separated by commas, the character `,`. A
+ /// trailing comma results in an empty entry at the end of the line. No empty
+ /// entry should be present otherwise.
+ ///
+ /// \param [in,out] LineStream the line to parse
+ /// \param [in,out] Data the container to store the parsed values
+ static void parse(std::stringstream &LineStream, std::vector<T> &Data) {
+ std::string Cell;
+ Data.clear();
+ while (std::getline(LineStream, Cell, ',')) {
+ Data.push_back(std::stoull(Cell));
+ }
+ // This checks for a trailing comma with no data after it.
+ if (!LineStream && Cell.empty()) {
+ // If there was a trailing comma then add an empty element.
+ Data.push_back(0);
+ }
+ }
+};
+
+/// Specialization for floating-point types.
+///
+/// \tparam T type of values to parse from the line
+///
+/// \pre \p T is a floating-point type:\code
+/// std::is_floating_point<T>::value
+/// \code
+template <typename T> struct CSVRowParser<T, false, false, true, false> {
+ STATIC_ASSERT((std::is_floating_point<T>::value),
+ "wrong type"); // Sanity check.
+
+ /// Parses a given row of CSV data into a given container.
+ ///
+ /// \p Data is cleared and then filled with values parsed from \p LineStream.
+ /// Entries in the line are to be separated by commas, the character `,`. A
+ /// trailing comma results in an empty entry at the end of the line. No empty
+ /// entry should be present otherwise.
+ ///
+ /// \param [in,out] LineStream the line to parse
+ /// \param [in,out] Data the container to store the parsed values
+ static void parse(std::stringstream &LineStream, std::vector<T> &Data) {
+ std::string Cell;
+ Data.clear();
+ while (std::getline(LineStream, Cell, ',')) {
+ Data.push_back(std::stold(Cell));
+ }
+ // This checks for a trailing comma with no data after it.
+ if (!LineStream && Cell.empty()) {
+ // If there was a trailing comma then add an empty element.
+ Data.push_back(0);
+ }
+ }
+};
+
+/// Specialization for \c std::string.
+///
+/// \tparam T type of values to parse from the line
+///
+/// \pre \p T is \c std::string:\code
+/// std::is_same<T, std::string>::value
+/// \code
+template <typename T> struct CSVRowParser<T, false, false, false, true> {
+ STATIC_ASSERT((std::is_same<T, std::string>::value),
+ "wrong type"); // Sanity check.
+
+ /// Parses a given row of CSV data into a given container.
+ ///
+ /// \p Data is cleared and then filled with values parsed from \p LineStream.
+ /// Entries in the line are to be separated by commas, the character `,`. A
+ /// trailing comma results in an empty entry at the end of the line. No empty
+ /// entry should be present otherwise.
+ ///
+ /// \param [in,out] LineStream the line to parse
+ /// \param [in,out] Data the container to store the parsed values
+ static void parse(std::stringstream &LineStream, std::vector<T> &Data) {
+ std::string Cell;
+ Data.clear();
+ while (std::getline(LineStream, Cell, ',')) {
+ Data.push_back(Cell);
+ }
+ // This checks for a trailing comma with no data after it.
+ if (!LineStream && Cell.empty()) {
+ // If there was a trailing comma then add an empty element.
+ Data.push_back("");
+ }
+ }
+};
+
+/// Parses and stores entries from a row of CSV data.
+///
+/// \tparam T type 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 T.
+template <typename T>
+class CSVRow {
+public:
+ /// Gives a constant reference for an entry at a given position of the row.
+ ///
+ /// \note No bounds checking is performed.
+ ///
+ /// \param Index the position of the entry
+ ///
+ /// \return constant reference for the stored entry at position \p Index
+ const T &operator[](const size_t Index) const noexcept {
+ return Data[Index];
+ }
+
+ /// Tells the number of entries stored in the row.
+ ///
+ /// \return number of stored entries.
+ size_t size(void) const noexcept { return Data.size(); }
+
+ /// 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) {
+ std::string Line;
+ std::getline(Str, Line);
+ std::stringstream LineStream(Line);
+ CSVRowParser<T>::parse(LineStream, Data);
+ }
+
+private:
+ std::vector<T> Data; ///< Stores parsed entries
+};
+
+/// 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.
+///
+/// \note A CSV file should contain no empty lines.
+///
+/// \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 T>
+std::istream &operator>>(std::istream &Str, CSVRow<T> &Data) {
+ Data.readNextRow(Str);
+ return Str;
+}
+
+} // End namespace
+
+/// Provides `InputIterator` features for iterating over a CSV file in a
+/// flat way.
+///
+/// The iterator hides rows of the CSV file, and iterates over the entries
+/// row-by-row.
+///
+/// \note A CSV file should contain no empty lines.
+///
+/// \tparam T type of values to iterate over, i.e. entries in the CSV file.
+///
+/// \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 T.
+template <typename T>
+class CSVFlatIterator {
+public:
+ /// \defgroup CSVIteratorTypedefs
+ ///
+ /// Standard `typedef`s for iterators.
+ ///
+ ///@{
+ typedef std::input_iterator_tag
+ iterator_category; ///< Category of the iterator.
+ typedef T value_type; ///< Type of values iterated over.
+ typedef std::size_t difference_type; ///< Type to identify distance.
+ typedef T *pointer; ///< Pointer to the type iterated over.
+ typedef T &reference; ///< Reference to the type iterated over.
+ ///@}
+
+ /// Creates a new instance.
+ ///
+ /// \param [in,out] S input stream to iterate over
+ CSVFlatIterator(std::istream &S) : Str(S.good() ? &S : nullptr) { ++(*this); }
+
+ /// Creates an empty new instance.
+ CSVFlatIterator(void) noexcept : Str(nullptr) {}
+
+ /// Pre-increment operator.
+ ///
+ /// The implementation moves over the entries in the current row and advances
+ /// to the next row when the end of the current row is reached. 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.
+ CSVFlatIterator &operator++() {
+ if (Pos < Row.size()) {
+ ++Pos;
+ } else if (Str) {
+ if (!((*Str) >> Row)) {
+ Str = nullptr;
+ } else {
+ Pos = 0;
+ }
+ }
+ 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.
+ CSVFlatIterator operator++(int) {
+ CSVFlatIterator 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 T &operator*(void)const noexcept {
+ return Row[Pos];
+ }
+
+ /// 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 T *operator->(void)const noexcept { return &Row[Pos]; }
+
+ /// 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 CSVFlatIterator &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 CSVFlatIterator &RHS) const noexcept {
+ return !((*this) == RHS);
+ }
+
+private:
+ std::istream *Str; ///< Input stream of a CSV file to iterate over.
+ CSVRow<T> Row; ///< Content of the current row iterating over.
+ size_t Pos; ///< Current position within the current row.
+};
+
+} // End namespace csv
+} // End namespace rosa
+
+#endif // ROSA_SUPPOR_CSV_CSVREADER_HPP
diff --git a/include/rosa/support/csv/CSVWriter.hpp b/include/rosa/support/csv/CSVWriter.hpp
new file mode 100755
index 0000000..17046a4
--- /dev/null
+++ b/include/rosa/support/csv/CSVWriter.hpp
@@ -0,0 +1,99 @@
+//===-- rosa/support/csv/CSVWriter.hpp --------------------------*- C++ -*-===//
+//
+// The RoSA Framework
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file rosa/support/csv/CSVWriter.hpp
+///
+/// \author David Juhasz (david.juhasz@tuwien.ac.at)
+///
+/// \date 2017
+///
+/// \brief Facitilities to write CSV files.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef ROSA_SUPPORT_CSV_CSVWRITER_HPP
+#define ROSA_SUPPORT_CSV_CSVWRITER_HPP
+
+#include <ostream>
+
+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 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 [in,out] 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
diff --git a/include/rosa/support/csv/namespace.h b/include/rosa/support/csv/namespace.h
new file mode 100755
index 0000000..85ad49e
--- /dev/null
+++ b/include/rosa/support/csv/namespace.h
@@ -0,0 +1,25 @@
+//===-- rosa/support/csv/namespace.h ----------------------------*- C++ -*-===//
+//
+// The RoSA Framework
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file rosa/support/csv/namespace.h
+///
+/// \author David Juhasz (david.juhasz@tuwien.ac.at)
+///
+/// \date 2017
+///
+/// \brief Documentation for the namespace \c rosa::csv.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef ROSA_SUPPORT_CSV_NAMESPACE_H
+#define ROSA_SUPPORT_CSV_NAMESPACE_H
+
+namespace rosa {
+/// Provides facilities to work with CSV files.
+namespace csv {}
+} // End namespace rosa
+
+#endif // ROSA_SUPPORT_CSV_NAMESPACE_H
diff --git a/include/rosa/support/math.hpp b/include/rosa/support/math.hpp
index 768079f..f88a13d 100644
--- a/include/rosa/support/math.hpp
+++ b/include/rosa/support/math.hpp
@@ -1,35 +1,57 @@
//===-- rosa/support/math.hpp -----------------------------------*- C++ -*-===//
//
// The RoSA Framework
//
//===----------------------------------------------------------------------===//
///
/// \file rosa/support/math.hpp
///
/// \author David Juhasz (david.juhasz@tuwien.ac.at)
///
/// \date 2017
///
/// \brief Math helpers.
///
//===----------------------------------------------------------------------===//
#ifndef ROSA_SUPPORT_MATH_HPP
#define ROSA_SUPPORT_MATH_HPP
+#include <cmath>
#include <cstdlib>
+#include <limits>
+#include <type_traits>
namespace rosa {
/// Computes log base 2 of a number.
///
/// \param N the number to compute log base 2 for
///
/// \return log base 2 of \p N
constexpr size_t log2(const size_t N) {
return ((N < 2) ? 1 : 1 + log2(N / 2));
}
+/// Tells the next representable floating point value.
+///
+/// \tparam T type to operate on
+///
+/// \note The second type argument enforces \p T being a floating point type,
+/// always use the default value!
+///
+/// \param V value to which find the next representable one
+///
+/// \return the next representable value of type \p T after value \p V
+///
+/// \pre Type \p T must be a floating point type, which is enforced by
+/// `std::enable_if` in the second type argument.
+template <typename T,
+ typename = std::enable_if_t<std::is_floating_point<T>::value>>
+T nextRepresentableFloatingPoint(const T V) {
+ return std::nextafter(V, std::numeric_limits<T>::infinity());
+}
+
} // End namespace rosa
#endif // ROSA_SUPPORT_MATH_HPP
diff --git a/lib/support/CMakeLists.txt b/lib/support/CMakeLists.txt
index 1a7ea9b..6e191ef 100644
--- a/lib/support/CMakeLists.txt
+++ b/lib/support/CMakeLists.txt
@@ -1,32 +1,38 @@
set(LIB_INCLUDE_DIR ${ROSA_MAIN_INCLUDE_DIR}/rosa/support)
add_library(ROSASupport
${LIB_INCLUDE_DIR}/debug.hpp
debug.cpp
${LIB_INCLUDE_DIR}/terminal_colors.h
terminal_colors.cpp
${LIB_INCLUDE_DIR}/log.h
log.cpp
${LIB_INCLUDE_DIR}/math.hpp
math.cpp
${LIB_INCLUDE_DIR}/type_helper.hpp
type_helper.cpp
${LIB_INCLUDE_DIR}/types.hpp
types.cpp
${LIB_INCLUDE_DIR}/atom.hpp
atom.cpp
${LIB_INCLUDE_DIR}/type_pair.hpp
type_pair.cpp
${LIB_INCLUDE_DIR}/type_list.hpp
type_list.cpp
${LIB_INCLUDE_DIR}/squashed_int.hpp
squashed_int.cpp
${LIB_INCLUDE_DIR}/type_numbers.hpp
type_numbers.cpp
${LIB_INCLUDE_DIR}/type_token.hpp
type_token.cpp
${LIB_INCLUDE_DIR}/tokenized_storages.hpp
tokenized_storages.cpp
${LIB_INCLUDE_DIR}/sequence.hpp
sequence.cpp
+ ${LIB_INCLUDE_DIR}/csv/namespace.h
+ csv/namespace.cpp
+ ${LIB_INCLUDE_DIR}/csv/CSVReader.hpp
+ csv/CSVReader.cpp
+ ${LIB_INCLUDE_DIR}/csv/CSVWriter.hpp
+ csv/CSVWriter.cpp
)
diff --git a/lib/support/csv/CSVReader.cpp b/lib/support/csv/CSVReader.cpp
new file mode 100755
index 0000000..bf055fb
--- /dev/null
+++ b/lib/support/csv/CSVReader.cpp
@@ -0,0 +1,20 @@
+//===-- support/csv/CSVReader.cpp -------------------------------*- C++ -*-===//
+//
+// The RoSA Framework
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file support/csv/CSVReader.cpp
+///
+/// \author David Juhasz (david.juhasz@tuwien.ac.at)
+///
+/// \date 2017
+///
+/// \brief Implementation for rosa/support/csv/CSVReader.hpp.
+///
+/// \note Empty implementation, source file here to have a compile database
+/// entry for rosa/support/csv/CSVReader.hpp.
+///
+//===----------------------------------------------------------------------===//
+
+#include "rosa/support/csv/CSVReader.hpp"
diff --git a/lib/support/csv/CSVWriter.cpp b/lib/support/csv/CSVWriter.cpp
new file mode 100755
index 0000000..4310703
--- /dev/null
+++ b/lib/support/csv/CSVWriter.cpp
@@ -0,0 +1,20 @@
+//===-- support/csv/CSVWriter.cpp -------------------------------*- C++ -*-===//
+//
+// The RoSA Framework
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file support/csv/CSVWriter.cpp
+///
+/// \author David Juhasz (david.juhasz@tuwien.ac.at)
+///
+/// \date 2017
+///
+/// \brief Implementation for rosa/support/csv/CSVWriter.hpp.
+///
+/// \note Empty implementation, source file here to have a compile database
+/// entry for rosa/support/csv/CSVWriter.hpp.
+///
+//===----------------------------------------------------------------------===//
+
+#include "rosa/support/csv/CSVWriter.hpp"
diff --git a/lib/support/csv/namespace.cpp b/lib/support/csv/namespace.cpp
new file mode 100755
index 0000000..744e6c1
--- /dev/null
+++ b/lib/support/csv/namespace.cpp
@@ -0,0 +1,20 @@
+//===-- support/csv/namespace.cpp -------------------------------*- C++ -*-===//
+//
+// The RoSA Framework
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file support/csv/namespace.cpp
+///
+/// \author David Juhasz (david.juhasz@tuwien.ac.at)
+///
+/// \date 2017
+///
+/// \brief Placeholder for rosa/support/csv/namespace.h.
+///
+/// \note Empty implementation, source file here to have a compile database
+/// entry for rosa/support/csv/namespace.h.
+///
+//===----------------------------------------------------------------------===//
+
+#include "rosa/support/csv/namespace.h"
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sat, Mar 15, 3:08 PM (1 d, 1 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
129088
Default Alt Text
(36 KB)
Attached To
Mode
R20 SoC_Rosa_repo
Attached
Detach File
Event Timeline
Log In to Comment