Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F376148
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Size
45 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/include/rosa/support/csv/CSVWriter.hpp b/include/rosa/support/csv/CSVWriter.hpp
index 574806b..1c06bbb 100755
--- a/include/rosa/support/csv/CSVWriter.hpp
+++ b/include/rosa/support/csv/CSVWriter.hpp
@@ -1,152 +1,161 @@
//===-- 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 <iostream>
#include <ostream>
#include <tuple>
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:
+ /// \defgroup CSVWriterTypedefs Typedefs of rosa::csv::CSVWriter
+ ///
+ /// Useful `typedef`s for writers.
+ ///
+ ///@{
+ typedef T value_type; ///< Type of values written
+ typedef T &reference; ///< Reference to the type written
+ ///@}
+
/// 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 tpyes of values to write
template <typename... Ts> class CSVTupleWriter {
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.
CSVTupleWriter(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;
}
template<size_t i = 0>
void write(std::tuple<Ts...> values) {
size_t size = 0;
std::cout << "Writing tuple values into file" << std::endl;
std::cout << "Tuple has ";
std::cout << std::tuple_size<decltype (values)>::value;
std::cout << " elements." << std::endl;
size = std::tuple_size<decltype (values)>::value;
std::cout << std::get<i>(values) << std::endl;
if(Str){
if constexpr(i+1 != sizeof...(Ts)){
*Str << std::get<i>(values) << " ,";
write<i+1>(values);
}else if constexpr(i + 1 == sizeof...(Ts)){
*Str << std::get<i>(values) << '\n';
}
}
}
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 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/iterator/split_tuple_iterator.hpp b/include/rosa/support/iterator/split_tuple_iterator.hpp
index f64b346..3d1b9e9 100644
--- a/include/rosa/support/iterator/split_tuple_iterator.hpp
+++ b/include/rosa/support/iterator/split_tuple_iterator.hpp
@@ -1,427 +1,431 @@
//===-- rosa/support/iterator/split_tuple_iterator.hpp ----------*- C++ -*-===/
//
// The RoSA Framework
//
//===----------------------------------------------------------------------===/
///
/// \file rosa/support/iterator/split_tuple_iterator.hpp
///
/// \authors David Juhasz (david.juhasz@tuwien.ac.at)
///
/// \date 2019
///
/// \brief Facilities to split iterators of \c std::tuple into iterators of
/// their elements.
///
//===----------------------------------------------------------------------===/
#ifndef ROSA_SUPPORT_ITERATOR_SPLIT_TUPLE_ITERATOR_HPP
#define ROSA_SUPPORT_ITERATOR_SPLIT_TUPLE_ITERATOR_HPP
#include "rosa/support/debug.hpp"
#include "rosa/support/sequence.hpp"
#include <memory>
#include <tuple>
#include <type_traits>
#include <queue>
namespace rosa {
namespace iterator {
/// Anonymous namespace providing implementation for splitting tuple iterators;
/// consider it private.
namespace {
/// Iterator of values provided by a buffer based on an index
///
/// \tparam TB buffer providing values to iterate
/// \tparam I index of the values to iterator from \p TB
///
/// \note \p TB is expected to implemnet an interface matching that of \c
/// TupleIteratorBuffer.
template <typename TB, size_t I>
class SplittedElementIterator {
public:
/// Type alias for the values the iterator iterates.
using T = typename TB::template element_type<I>;
/// \defgroup SplittedElementIteratorTypedefs Typedefs of
/// \c SplittedElementIterator
///
/// 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 ver.
///@}
/// Creates a new instance.
///
/// \param Buffer buffer providing values for \p this object
///
/// \note \p Buffer is captured as a \c std::shared_ptr because it is shared
/// among iterators for its element positions.
SplittedElementIterator(std::shared_ptr<TB> Buffer)
: Buffer(Buffer), Value() {
// \c Value is initialized empty so the first incrementation here will read
// the first value.
++(*this);
}
/// Creates an empty new instance.
SplittedElementIterator(void) noexcept : Buffer(), Value() {}
/// Pre-increment operator.
///
/// The implementation reads the next value from \c Buffer. If no more values
/// can be provided by \c Buffer, \p this object becomes empty and the
/// operator has no further effect.
///
/// \return \p this object after incrementing it.
SplittedElementIterator &operator++() {
if (Buffer->template hasMore<I>()) {
Value = Buffer->template next<I>();
} else {
// Reached end of range, remove reference of \c Buffer.
Buffer.reset();
}
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.
SplittedElementIterator operator++(int) {
SplittedElementIterator<TB, I> Tmp(*this);
++(*this);
return Tmp;
}
/// Returns a constant reference to the current value.
///
/// \note Should not dereference the iterator when it is empty.
///
/// \return constant reference to the current value.
const T &operator*(void)const noexcept { return Value; }
/// Returns a constant pointer to the current value.
///
/// \note Should not dereference the iterator when it is empty.
///
/// \return constant pointer to the current value.
const T *operator->(void)const noexcept { return &Value; }
/// Tells if \p this object is equal to another one.
///
/// Two \c SplittedElementIterator 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 SplittedElementIterator &RHS) const noexcept {
return ((this == &RHS) || (!Buffer && !RHS.Buffer));
}
/// Tells if \p this object is not equal to another one.
///
/// \see SplittedElementIterator::operator==
///
/// \param RHS other object to compare to
///
/// \return whether \p this object is not equal with \p RHS.
bool operator!=(const SplittedElementIterator &RHS) const noexcept {
return !((*this) == RHS);
}
private:
std::shared_ptr<TB> Buffer; ///< Buffer providing values for \p this object
T Value; ///< The current value of the iterator
};
///\defgroup TupleBufferContainer Type converter turning a \c std::tuple of
///types into a \c std::tuple of container of those types.
///
/// The new type is used for buffering elements of tuples separately.
///
///@{
/// Template declaration.
///
/// \tparam T type to convert
///
/// \note The template is defined only when \p T is a \c std::tuple.
///
/// Usage for a type \c Tuple as:\code
/// typename TupleBufferContainer<Tuple>::Type
/// \endcode
template <typename T> struct TupleBufferContainer;
/// Template definition for \c std::tuple.
template <typename... Ts> struct TupleBufferContainer<std::tuple<Ts...>> {
/// The converted type.
using Type = std::tuple<std::queue<Ts>...>;
};
///@}
/// Convenience template type alias for easy use of \c TupleBufferContainer.
///
/// Converts a \c std::tuple of types into a \c std::tuple of container of those
/// types.
///
/// \tparam Tuple type to convert
template <typename Tuple>
using tuple_buffer_container_t = typename TupleBufferContainer<Tuple>::Type;
/// Buffer for element values for iterator of \c std::tuple.
///
/// The class can be instantiated with a range of iterator of \c std::tuple and
/// provides an interface for accessing elements of the iterated tuples one by
/// one.
///
/// \note The class is utilized by \c SplittedElementIterator.
///
/// \tparam TupleIterator the iterator type that provides values of \c
/// std::tuple
///
/// \todo Consider thread safety of the class.
template <typename TupleIterator>
class TupleIteratorBuffer {
public:
/// Type alias for the value type of \p TupleIterator.
/// \note The type is expected to be \c std::tuple.
using iterator_value_type = typename TupleIterator::value_type;
/// The number of elements of \c iterator_value_type.
static constexpr size_t iterator_value_size =
std::tuple_size_v<iterator_value_type>;
/// Template type alias to get element types of \c iterator_value_type by
/// index.
/// \tparam I the index of the element
template <size_t I>
using element_type =
typename std::tuple_element<I, iterator_value_type>::type;
+ /// Type alias for index sequence for accessing elements of \c
+ /// iterator_value_type.
+ using element_idx_seq_t = seq_t<iterator_value_size>;
+
/// Creates a new instance.
///
/// \param Begin the beginning of the iterator range to buffer
/// \param End the end of the iterator range to buffer
TupleIteratorBuffer(TupleIterator &&Begin, const TupleIterator &End) noexcept
: Iterator(Begin), End(End), Buffer() {}
/// Tells whether there is any more value in the handled range for index \p I.
///
/// \tparam I the index of the element to check
///
/// \return whether there is more value for index \p I
template <size_t I> bool hasMore(void) const noexcept {
const auto &ElementBuffer = std::get<I>(Buffer);
// There is more value if some has already been buffered or the end of the
// handled range is not reached yet.
return !ElementBuffer.empty() || Iterator != End;
}
/// Gives the next value from the handled range for index \p I.
///
/// \note The function should not be called if there is no more value for
/// index \p I (i.e., \c hasMore<I>() returns \c false). If it is called in
/// that situation, it returns the default value of \c element_type<I>.
///
/// \tparam I the index of the element to fetch next value for
///
/// \return the next value for index \p I
template <size_t I> element_type<I> next(void) noexcept {
auto &ElementBuffer = std::get<I>(Buffer);
if (ElementBuffer.empty()) {
// This position needs a new value from Iterator if there is more.
if (Iterator != End) {
// Push next value for all elements.
- push(*Iterator++, seq_t<iterator_value_size>());
+ push(*Iterator++, element_idx_seq_t());
} else {
// No more values; called when hasMore<I>() is false.
// Return default value.
return element_type<I>();
}
}
// Buffer is not empty here, return the next value.
ASSERT(!ElementBuffer.empty() && "Unexpected condition");
// Get the next value and also pop it from the buffer.
const element_type<I> Elem = ElementBuffer.front();
ElementBuffer.pop();
return Elem;
}
private:
/// Buffers next tuple value elementwise into element containers.
///
/// \tparam S0 indices for accessing elements of \c std::tuple
///
/// \param Tuple the values to buffer
///
/// \note The second parameter provides indices as template parameter \p S0
/// and its actual value is ignored.
template <size_t... S0>
void push(const iterator_value_type &Tuple, Seq<S0...>) noexcept {
(std::get<S0>(Buffer).push(std::get<S0>(Tuple)), ...);
}
TupleIterator Iterator; ///< Current input iterator
const TupleIterator End; ///< End of iterator range to handle
tuple_buffer_container_t<iterator_value_type>
Buffer; ///< Container for elementwise buffering
};
/// Template type alias for iterator of an element based on buffered iterator of
/// \c std::tuple.
///
/// The alias utilizes \c SplittedElementIterator for iterating over the values
/// provided by \p TB.
///
/// \tparam TB buffer providing values to iterate
/// \tparam I index of the values to iterator from \p TB
template <typename TB, size_t I>
using element_iterator_t = SplittedElementIterator<TB, I>;
/// Template type alias for iterator-range of an element based on buffered
/// iterator of \c std::tuple.
///
/// \tparam TB buffer providing values to iterate
/// \tparam I index of the values to iterator from \p TB
template <typename TB, size_t I>
using element_iterator_range_t =
std::pair<element_iterator_t<TB, I>, element_iterator_t<TB, I>>;
///\defgroup ElementIteratorRanges Type converter turning a buffer of \c
/// std::tuple into a \c std::tuple of corresponding \c
/// element_iterator_range_t.
///
///@{
/// Template declaration.
///
/// \tparam TB buffer providing values
/// \tparam S type providing indices for accessing elements of \c std::tuple
///
/// \note \p TB is expected to implement an interface matching that of \c
/// TupleIteratorBuffer.
///
/// \note The template is defined only when \p S is a \c rosa::Seq.
///
/// Usage for a proper buffer type \c TB:\code
-/// typename ElementIteratorRanges<TB, seq_t<TB::iterator_value_size>>::Type
+/// typename ElementIteratorRanges<TB, typename TB::element_idx_seq_t>::Type
/// \endcode
template <typename TB, typename S> struct ElementIteratorRanges;
/// Template definition.
template <typename TB, size_t... S0>
struct ElementIteratorRanges<TB, Seq<S0...>> {
/// The converted type.
using Type = std::tuple<element_iterator_range_t<TB, S0>...>;
};
///@}
/// Convenience template type alias for easy use of \c ElementIteratorRanges.
///
/// Converts a buffer of \c std::tuple into a \c std::tuple of corresponding \c
/// element_iterator_range_t.
///
/// \tparam TB buffer providing values
///
/// \note \p TB is expected to implement an interface matching that of \c
/// TupleIteratorBuffer.
template <typename TB>
using element_iterator_ranges_t =
- typename ElementIteratorRanges<TB, seq_t<TB::iterator_value_size>>::Type;
+ typename ElementIteratorRanges<TB, typename TB::element_idx_seq_t>::Type;
/// Template type alias for turning an iterator of \c std::tuple into
/// corresponding \c element_iterator_ranges_t.
///
/// The alias utilizes \c TupleIteratorBuffer for buffering the values provided
/// by \p TupleIterator. The elementwise iterators are \c
/// SplittedElementIterator.
///
/// \tparam TupleIterator iterator of \c std::tuple
template <typename TupleIterator>
using splitted_tuple_iterator_ranges_t =
element_iterator_ranges_t<TupleIteratorBuffer<TupleIterator>>;
/// Creates elementwise iterator ranges for an iterator range of \c std::tuple.
///
/// \note Implementation for \c rosa::iterator::splitTupleIterator.
///
/// \tparam TupleIterator iterator of \c std::tuple
/// \tparam S0 indices for accessing elements of \c std::tuple
///
/// \param Begin the beginning of the iterator range to handle
/// \param End the end of the iterator range to handle
///
/// \note The last parameter provides indices as template parameter \p S0 and
/// its actual value is ignored.
///
/// \return \c std::tuple of elementwise iterator ranges corresponding to \p
/// Begin and \p End
template <typename TupleIterator, size_t... S0>
splitted_tuple_iterator_ranges_t<TupleIterator>
splitTupleIteratorImpl(TupleIterator &&Begin, const TupleIterator &End,
Seq<S0...>) noexcept {
using TB = TupleIteratorBuffer<TupleIterator>;
// Create a buffer in shared pointer. The buffer will be destructed once
// all corresponding element iterators (created below) have reached the end of
// the handled range or have been destructed.
auto Buffer = std::make_shared<TB>(std::move(Begin), End);
return {std::make_pair(element_iterator_t<TB, S0>(Buffer),
element_iterator_t<TB, S0>())...};
}
} // End namespace
/// Creates elementwise iterator ranges for an iterator range of \c std::tuple.
///
/// \note The implementation utilizes \c splitTupleIteratorImpl.
///
/// Obtain element iterator ranges for an iterator range \c Begin and \c End of
/// iterator type \c TupleIterator of \c std::tuple<T1, T2, T3> as \code
/// auto [T1Range, T2Range, T3Range] = splitTupleIterator(std::move(Begin), End);
/// auto [T1Begin, T1End] = T1Range;
/// auto [T2Begin, T2End] = T2Range;
/// auto [T3Begin, T3End] = T3Range;
/// \endcode
///
/// The function returns a tuple of ranges (i.e., \c std::pair of iterators),
/// which can be assigned to variables using structured binding. The ranges can
/// be dissected into begin and end iterators by separate structured bindings.
///
-/// The function moves its first argument (i.e., \p Begin cannot be used after
-/// splitting it). If the first argument is a variable, it needs to be moved
-/// explicitly by \c std::move() as in the example.
+/// The function moves its first argument (i.e., \p Begin cannot be used
+/// directly after splitting it). If the first argument is a variable, it needs
+/// to be moved explicitly by \c std::move() as in the example.
///
/// \tparam TupleIterator iterator of \c std::tuple
///
/// \param Begin the beginning of the iterator range to handle
/// \param End the end of the iterator range to handle
///
/// \return \c std::tuple of elementwise iterator ranges corresponding to \p
/// Begin and \p End
template <typename TupleIterator>
splitted_tuple_iterator_ranges_t<TupleIterator>
splitTupleIterator(TupleIterator &&Begin, const TupleIterator &End) noexcept {
return splitTupleIteratorImpl(
std::move(Begin), End,
seq_t<std::tuple_size_v<typename TupleIterator::value_type>>());
}
} // End namespace iterator
} // End namespace rosa
#endif // ROSA_SUPPORT_ITERATOR_SPLIT_TUPLE_ITERATOR_HPP
diff --git a/include/rosa/support/writer/namespace.h b/include/rosa/support/writer/namespace.h
new file mode 100644
index 0000000..3349a93
--- /dev/null
+++ b/include/rosa/support/writer/namespace.h
@@ -0,0 +1,25 @@
+//===-- rosa/support/writer/namespace.h --------------------------*- C++ -*-===/
+//
+// The RoSA Framework
+//
+//===----------------------------------------------------------------------===/
+///
+/// \file rosa/support/writer/namespace.h
+///
+/// \author David Juhasz (david.juhasz@tuwien.ac.at)
+///
+/// \date 2019
+///
+/// \brief Documentation for the namespace \c rosa::writer.
+///
+//===----------------------------------------------------------------------===/
+
+#ifndef ROSA_SUPPORT_WRITER_NAMESPACE_H
+#define ROSA_SUPPORT_WRITER_NAMESPACE_H
+
+namespace rosa {
+/// Provides facilities to work with writers.
+namespace writer {}
+} // End namespace rosa
+
+#endif // ROSA_SUPPORT_WRITER_NAMESPACE_H
diff --git a/include/rosa/support/writer/split_tuple_writer.hpp b/include/rosa/support/writer/split_tuple_writer.hpp
new file mode 100644
index 0000000..22e3a35
--- /dev/null
+++ b/include/rosa/support/writer/split_tuple_writer.hpp
@@ -0,0 +1,554 @@
+//===-- rosa/support/writer/split_tuple_writer.hpp ---------------*- C++ -*-===/
+//
+// The RoSA Framework
+//
+//===----------------------------------------------------------------------===/
+///
+/// \file rosa/support/writer/split_tuple_writer.hpp
+///
+/// \authors David Juhasz (david.juhasz@tuwien.ac.at)
+///
+/// \date 2019
+///
+/// \brief Facilities to split writers of \c std::tuple into writers of
+/// their elements.
+///
+//===----------------------------------------------------------------------===/
+
+#ifndef ROSA_SUPPORT_WRITER_SPLIT_TUPLE_WRITER_HPP
+#define ROSA_SUPPORT_WRITER_SPLIT_TUPLE_WRITER_HPP
+
+#include "rosa/support/debug.hpp"
+#include "rosa/support/sequence.hpp"
+
+#include <memory>
+#include <tuple>
+#include <queue>
+
+namespace rosa {
+namespace writer {
+
+/// What to do when splitted element writers got destructed so that some
+/// incomplete tuples remain in the buffer.
+enum IncompleteTuplePolicy {
+ Ignore, ///< ignore incomplete tuples, data discarded
+ Flush ///< flush incomplete tuples, use default value for missing elements
+};
+
+/// Anonymous namespace providing implementation for splitting tuple writers;
+/// consider it private.
+namespace {
+
+/// Writes values into a buffer based on an index.
+///
+/// The values are first buffered and flushed out later once a corresponding
+/// tuple gets complete (i.e., other elementwise writers put the corresponding
+/// values into the buffer). Since the underlying buffer waits for tuples to
+/// become complete, the elementwise writers are expected to provide the same
+/// number of values for the buffer (i.e., completing all tuples that have an
+/// element). That is, however, not enforced in any ways.
+///
+/// Once all elementwise writers are destructed, the underlying buffer gets
+/// destructed as well. Should the buffer contain some values, which are
+/// elements of incomplete tuples, the destructor of the buffer handles the
+/// situation according to the \c rosa::writer::IncompleteTuplePolicy set when
+/// the elementwise writers were created by \c rosa::writer::splitTupleWriter().
+///
+/// \tparam TB buffer to write into
+/// \tparam I index of the values to write to \p TB
+///
+/// \note \p TB is expected to implemnet an interface matching that of \c
+/// TupleWriterBuffer.
+///
+/// \note the
+template <typename TB, size_t I>
+class SplittedElementWriter {
+public:
+ /// Type alias for the values the writer writes.
+ using T = typename TB::template element_type<I>;
+
+ /// \defgroup SplittedElemenWriterTypedefs Typedefs of
+ /// \c SplittedElementWriter
+ ///
+ /// Useful `typedef`s for writers.
+ ///
+ ///@{
+ typedef T value_type; ///< Type of values written.
+ typedef T &reference; ///< Reference to the type written
+ ///@}
+
+ /// Creates a new instance.
+ ///
+ /// \param Buffer buffer \p this object writes values into
+ ///
+ /// \note \p Buffer is captured as a \c std::shared_ptr because it is shared
+ /// among writers for its element positions.
+ SplittedElementWriter(std::shared_ptr<TB> Buffer) : Buffer(Buffer) {}
+
+ /// Tells how many values are still in the buffer.
+ ///
+ /// Values are buffered as long as all elements of their corresponding tuples
+ /// are written into the buffer by other elementwise writers and in turn
+ /// complete tuples written by the buffer itself. This function tells how many
+ /// values are still in the buffer waiting for their containing tuples to be
+ /// complete and written out from the buffer.
+ ///
+ /// \note The function simply calles the corresponding function of \p TB.
+ ///
+ /// \return how many values are still in the buffer.
+ size_t buffered(void) const noexcept {
+ return Buffer->template buffered<I>();
+ }
+
+ /// Tells if the last write operation of the buffer was successful.
+ ///
+ /// Values are buffered until their corresponding tuples gets complete. The
+ /// buffer writes complete tuples by the underlying writer. This function
+ /// tells if the buffer successfully has written the latest complete tuple by
+ /// the underlying writer.
+ ///
+ /// Once this function returns \c false, further \c write() calls has no
+ /// effect and the last \c buffered() values will not be written to the
+ /// underlying writer of \c std::tuple.
+ ///
+ /// \note The function simply calles the corresponding function of \p TB.
+ ///
+ /// \return if the last write operation was successful
+ bool good(void) const noexcept { return Buffer->good(); }
+
+ /// Writes an entry to the buffer.
+ ///
+ /// The function has no effect if an earlier write operation of the buffer has
+ /// failed, that is \c good() returns \c false.
+ ///
+ /// \note The function simply calles the corresponding function of \p TB.
+ ///
+ /// \param V value to write
+ void write(const T &V) { Buffer->template write<I>(V); }
+
+private:
+ std::shared_ptr<TB> Buffer; ///< Buffer \p this object writes into
+};
+
+/// Writes an element of a tuple.
+///
+/// \see SplittedElementWriter
+///
+/// \tparam TB type of the buffer \p W writes into
+/// \tparam I index of the values \p W write to \p TB
+///
+/// \param [in,out] W object to write with
+/// \param V value to write
+///
+/// \return \p W after writing \p V with it
+template <typename TB, size_t I>
+SplittedElementWriter<TB, I> &
+operator<<(SplittedElementWriter<TB, I> &W,
+ const typename SplittedElementWriter<TB, I>::value_type &V) {
+ W.write(V);
+ return W;
+}
+
+///\defgroup TupleBufferContainer Type converter turning a \c std::tuple of
+///types into a \c std::tuple of container of those types.
+///
+/// The new type is used for buffering elements of tuples separately.
+///
+///@{
+
+/// Template declaration.
+///
+/// \tparam T type to convert
+///
+/// \note The template is defined only when \p T is a \c std::tuple.
+///
+/// Usage for a type \c Tuple as:\code
+/// typename TupleBufferContainer<Tuple>::Type
+/// \endcode
+template <typename T> struct TupleBufferContainer;
+
+/// Template definition for \c std::tuple.
+template <typename... Ts> struct TupleBufferContainer<std::tuple<Ts...>> {
+ /// The converted type.
+ using Type = std::tuple<std::queue<Ts>...>;
+};
+
+///@}
+
+/// Convenience template type alias for easy use of \c TupleBufferContainer.
+///
+/// Converts a \c std::tuple of types into a \c std::tuple of container of those
+/// types.
+///
+/// \tparam Tuple type to convert
+template <typename Tuple>
+using tuple_buffer_container_t = typename TupleBufferContainer<Tuple>::Type;
+
+/// Buffer for element values for writer of \c std::tuple.
+///
+/// The class can be instantiated with a writer of \c std::tuple and provides
+/// an interface for writing elements into tuples one by one.
+///
+/// \note The class is utilized by \c SplittedElementWriter.
+///
+/// \tparam TupleWriter the writer type that handles values of \c std::tuple
+///
+/// \note The elements of the written \c std::tuple need to be default
+/// constructible because of \c rosa::writer::IncompleteTuplePolicy::Flush.
+///
+/// \todo Consider thread safety of the class.
+template <typename TupleWriter>
+class TupleWriterBuffer {
+public:
+ /// Type alias for the value type of \p TupleWriter.
+ /// \note The type is expected to be \c std::tuple.
+ using writer_value_type = typename TupleWriter::value_type;
+
+ /// The number of elements of \c writer_value_type.
+ static constexpr size_t writer_value_size =
+ std::tuple_size_v<writer_value_type>;
+
+ /// Template type alias to get element types of \c writer_value_type by
+ /// index.
+ /// \tparam I the index of the element
+ template <size_t I>
+ using element_type =
+ typename std::tuple_element<I, writer_value_type>::type;
+
+ /// Type alias for index sequence for accessing elements of \c
+ /// writer_value_size.
+ using element_idx_seq_t = seq_t<writer_value_size>;
+
+ /// Creates a new instance.
+ ///
+ /// \param Writer the writer \p this object uses to write tuples
+ /// \param Policy what to do with incomplete tuples when destructing \p
+ /// this object
+ TupleWriterBuffer(TupleWriter &&Writer,
+ const IncompleteTuplePolicy Policy) noexcept
+ : Writer(Writer), Policy(Policy), Buffer() {}
+
+ /// Destructor.
+ ///
+ /// Should \p this object has some values in \c Buffer (i.e., incomplete
+ /// tuples), the destructor takes care of them according to \c Policy.
+ ///
+ /// \note The destructor may flush the buffered values if the last write
+ /// operation was successful, that is \c good() returns \c true.
+ ~TupleWriterBuffer(void) noexcept {
+ if (good()) {
+ switch (Policy) {
+ default:
+ ASSERT(false && "Unexpected Policy");
+ case Ignore:
+ // Do not care about incomplete tuples in the buffer.
+ break;
+ case Flush:
+ // Whatever we have in the buffer, flush it out.
+ flush();
+ break;
+ }
+ }
+ }
+
+ /// Tells how many values are in the buffer for index \p I.
+ ///
+ /// \tparam I the index of the element to check
+ ///
+ /// \return the number of values in buffer for index \p I
+ template <size_t I> size_t buffered(void) const noexcept {
+ return std::get<I>(Buffer).size();
+ }
+
+ /// Tells if the last write operation was successful.
+ ///
+ /// Values are buffered until their corresponding tuples gets complete.
+ /// Once a tuple becomes complete, it is written by \c Writer. This function
+ /// tells if writing the latest complete tuple was successful.
+ ///
+ /// Once this function returns \c false, further \c write<I>() calls has no
+ /// effect and the last \c buffered<I>() values will not be written to the
+ /// underlying writer of \c std::tuple.
+ ///
+ /// \return if the last write operation was successful
+ bool good(void) const noexcept { return Writer.good(); }
+
+ /// Writes an entry to the buffer for index \p I.
+ ///
+ /// The function has no effect if an earlier write operation of the buffer has
+ /// failed, that is \c good() returns \c false.
+ ///
+ /// The value is buffered first and written by \p Writer once its
+ /// corresponding tuple becomes complete (i.e., all other elements of the
+ /// tuple are written into \p this object by corresponding elementwise
+ /// writers).
+ ///
+ /// \tparam I the index of the element to write
+ ///
+ /// \param V value to write
+ template <size_t I> void write(const element_type<I> &V) {
+ ASSERT(!hasCompleteTuple(element_idx_seq_t()));
+ if (good()) {
+ std::get<I>(Buffer).push(V);
+ if (hasCompleteTuple(element_idx_seq_t())) {
+ writeTuple(false);
+ }
+ }
+ ASSERT(!hasCompleteTuple(element_idx_seq_t()));
+ }
+
+private:
+ /// Tells whether \c Buffer is completely empty, all elements of it are empty.
+ ///
+ /// \tparam S0 indices for accessing elements of \c std::tuple
+ ///
+ /// \note The parameter provides indices as template parameter \p S0 and its
+ /// actual value is ignored.
+ ///
+ /// \return whether all elements of \c Buffer are empty
+ template <size_t... S0> bool empty(Seq<S0...>) const noexcept {
+ return (true && ... && std::get<S0>(Buffer).empty());
+ }
+
+ /// Tells whether \c Buffer contains at least one complete tuple.
+ ///
+ /// \tparam S0 indices for accessing elements of \c std::tuple
+ ///
+ /// \note The parameter provides indices as template parameter \p S0 and its
+ /// actual value is ignored.
+ ///
+ /// \return whether there is at least one complete tuple in \c Buffer
+ template <size_t... S0> bool hasCompleteTuple(Seq<S0...>) const noexcept {
+ return (true && ... && !std::get<S0>(Buffer).empty());
+ }
+
+ /// Makes sure \c Buffer has one complete tuple in front.
+ ///
+ /// If the tuple in front of \c Buffer is not complete, missing elements are
+ /// default constructed in \c Buffer to complete the tuple.
+ ///
+ /// \tparam S0 indices for accessing elements of \c std::tuple
+ ///
+ /// \note The parameter provides indices as template parameter \p S0 and its
+ /// actual value is ignored.
+ template <size_t... S0> void makeCompleteTuple(Seq<S0...>) noexcept {
+ auto addDefaultIfEmpty = [](auto &Queue) {
+ if (Queue.empty()) {
+ Queue.emplace(); // default construct a value in the empty queue.
+ }
+ };
+ (addDefaultIfEmpty(std::get<S0>(Buffer)), ...);
+ }
+
+ /// Gives the first complete tuple from \c Buffer.
+ ///
+ /// \tparam S0 indices for accessing elements of \c std::tuple
+ ///
+ /// \note The parameter provides indices as template parameter \p S0 and its
+ /// actual value is ignored.
+ ///
+ /// \return the first complete tuple from \c Buffer
+ ///
+ /// \pre There is at least one complete tuple in \c Buffer:\code
+ /// hasCompleteTuple(element_idx_seq_t())
+ /// \endcode
+ template <size_t... S0> writer_value_type front(Seq<S0...>) const noexcept {
+ ASSERT(hasCompleteTuple(element_idx_seq_t()));
+ return {std::get<S0>(Buffer).front()...};
+ }
+
+ /// Removes the first complete tuple from \c Buffer.
+ ///
+ /// \tparam S0 indices for accessing elements of \c std::tuple
+ ///
+ /// \note The parameter provides indices as template parameter \p S0 and its
+ /// actual value is ignored.
+ ///
+ /// \pre There is at least one complete tuple in \c Buffer:\code
+ /// hasCompleteTuple(element_idx_seq_t())
+ /// \endcode
+ template <size_t... S0> void pop(Seq<S0...>) noexcept {
+ ASSERT(hasCompleteTuple(element_idx_seq_t()));
+ (std::get<S0>(Buffer).pop(), ...);
+ }
+
+ /// Takes the first tuple from \c Buffer and writes it with \c Writer.
+ ///
+ /// \c Buffer need to contain a complete tuple to write it with \c Writer. The
+ /// function makes sure that the tuple in front of \c Buffer is complete if \p
+ /// MakeComplete is true. The tuple in fron of \c Buffer are expected to be
+ /// complete otherwise.
+ ///
+ /// \param MakeComplete whether to make the first tuple complete
+ ///
+ /// \pre There is at least one complete tuple in \c Buffer if not \p
+ /// MakeComplete: \code
+ /// MakeComplete || hasCompleteTuple(element_idx_seq_t())
+ /// \endcode
+ void writeTuple(const bool MakeComplete) noexcept {
+ if (MakeComplete) {
+ makeCompleteTuple(element_idx_seq_t());
+ }
+ ASSERT(hasCompleteTuple(element_idx_seq_t()));
+ Writer.write(front(element_idx_seq_t()));
+ pop(element_idx_seq_t());
+ }
+
+ /// Empties \c Buffer by writing out all tuples from it so that missing
+ /// elements of incomplete tuples are extended with default constructed
+ /// values.
+ void flush(void) noexcept {
+ while (!empty(element_idx_seq_t())) {
+ ASSERT(!hasCompleteTuple(element_idx_seq_t())); // Sanity check.
+ writeTuple(true);
+ }
+ }
+
+ TupleWriter Writer; ///< The splitted writer
+ const IncompleteTuplePolicy Policy; ///< what to do with incomplete tuples
+ ///< when destructing \p this object
+ tuple_buffer_container_t<writer_value_type>
+ Buffer; ///< Container for elementwise buffering
+};
+
+/// Template type alias for writer of an element based on buffered writer of
+/// \c std::tuple.
+///
+/// The alias utilizes \c SplittedElementWriter for writing element values by
+/// \p TB.
+///
+/// \tparam TB buffer to write into
+/// \tparam I index of the values to write to \p TB
+template <typename TB, size_t I>
+using element_writer_t = SplittedElementWriter<TB, I>;
+
+///\defgroup ElementWriters Type converter turning a buffer of \c std::tuple
+///into a \c std::tuple of corresponding \c element_writer_t.
+///
+///@{
+
+/// Template declaration.
+///
+/// \tparam TB buffer to write into
+/// \tparam S type providing indices for accessing elements of \c std::tuple
+///
+/// \note \p TB is expected to implement an interface matching that of \c
+/// TupleWriterBuffer.
+///
+/// \note The template is defined only when \p S is a \c rosa::Seq.
+///
+/// Usage for a proper buffer type \c TB:\code
+/// typename ElementIteratorWriters<TB, typename TB::element_idx_seq_t>::Type
+/// \endcode
+template <typename TB, typename S> struct ElementWriters;
+
+/// Template definition.
+template <typename TB, size_t... S0>
+struct ElementWriters<TB, Seq<S0...>> {
+ /// The converted type.
+ using Type = std::tuple<element_writer_t<TB, S0>...>;
+};
+
+///@}
+
+/// Convenience template type alias for easy use of \c ElementIteratorWriters.
+///
+/// Converts a buffer of \c std::tuple into a \c std::tuple of corresponding \c
+/// element_writer_t.
+///
+/// \tparam TB buffer to write into
+///
+/// \note \p TB is expected to implement an interface matching that of \c
+/// TupleWriterBuffer.
+template <typename TB>
+using element_writers_t =
+ typename ElementWriters<TB, typename TB::element_idx_seq_t>::Type;
+
+/// Template type alias for turning a writer of \c std::tuple into
+/// corresponding \c element_writers_t.
+///
+/// The alias utilizes \c TupleWriterBuffer for buffering values before writing
+/// them by \p TupleWriter. The elementwise writers are \c
+/// SplittedElementWriter.
+///
+/// \tparam TupleWriter writer of \c std::tuple
+template <typename TupleWriter>
+using splitted_tuple_writers_t =
+ element_writers_t<TupleWriterBuffer<TupleWriter>>;
+
+/// Creates elementwise writers for a writer of \c std::tuple.
+///
+/// \note Implementation for \c rosa::iterator::splitTupleWriter.
+///
+/// \tparam TupleWriter writer of \c std::tuple
+/// \tparam S0 indices for accessing elements of \c std::tuple
+///
+/// \param Writer the writer to write tuples with
+/// \param Policy how to handle incomplete tuples when destructing the
+/// underlying buffer
+///
+/// \note The last parameter provides indices as template parameter \p S0 and
+/// its actual value is ignored.
+///
+/// \return \c std::tuple of elementwise writers corresponding to \p Writer
+template <typename TupleWriter, size_t... S0>
+splitted_tuple_writers_t<TupleWriter>
+splitTupleWriterImpl(TupleWriter &&Writer, const IncompleteTuplePolicy Policy,
+ Seq<S0...>) noexcept {
+ using TB = TupleWriterBuffer<TupleWriter>;
+ // Create a buffer in shared pointer. The buffer will be destructed once
+ // all corresponding element writers (created below) have been destructed.
+ auto Buffer = std::make_shared<TB>(std::move(Writer), Policy);
+ return {element_writer_t<TB, S0>(Buffer)...};
+}
+
+} // End namespace
+
+/// Creates elementwise writers for a writer of \c std::tuple.
+///
+/// \note The implementation utilizes \c splitTupleWriterImpl.
+///
+/// Obtain elementwise writers for a writer \p Writer of type \c TupleWriter of
+/// \c std::tuple<T1, T2, T3> as \code
+/// auto [T1Writer, T2Writer, T3Writer] = splitTupleWriter(std::move(Writer),
+/// Ignore);
+/// \endcode
+///
+/// The function returns a tuple of writers, which can be assigned to variables
+/// using structured binding.
+///
+/// The function moves its first argument (i.e., \p Writer cannot be used
+/// directly after splitting it). If the first argument is a variable, it needs
+/// to be moved explicitly by \c std::move() as in the example.
+///
+/// While a tuple could be written with \p Writer directly as \code
+/// Writer << std::make_tuple(T1(), T2(), T3());
+/// \endcode The same tuple is written with splitted writers as \code
+/// T1Writer << T1();
+/// T2Writer << T2();
+/// T3Writer << T3();
+/// \endcode
+///
+/// \tparam TupleWriter writer of \c std::tuple
+///
+/// \note The elements of the written \c std::tuple need to be default
+/// constructible because of \c rosa::writer::IncompleteTuplePolicy::Flush.
+///
+/// \param Writer the writer to write tuples with
+/// \param Policy what to do with incomplete tuples when destructing the
+/// underlying buffer
+///
+/// \return \c std::tuple of elementwise writers corresponding to \p Writer
+template <typename TupleWriter>
+splitted_tuple_writers_t<TupleWriter>
+splitTupleWriter(TupleWriter &&Writer,
+ const IncompleteTuplePolicy Policy) noexcept {
+ return splitTupleWriterImpl(
+ std::move(Writer), Policy,
+ seq_t<std::tuple_size_v<typename TupleWriter::value_type>>());
+}
+
+} // End namespace writer
+} // End namespace rosa
+
+#endif // ROSA_SUPPORT_WRITER_SPLIT_TUPLE_WRITER_HPP
diff --git a/lib/support/CMakeLists.txt b/lib/support/CMakeLists.txt
index 12a3334..318486d 100644
--- a/lib/support/CMakeLists.txt
+++ b/lib/support/CMakeLists.txt
@@ -1,42 +1,46 @@
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
${LIB_INCLUDE_DIR}/iterator/namespace.h
iterator/namespace.cpp
${LIB_INCLUDE_DIR}/iterator/split_tuple_iterator.hpp
iterator/split_tuple_iterator.cpp
+ ${LIB_INCLUDE_DIR}/writer/namespace.h
+ writer/namespace.cpp
+ ${LIB_INCLUDE_DIR}/writer/split_tuple_writer.hpp
+ writer/split_tuple_writer.cpp
)
diff --git a/lib/support/writer/namespace.cpp b/lib/support/writer/namespace.cpp
new file mode 100644
index 0000000..b659e2d
--- /dev/null
+++ b/lib/support/writer/namespace.cpp
@@ -0,0 +1,20 @@
+//===-- support/writer/namespace.cpp -----------------------------*- C++ -*-===/
+//
+// The RoSA Framework
+//
+//===----------------------------------------------------------------------===/
+///
+/// \file support/writer/namespace.cpp
+///
+/// \author David Juhasz (david.juhasz@tuwien.ac.at)
+///
+/// \date 2019
+///
+/// \brief Placeholder for rosa/support/iterator/namespace.h.
+///
+/// \note Empty implementation, source file here to have a compile database
+/// entry for rosa/support/writer/namespace.h.
+///
+//===----------------------------------------------------------------------===/
+
+#include "rosa/support/writer/namespace.h"
diff --git a/lib/support/writer/split_tuple_writer.cpp b/lib/support/writer/split_tuple_writer.cpp
new file mode 100644
index 0000000..651e012
--- /dev/null
+++ b/lib/support/writer/split_tuple_writer.cpp
@@ -0,0 +1,20 @@
+//===-- support/writer/split_tuple_writer.cpp --------------------*- C++ -*-===/
+//
+// The RoSA Framework
+//
+//===----------------------------------------------------------------------===/
+///
+/// \file support/writer/split_tuple_writer.cpp
+///
+/// \author David Juhasz (david.juhasz@tuwien.ac.at)
+///
+/// \date 2019
+///
+/// \brief Implementation for rosa/support/writer/split_tuple_writer.hpp.
+///
+/// \note Empty implementation, source file here to have a compile database
+/// entry for rosa/support/writer/split_tuple_writer.hpp.
+///
+//===----------------------------------------------------------------------===/
+
+#include "rosa/support/writer/split_tuple_writer.hpp"
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sun, Jun 8, 7:51 PM (20 h, 34 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
150512
Default Alt Text
(45 KB)
Attached To
Mode
R20 SoC_Rosa_repo
Attached
Detach File
Event Timeline
Log In to Comment