sources/list.h

changeset 1
4dd5bde4e777
child 5
146825d63b9a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sources/list.h	Wed Dec 10 19:17:00 2014 +0200
@@ -0,0 +1,609 @@
+/*
+	Copyright 2014 Teemu Piippo
+	All rights reserved.
+
+	Redistribution and use in source and binary forms, with or without
+	modification, are permitted provided that the following conditions
+	are met:
+
+	1. Redistributions of source code must retain the above copyright
+	   notice, this list of conditions and the following disclaimer.
+	2. Redistributions in binary form must reproduce the above copyright
+	   notice, this list of conditions and the following disclaimer in the
+	   documentation and/or other materials provided with the distribution.
+	3. Neither the name of the copyright holder nor the names of its
+	   contributors may be used to endorse or promote products derived from
+	   this software without specific prior written permission.
+
+	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+	"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+	TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+	PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
+	OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+	EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+	PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+	PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+	LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+	NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+	SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#pragma once
+#include "basics.h"
+#include <algorithm>
+#include <deque>
+#include <initializer_list>
+#include <functional>
+#include <cassert>
+#include "range.h"
+
+//
+// -------------------------------------------------------------------------------------------------
+//
+
+template<typename T, typename C>
+class Container
+{
+public:
+	using Iterator = typename C::iterator;
+	using ConstIterator = typename C::const_iterator;
+	using ReverseIterator = typename C::reverse_iterator;
+	using ConstReverseIterator = typename C::const_reverse_iterator;
+	using Self = Container<T, C>;
+
+	Container();
+	Container (int numvalues);
+	Container (const C& a);
+	Container (std::initializer_list<T>&& a);
+
+	auto append (const T& value) -> T&;
+	auto begin() -> Iterator;
+	auto begin() const -> ConstIterator;
+	auto clear() -> void;
+	auto contains (const T& a) const -> bool;
+	auto crbegin() const -> ConstReverseIterator;
+	auto crend() const -> ConstReverseIterator;
+	auto container() const -> const C&;
+	auto end() -> Iterator;
+	auto end() const -> ConstIterator;
+	auto find (const T& needle) -> Iterator;
+	auto find (const T& needle) const -> ConstIterator;
+	auto find (Function<bool (T const&)> func) -> Iterator;
+	auto find (Function<bool (T const&)> func) const -> ConstIterator;
+	auto first() const -> const T&;
+	auto insert (int pos, const T& value) -> void;
+	auto is_empty() const -> bool;
+	auto last() const -> const T&;
+	auto merge (const Self& other) -> void;
+	auto pop (T& val) -> bool;
+	auto prepend (const T& value) -> T&;
+	auto rbegin() -> ReverseIterator;
+	auto remove_at (int pos) -> void;
+	auto remove_duplicates() -> void;
+	auto remove_one (const T& it) -> void;
+	auto rend() -> ReverseIterator;
+	auto resize (int size) -> void;
+	auto reverse() const -> Self;
+	auto size() const -> int;
+	auto sort() -> void;
+	auto splice (int a, int b) const -> Self;
+	auto splice (const Range<int>& a) const -> Self;
+
+	auto operator<< (const T& value) -> Self&;
+	auto operator<< (const Self& vals) -> Self&;
+	auto operator[] (int n) -> T&;
+	auto operator[] (int n) const -> const T&;
+	auto operator[] (Range<int> const& n) const -> Self;
+	auto operator+ (const Self& other) const -> Self;
+
+protected:
+	C m_container;
+};
+
+template<typename T, typename C>
+Container<T, C>& operator>> (const T& value, Container<T, C>& haystack);
+
+template<typename T>
+using List = Container<T, std::deque<T>>;
+
+template<typename T>
+class Vector : public Container<T, std::vector<T>>
+{
+public:
+	using Super = Container<T, std::vector<T>>;
+
+	template<typename... Args>
+	Vector (Args ...args) :
+		Super (args...) {}
+
+	auto data() -> T*
+	{
+		return Super::m_container.data();
+	}
+
+	auto data() const -> const T*
+	{
+		return Super::m_container.data();
+	}
+
+	operator const T*() const
+	{
+		return data();
+	}
+};
+
+//
+// -------------------------------------------------------------------------------------------------
+//
+// IMPLEMENTATIONS
+//
+
+template<typename T, typename C>
+Container<T, C>::Container() {}
+
+//
+// -------------------------------------------------------------------------------------------------
+//
+
+template<typename T, typename C>
+Container<T, C>::Container (const C& other) :
+	m_container (other) {}
+
+//
+// -------------------------------------------------------------------------------------------------
+//
+
+template<typename T, typename C>
+Container<T, C>::Container (std::initializer_list<T> && a) :
+	m_container (a) {}
+
+//
+// -------------------------------------------------------------------------------------------------
+//
+
+template<typename T, typename C>
+Container<T, C>::Container (int numvalues) :
+	m_container (numvalues) {}
+
+//
+// -------------------------------------------------------------------------------------------------
+//
+
+template<typename T, typename C>
+auto Container<T, C>::begin() -> Iterator
+{
+	return m_container.begin();
+}
+
+//
+// -------------------------------------------------------------------------------------------------
+//
+
+template<typename T, typename C>
+auto Container<T, C>::begin() const -> ConstIterator
+{
+	return m_container.cbegin();
+}
+
+//
+// -------------------------------------------------------------------------------------------------
+//
+
+template<typename T, typename C>
+auto Container<T, C>::end() -> Iterator
+{
+	return m_container.end();
+}
+
+//
+// -------------------------------------------------------------------------------------------------
+//
+
+template<typename T, typename C>
+auto Container<T, C>::end() const -> ConstIterator
+{
+	return m_container.cend();
+}
+
+//
+// -------------------------------------------------------------------------------------------------
+//
+
+template<typename T, typename C>
+auto Container<T, C>::rbegin() -> ReverseIterator
+{
+	return m_container.rbegin();
+}
+
+//
+// -------------------------------------------------------------------------------------------------
+//
+
+template<typename T, typename C>
+auto Container<T, C>::crbegin() const -> ConstReverseIterator
+{
+	return m_container.crbegin();
+}
+
+//
+// -------------------------------------------------------------------------------------------------
+//
+
+template<typename T, typename C>
+auto Container<T, C>::rend() -> ReverseIterator
+{
+	return m_container.rend();
+}
+
+//
+// -------------------------------------------------------------------------------------------------
+//
+
+template<typename T, typename C>
+auto Container<T, C>::crend() const -> ConstReverseIterator
+{
+	return m_container.crend();
+}
+
+//
+// -------------------------------------------------------------------------------------------------
+//
+
+template<typename T, typename C>
+auto Container<T, C>::remove_at (int pos) -> void
+{
+	assert (pos < size());
+	m_container.erase (m_container.begin() + pos);
+}
+
+//
+// -------------------------------------------------------------------------------------------------
+//
+
+template<typename T, typename C>
+auto Container<T, C>::prepend (const T& value) -> T&
+{
+	m_container.push_front (value);
+	return m_container[0];
+}
+
+//
+// -------------------------------------------------------------------------------------------------
+//
+
+template<typename T, typename C>
+auto Container<T, C>::append (const T& value) -> T&
+{
+	m_container.push_back (value);
+	return m_container[m_container.size() - 1];
+}
+
+//
+// -------------------------------------------------------------------------------------------------
+//
+
+template<typename T, typename C>
+auto Container<T, C>::merge (const Self& other) -> void
+{
+	int oldsize = size();
+	resize (size() + other.size());
+	std::copy (other.begin(), other.end(), begin() + oldsize);
+}
+
+//
+// -------------------------------------------------------------------------------------------------
+//
+
+template<typename T, typename C>
+auto Container<T, C>::pop (T& val) -> bool
+{
+	if (is_empty())
+		return false;
+
+	val = m_container[size() - 1];
+	m_container.erase (m_container.end() - 1);
+	return true;
+}
+
+//
+// -------------------------------------------------------------------------------------------------
+//
+
+template<typename T, typename C>
+auto Container<T, C>::operator<< (const T& value) -> Self&
+{
+	append (value);
+	return *this;
+}
+
+//
+// -------------------------------------------------------------------------------------------------
+//
+
+template<typename T, typename C>
+auto Container<T, C>::operator<< (const Self& vals) -> Self&
+{
+	merge (vals);
+	return *this;
+}
+
+//
+// -------------------------------------------------------------------------------------------------
+//
+
+template<typename T, typename C>
+auto Container<T, C>::reverse() const -> Self
+{
+	Self rev;
+	std::copy (rbegin(), rend(), rev.begin());
+	return rev;
+}
+
+//
+// -------------------------------------------------------------------------------------------------
+//
+
+template<typename T, typename C>
+auto Container<T, C>::clear() -> void
+{
+	m_container.clear();
+}
+
+//
+// -------------------------------------------------------------------------------------------------
+//
+
+template<typename T, typename C>
+auto Container<T, C>::insert (int pos, const T& value) -> void
+{
+	m_container.insert (m_container.begin() + pos, value);
+}
+
+//
+// -------------------------------------------------------------------------------------------------
+//
+
+template<typename T, typename C>
+auto Container<T, C>::remove_duplicates() -> void
+{
+	sort();
+	resize (std::distance (begin(), std::unique (begin(), end())));
+}
+
+//
+// -------------------------------------------------------------------------------------------------
+//
+
+template<typename T, typename C>
+auto Container<T, C>::size() const -> int
+{
+	return m_container.size();
+}
+
+//
+// -------------------------------------------------------------------------------------------------
+//
+
+template<typename T, typename C>
+auto Container<T, C>::operator[] (int n) -> T&
+{
+	assert (n < size());
+	return m_container[n];
+}
+
+//
+// -------------------------------------------------------------------------------------------------
+//
+
+template<typename T, typename C>
+auto Container<T, C>::operator[] (int n) const -> const T&
+{
+	assert (n < size());
+	return m_container[n];
+}
+
+//
+// -------------------------------------------------------------------------------------------------
+//
+
+template<typename T, typename C>
+auto Container<T, C>::operator[] (const Range<int>& n) const -> Self
+{
+	return splice (n);
+}
+
+//
+// -------------------------------------------------------------------------------------------------
+//
+
+template<typename T, typename C>
+auto Container<T, C>::resize (int size) -> void
+{
+	m_container.resize (size);
+}
+
+//
+// -------------------------------------------------------------------------------------------------
+//
+
+template<typename T, typename C>
+auto Container<T, C>::sort() -> void
+{
+	std::sort (begin(), end());
+}
+
+//
+// -------------------------------------------------------------------------------------------------
+//
+
+template<typename T, typename C>
+auto Container<T, C>::find (const T& needle) -> Iterator
+{
+	auto it = std::find (m_container.begin(), m_container.end(), needle);
+
+	if (it == m_container.end())
+		return end();
+
+	return it;
+}
+
+//
+// -------------------------------------------------------------------------------------------------
+//
+
+template<typename T, typename C>
+auto Container<T, C>::find (const T& needle) const -> ConstIterator
+{
+	auto it = std::find (m_container.cbegin(), m_container.cend(), needle);
+
+	if (it == m_container.cend())
+		return end();
+
+	return it;
+}
+
+//
+// -------------------------------------------------------------------------------------------------
+//
+
+template<typename T, typename C>
+auto Container<T, C>::find (Function<bool (T const&)> func) -> Iterator
+{
+	for (Iterator it = begin(); it != end(); ++it)
+	{
+		if (func (*it))
+			return it;
+	}
+
+	return end();
+}
+
+//
+// -------------------------------------------------------------------------------------------------
+//
+
+template<typename T, typename C>
+auto Container<T, C>::find (Function<bool (T const&)> func) const -> ConstIterator
+{
+	for (ConstIterator it = begin(); it != end(); ++it)
+	{
+		if (func (*it))
+			return it;
+	}
+
+	return end();
+}
+
+//
+// -------------------------------------------------------------------------------------------------
+//
+
+template<typename T, typename C>
+auto Container<T, C>::remove_one (const T& a) -> void
+{
+	auto it = std::find (m_container.begin(), m_container.end(), a);
+
+	if (it != m_container.end())
+		m_container.erase (it);
+}
+
+//
+// -------------------------------------------------------------------------------------------------
+//
+
+template<typename T, typename C>
+auto Container<T, C>::is_empty() const -> bool
+{
+	return size() == 0;
+}
+
+//
+// -------------------------------------------------------------------------------------------------
+//
+
+template<typename T, typename C>
+auto Container<T, C>::splice (int a, int b) const -> Self
+{
+	if (a < 0 or b >= size() or b < a)
+		return Self();
+
+	Self result;
+
+	for (int i = a; i <= b; ++i)
+		result << operator[] (i);
+
+	return result;
+}
+
+//
+// -------------------------------------------------------------------------------------------------
+//
+
+template<typename T, typename C>
+auto Container<T, C>::splice (const Range<int>& a) const -> Self
+{
+	return splice (a.min(), a.max());
+}
+
+//
+// -------------------------------------------------------------------------------------------------
+//
+
+template<typename T, typename C>
+auto Container<T, C>::container() const -> const C&
+{
+	return m_container;
+}
+
+//
+// -------------------------------------------------------------------------------------------------
+//
+
+template<typename T, typename C>
+auto Container<T, C>::first() const -> const T&
+{
+	return *m_container.cbegin();
+}
+
+//
+// -------------------------------------------------------------------------------------------------
+//
+
+template<typename T, typename C>
+auto Container<T, C>::last() const -> const T&
+{
+	return *(m_container.cend() - 1);
+}
+
+//
+// -------------------------------------------------------------------------------------------------
+//
+
+template<typename T, typename C>
+auto Container<T, C>::contains (const T& a) const -> bool
+{
+	return std::find (m_container.cbegin(), m_container.cend(), a) != m_container.end();
+}
+
+//
+// -------------------------------------------------------------------------------------------------
+//
+
+template<typename T, typename C>
+auto Container<T, C>::operator+ (const Self& other) const -> Self
+{
+	Self out (*this);
+	out.merge (other);
+	return out;
+}
+
+//
+// -------------------------------------------------------------------------------------------------
+//
+
+template<typename T, typename C>
+auto operator>> (const T& value, Container<T, C>& haystack) -> Container<T, C>&
+{
+	haystack.prepend (value);
+	return haystack;
+}

mercurial