Page MenuHomePhorge

No OneTemporary

Size
45 KB
Referenced Files
None
Subscribers
None
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

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)

Event Timeline