diff --git a/include/stxxl/bits/stream/range.h b/include/stxxl/bits/stream/range.h new file mode 100644 index 000000000..fd5943eb5 --- /dev/null +++ b/include/stxxl/bits/stream/range.h @@ -0,0 +1,140 @@ +/*************************************************************************** + * include/stxxl/bits/stream/range.h + * + * Part of the STXXL. See http://stxxl.org + * + * Copyright (C) 2018 Michael Hamann + * + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + **************************************************************************/ + +#ifndef STXXL_STREAM_RANGE_HEADER +#define STXXL_STREAM_RANGE_HEADER + +#include + +#include + +namespace stxxl { + +//! Stream package subnamespace. +namespace stream { + +//! \addtogroup streampack +//! \{ + +//! An output range adapter for a stream, to be used in range-based for loops. +template +class stream2range +{ +private: + InputStream& m_input; + +public: + //! Type of the elements of the stream and range + using value_type = typename InputStream::value_type; + + class range { + private: + InputStream* m_stream; + + public: + //! Construct a range for the given stream. + range(InputStream* stream) : m_stream(stream) + { } + + //! Copy constructor: delete as the semantics are broken, + //! copies would not be independent. + range(const range&) = delete; + + //! Copy assignment: delete as the semantics are broken, + //! copies would not be independent. + range& operator=(const range&) = delete; + + //! Move constructor + range(range&&) = default; + + //! Move assignment + range& operator=(range&&) = default; + + //! Increment underlying stream. + range& operator ++ () + { + ++(*m_stream); + + if (TLX_UNLIKELY(m_stream->empty())) { + m_stream = nullptr; + } + + return *this; + } + + //! Check equality with another range + //! + //! All ranges pointing to the same stream are equal. + //! Ranges pointing past the end are all equal. + bool operator == (const range& other) + { + return m_stream == other.m_stream; + } + + //! Check inequality with another range + //! + //! All ranges pointing to the same stream are equal. + //! Ranges pointing past the end are all equal. + bool operator != (const range& other) + { + return m_stream != other.m_stream; + } + + //! Dereference the underlying stream. + //! + //! Dereferencing a range that is past the end is a null + //! pointer dereference. + const value_type& operator * () + { + return *(*m_stream); + } + + const value_type* operator -> () const + { + return &(*(*m_stream)); + } + }; + + //! Initialize the stream2range container + //! + //! Stores a reference to the given input. + stream2range(InputStream& input) + : m_input(input) + { } + + //! Return a range pointing to the current position of the underlying stream. + range begin() const + { + return range(&this->m_input); + } + + //! Return a range pointing past the end of any stream. + range end() const + { + return range(nullptr); + } +}; + +//! Utility function to construct a stream2range container from the given stream. +template +stream2range range(InputStream& input) +{ + return stream2range(input); +} + + +//! \} + +} // namespace stream +} // namespace stxxl + +#endif // !STXXL_STREAM_RANGE_HEADER diff --git a/include/stxxl/bits/stream/stream.h b/include/stxxl/bits/stream/stream.h index 261e049c0..2606e528e 100644 --- a/include/stxxl/bits/stream/stream.h +++ b/include/stxxl/bits/stream/stream.h @@ -1238,6 +1238,7 @@ class make_tuple #include #include #include +#include #endif // !STXXL_STREAM_STREAM_HEADER // vim: et:ts=4:sw=4 diff --git a/tests/stream/CMakeLists.txt b/tests/stream/CMakeLists.txt index eb603dda7..3b5a2e4f6 100644 --- a/tests/stream/CMakeLists.txt +++ b/tests/stream/CMakeLists.txt @@ -17,6 +17,7 @@ stxxl_build_test(test_push_sort) stxxl_build_test(test_sorted_runs) stxxl_build_test(test_stream) stxxl_build_test(test_stream1) +stxxl_build_test(test_range) add_define(test_stream1 "STXXL_VERBOSE_LEVEL=1") add_define(test_push_sort "STXXL_VERBOSE_LEVEL=0") @@ -32,3 +33,4 @@ stxxl_test(test_push_sort) stxxl_test(test_sorted_runs) stxxl_test(test_stream) stxxl_test(test_stream1) +stxxl_test(test_range) diff --git a/tests/stream/test_range.cpp b/tests/stream/test_range.cpp new file mode 100644 index 000000000..1a6cf69f9 --- /dev/null +++ b/tests/stream/test_range.cpp @@ -0,0 +1,45 @@ +/*************************************************************************** + * tests/stream/test_range.cpp + * + * Part of the STXXL. See http://stxxl.org + * + * Copyright (C) 2018 Michael Hamann + * + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + **************************************************************************/ + +#include +#include +#include + +#include + +#include + +int main() +{ + constexpr size_t num_values = 1024; + using value_type = uint64_t; + + std::vector values; + values.reserve(num_values); + + for (size_t i = 0; i < num_values; ++i) { + values.push_back(i); + } + + auto stream = stxxl::stream::streamify(values.begin(), values.end()); + + size_t i = 0; + for (size_t v : stxxl::stream::range(stream)) + { + die_unequal(i, v); + ++i; + } + + die_unequal(i, num_values); + + return 0; +}