From a2b10e7042ec97a186a3cd76638ca43b2986440b Mon Sep 17 00:00:00 2001 From: Sergey Magidovich Date: Tue, 15 Dec 2015 21:04:34 +0300 Subject: [PATCH] Add range_iterator. --- base/base.pro | 1 + base/base_tests/base_tests.pro | 1 + base/base_tests/range_iterator_test.cpp | 43 ++++++++++++ base/range_iterator.hpp | 93 +++++++++++++++++++++++++ 4 files changed, 138 insertions(+) create mode 100644 base/base_tests/range_iterator_test.cpp create mode 100644 base/range_iterator.hpp diff --git a/base/base.pro b/base/base.pro index 3d85e27022..df72d751d2 100644 --- a/base/base.pro +++ b/base/base.pro @@ -51,6 +51,7 @@ HEADERS += \ mutex.hpp \ object_tracker.hpp \ observer_list.hpp \ + range_iterator.hpp \ regexp.hpp \ rolling_hash.hpp \ scope_guard.hpp \ diff --git a/base/base_tests/base_tests.pro b/base/base_tests/base_tests.pro index 6f4a12b939..07b397a618 100644 --- a/base/base_tests/base_tests.pro +++ b/base/base_tests/base_tests.pro @@ -24,6 +24,7 @@ SOURCES += \ matrix_test.cpp \ mem_trie_test.cpp \ observer_list_test.cpp \ + range_iterator_test.cpp \ regexp_test.cpp \ rolling_hash_test.cpp \ scope_guard_test.cpp \ diff --git a/base/base_tests/range_iterator_test.cpp b/base/base_tests/range_iterator_test.cpp new file mode 100644 index 0000000000..29b857283d --- /dev/null +++ b/base/base_tests/range_iterator_test.cpp @@ -0,0 +1,43 @@ +#include "testing/testing.hpp" + +#include "base/range_iterator.hpp" + +#include "std/vector.hpp" + +UNIT_TEST(RangeIterator) +{ + using namespace base; + + { + vector result; + for (auto const i : range(5)) + result.push_back(i); + TEST_EQUAL(result, (vector{0, 1, 2, 3, 4}), ()); + } + + { + vector result; + for (auto const i : range(2, 5)) + result.push_back(i); + TEST_EQUAL(result, (vector{2, 3, 4}), ()); + } + + { + vector result; + for (auto const i : reverse_range(5)) + result.push_back(i); + TEST_EQUAL(result, (vector{4, 3, 2, 1, 0}), ()); + } + + { + vector result; + for (auto const i : reverse_range(2, 5)) + result.push_back(i); + TEST_EQUAL(result, (vector{4, 3, 2}), ()); + } + + { + TEST_EQUAL(std::vector(MakeRangeIterator(0), MakeRangeIterator(5)), + (std::vector{0, 1, 2, 3, 4}), ()); + } +} diff --git a/base/range_iterator.hpp b/base/range_iterator.hpp new file mode 100644 index 0000000000..bb799aa76e --- /dev/null +++ b/base/range_iterator.hpp @@ -0,0 +1,93 @@ +#include "std/iterator.hpp" +#include "std/type_traits.hpp" + +namespace base +{ +template +struct RangeIterator +{ + explicit RangeIterator(TCounter const current): + m_current(current) + { + } + + RangeIterator & operator++() { ++m_current; return *this; } + RangeIterator & operator--() { --m_current; return *this; } + + bool operator==(RangeIterator const & it) const { return m_current == it.m_current; } + bool operator!=(RangeIterator const & it) const { return !(*this == it); } + + TCounter operator*() const { return m_current; } + + TCounter m_current; +}; +} // namespace base + +namespace std +{ +template +struct iterator_traits> +{ + using difference_type = T; + using value_type = T; + using pointer = void; + using reference = T; + using iterator_category = std::bidirectional_iterator_tag; +}; +} // namespace std + +namespace base +{ +template +struct RangeWrapper +{ + + using value_type = typename std::remove_cv::type; + using iterator_base = RangeIterator; + using iterator = typename std::conditional>::type; + + RangeWrapper(TCounter const from, TCounter const to): + m_begin(from), + m_end(to) + { + } + + iterator begin() const { return iterator(iterator_base(m_begin)); } + iterator end() const { return iterator(iterator_base(m_end)); } + + value_type const m_begin; + value_type const m_end; +}; + +template +RangeWrapper range(TCounter const to) +{ + return {{}, to}; +} + +template +RangeWrapper range(TCounter const from, TCounter const to) +{ + return {from, to}; +} + +template +RangeWrapper reverse_range(TCounter const to) +{ + return {to, {}}; +} + +template +RangeWrapper reverse_range(TCounter const from, TCounter const to) +{ + return {to, from}; +} + +template +RangeIterator MakeRangeIterator(TCounter const counter) +{ + return RangeIterator(counter); +} +} // namespace base