From 5f98218fe0ed95c93cd5fa605827d3d9d2da57ee Mon Sep 17 00:00:00 2001
From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz>
Date: Tue, 27 Jun 2017 12:06:53 +0200
Subject: [PATCH] add range class

---
 alib2std/src/extensions/range.hpp          | 116 +++++++++++++++++++++
 alib2std/src/range                         |   9 ++
 alib2std/test-src/extensions/RangeTest.cpp |  82 +++++++++++++++
 alib2std/test-src/extensions/RangeTest.h   |  24 +++++
 4 files changed, 231 insertions(+)
 create mode 100644 alib2std/src/extensions/range.hpp
 create mode 100644 alib2std/src/range
 create mode 100644 alib2std/test-src/extensions/RangeTest.cpp
 create mode 100644 alib2std/test-src/extensions/RangeTest.h

diff --git a/alib2std/src/extensions/range.hpp b/alib2std/src/extensions/range.hpp
new file mode 100644
index 0000000000..5e08a279f3
--- /dev/null
+++ b/alib2std/src/extensions/range.hpp
@@ -0,0 +1,116 @@
+/*
+ * range.hpp as proposed http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3350.html by Jeffrey Yasskin <jyasskin@google.com>
+ *
+ * Created on: May 28, 2015
+ * Author: Jan Travnicek
+ */
+
+#ifndef __RANGE_HPP_
+#define __RANGE_HPP_
+
+#include <utility>
+#include <iterator>
+
+namespace std {
+
+template<typename Iterator>
+class range {
+	Iterator m_begin;
+	Iterator m_end;
+public:
+	// types
+	typedef typename iterator_traits< Iterator >::iterator_category iterator_category;
+	typedef typename iterator_traits< Iterator >::value_type value_type;
+	typedef typename iterator_traits< Iterator >::difference_type difference_type;
+	typedef typename iterator_traits< Iterator >::reference reference;
+	typedef typename iterator_traits< Iterator >::pointer pointer;
+
+	// constructors
+	range() {
+	}
+
+	constexpr range(Iterator begin, Iterator end) : m_begin ( begin ), m_end ( end ) {
+	}
+
+	// iterator access
+	constexpr Iterator begin() const {
+		return m_begin;
+	}
+
+	constexpr Iterator end() const {
+		return m_end;
+	}
+
+	// element access
+	constexpr reference front() const {
+		return * m_begin;
+	}
+
+	constexpr reference back() const {
+		return * ( m_end - 1 );
+	}
+
+	constexpr reference operator[](difference_type index) const {
+		return m_begin [ index ];
+	}
+
+	// size
+	constexpr bool empty() const {
+		return m_begin == m_end;
+	}
+
+	constexpr difference_type size() const {
+		return std::distance ( m_begin, m_end );
+	}
+
+	// traversal from the beginning of the range
+	void pop_front() {
+		++ m_begin;
+	}
+
+	void pop_front(difference_type n) {
+		m_begin = m_begin + n;
+	}
+
+	// traversal from the end of the range
+	void pop_back() {
+		-- m_end;
+	}
+
+	void pop_back(difference_type n) {
+		m_end = m_end - n;
+	}
+
+	// creating derived ranges
+	pair< range, range > split(difference_type index) const {
+		return std::make_pair ( slice ( 0, index ), slice ( index, 0 ) );
+	}
+
+	range slice(difference_type start, difference_type stop) const {
+		return range ( ( start >= 0 ? m_begin : m_end ) + start, ( stop > 0 ? m_begin : m_end ) + stop );
+	}
+
+	range slice(difference_type start) const {
+		return slice ( start, 0 );
+	}
+};
+
+template < typename Iter >
+std::range < Iter > make_range ( Iter begin, Iter end ) {
+	return std::range < Iter > ( begin, end );
+}
+
+template < typename Container >
+auto make_range ( Container & container ) {
+	return std::make_range ( container.begin ( ), container.end ( ) );
+}
+
+template < typename Container >
+auto make_range ( const Container & container ) {
+	return std::make_range ( container.begin ( ), container.end ( ) );
+}
+
+} /* namespace std */
+
+#endif /* __RANGE_HPP_ */
+
diff --git a/alib2std/src/range b/alib2std/src/range
new file mode 100644
index 0000000000..0661f8a86b
--- /dev/null
+++ b/alib2std/src/range
@@ -0,0 +1,9 @@
+#ifndef __ALIB_INTERNAL_STD_EXTENSION_
+	#define __ALIB_INTERNAL_STD_EXTENSION_
+
+	#include "extensions/range.hpp"
+
+	#undef __ALIB_INTERNAL_STD_EXTENSION_
+#else
+
+#endif /* __ALIB_INTERNAL_STD_EXTENSION_ */
diff --git a/alib2std/test-src/extensions/RangeTest.cpp b/alib2std/test-src/extensions/RangeTest.cpp
new file mode 100644
index 0000000000..a70359d534
--- /dev/null
+++ b/alib2std/test-src/extensions/RangeTest.cpp
@@ -0,0 +1,82 @@
+#include "RangeTest.h"
+#include <range>
+#include <vector>
+#include <list>
+
+CPPUNIT_TEST_SUITE_NAMED_REGISTRATION ( RangeTest, "bits" );
+CPPUNIT_TEST_SUITE_REGISTRATION ( RangeTest );
+
+void RangeTest::setUp ( ) {
+}
+
+void RangeTest::tearDown ( ) {
+}
+
+void RangeTest::constructorTest ( ) {
+	int arr[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+	std::range < int * > ra1 ( arr, arr + sizeof ( arr ) / sizeof ( * arr ) );
+
+	std::vector < int > v1 = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+	std::range < std::vector < int >::iterator > rv1 ( v1.begin ( ), v1.end ( ) );
+
+	CPPUNIT_ASSERT ( ( std::equal ( ra1.begin ( ), ra1.end ( ), rv1.begin ( ), rv1.end ( ) ) ) );
+
+	auto rv2 = std::make_range ( v1 );
+
+	CPPUNIT_ASSERT ( ( std::equal ( rv1.begin ( ), rv1.end ( ), rv2.begin ( ), rv2.end ( ) ) ) );
+}
+
+void RangeTest::sizeTest ( ) {
+	int arr[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+	std::range < int * > ra1 ( arr, arr + sizeof ( arr ) / sizeof ( * arr ) );
+
+	CPPUNIT_ASSERT ( ra1.size ( ) == 10 );
+
+	std::vector < int > v1 = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+	std::range < std::vector < int >::iterator > rv1 ( v1.begin ( ), v1.end ( ) );
+
+	CPPUNIT_ASSERT ( rv1.size ( ) == 10 );
+
+	std::list < int > l1 = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+	std::range < std::list < int >::iterator > rl1 ( l1.begin ( ), l1.end ( ) );
+
+	CPPUNIT_ASSERT ( rl1.size ( ) == 10 );
+}
+
+void RangeTest::splitTest ( ) {
+	std::vector < int > v1 = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+	auto r1 = std::make_range ( v1 );
+
+	std::vector < int > v2 = { 0, 1, 2 };
+
+	auto r2 = std::make_range ( v2 );
+
+	std::vector < int > v3 = { 3, 4, 5, 6, 7, 8, 9 };
+
+	auto r3 = std::make_range ( v3 );
+
+	auto splitted = r1.split ( 3 );
+
+	CPPUNIT_ASSERT ( ( std::equal ( splitted.first.begin ( ), splitted.first.end ( ), r2.begin ( ), r2.end ( ) ) ) );
+	CPPUNIT_ASSERT ( ( std::equal ( splitted.second.begin ( ), splitted.second.end ( ), r3.begin ( ), r3.end ( ) ) ) );
+}
+
+void RangeTest::sliceTest ( ) {
+	std::vector < int > v1 = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+	auto r1 = std::make_range ( v1 );
+
+	std::vector < int > v2 = { 4, 5, 6 };
+
+	auto r2 = std::make_range ( v2 );
+
+	auto sliced = r1.slice ( 4, -3 );
+
+	CPPUNIT_ASSERT ( ( std::equal ( sliced.begin ( ), sliced.end ( ), r2.begin ( ), r2.end ( ) ) ) );
+}
diff --git a/alib2std/test-src/extensions/RangeTest.h b/alib2std/test-src/extensions/RangeTest.h
new file mode 100644
index 0000000000..e4cd64b6fc
--- /dev/null
+++ b/alib2std/test-src/extensions/RangeTest.h
@@ -0,0 +1,24 @@
+#ifndef RANGE_TEST_H_
+#define RANGE_TEST_H_
+
+#include <cppunit/extensions/HelperMacros.h>
+
+class RangeTest : public CppUnit::TestFixture {
+	CPPUNIT_TEST_SUITE ( RangeTest );
+	CPPUNIT_TEST ( constructorTest );
+	CPPUNIT_TEST ( sizeTest );
+	CPPUNIT_TEST ( splitTest );
+	CPPUNIT_TEST ( sliceTest );
+	CPPUNIT_TEST_SUITE_END ( );
+
+public:
+	void setUp ( );
+	void tearDown ( );
+
+	void constructorTest ( );
+	void sizeTest ( );
+	void splitTest ( );
+	void sliceTest ( );
+};
+
+#endif // RANGE_TEST_H_
-- 
GitLab