From 8feac38d029b8897ab294b2122dab89dbac76ae5 Mon Sep 17 00:00:00 2001 From: jwellbelove Date: Mon, 3 Nov 2014 12:32:43 +0000 Subject: [PATCH] Double ended queue container added --- deque.h | 153 ++++ deque_base.h | 182 ++++ ideque.h | 1381 ++++++++++++++++++++++++++++++ test/test_deque.cpp | 1976 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 3692 insertions(+) create mode 100644 deque.h create mode 100644 deque_base.h create mode 100644 ideque.h create mode 100644 test/test_deque.cpp diff --git a/deque.h b/deque.h new file mode 100644 index 00000000..c13e2365 --- /dev/null +++ b/deque.h @@ -0,0 +1,153 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. + +Copyright(c) 2014 jwellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef __etl_deque__ +#define __etl_deque__ + +#include +#include +#include + +#include "ideque.h" +#include "container.h" + +//***************************************************************************** +///\defgroup deque deque +/// A double ended queue with the capacity defined at compile time. +///\ingroup containers +//***************************************************************************** + +namespace etl +{ + //*************************************************************************** + /// A fixed capacity double ended queue. + ///\tparam T The type of items this deque holds. + ///\tparam MAX_SIZE_ The capacity of the deque + ///\ingroup deque + //*************************************************************************** + template + class deque : public ideque + { + public: + + static const size_t MAX_SIZE = MAX_SIZE_; + + private: + + static const size_t BUFFER_SIZE = MAX_SIZE + 1; + + public: + + typedef T value_type; + typedef T* pointer; + typedef const T* const_pointer; + typedef T& reference; + typedef const T& const_reference; + typedef size_t size_type; + typedef typename std::iterator_traits::difference_type difference_type; + + //************************************************************************* + /// Default constructor. + //************************************************************************* + deque() + : ideque(&buffer[0], MAX_SIZE, BUFFER_SIZE) + { + } + + //************************************************************************* + /// Copy constructor. + //************************************************************************* + deque(const deque& other) + : ideque(&buffer[0], MAX_SIZE, BUFFER_SIZE) + { + ideque::assign(other.begin(), other.end()); + } + + //************************************************************************* + /// Assigns data to the deque. + //************************************************************************* + template + deque(TIterator begin, TIterator end) + : ideque(&buffer[0], MAX_SIZE, BUFFER_SIZE) + { + ideque::assign(begin, end); + } + + //************************************************************************* + /// Assigns data to the deque. + //************************************************************************* + explicit deque(size_t n, const value_type& value = value_type()) + : ideque(&buffer[0], MAX_SIZE, BUFFER_SIZE) + { + ideque::assign(n, value); + } + + //************************************************************************* + /// Assignment operator. + //************************************************************************* + deque& operator =(const deque& other) + { + ideque::assign(other.begin(), other.end()); + + return *this; + } + + //************************************************************************* + /// Swap + //************************************************************************* + void swap(deque& other) + { + // Swap the internal iterators. + first.swap(other.first); + last.swap(other.last); + + // Swap the other data. + std::swap_ranges(etl::begin(buffer), etl::end(buffer), etl::begin(other.buffer)); + std::swap(current_size, other.current_size); + } + + private: + + /// The buffer. + T buffer[BUFFER_SIZE]; + }; +} + +namespace std +{ + //************************************************************************* + /// Swap + //************************************************************************* + template + void swap(etl::deque< T, MAX_SIZE>& first, etl::deque< T, MAX_SIZE>& second) + { + first.swap(second); + } +} + +#endif diff --git a/deque_base.h b/deque_base.h new file mode 100644 index 00000000..0bf6dc12 --- /dev/null +++ b/deque_base.h @@ -0,0 +1,182 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. + +Copyright(c) 2014 jwellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef __etl_in_ideque_h__ +#error This header is a private element of etl::deque & etl::ideque +#endif + +#ifndef __etl_deque_base__ +#define __etl_deque_base__ + +#include + +#include "exception.h" + +namespace etl +{ +#ifdef ETL_USE_EXCEPTIONS + //*************************************************************************** + /// Exception base for deques + ///\ingroup deque + //*************************************************************************** + class deque_exception : public exception + { + public: + + deque_exception(const char* what) + : exception(what) + { + } + }; + + //*************************************************************************** + /// Deque full exception. + ///\ingroup deque + //*************************************************************************** + class deque_full : public deque_exception + { + public: + + deque_full() + : deque_exception("deque full") + { + } + }; + + //*************************************************************************** + /// Deque empty exception. + ///\ingroup deque + //*************************************************************************** + class deque_empty : public deque_exception + { + public: + + deque_empty() + : deque_exception("deque empty") + { + } + }; + + //*************************************************************************** + /// Deque out of bounds exception. + ///\ingroup deque + //*************************************************************************** + class deque_out_of_bounds : public deque_exception + { + public: + + deque_out_of_bounds() + : deque_exception("deque out of bounds") + { + } + }; + +#endif + + //*************************************************************************** + /// The base class for all templated deque types. + ///\ingroup deque + //*************************************************************************** + class deque_base + { + public: + + typedef size_t size_type; + + //************************************************************************* + /// Gets the current size of the deque. + ///\return The current size of the deque. + //************************************************************************* + size_type size() const + { + return current_size; + } + + //************************************************************************* + /// Checks the 'empty' state of the deque. + ///\return true if empty. + //************************************************************************* + bool empty() const + { + return (current_size == 0); + } + + //************************************************************************* + /// Checks the 'full' state of the deque. + ///\return true if full. + //************************************************************************* + bool full() const + { + return current_size == MAX_SIZE; + } + + //************************************************************************* + /// Returns the capacity of the deque. + ///\return The capacity of the deque. + //************************************************************************* + size_type capacity() const + { + return MAX_SIZE; + } + + //************************************************************************* + /// Returns the maximum possible size of the deque. + ///\return The maximum size of the deque. + //************************************************************************* + size_type max_size() const + { + return MAX_SIZE; + } + + //************************************************************************* + /// Clears the deque. + //************************************************************************* + void clear() + { + current_size = 0; + } + + protected: + + //************************************************************************* + /// Constructor. + //************************************************************************* + deque_base(size_t max_size, size_t buffer_size) + : current_size(0), + MAX_SIZE(max_size), + BUFFER_SIZE(buffer_size) + { + } + + size_type current_size; ///< The current number of elements in the deque. + const size_type MAX_SIZE; ///< The maximum number of elements in the deque. + const size_type BUFFER_SIZE; ///< The of elements in the buffer. + }; +} + +#endif diff --git a/ideque.h b/ideque.h new file mode 100644 index 00000000..0899aab8 --- /dev/null +++ b/ideque.h @@ -0,0 +1,1381 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. + +Copyright(c) 2014 jwellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef __etl_ideque__ +#define __etl_ideque__ +#define __etl_in_ideque_h__ + +#include +#include + +#include "type_traits.h" +#include "deque_base.h" + +namespace etl +{ + //*************************************************************************** + /// The base class for all etl::deque classes. + ///\tparam T The type of values this deque should hold. + ///\ingroup deque + //*************************************************************************** + template + class ideque : public deque_base + { + public: + + typedef T* pointer; + typedef const T* const_pointer; + typedef T& reference; + typedef const T& const_reference; + typedef size_t size_type; + typedef T value_type; + typedef typename std::iterator_traits::difference_type difference_type; + + private: + + //************************************************************************* + /// Test for an iterator. + //************************************************************************* + template + struct is_iterator : public etl::integral_constant::value && !etl::is_floating_point::value> + { + }; + + //************************************************************************* + /// Iterator common parts. + //************************************************************************* + struct iterator_common + { + //*************************************************** + iterator_common() + : index(0), + p_buffer(nullptr), + p_deque(nullptr) + { + } + + //*************************************************** + iterator_common(difference_type index, + ideque& the_deque, + pointer p_buffer) + : index(index), + p_deque(&the_deque), + p_buffer(p_buffer) + { + } + + //*************************************************** + inline difference_type get_index() const + { + return index; + } + + //*************************************************** + inline ideque& get_deque() const + { + return *p_deque; + } + + //*************************************************** + inline pointer get_buffer() const + { + return p_buffer; + } + + //*************************************************** + void swap(iterator_common& other) + { + std::swap(index, other.index); + } + + protected: + + difference_type index; + pointer p_buffer; + ideque* p_deque; + }; + + public: + + //************************************************************************* + /// Iterator + //************************************************************************* + struct iterator : public iterator_common, + public std::iterator + { + friend class ideque; + + //*************************************************** + iterator() + : iterator_common() + { + } + + //*************************************************** + iterator(const iterator& other) + : iterator_common(other.index, *other.p_deque, other.p_buffer) + { + } + + //*************************************************** + iterator& operator ++() + { + index = (index == p_deque->MAX_SIZE) ? 0 : index + 1; + + return *this; + } + + //*************************************************** + iterator operator ++(int) + { + iterator previous(*this); + index = (index == p_deque->MAX_SIZE) ? 0 : index + 1; + + return previous; + } + + //*************************************************** + reference operator +=(difference_type offset) + { + if (offset > 0) + { + index += offset; + index = (static_cast(index) > p_deque->MAX_SIZE) ? index - p_deque->BUFFER_SIZE : index; + } + else if (offset < 0) + { + operator -= (-offset); + } + + return p_buffer[index]; + } + + //*************************************************** + reference operator -=(difference_type offset) + { + if (offset > 0) + { + index -= offset; + index = (index < 0) ? index + p_deque->BUFFER_SIZE : index; + } + else if (offset < 0) + { + operator += (-offset); + } + + return p_buffer[index]; + } + + //*************************************************** + iterator& operator --() + { + index = (index == 0) ? p_deque->MAX_SIZE : index - 1; + + return *this; + } + + //*************************************************** + iterator operator --(int) + { + iterator previous(*this); + index = (index == 0) ? p_deque->MAX_SIZE : index - 1; + + return previous; + } + + //*************************************************** + reference operator *() + { + return p_buffer[index]; + } + + //*************************************************** + const_reference operator *() const + { + return p_buffer[index]; + } + + //*************************************************** + pointer operator ->() + { + return &p_buffer[index]; + } + + //*************************************************** + const_pointer operator ->() const + { + return &p_buffer[index]; + } + + //*************************************************** + bool operator <(const iterator& other) const + { + return ideque::distance(*this, other) > 0; + } + + //*************************************************** + friend iterator operator +(const iterator& lhs, difference_type offset) + { + iterator result(lhs); + result += offset; + return result; + } + + //*************************************************** + friend iterator operator -(const iterator& lhs, difference_type offset) + { + iterator result(lhs); + result -= offset; + return result; + } + + //*************************************************** + friend bool operator == (const iterator& lhs, const iterator& rhs) + { + return lhs.index == rhs.index; + } + + //*************************************************** + friend bool operator != (const iterator& lhs, const iterator& rhs) + { + return !(lhs == rhs); + } + + private: + + //*************************************************** + iterator(difference_type index, ideque& the_deque, pointer p_buffer) + : iterator_common(index, the_deque, p_buffer) + { + } + }; + + //************************************************************************* + /// Const Iterator + //************************************************************************* + struct const_iterator : public iterator_common, + public std::iterator + { + friend class ideque; + + //*************************************************** + const_iterator() + : iterator_common() + { + } + + //*************************************************** + const_iterator(const const_iterator& other) + : iterator_common(other.index, *other.p_deque, other.p_buffer) + { + } + + //*************************************************** + const_iterator(const typename ideque::iterator& other) + : iterator_common(other.get_index(), other.get_deque(), other.get_buffer()) + { + } + + //*************************************************** + const_iterator& operator ++() + { + index = (index == p_deque->MAX_SIZE) ? 0 : index + 1; + + return *this; + } + + //*************************************************** + const_iterator operator ++(int) + { + const_iterator previous(*this); + index = (index == p_deque->MAX_SIZE) ? 0 : index + 1; + + return previous; + } + + //*************************************************** + reference operator +=(difference_type offset) + { + if (offset > 0) + { + index += offset; + index = (static_cast(index) > p_deque->MAX_SIZE) ? index - p_deque->BUFFER_SIZE : index; + } + else if (offset < 0) + { + operator -= (-offset); + } + + return p_buffer[index]; + } + + //*************************************************** + reference operator -=(difference_type offset) + { + if (offset > 0) + { + index -= offset; + index = (index < 0) ? index + p_deque->BUFFER_SIZE : index; + } + else if (offset < 0) + { + operator += (-offset); + } + + return p_buffer[index]; + } + + //*************************************************** + const_iterator& operator --() + { + index = (index == 0) ? p_deque->MAX_SIZE : index - 1; + + return *this; + } + + //*************************************************** + const_iterator operator --(int) + { + iterator previous(*this); + index = (index == 0) ? p_deque->MAX_SIZE : index - 1; + + return previous; + } + + //*************************************************** + const_reference operator *() const + { + return p_buffer[index]; + } + + //*************************************************** + const_pointer operator ->() const + { + return &p_buffer[index]; + } + + //*************************************************** + bool operator <(const const_iterator& other) const + { + return ideque::distance(*this, other) > 0; + } + + //*************************************************** + friend const_iterator operator +(const const_iterator& lhs, difference_type offset) + { + const_iterator result(lhs); + result += offset; + return result; + } + + //*************************************************** + friend const_iterator operator -(const const_iterator& lhs, difference_type offset) + { + const_iterator result(lhs); + result -= offset; + return result; + } + + //*************************************************** + friend bool operator == (const const_iterator& lhs, const const_iterator& rhs) + { + return lhs.index == rhs.index; + } + + //*************************************************** + friend bool operator != (const const_iterator& lhs, const const_iterator& rhs) + { + return !(lhs == rhs); + } + + private: + + //*************************************************** + static difference_type distance(difference_type firstIndex, difference_type index) + { + if (index < firstIndex) + { + return p_deque->BUFFER_SIZE + index - firstIndex; + } + else + { + return index - firstIndex; + } + } + + //*************************************************** + const_iterator(difference_type index, ideque& the_deque, pointer p_buffer) + : iterator_common(index, the_deque, p_buffer) + { + } + }; + + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; + + //************************************************************************* + /// Clears the deque. + //************************************************************************* + void clear() + { + first = iterator(0, *this, p_buffer); + last = iterator(0, *this, p_buffer); + current_size = 0; + } + + //************************************************************************* + /// Gets an iterator to the beginning of the deque. + //************************************************************************* + inline iterator begin() + { + return first; + } + + //************************************************************************* + /// Gets an iterator to the end of the deque. + //************************************************************************* + inline iterator end() + { + return ++iterator(last); + } + + //************************************************************************* + /// Gets a const iterator to the beginning of the deque. + //************************************************************************* + inline const_iterator begin() const + { + return first; + } + + //************************************************************************* + /// Gets a const iterator to the end of the deque. + //************************************************************************* + inline const_iterator end() const + { + return ++iterator(last); + } + + //************************************************************************* + /// Gets a const iterator to the beginning of the deque. + //************************************************************************* + inline const_iterator cbegin() const + { + return first; + } + + //************************************************************************* + /// Gets a const iterator to the end of the deque. + //************************************************************************* + inline const_iterator cend() const + { + return ++const_iterator(last); + } + + //************************************************************************* + /// Gets a reverse iterator to the end of the deque. + //************************************************************************* + inline reverse_iterator rbegin() + { + return reverse_iterator(end()); + } + + //************************************************************************* + /// Gets a reverse iterator to the beginning of the deque. + //************************************************************************* + inline reverse_iterator rend() + { + return reverse_iterator(begin()); + } + + //************************************************************************* + /// Gets a const reverse iterator to the end of the deque. + //************************************************************************* + inline const_reverse_iterator rbegin() const + { + return const_reverse_iterator(end()); + } + + //************************************************************************* + /// Gets a const reverse iterator to the beginning of the deque. + //************************************************************************* + inline const_reverse_iterator rend() const + { + return const_reverse_iterator(begin()); + } + + //************************************************************************* + /// Gets a const reverse iterator to the end of the deque. + //************************************************************************* + inline const_reverse_iterator crbegin() const + { + return const_reverse_iterator(cend()); + } + + //************************************************************************* + /// Gets a const reverse iterator to the beginning of the deque. + //************************************************************************* + inline const_reverse_iterator crend() const + { + return const_reverse_iterator(cbegin()); + } + + //************************************************************************* + /// Assigns a range to the deque. + //************************************************************************* + template + typename etl::enable_if::value, void>::type + assign(TIterator range_begin, TIterator range_end) + { + clear(); + + while (range_begin != range_end) + { + push_back(*range_begin++); + } + } + + //************************************************************************* + /// Assigns 'n' copies of a value to the deque. + /// If ETL_USE_EXCEPTIONS is defined, throws an etl::deque_full is 'n' is too large. + ///\param n The number of copies to assign. + ///\param value The value to add.< + //************************************************************************* + void assign(size_type n, const value_type& value) + { +#ifdef ETL_USE_EXCEPTIONS + if (n > MAX_SIZE) + { + throw deque_full(); + } +#endif + + clear(); + + std::fill_n(p_buffer, n, value); + + first.index = 0; + last.index = n - 1; + current_size = n; + } + + //************************************************************************* + /// Resizes the deque. + /// If ETL_USE_EXCEPTIONS is defined, throws an etl::deque_full is 'new_size' is too large. + ///\param new_size The new size of the deque. + ///\param value The value to assign if the new size is larger. Default = Default constructed value. + //************************************************************************* + void resize(size_t new_size, const value_type& value = value_type()) + { + if (new_size <= MAX_SIZE) + { + // Make it smaller? + if (new_size < current_size) + { + last -= (current_size - new_size); + } + // Make it larger? + else if (new_size > current_size) + { + size_t count = new_size - current_size; + + for (size_t i = 0; i < count; ++i) + { + *(++last) = value; + } + } + + current_size = new_size; + } +#ifdef ETL_USE_EXCEPTIONS + else + { + throw deque_out_of_bounds(); + } +#endif + } + + //************************************************************************* + /// Adds an item to the front of the deque. + /// If ETL_USE_EXCEPTIONS is defined, throws an etl::deque_full is the deque is already full. + ///\param item The item to push to the deque. + //************************************************************************* + void push_front(const_reference item) + { + if (!full()) + { + if (!empty()) + { + --first; + } + + *first = item; + ++current_size; + } +#ifdef ETL_USE_EXCEPTIONS + else + { + throw deque_full(); + } +#endif + } + + //************************************************************************* + /// Adds one to the front of the deque and returns a reference to the new element. + /// If ETL_USE_EXCEPTIONS is defined, throws an etl::deque_full is the deque is already full. + ///\return A reference to the item to assign to. + //************************************************************************* + reference push_front() + { + if (!full()) + { + if (!empty()) + { + --first; + } + + ++current_size; + } +#ifdef ETL_USE_EXCEPTIONS + else + { + throw deque_full(); + } +#endif + + return *first; + } + + //************************************************************************* + /// Adds an item to the back of the deque. + /// If ETL_USE_EXCEPTIONS is defined, throws an etl::deque_full is the deque is already full. + ///\param "item The item to push to the deque. + //************************************************************************* + void push_back(const_reference item) + { + if (!full()) + { + if (!empty()) + { + ++last; + } + + *last = item; + ++current_size; + } +#ifdef ETL_USE_EXCEPTIONS + else + { + throw deque_full(); + } +#endif + } + + //************************************************************************* + /// Adds one to the front of the deque and returns a reference to the new element. + /// If ETL_USE_EXCEPTIONS is defined, throws an etl::deque_full is the deque is already full. + ///\return A reference to the item to assign to. + //************************************************************************* + reference push_back() + { + if (!full()) + { + if (!empty()) + { + ++last; + } + + ++current_size; + } +#ifdef ETL_USE_EXCEPTIONS + else + { + throw deque_full(); + } +#endif + + return *last; + } + + //************************************************************************* + /// Removes the oldest item from the deque. + //************************************************************************* + void pop_front() + { + if (!empty()) + { + ++first; + --current_size; + } + } + + //************************************************************************* + /// Removes the oldest item from the deque. + //************************************************************************* + void pop_back() + { + if (!empty()) + { + --last; + --current_size; + } + } + + //************************************************************************* + /// Gets a reference to the item at the front of the deque. + /// If ETL_USE_EXCEPTIONS is defined, throws an etl::deque_empty if the deque is empty. + ///\return A reference to the item at the front of the deque. + //************************************************************************* + reference front() + { +#ifdef ETL_USE_EXCEPTIONS + if (empty()) + { + throw deque_empty(); + } +#endif + + return *first; + } + + //************************************************************************* + /// Gets a const reference to the item at the front of the deque. + /// If ETL_USE_EXCEPTIONS is defined, throws an etl::deque_empty if the deque is empty. + ///\return A const reference to the item at the front of the deque. + //************************************************************************* + const_reference front() const + { +#ifdef ETL_USE_EXCEPTIONS + if (empty()) + { + throw deque_empty(); + } +#endif + + return *first; + } + + //************************************************************************* + /// Gets a reference to the item at the back of the deque. + /// If ETL_USE_EXCEPTIONS is defined, throws an etl::deque_empty if the deque is empty. + ///\return A reference to the item at the back of the deque. + //************************************************************************* + reference back() + { +#ifdef ETL_USE_EXCEPTIONS + if (empty()) + { + throw deque_empty(); + } +#endif + + return *last; + } + + //************************************************************************* + /// Gets a const reference to the item at the back of the deque. + /// If ETL_USE_EXCEPTIONS is defined, throws an etl::deque_empty if the deque is empty. + ///\return A const reference to the item at the back of the deque. + //************************************************************************* + const_reference back() const + { +#ifdef ETL_USE_EXCEPTIONS + if (empty()) + { + throw deque_empty(); + } +#endif + + return *last; + } + + //************************************************************************* + /// Gets a reference to the item at the index. + /// If ETL_USE_EXCEPTIONS is defined, throws an etl::deque_out_of_bounds if the index is out of range. + ///\return A reference to the item at the index. + //************************************************************************* + reference operator [](size_t index) + { +#ifdef ETL_USE_EXCEPTIONS + if (index >= current_size) + { + throw deque_out_of_bounds(); + } +#endif + + iterator result(first); + result += index; + + return *result; + } + + //************************************************************************* + /// Gets a const reference to the item at the index. + /// If ETL_USE_EXCEPTIONS is defined, throws an etl::deque_out_of_bounds if the index is out of range. + ///\return A const reference to the item at the index. + //************************************************************************* + const_reference operator [](size_t index) const + { +#ifdef ETL_USE_EXCEPTIONS + if (index >= current_size) + { + throw deque_out_of_bounds(); + } +#endif + + iterator result(first); + result += index; + + return *result; + } + + //************************************************************************* + /// Inserts data into the deque. + /// If ETL_USE_EXCEPTIONS is defined, throws an etl::deque_full if the deque is full. + ///\param insert_position>The insert position. + ///\param value>The value to insert. + //************************************************************************* + iterator insert(const_iterator insert_position, const value_type& value) + { + iterator position(insert_position.index, *this, p_buffer); + + if (!full()) + { + if (insert_position == begin()) + { + push_front(value); + position = first; + } + else if (insert_position == end()) + { + push_back(value); + position = last; + } + else + { + // Are we closer to the front? + if (std::distance(first, position) < std::distance(position, last)) + { + // Move the values. + std::copy(first, position, first - 1); + + // Write the new value. + *(--position) = value; + + // Adjust the iterator + --first; + } + else + { + // Adjust the iterator + ++last; + + // Move the values. + std::copy_backward(position, last, last + 1); + + // Write the new value. + *position = value; + } + + ++current_size; + } + } + else +#ifdef ETL_USE_EXCEPTIONS + { + throw deque_full(); + } +#endif + + return position; + } + + //************************************************************************* + /// Inserts 'n' copies of a value into the deque. + /// If ETL_USE_EXCEPTIONS is defined, throws an etl::deque_full if the deque is full. + ///\param insert_position The insert position. + ///\param n The number of values to insert. + ///\param value The value to insert. + //************************************************************************* + iterator insert(const_iterator insert_position, size_type n, const value_type& value) + { + iterator position; + + if ((current_size + n) <= MAX_SIZE) + { + if (insert_position == begin()) + { + first -= n; + std::fill_n(first, n, value); + position = first; + } + else if (insert_position == end()) + { + position = last + 1; + std::fill_n(position, n, value); + last += n; + } + else + { + // Non-const insert iterator. + position = iterator(insert_position.index, *this, p_buffer); + + // Are we closer to the front? + if (distance(first, insert_position) < difference_type(current_size / 2)) + { + iterator new_first = first - n; + iterator new_position = position - n; + + // Move the values. + std::copy(first, position, new_first); + + // Write the new value. + std::fill_n(new_position, n, value); + + // Adjust the iterators + first = new_first; + position = new_position; + } + else + { + iterator new_last = last + n; + + // Move the values. + std::copy_backward(position, last + 1, new_last + 1); + + // Write the new value. + std::fill_n(position, n, value); + + // Adjust the iterator + last = new_last; + } + } + + current_size += n; + } +#ifdef ETL_USE_EXCEPTIONS + else + { + throw deque_full(); + } +#endif + + return position; + } + + //************************************************************************* + /// Inserts a range into the deque. + /// If ETL_USE_EXCEPTIONS is defined, throws an etl::deque_empty if the deque is full. + ///\param insert_position>The insert position. + ///\param range_begin The beginning of the range to insert. + ///\param range_end The end of the range to insert. + //************************************************************************* + template + typename enable_if::value, iterator>::type + insert(const_iterator insert_position, TIterator range_begin, TIterator range_end) + { + iterator position; + + // Find out how much room we need. + size_t n = std::distance(range_begin, range_end); + + if ((current_size + n) <= MAX_SIZE) + { + if (insert_position == begin()) + { + // Adjust the iterator. + first -= n; + iterator destination(first); + + // Copy them over. + while (range_begin != range_end) + { + *destination++ = *range_begin++; + } + + position = first; + } + else if (insert_position == end()) + { + position = last + 1; + + while (range_begin != range_end) + { + *(++last) = *range_begin++; + } + } + else + { + // Non-const insert iterator. + position = iterator(insert_position.index, *this, p_buffer); + + // Are we closer to the front? + if (distance(first, insert_position) < difference_type(current_size / 2)) + { + iterator new_first = first - n; + iterator new_position = position - n; + + // Move the values. + std::copy(first, position, new_first); + + // Write the new values. + std::copy(range_begin, range_end, new_position); + + // Adjust the iterators + first = new_first; + position = new_position; + } + else + { + iterator new_last = last + n; + + // Move the values. + std::copy_backward(position, last + 1, new_last + 1); + + // Write the new values. + std::copy(range_begin, range_end, position); + + // Adjust the iterator. + last = new_last; + } + } + + current_size += n; + } +#ifdef ETL_USE_EXCEPTIONS + else + { + throw deque_full(); + } +#endif + + return position; + } + + //************************************************************************* + /// erase an item. + /// If ETL_USE_EXCEPTIONS is defined, throws an etl::deque_out_of_bounds if the position is out of range. + ///\param erase_position The position to erase. + //************************************************************************* + iterator erase(const_iterator erase_position) + { + iterator position(erase_position.index, *this, p_buffer); + + if (distance(position) <= difference_type(current_size)) + { + if (position == first) + { + ++first; + position = first; + } + else if (position == last) + { + --last; + } + else + { + // Are we closer to the front? + if (distance(first, position) < difference_type(current_size / 2)) + { + std::copy_backward(first, position, position + 1); + ++first; + ++position; + } + else + { + std::copy(position + 1, last + 1, position); + --last; + } + } + + --current_size; + } +#ifdef ETL_USE_EXCEPTIONS + else + { + throw deque_out_of_bounds(); + } +#endif + + return position; + } + + //************************************************************************* + /// erase a range. + /// If ETL_USE_EXCEPTIONS is defined, throws an etl::deque_out_of_bounds if the iterators are out of range. + ///\param range_begin The beginning of the range to erase. + ///\param range_end The end of the range to erase. + //************************************************************************* + iterator erase(const_iterator range_begin, const_iterator range_end) + { + iterator position(range_begin.index, *this, p_buffer); + + if ((distance(range_begin) <= difference_type(current_size)) && + (distance(range_end) <= difference_type(current_size))) + { + // How many to erase? + difference_type length = std::distance(range_begin, range_end); + + // At the beginning? + if (position == first) + { + first += length; + position = first; + } + // At the end? + else if (position == last - length + 1) + { + last -= length; + } + else + { + // Copy the smallest number of items. + // Are we closer to the front? + if (distance(first, position) < difference_type(current_size / 2)) + { + // Move the items. + std::copy_backward(first, position, position + length); + first += length; + position += length; + } + else + // Must be closer to the back. + { + // Move the items. + std::copy(position + length, last + 1, position); + last -= length; + } + } + + current_size -= length; + } +#ifdef ETL_USE_EXCEPTIONS + else + { + throw deque_out_of_bounds(); + } +#endif + + return position; + } + + //************************************************************************* + /// Assignment operator. + //************************************************************************* + ideque& operator =(const ideque& other) + { + assign(other.begin(), other.end()); + + return *this; + } + + //************************************************************************* + /// - operator for iterator + //************************************************************************* + friend difference_type operator -(const iterator& lhs, const iterator& rhs) + { + return distance(rhs, lhs); + } + + //************************************************************************* + /// - operator for const_iterator + //************************************************************************* + friend difference_type operator -(const const_iterator& lhs, const const_iterator& rhs) + { + return distance(rhs, lhs); + } + + //************************************************************************* + /// - operator for reverse_iterator + //************************************************************************* + friend difference_type operator -(const reverse_iterator& lhs, const reverse_iterator& rhs) + { + return distance(lhs.base(), rhs.base()); + } + + //************************************************************************* + /// - operator for const_reverse_iterator + //************************************************************************* + friend difference_type operator -(const const_reverse_iterator& lhs, const const_reverse_iterator& rhs) + { + return distance(lhs.base(), rhs.base()); + } + + //************************************************************************* + /// Equality operator. + //************************************************************************* + friend bool operator ==(const ideque& lhs, const ideque& rhs) + { + return (lhs.size() == rhs.size()) && std::equal(lhs.begin(), lhs.end(), rhs.begin()); + } + + //************************************************************************* + /// Inequality operator. + //************************************************************************* + friend bool operator !=(const ideque& lhs, const ideque& rhs) + { + return !(lhs == rhs); + } + + protected: + + //************************************************************************* + /// Constructor. + //************************************************************************* + ideque(T* p_buffer, size_t max_size, size_t buffer_size) + : deque_base(max_size, buffer_size), + p_buffer(p_buffer) + { + clear(); + } + + iterator first; ///Iterator to the first item in the deque. + iterator last; ///Iterator to the last item in the deque. + T* p_buffer; ///The buffer. + + private: + + //************************************************************************* + /// Measures the distance between two iterators. + //************************************************************************* + template + static difference_type distance(const TIterator1& range_begin, const TIterator2& range_end) + { + difference_type distance1 = distance(range_begin); + difference_type distance2 = distance(range_end); + + return distance2 - distance1; + } + + //************************************************************************* + /// Measures the distance from the first iterator to the specified iterator. + //************************************************************************* + template + static difference_type distance(const TIterator& it) + { + const difference_type index = it.get_index(); + const difference_type reference_index = it.get_deque().first.index; + const size_t buffer_size = it.get_deque().BUFFER_SIZE; + + if (index < reference_index) + { + return buffer_size + index - reference_index; + } + else + { + return index - reference_index; + } + } + }; +} + +//*************************************************************************** +/// Equal operator. +///\param lhs Reference to the first array. +///\param rhs Reference to the second array. +///\return true if the arrays are equal, otherwise false +///\ingroup deque +//*************************************************************************** +template +bool operator ==(const etl::ideque& lhs, const etl::ideque& rhs) +{ + return (lhs.size() == rhs.size()) && std::equal(lhs.begin(), lhs.end(), rhs.begin()); +} + +//*************************************************************************** +/// Not equal operator. +///\param lhs Reference to the first array. +///\param rhs Reference to the second array. +///\return true if the arrays are not equal, otherwise false +///\ingroup deque +//*************************************************************************** +template +bool operator !=(const etl::ideque& lhs, const etl::ideque& rhs) +{ + return !(lhs == rhs); +} + +//*************************************************************************** +/// Less than operator. +///\param lhs Reference to the first array. +///\param rhs Reference to the second array. +///\return true if the first array is lexigraphically less than the second, otherwise false +///\ingroup deque +//*************************************************************************** +template +bool operator <(const etl::ideque& lhs, const etl::ideque& rhs) +{ + return std::lexicographical_compare(lhs.begin(), + lhs.end(), + rhs.begin(), + rhs.end()); +} + +//*************************************************************************** +/// Greater than operator. +///\param lhs Reference to the first array. +///\param rhs Reference to the second array. +///\return true if the first array is lexigraphically greater than the second, otherwise false +///\ingroup deque +//*************************************************************************** +template +bool operator >(const etl::ideque& lhs, const etl::ideque& rhs) +{ + return std::lexicographical_compare(lhs.begin(), + lhs.end(), + rhs.begin(), + rhs.end(), + std::greater()); +} + +//*************************************************************************** +/// Less than or equal operator. +///\param lhs Reference to the first array. +///\param rhs Reference to the second array. +///\return true if the first array is lexigraphically less than or equal to the second, otherwise false +///\ingroup deque +//*************************************************************************** +template +bool operator <=(const etl::ideque& lhs, const etl::ideque& rhs) +{ + return !operator >(lhs, rhs); +} + +//*************************************************************************** +/// Greater than or equal operator. +///\param "lhs Reference to the first array. +///\param "rhs Reference to the second array. +///\return true if the first array is lexigraphically greater than or equal to the second, otherwise false +///\ingroup deque +//*************************************************************************** +template +bool operator >=(const etl::ideque& lhs, const etl::ideque& rhs) +{ + return !operator <(lhs, rhs); +} + +#endif diff --git a/test/test_deque.cpp b/test/test_deque.cpp new file mode 100644 index 00000000..a3f61443 --- /dev/null +++ b/test/test_deque.cpp @@ -0,0 +1,1976 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. + +Copyright(c) 2014 jwellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include + +#include "../deque.h" + +#include +#include + +const size_t SIZE = 6; + +typedef etl::deque Data; +typedef std::vector CompareData; + +namespace FixedDequeTest +{ + SUITE(TestDeque) + { + //************************************************************************* + TEST(Contruct) + { + Data data; + + CHECK_EQUAL(SIZE, data.capacity()); + CHECK_EQUAL(SIZE, data.max_size()); + } + + //************************************************************************* + TEST(ContructFill) + { + CompareData compare_data = { 5, 5, 5, 5, 5, 5}; + Data data(SIZE, 5); + + CHECK_EQUAL(compare_data.size(), data.size()); + CHECK(std::equal(compare_data.begin(), compare_data.end(), data.begin())); + } + + //************************************************************************* + TEST(ContructFillExcess) + { + CHECK_THROW(Data(SIZE + 1, 5), etl::deque_full); + } + + //************************************************************************* + TEST(ContructRange) + { + CompareData compare_data = { 1, 2, 3, 4, 5 }; + Data data(compare_data.begin(), compare_data.end()); + + CHECK_EQUAL(compare_data.size(), data.size()); + CHECK(std::equal(compare_data.begin(), compare_data.end(), data.begin())); + } + + //************************************************************************* + TEST(ContructRangeExcess) + { + CompareData compare_data = { 1, 2, 3, 4, 5, 6, 7 }; + + CHECK_THROW(Data data(compare_data.begin(), compare_data.end()), etl::deque_full); + } + + //************************************************************************* + TEST(CopyContruct) + { + CompareData original = { 1, 2, 3, 4, 5, 6 }; + CompareData modified = { 6, 5, 4, 3, 2, 1 }; + + Data testDeque1(original.begin(), original.end()); + Data testDeque2(testDeque1); + + CHECK_EQUAL(testDeque1.size(), testDeque2.size()); + CHECK(std::equal(original.begin(), original.end(), testDeque2.begin())); + + // Change testDeque2's data. + std::copy(modified.begin(), modified.end(), testDeque2.begin()); + CHECK(std::equal(original.begin(), original.end(), testDeque1.begin())); + CHECK(std::equal(modified.begin(), modified.end(), testDeque2.begin())); + } + + //************************************************************************* + TEST(Assignment) + { + CompareData original = { 1, 2, 3, 4, 5, 6 }; + CompareData modified = { 6, 5, 4, 3, 2, 1 }; + + Data testDeque1(original.begin(), original.end()); + Data testDeque2; + + testDeque2 = testDeque1; + + CHECK_EQUAL(testDeque1.size(), testDeque2.size()); + CHECK(std::equal(original.begin(), original.end(), testDeque2.begin())); + + // Change testDeque2's data. + std::copy(modified.begin(), modified.end(), testDeque2.begin()); + CHECK(std::equal(original.begin(), original.end(), testDeque1.begin())); + CHECK(std::equal(modified.begin(), modified.end(), testDeque2.begin())); + } + + //************************************************************************* + TEST(StdSwap) + { + CompareData compare_data1 = { 1, 2, 3, 4, 5, 6 }; + CompareData compare_data2 = { 6, 5, 4 }; + + Data data1(compare_data1.begin(), compare_data1.end()); + Data data2(compare_data2.begin(), compare_data2.end()); + + std::swap(data1, data2); + + CHECK_EQUAL(compare_data2.size(), data1.size()); + CHECK_EQUAL(compare_data1.size(), data2.size()); + + CHECK_EQUAL(std::distance(compare_data2.begin(), compare_data2.end()), std::distance(data1.begin(), data1.end())); + CHECK_EQUAL(std::distance(compare_data1.begin(), compare_data1.end()), std::distance(data2.begin(), data2.end())); + + CHECK(std::equal(compare_data2.begin(), compare_data2.end(), data1.begin())); + CHECK(std::equal(compare_data1.begin(), compare_data1.end(), data2.begin())); + } + + //************************************************************************* + TEST(Clear) + { + Data data; + + data.resize(SIZE); + data.clear(); + CHECK(data.empty()); + } + + //************************************************************************* + TEST(AssignFromRange) + { + CompareData compare_data = { 1, 2, 3, 4, 5 }; + Data data; + + CHECK_NO_THROW(data.assign(compare_data.begin(), compare_data.end())); + + CHECK_EQUAL(compare_data.size(), data.size()); + CHECK(std::equal(compare_data.begin(), compare_data.end(), data.begin())); + } + + //************************************************************************* + TEST(AssignFromRangeExcess) + { + CompareData compare_data = { 1, 2, 3, 4, 5, 6, 7 }; + Data data; + + CHECK_THROW(data.assign(compare_data.begin(), compare_data.end()), etl::deque_full); + } + + //************************************************************************* + TEST(AssignFill) + { + CompareData compare_data = { 5, 5, 5, 5, 5, 5 }; + + Data data; + + CHECK_NO_THROW(data.assign(SIZE, 5)); + + CHECK_EQUAL(compare_data.size(), data.size()); + CHECK(std::equal(compare_data.begin(), compare_data.end(), data.begin())); + } + + //************************************************************************* + TEST(AssignFillExcess) + { + Data data; + + CHECK_THROW(data.assign(SIZE + 1, 5), etl::deque_full); + } + + //************************************************************************* + TEST(PushBackNoValue) + { + CompareData compare_data = { 1, 2, 3, 4, 5 }; + Data data; + + CHECK_NO_THROW(data.push_back()); + CHECK_NO_THROW(data.back() = 1); + CHECK_EQUAL(size_t(1), data.size()); + + CHECK_NO_THROW(data.push_back()); + CHECK_NO_THROW(data.back() = 2); + CHECK_EQUAL(size_t(2), data.size()); + + CHECK_NO_THROW(data.push_back()); + CHECK_NO_THROW(data.back() = 3); + CHECK_EQUAL(size_t(3), data.size()); + + CHECK_NO_THROW(data.push_back()); + CHECK_NO_THROW(data.back() = 4); + CHECK_EQUAL(size_t(4), data.size()); + + CHECK_NO_THROW(data.push_back()); + CHECK_NO_THROW(data.back() = 5); + CHECK_EQUAL(size_t(5), data.size()); + + CHECK(std::equal(compare_data.begin(), compare_data.end(), data.begin())); + } + + //************************************************************************* + TEST(push_back) + { + CompareData compare_data = { 1, 2, 3, 4, 5}; + Data data; + + CHECK_NO_THROW(data.push_back(1)); + CHECK_EQUAL(size_t(1), data.size()); + CHECK(std::equal(compare_data.begin(), compare_data.end() - 4, data.begin())); + + CHECK_NO_THROW(data.push_back(2)); + CHECK_EQUAL(size_t(2), data.size()); + CHECK(std::equal(compare_data.begin(), compare_data.end() - 3, data.begin())); + + CHECK_NO_THROW(data.push_back(3)); + CHECK_EQUAL(size_t(3), data.size()); + CHECK(std::equal(compare_data.begin(), compare_data.end() - 2, data.begin())); + + CHECK_NO_THROW(data.push_back(4)); + CHECK_EQUAL(size_t(4), data.size()); + CHECK(std::equal(compare_data.begin(), compare_data.end() - 1, data.begin())); + + CHECK_NO_THROW(data.push_back(5)); + CHECK_EQUAL(size_t(5), data.size()); + CHECK(std::equal(compare_data.begin(), compare_data.end(), data.begin())); + } + + //************************************************************************* + TEST(PushBackExcess) + { + Data data; + + CHECK_NO_THROW(data.push_back(1)); + CHECK_NO_THROW(data.push_back(2)); + CHECK_NO_THROW(data.push_back(3)); + CHECK_NO_THROW(data.push_back(4)); + CHECK_NO_THROW(data.push_back(5)); + CHECK_NO_THROW(data.push_back(6)); + CHECK_THROW(data.push_back(7), etl::deque_full); + } + + //************************************************************************* + TEST(PushFrontNoValue) + { + CompareData compare_data = {5, 4, 3, 2, 1 }; + Data data; + + CHECK_NO_THROW(data.push_front()); + CHECK_NO_THROW(data.front() = 1); + CHECK_EQUAL(size_t(1), data.size()); + + CHECK_NO_THROW(data.push_front()); + CHECK_NO_THROW(data.front() = 2); + CHECK_EQUAL(size_t(2), data.size()); + + CHECK_NO_THROW(data.push_front()); + CHECK_NO_THROW(data.front() = 3); + CHECK_EQUAL(size_t(3), data.size()); + + CHECK_NO_THROW(data.push_front()); + CHECK_NO_THROW(data.front() = 4); + CHECK_EQUAL(size_t(4), data.size()); + + CHECK_NO_THROW(data.push_front()); + CHECK_NO_THROW(data.front() = 5); + CHECK_EQUAL(size_t(5), data.size()); + + CHECK(std::equal(compare_data.begin(), compare_data.end(), data.begin())); + } + + //************************************************************************* + TEST(PushFront) + { + CompareData compare_data = { 5, 4, 3, 2, 1 }; + Data data; + + CHECK_NO_THROW(data.push_front(1)); + CHECK_EQUAL(size_t(1), data.size()); + CHECK(std::equal(compare_data.begin() + 4, compare_data.end(), data.begin())); + + CHECK_NO_THROW(data.push_front(2)); + CHECK_EQUAL(size_t(2), data.size()); + CHECK(std::equal(compare_data.begin() + 3, compare_data.end(), data.begin())); + + CHECK_NO_THROW(data.push_front(3)); + CHECK_EQUAL(size_t(3), data.size()); + CHECK(std::equal(compare_data.begin() + 2, compare_data.end(), data.begin())); + + CHECK_NO_THROW(data.push_front(4)); + CHECK_EQUAL(size_t(4), data.size()); + CHECK(std::equal(compare_data.begin() + 1, compare_data.end(), data.begin())); + + CHECK_NO_THROW(data.push_front(5)); + CHECK_EQUAL(size_t(5), data.size()); + CHECK(std::equal(compare_data.begin(), compare_data.end(), data.begin())); + } + + //************************************************************************* + TEST(PushFrontExcess) + { + Data data; + + for (size_t i = 0; i < SIZE; ++i) + { + CHECK_NO_THROW(data.push_front(i)); + } + + CHECK_THROW(data.push_front(SIZE), etl::deque_full); + } + + //************************************************************************* + TEST(PushFrontPushBack) + { + CompareData compare_data = { 1, 2, 3, 4, 5}; + Data data; + + CHECK_NO_THROW(data.push_back(3)); + CHECK_NO_THROW(data.push_front(2)); + CHECK_NO_THROW(data.push_back(4)); + CHECK_NO_THROW(data.push_front(1)); + CHECK_NO_THROW(data.push_back(5)); + + CHECK(std::equal(compare_data.begin(), compare_data.end(), data.begin())); + } + + //************************************************************************* + TEST(PopFront) + { + CompareData compare_data = { 1, 2, 3, 4, 5 }; + Data data; + + data.assign(compare_data.begin(), compare_data.end()); + + data.pop_front(); + CHECK_EQUAL(size_t(4), data.size()); + CHECK(std::equal(compare_data.begin() + 1, compare_data.end(), data.begin())); + + data.pop_front(); + CHECK_EQUAL(size_t(3), data.size()); + CHECK(std::equal(compare_data.begin() + 2, compare_data.end(), data.begin())); + + data.pop_front(); + CHECK_EQUAL(size_t(2), data.size()); + CHECK(std::equal(compare_data.begin() + 3, compare_data.end(), data.begin())); + + data.pop_front(); + CHECK_EQUAL(size_t(1), data.size()); + CHECK(std::equal(compare_data.begin() + 4, compare_data.end(), data.begin())); + + data.pop_front(); + CHECK_EQUAL(size_t(0), data.size()); + } + + //************************************************************************* + TEST(PopBack) + { + CompareData compare_data = { 1, 2, 3, 4, 5 }; + Data data; + + data.assign(compare_data.begin(), compare_data.end()); + + data.pop_back(); + CHECK_EQUAL(size_t(4), data.size()); + CHECK(std::equal(compare_data.begin(), compare_data.end() - 1, data.begin())); + + data.pop_back(); + CHECK_EQUAL(size_t(3), data.size()); + CHECK(std::equal(compare_data.begin(), compare_data.end() - 2, data.begin())); + + data.pop_back(); + CHECK_EQUAL(size_t(2), data.size()); + CHECK(std::equal(compare_data.begin(), compare_data.end() - 3, data.begin())); + + data.pop_back(); + CHECK_EQUAL(size_t(1), data.size()); + CHECK(std::equal(compare_data.begin(), compare_data.end() - 4, data.begin())); + + data.pop_back(); + CHECK_EQUAL(size_t(0), data.size()); + } + + //************************************************************************* + TEST(Resize) + { + CompareData compare_data = { 1, 2, 0, 0, 0 }; + Data data; + + data.push_front(1); + data.push_back(2); + data.resize(SIZE); + + CHECK_EQUAL(size_t(SIZE), data.size()); + CHECK(std::equal(compare_data.begin(), compare_data.end(), data.begin())); + } + + //************************************************************************* + TEST(ResizeWithValue) + { + CompareData compare_data = { 1, 2, 3, 3, 3 }; + Data data; + + data.push_front(1); + data.push_back(2); + data.resize(SIZE, 3); + + CHECK_EQUAL(size_t(SIZE), data.size()); + CHECK(std::equal(compare_data.begin(), compare_data.end(), data.begin())); + } + + //************************************************************************* + TEST(ResizeExcess) + { + Data data; + + CHECK_THROW(data.resize(SIZE + 1), etl::deque_out_of_bounds); + } + + //************************************************************************* + TEST(Full) + { + Data data; + data.resize(SIZE); + + CHECK(data.full()); + } + + //************************************************************************* + TEST(empty) + { + Data data; + + CHECK(data.empty()); + } + + //************************************************************************* + TEST(Front) + { + Data data; + + data.push_front(1); + CHECK_EQUAL(1, data.front()); + + data.push_front(2); + CHECK_EQUAL(2, data.front()); + + data.push_front(3); + CHECK_EQUAL(3, data.front()); + + data.push_front(4); + CHECK_EQUAL(4, data.front()); + + data.push_front(5); + CHECK_EQUAL(5, data.front()); + } + + //************************************************************************* + TEST(FrontEmpty) + { + Data data; + + CHECK_THROW(int i = data.front(), etl::deque_empty); + } + + //************************************************************************* + TEST(FrontConst) + { + Data data; + const Data& ctestDeque = data; + + data.push_front(1); + CHECK_EQUAL(1, ctestDeque.front()); + + data.push_front(2); + CHECK_EQUAL(2, ctestDeque.front()); + + data.push_front(3); + CHECK_EQUAL(3, ctestDeque.front()); + + data.push_front(4); + CHECK_EQUAL(4, ctestDeque.front()); + + data.push_front(5); + CHECK_EQUAL(5, ctestDeque.front()); + } + + //************************************************************************* + TEST(Back) + { + Data data; + + data.push_back(1); + CHECK_EQUAL(1, data.back()); + + data.push_back(2); + CHECK_EQUAL(2, data.back()); + + data.push_back(3); + CHECK_EQUAL(3, data.back()); + + data.push_back(4); + CHECK_EQUAL(4, data.back()); + + data.push_back(5); + CHECK_EQUAL(5, data.back()); + } + + //************************************************************************* + TEST(BackConst) + { + Data data; + const Data& ctestDeque = data; + + data.push_back(1); + CHECK_EQUAL(1, ctestDeque.back()); + + data.push_back(2); + CHECK_EQUAL(2, ctestDeque.back()); + + data.push_back(3); + CHECK_EQUAL(3, ctestDeque.back()); + + data.push_back(4); + CHECK_EQUAL(4, ctestDeque.back()); + + data.push_back(5); + CHECK_EQUAL(5, ctestDeque.back()); + } + + //************************************************************************* + TEST(BackEmpty) + { + Data data; + + CHECK_THROW(int i = data.back(), etl::deque_empty); + } + + //************************************************************************* + TEST(Index) + { + CompareData compare_data = { 1, 2, 3, 4, 5 }; + Data data(compare_data.begin(), compare_data.end()); + + CHECK_EQUAL(compare_data[0], data[0]); + CHECK_EQUAL(compare_data[1], data[1]); + CHECK_EQUAL(compare_data[2], data[2]); + CHECK_EQUAL(compare_data[3], data[3]); + CHECK_EQUAL(compare_data[4], data[4]); + } + + //************************************************************************* + TEST(IndexOutOfRange) + { + CompareData compare_data = { 1, 2, 3, 4, 5 }; + Data data(compare_data.begin(), compare_data.end()); + + CHECK_THROW(int i = data[5], etl::deque_out_of_bounds); + } + + //************************************************************************* + TEST(IndexConst) + { + CompareData compare_data = { 1, 2, 3, 4, 5 }; + Data data(compare_data.begin(), compare_data.end()); + const Data& ctestDeque(data); + + CHECK_EQUAL(compare_data[0], ctestDeque[0]); + CHECK_EQUAL(compare_data[1], ctestDeque[1]); + CHECK_EQUAL(compare_data[2], ctestDeque[2]); + CHECK_EQUAL(compare_data[3], ctestDeque[3]); + CHECK_EQUAL(compare_data[4], ctestDeque[4]); + } + + //************************************************************************* + TEST(IndexConstOutOfRange) + { + CompareData compare_data = { 1, 2, 3, 4, 5 }; + Data data(compare_data.begin(), compare_data.end()); + const Data& ctestDeque(data); + + CHECK_THROW(int i = ctestDeque[5], etl::deque_out_of_bounds); + } + + //************************************************************************* + TEST(InsertValueBegin) + { + CompareData original = { 1, 2, 3, 4 }; + CompareData expected = { 5, 1, 2, 3, 4 }; + Data data(original.begin(), original.end()); + + Data::iterator position = data.insert(data.begin(), 5); + + CHECK_EQUAL(expected.size(), data.size()); + CHECK(std::equal(expected.begin(), expected.end(), data.begin())); + CHECK_EQUAL(0, std::distance(data.begin(), position)); + } + + //************************************************************************* + TEST(InsertValueEnd) + { + CompareData original = { 1, 2, 3, 4 }; + CompareData expected = { 1, 2, 3, 4, 5 }; + Data data(original.begin(), original.end()); + + Data::iterator position = data.insert(data.end(), 5); + + CHECK_EQUAL(expected.size(), data.size()); + CHECK(std::equal(expected.begin(), expected.end(), data.begin())); + CHECK_EQUAL(4, std::distance(data.begin(), position)); + } + + //************************************************************************* + TEST(InsertValueMiddle) + { + CompareData original = { 1, 2, 3, 4 }; + CompareData expected1 = { 1, 5, 2, 3, 4 }; + CompareData expected2 = { 1, 2, 5, 3, 4 }; + Data data(original.begin(), original.end()); + + Data::iterator position = data.insert(data.begin() + 1, 5); + + CHECK_EQUAL(expected1.size(), data.size()); + CHECK(std::equal(expected1.begin(), expected1.end(), data.begin())); + CHECK_EQUAL(1, std::distance(data.begin(), position)); + + data.assign(original.begin(), original.end()); + + position = data.insert(data.begin() + 2, 5); + + CHECK_EQUAL(expected2.size(), data.size()); + CHECK(std::equal(expected2.begin(), expected2.end(), data.begin())); + CHECK_EQUAL(2, std::distance(data.begin(), position)); + } + + //************************************************************************* + TEST(InsertNValueBegin) + { + CompareData original = { 1, 2, 3 }; + CompareData expected = { 5, 5, 1, 2, 3 }; + Data data(original.begin(), original.end()); + + Data::iterator position = data.insert(data.begin(), 2, 5); + + CHECK_EQUAL(expected.size(), data.size()); + CHECK(std::equal(expected.begin(), expected.end(), data.begin())); + CHECK_EQUAL(0, std::distance(data.begin(), position)); + } + + //************************************************************************* + TEST(InsertNValueEnd) + { + CompareData original = { 1, 2, 3 }; + CompareData expected = { 1, 2, 3, 5, 5 }; + Data data(original.begin(), original.end()); + + Data::iterator position = data.insert(data.end(), 2, 5); + + CHECK_EQUAL(expected.size(), data.size()); + CHECK(std::equal(expected.begin(), expected.end(), data.begin())); + CHECK_EQUAL(3, std::distance(data.begin(), position)); + } + + //************************************************************************* + TEST(InsertNValueMiddle) + { + CompareData original = { 1, 2, 3, 4 }; + CompareData expected1 = { 1, 5, 5, 2, 3, 4 }; + CompareData expected2 = { 1, 2, 3, 5, 5, 4 }; + Data data(original.begin(), original.end()); + + Data::iterator position = data.insert(data.begin() + 1, 2, 5); + + CHECK_EQUAL(expected1.size(), data.size()); + CHECK(std::equal(expected1.begin(), expected1.end(), data.begin())); + CHECK_EQUAL(1, std::distance(data.begin(), position)); + + data.assign(data.max_size(), -1); + data.assign(original.begin(), original.end()); + + position = data.insert(data.begin() + 3, 2, 5); + + CHECK_EQUAL(expected2.size(), data.size()); + CHECK(std::equal(expected2.begin(), expected2.end(), data.begin())); + CHECK_EQUAL(3, std::distance(data.begin(), position)); + } + + //************************************************************************* + TEST(InsertNValueExcess) + { + CompareData original = { 1, 2, 3, 4 }; + Data data(original.begin(), original.end()); + + CHECK_THROW(data.insert(data.begin(), 3, 5), etl::deque_full); + CHECK_THROW(data.insert(data.end(), 3, 5), etl::deque_full); + CHECK_THROW(data.insert(data.begin() + 2, 3, 5), etl::deque_full); + } + + //************************************************************************* + TEST(InsertRangeBegin) + { + CompareData original = { 1, 2, 3 }; + CompareData range = { 4, 5 }; + CompareData expected = { 4, 5, 1, 2, 3 }; + Data data(original.begin(), original.end()); + + Data::iterator position = data.insert(data.begin(), range.begin(), range.end()); + + CHECK_EQUAL(expected.size(), data.size()); + CHECK(std::equal(expected.begin(), expected.end(), data.begin())); + } + + //************************************************************************* + TEST(InsertRangeEnd) + { + CompareData original = { 1, 2, 3 }; + CompareData range = { 4, 5 }; + CompareData expected = { 1, 2, 3, 4, 5 }; + Data data(original.begin(), original.end()); + + Data::iterator position = data.insert(data.end(), range.cbegin(), range.cend()); + + CHECK_EQUAL(expected.size(), data.size()); + CHECK(std::equal(expected.begin(), expected.end(), data.begin())); + } + + //************************************************************************* + TEST(InsertRangeMiddle) + { + CompareData original = { 1, 2, 3, 4 }; + CompareData range = { 5, 6 }; + CompareData expected1 = { 1, 5, 6, 2, 3, 4 }; + CompareData expected2 = { 1, 2, 3, 5, 6, 4 }; + Data data(original.begin(), original.end()); + + Data::iterator position = data.insert(data.begin() + 1, range.begin(), range.end()); + + CHECK_EQUAL(expected1.size(), data.size()); + CHECK(std::equal(expected1.begin(), expected1.end(), data.begin())); + CHECK_EQUAL(1, std::distance(data.begin(), position)); + + data.assign(original.begin(), original.end()); + + position = data.insert(data.begin() + 3, range.begin(), range.end()); + + CHECK_EQUAL(expected2.size(), data.size()); + CHECK(std::equal(expected2.begin(), expected2.end(), data.begin())); + CHECK_EQUAL(3, std::distance(data.begin(), position)); + } + + //************************************************************************* + TEST(InsertRangeExcess) + { + CompareData original = { 1, 2, 3, 4 }; + CompareData range = { 5, 6, 7 }; + Data data(original.begin(), original.end()); + + CHECK_THROW(data.insert(data.begin(), range.begin(), range.end()), etl::deque_full); + CHECK_THROW(data.insert(data.end(), range.begin(), range.end()), etl::deque_full); + CHECK_THROW(data.insert(data.begin() + 2, range.begin(), range.end()), etl::deque_full); + } + + //************************************************************************* + TEST(EraseBegin) + { + CompareData original = { 0, 0, 1, 2, 3, 4 }; + CompareData expected = { 2, 3, 4, 5, 6 }; + Data data(original.begin(), original.end()); + + // Cause rollover. + data.pop_front(); + data.pop_front(); + data.push_back(5); + data.push_back(6); + + Data::iterator i_next = data.erase(data.begin()); + + CHECK_EQUAL(Data::difference_type(expected.size()), std::distance(data.begin(), data.end())); + CHECK(std::equal(expected.begin(), expected.end(), data.begin())); + CHECK_EQUAL(i_next.get_index(), data.begin().get_index()); + } + + //************************************************************************* + TEST(EraseEnd) + { + CompareData original = { 0, 0, 1, 2, 3, 4 }; + CompareData expected = { 1, 2, 3, 4, 5 }; + Data data(original.begin(), original.end()); + + // Cause rollover. + data.pop_front(); + data.pop_front(); + data.push_back(5); + data.push_back(6); + + Data::iterator i_next = data.erase(data.end() - 1); + + CHECK_EQUAL(Data::difference_type(expected.size()), std::distance(data.begin(), data.end())); + CHECK(std::equal(expected.begin(), expected.end(), data.begin())); + CHECK_EQUAL(i_next.get_index(), data.end().get_index()); + } + + //************************************************************************* + TEST(EraseMiddle) + { + CompareData original = { 0, 0, 1, 2, 3, 4 }; + CompareData expected1 = { 1, 3, 4, 5, 6 }; + CompareData expected2 = { 1, 2, 3, 4, 6 }; + + Data data(original.begin(), original.end()); + + // Cause rollover. + data.pop_front(); + data.pop_front(); + data.push_back(5); + data.push_back(6); + + // Erase near beginning. + Data::iterator i_next = data.erase(data.begin() + 1); + + CHECK_EQUAL(Data::difference_type(expected1.size()), std::distance(data.begin(), data.end())); + CHECK(std::equal(expected1.begin(), expected1.end(), data.begin())); + CHECK_EQUAL(i_next.get_index(), data.begin().get_index() + 1); + + data.assign(original.begin(), original.end()); + + // Cause rollover. + data.pop_front(); + data.pop_front(); + data.push_back(5); + data.push_back(6); + + // Erase near end. + i_next = data.erase(data.begin() + 4); + + CHECK_EQUAL(Data::difference_type(expected2.size()), std::distance(data.begin(), data.end())); + CHECK(std::equal(expected2.begin(), expected2.end(), data.begin())); + CHECK_EQUAL(i_next.get_index(), data.begin().get_index() + 4); + } + + //************************************************************************* + TEST(EraseRangeBegin) + { + CompareData original = { 0, 0, 1, 2, 3, 4 }; + CompareData expected = { 3, 4, 5, 6 }; + Data data(original.begin(), original.end()); + + // Cause rollover. + data.pop_front(); + data.pop_front(); + data.push_back(5); + data.push_back(6); + + Data::iterator i_next = data.erase(data.begin(), data.begin() + 2); + + CHECK_EQUAL(Data::difference_type(expected.size()), std::distance(data.begin(), data.end())); + CHECK(std::equal(expected.begin(), expected.end(), data.begin())); + CHECK_EQUAL(i_next.get_index(), data.begin().get_index()); + } + + //************************************************************************* + TEST(EraseRangeEnd) + { + CompareData original = { 0, 0, 1, 2, 3, 4 }; + CompareData expected = { 1, 2, 3, 4 }; + Data data(original.begin(), original.end()); + + // Cause rollover. + data.pop_front(); + data.pop_front(); + data.push_back(5); + data.push_back(6); + + Data::iterator i_next = data.erase(data.end() - 2, data.end()); + + CHECK_EQUAL(Data::difference_type(expected.size()), std::distance(data.begin(), data.end())); + CHECK(std::equal(expected.begin(), expected.end(), data.begin())); + CHECK_EQUAL(i_next.get_index(), data.end().get_index()); + } + + //************************************************************************* + TEST(EraseRangeMiddle) + { + CompareData original = { 0, 0, 1, 2, 3, 4 }; + CompareData expected1 = { 1, 4, 5, 6 }; + CompareData expected2 = { 1, 2, 3, 6 }; + + Data data(original.begin(), original.end()); + + // Cause rollover. + data.pop_front(); + data.pop_front(); + data.push_back(5); + data.push_back(6); + + Data::iterator i_next = data.erase(data.begin() + 1, data.begin() + 3); + + CHECK_EQUAL(Data::difference_type(expected1.size()), std::distance(data.begin(), data.end())); + CHECK(std::equal(expected1.begin(), expected1.end(), data.begin())); + CHECK_EQUAL(i_next.get_index(), (data.begin() + 1).get_index()); + + data.assign(original.begin(), original.end()); + + // Cause rollover. + data.pop_front(); + data.pop_front(); + data.push_back(5); + data.push_back(6); + + i_next = data.erase(data.begin() + 3, data.begin() + 5); + + CHECK_EQUAL(Data::difference_type(expected2.size()), std::distance(data.begin(), data.end())); + CHECK(std::equal(expected2.begin(), expected2.end(), data.begin())); + CHECK_EQUAL(i_next.get_index(), (data.begin() + 3).get_index()); + + CompareData original2 = { 0, 0, 0, 0, 1, 2}; + CompareData expected3 = { 1, 2, 5, 6 }; + + data.assign(original2.begin(), original2.end()); + + // Cause rollover. + data.pop_front(); + data.pop_front(); + data.pop_front(); + data.pop_front(); + data.push_back(3); + data.push_back(4); + data.push_back(5); + data.push_back(6); + + i_next = data.erase(data.begin() + 2, data.begin() + 4); + + CHECK_EQUAL(Data::difference_type(expected3.size()), std::distance(data.begin(), data.end())); + CHECK(std::equal(expected3.begin(), expected3.end(), data.begin())); + CHECK_EQUAL(i_next.get_index(), (data.begin() + 2).get_index()); + } + + //************************************************************************* + TEST(Sort) + { + CompareData original = { 5, 3, 4, 1, 2 }; + CompareData expected = { 1, 2, 3, 4, 5 }; + Data data(original.begin(), original.end()); + + std::sort(data.begin(), data.end()); + + CHECK(std::equal(expected.begin(), expected.end(), data.begin())); + } + + //************************************************************************* + TEST(ReverseForwardIterators) + { + CompareData original = { 1, 2, 3, 4, 5 }; + CompareData expected = { 5, 4, 3, 2, 1 }; + Data data(original.begin(), original.end()); + + std::reverse(data.begin(), data.end()); + + CHECK(std::equal(expected.begin(), expected.end(), data.begin())); + } + + //************************************************************************* + TEST(ReverseReverseIterators) + { + CompareData original = { 1, 2, 3, 4, 5 }; + CompareData expected = { 5, 4, 3, 2, 1 }; + Data data(original.begin(), original.end()); + + std::reverse(data.rbegin(), data.rend()); + + CHECK(std::equal(expected.begin(), expected.end(), data.begin())); + } + + //************************************************************************* + TEST(BeginEnd) + { + CompareData original = { 1, 2, 3, 4, 5 }; + Data data(original.begin(), original.end()); + + Data::iterator begin = data.begin(); + Data::iterator end = data.end(); + + CHECK_EQUAL(Data::difference_type(original.size()), std::distance(begin, end)); + CHECK(std::equal(begin, end, data.begin())); + } + + //************************************************************************* + TEST(BeginEndConst) + { + CompareData original = { 1, 2, 3, 4, 5 }; + Data data(original.begin(), original.end()); + + Data::const_iterator begin = data.begin(); + Data::const_iterator end = data.end(); + + CHECK_EQUAL(Data::difference_type(original.size()), std::distance(begin, end)); + CHECK(std::equal(begin, end, original.begin())); + } + + //************************************************************************* + TEST(CBeginCEnd) + { + CompareData original = { 1, 2, 3, 4, 5 }; + Data data(original.begin(), original.end()); + + Data::const_iterator begin = data.cbegin(); + Data::const_iterator end = data.cend(); + + CHECK_EQUAL(Data::difference_type(original.size()), std::distance(begin, end)); + CHECK(std::equal(begin, end, original.begin())); + } + + //************************************************************************* + TEST(RBeginREnd) + { + CompareData original = { 1, 2, 3, 4, 5 }; + CompareData expected = { 5, 4, 3, 2, 1 }; + Data data(original.begin(), original.end()); + + Data::reverse_iterator begin = data.rbegin(); + Data::reverse_iterator end = data.rend(); + + CHECK_EQUAL(Data::difference_type(expected.size()), std::distance(begin, end)); + CHECK(std::equal(begin, end, expected.begin())); + } + + //************************************************************************* + TEST(RBeginREndConst) + { + CompareData original = { 1, 2, 3, 4, 5 }; + CompareData expected = { 5, 4, 3, 2, 1 }; + Data data(original.begin(), original.end()); + + Data::const_reverse_iterator begin = data.rbegin(); + Data::const_reverse_iterator end = data.rend(); + + CHECK_EQUAL(Data::difference_type(expected.size()), std::distance(begin, end)); + CHECK(std::equal(begin, end, expected.begin())); + } + + //************************************************************************* + TEST(CRBeginCREnd) + { + CompareData original = { 1, 2, 3, 4, 5 }; + CompareData expected = { 5, 4, 3, 2, 1 }; + Data data(original.begin(), original.end()); + + Data::const_reverse_iterator begin = data.crbegin(); + Data::const_reverse_iterator end = data.crend(); + + CHECK_EQUAL(Data::difference_type(expected.size()), std::distance(begin, end)); + CHECK(std::equal(begin, end, expected.begin())); + } + + //************************************************************************* + TEST(Iterators) + { + CompareData original = { 1, 2, 3, 4, 5 }; + Data data(original.begin(), original.end()); + + Data::iterator begin = data.begin(); + Data::iterator end = data.begin(); + + CHECK_EQUAL(0, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(1, *end); + ++end; + CHECK_EQUAL(1, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(2, *end); + ++end; + CHECK_EQUAL(2, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(3, *end); + ++end; + CHECK_EQUAL(3, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(4, *end); + ++end; + CHECK_EQUAL(4, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(5, *end); + ++begin; + CHECK_EQUAL(3, std::distance(begin, end)); + CHECK_EQUAL(2, *begin); + CHECK_EQUAL(5, *end); + ++begin; + CHECK_EQUAL(2, std::distance(begin, end)); + CHECK_EQUAL(3, *begin); + CHECK_EQUAL(5, *end); + ++begin; + CHECK_EQUAL(1, std::distance(begin, end)); + CHECK_EQUAL(4, *begin); + CHECK_EQUAL(5, *end); + begin -= 3; + CHECK_EQUAL(4, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(5, *end); + end -= 2; + CHECK_EQUAL(2, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(3, *end); + } + + //************************************************************************* + TEST(IteratorsRolloverRight) + { + CompareData original = { 1, 2, 3, 4, 5 }; + Data data(original.begin(), original.end()); + + // Cause rollover right. + data.pop_front(); + data.pop_front(); + data.pop_front(); + data.push_back(6); + data.push_back(7); + data.push_back(8); + + Data::iterator begin = data.begin(); + Data::iterator end = data.begin(); + + CHECK_EQUAL(0, std::distance(begin, end)); + CHECK_EQUAL(4, *begin); + CHECK_EQUAL(4, *end); + ++end; + CHECK_EQUAL(1, std::distance(begin, end)); + CHECK_EQUAL(4, *begin); + CHECK_EQUAL(5, *end); + ++end; + CHECK_EQUAL(2, std::distance(begin, end)); + CHECK_EQUAL(4, *begin); + CHECK_EQUAL(6, *end); + ++end; + CHECK_EQUAL(3, std::distance(begin, end)); + CHECK_EQUAL(4, *begin); + CHECK_EQUAL(7, *end); + ++end; + CHECK_EQUAL(4, std::distance(begin, end)); + CHECK_EQUAL(4, *begin); + CHECK_EQUAL(8, *end); + ++begin; + CHECK_EQUAL(3, std::distance(begin, end)); + CHECK_EQUAL(5, *begin); + CHECK_EQUAL(8, *end); + ++begin; + CHECK_EQUAL(2, std::distance(begin, end)); + CHECK_EQUAL(6, *begin); + CHECK_EQUAL(8, *end); + ++begin; + CHECK_EQUAL(1, std::distance(begin, end)); + CHECK_EQUAL(7, *begin); + CHECK_EQUAL(8, *end); + begin -= 3; + CHECK_EQUAL(4, std::distance(begin, end)); + CHECK_EQUAL(4, *begin); + CHECK_EQUAL(8, *end); + end -= 2; + CHECK_EQUAL(2, std::distance(begin, end)); + CHECK_EQUAL(4, *begin); + CHECK_EQUAL(6, *end); + } + + //************************************************************************* + TEST(IteratorsRolloverLeft) + { + CompareData original = { 4, 5, 6, 7, 8 }; + Data data(original.begin(), original.end()); + + // Cause rollover left. + data.pop_back(); + data.pop_back(); + data.pop_back(); + data.push_front(3); + data.push_front(2); + data.push_front(1); + + Data::iterator begin = data.begin(); + Data::iterator end = data.begin(); + + CHECK_EQUAL(0, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(1, *end); + ++end; + CHECK_EQUAL(1, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(2, *end); + ++end; + CHECK_EQUAL(2, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(3, *end); + ++end; + CHECK_EQUAL(3, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(4, *end); + ++end; + CHECK_EQUAL(4, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(5, *end); + ++begin; + CHECK_EQUAL(3, std::distance(begin, end)); + CHECK_EQUAL(2, *begin); + CHECK_EQUAL(5, *end); + ++begin; + CHECK_EQUAL(2, std::distance(begin, end)); + CHECK_EQUAL(3, *begin); + CHECK_EQUAL(5, *end); + ++begin; + CHECK_EQUAL(1, std::distance(begin, end)); + CHECK_EQUAL(4, *begin); + CHECK_EQUAL(5, *end); + begin -= 3; + CHECK_EQUAL(4, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(5, *end); + end -= 2; + CHECK_EQUAL(2, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(3, *end); + } + + //************************************************************************* + TEST(ConstIterators) + { + CompareData original = { 1, 2, 3, 4, 5 }; + Data data(original.begin(), original.end()); + + Data::const_iterator begin = data.cbegin(); + Data::const_iterator end = data.cbegin(); + + CHECK_EQUAL(0, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(1, *end); + ++end; + CHECK_EQUAL(1, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(2, *end); + ++end; + CHECK_EQUAL(2, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(3, *end); + ++end; + CHECK_EQUAL(3, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(4, *end); + ++end; + CHECK_EQUAL(4, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(5, *end); + ++begin; + CHECK_EQUAL(3, std::distance(begin, end)); + CHECK_EQUAL(2, *begin); + CHECK_EQUAL(5, *end); + ++begin; + CHECK_EQUAL(2, std::distance(begin, end)); + CHECK_EQUAL(3, *begin); + CHECK_EQUAL(5, *end); + ++begin; + CHECK_EQUAL(1, std::distance(begin, end)); + CHECK_EQUAL(4, *begin); + CHECK_EQUAL(5, *end); + begin -= 3; + CHECK_EQUAL(4, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(5, *end); + end -= 2; + CHECK_EQUAL(2, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(3, *end); + } + + //************************************************************************* + TEST(ConstIteratorsRolloverRight) + { + CompareData original = { 1, 2, 3, 4, 5 }; + Data data(original.begin(), original.end()); + + // Cause rollover right. + data.pop_front(); + data.pop_front(); + data.pop_front(); + data.push_back(6); + data.push_back(7); + data.push_back(8); + + Data::const_iterator begin = data.cbegin(); + Data::const_iterator end = data.cbegin(); + + CHECK_EQUAL(0, std::distance(begin, end)); + CHECK_EQUAL(4, *begin); + CHECK_EQUAL(4, *end); + ++end; + CHECK_EQUAL(1, std::distance(begin, end)); + CHECK_EQUAL(4, *begin); + CHECK_EQUAL(5, *end); + ++end; + CHECK_EQUAL(2, std::distance(begin, end)); + CHECK_EQUAL(4, *begin); + CHECK_EQUAL(6, *end); + ++end; + CHECK_EQUAL(3, std::distance(begin, end)); + CHECK_EQUAL(4, *begin); + CHECK_EQUAL(7, *end); + ++end; + CHECK_EQUAL(4, std::distance(begin, end)); + CHECK_EQUAL(4, *begin); + CHECK_EQUAL(8, *end); + ++begin; + CHECK_EQUAL(3, std::distance(begin, end)); + CHECK_EQUAL(5, *begin); + CHECK_EQUAL(8, *end); + ++begin; + CHECK_EQUAL(2, std::distance(begin, end)); + CHECK_EQUAL(6, *begin); + CHECK_EQUAL(8, *end); + ++begin; + CHECK_EQUAL(1, std::distance(begin, end)); + CHECK_EQUAL(7, *begin); + CHECK_EQUAL(8, *end); + begin -= 3; + CHECK_EQUAL(4, std::distance(begin, end)); + CHECK_EQUAL(4, *begin); + CHECK_EQUAL(8, *end); + end -= 2; + CHECK_EQUAL(2, std::distance(begin, end)); + CHECK_EQUAL(4, *begin); + CHECK_EQUAL(6, *end); + } + + //************************************************************************* + TEST(ConstIteratorsRolloverLeft) + { + CompareData original = { 4, 5, 6, 7, 8 }; + Data data(original.begin(), original.end()); + + // Cause rollover left. + data.pop_back(); + data.pop_back(); + data.pop_back(); + data.push_front(3); + data.push_front(2); + data.push_front(1); + + Data::const_iterator begin = data.cbegin(); + Data::const_iterator end = data.cbegin(); + + CHECK_EQUAL(0, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(1, *end); + ++end; + CHECK_EQUAL(1, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(2, *end); + ++end; + CHECK_EQUAL(2, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(3, *end); + ++end; + CHECK_EQUAL(3, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(4, *end); + ++end; + CHECK_EQUAL(4, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(5, *end); + ++begin; + CHECK_EQUAL(3, std::distance(begin, end)); + CHECK_EQUAL(2, *begin); + CHECK_EQUAL(5, *end); + ++begin; + CHECK_EQUAL(2, std::distance(begin, end)); + CHECK_EQUAL(3, *begin); + CHECK_EQUAL(5, *end); + ++begin; + CHECK_EQUAL(1, std::distance(begin, end)); + CHECK_EQUAL(4, *begin); + CHECK_EQUAL(5, *end); + begin -= 3; + CHECK_EQUAL(4, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(5, *end); + end -= 2; + CHECK_EQUAL(2, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(3, *end); + } + + //************************************************************************* + TEST(ReverseIterators) + { + CompareData original = { 5, 4, 3, 2, 1 }; + Data data(original.begin(), original.end()); + + Data::reverse_iterator begin = data.rbegin(); + Data::reverse_iterator end = data.rbegin(); + + CHECK_EQUAL(0, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(1, *end); + ++end; + CHECK_EQUAL(1, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(2, *end); + ++end; + CHECK_EQUAL(2, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(3, *end); + ++end; + CHECK_EQUAL(3, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(4, *end); + ++end; + CHECK_EQUAL(4, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(5, *end); + ++begin; + CHECK_EQUAL(3, std::distance(begin, end)); + CHECK_EQUAL(2, *begin); + CHECK_EQUAL(5, *end); + ++begin; + CHECK_EQUAL(2, std::distance(begin, end)); + CHECK_EQUAL(3, *begin); + CHECK_EQUAL(5, *end); + ++begin; + CHECK_EQUAL(1, std::distance(begin, end)); + CHECK_EQUAL(4, *begin); + CHECK_EQUAL(5, *end); + begin -= 3; + CHECK_EQUAL(4, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(5, *end); + end -= 2; + CHECK_EQUAL(2, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(3, *end); + } + + //************************************************************************* + TEST(ReverseIteratorsRolloverRight) + { + CompareData original = { 0, 0, 0, 5, 4 }; + Data data(original.begin(), original.end()); + + // Cause rollover right. + data.pop_front(); + data.pop_front(); + data.pop_front(); + data.push_back(3); + data.push_back(2); + data.push_back(1); + + Data::reverse_iterator begin = data.rbegin(); + Data::reverse_iterator end = data.rbegin(); + + CHECK_EQUAL(0, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(1, *end); + ++end; + CHECK_EQUAL(1, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(2, *end); + ++end; + CHECK_EQUAL(2, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(3, *end); + ++end; + CHECK_EQUAL(3, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(4, *end); + ++end; + CHECK_EQUAL(4, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(5, *end); + ++begin; + CHECK_EQUAL(3, std::distance(begin, end)); + CHECK_EQUAL(2, *begin); + CHECK_EQUAL(5, *end); + ++begin; + CHECK_EQUAL(2, std::distance(begin, end)); + CHECK_EQUAL(3, *begin); + CHECK_EQUAL(5, *end); + ++begin; + CHECK_EQUAL(1, std::distance(begin, end)); + CHECK_EQUAL(4, *begin); + CHECK_EQUAL(5, *end); + begin -= 3; + CHECK_EQUAL(4, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(5, *end); + end -= 2; + CHECK_EQUAL(2, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(3, *end); + } + + //************************************************************************* + TEST(ReverseIteratorsRolloverLeft) + { + CompareData original = { 2, 1, 0, 0, 0 }; + Data data(original.begin(), original.end()); + + // Cause rollover left. + data.pop_back(); + data.pop_back(); + data.pop_back(); + data.push_front(3); + data.push_front(4); + data.push_front(5); + + Data::reverse_iterator begin = data.rbegin(); + Data::reverse_iterator end = data.rbegin(); + + CHECK_EQUAL(0, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(1, *end); + ++end; + CHECK_EQUAL(1, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(2, *end); + ++end; + CHECK_EQUAL(2, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(3, *end); + ++end; + CHECK_EQUAL(3, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(4, *end); + ++end; + CHECK_EQUAL(4, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(5, *end); + ++begin; + CHECK_EQUAL(3, std::distance(begin, end)); + CHECK_EQUAL(2, *begin); + CHECK_EQUAL(5, *end); + ++begin; + CHECK_EQUAL(2, std::distance(begin, end)); + CHECK_EQUAL(3, *begin); + CHECK_EQUAL(5, *end); + ++begin; + CHECK_EQUAL(1, std::distance(begin, end)); + CHECK_EQUAL(4, *begin); + CHECK_EQUAL(5, *end); + begin -= 3; + CHECK_EQUAL(4, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(5, *end); + end -= 2; + CHECK_EQUAL(2, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(3, *end); + } + + //************************************************************************* + TEST(ConstReverseIterators) + { + CompareData original = { 5, 4, 3, 2, 1 }; + Data data(original.begin(), original.end()); + + Data::const_reverse_iterator begin = data.crbegin(); + Data::const_reverse_iterator end = data.crbegin(); + + CHECK_EQUAL(0, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(1, *end); + ++end; + CHECK_EQUAL(1, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(2, *end); + ++end; + CHECK_EQUAL(2, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(3, *end); + ++end; + CHECK_EQUAL(3, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(4, *end); + ++end; + CHECK_EQUAL(4, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(5, *end); + ++begin; + CHECK_EQUAL(3, std::distance(begin, end)); + CHECK_EQUAL(2, *begin); + CHECK_EQUAL(5, *end); + ++begin; + CHECK_EQUAL(2, std::distance(begin, end)); + CHECK_EQUAL(3, *begin); + CHECK_EQUAL(5, *end); + ++begin; + CHECK_EQUAL(1, std::distance(begin, end)); + CHECK_EQUAL(4, *begin); + CHECK_EQUAL(5, *end); + begin -= 3; + CHECK_EQUAL(4, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(5, *end); + end -= 2; + CHECK_EQUAL(2, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(3, *end); + } + + //************************************************************************* + TEST(ConstReverseIteratorsRolloverRight) + { + CompareData original = { 0, 0, 0, 5, 4 }; + Data data(original.begin(), original.end()); + + // Cause rollover right. + data.pop_front(); + data.pop_front(); + data.pop_front(); + data.push_back(3); + data.push_back(2); + data.push_back(1); + + Data::const_reverse_iterator begin = data.crbegin(); + Data::const_reverse_iterator end = data.crbegin(); + + CHECK_EQUAL(0, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(1, *end); + ++end; + CHECK_EQUAL(1, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(2, *end); + ++end; + CHECK_EQUAL(2, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(3, *end); + ++end; + CHECK_EQUAL(3, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(4, *end); + ++end; + CHECK_EQUAL(4, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(5, *end); + ++begin; + CHECK_EQUAL(3, std::distance(begin, end)); + CHECK_EQUAL(2, *begin); + CHECK_EQUAL(5, *end); + ++begin; + CHECK_EQUAL(2, std::distance(begin, end)); + CHECK_EQUAL(3, *begin); + CHECK_EQUAL(5, *end); + ++begin; + CHECK_EQUAL(1, std::distance(begin, end)); + CHECK_EQUAL(4, *begin); + CHECK_EQUAL(5, *end); + begin -= 3; + CHECK_EQUAL(4, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(5, *end); + end -= 2; + CHECK_EQUAL(2, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(3, *end); + } + + //************************************************************************* + TEST(ConstReverseIteratorsRolloverLeft) + { + CompareData original = { 2, 1, 0, 0, 0 }; + Data data(original.begin(), original.end()); + + // Cause rollover left. + data.pop_back(); + data.push_front(3); + data.pop_back(); + data.push_front(4); + data.pop_back(); + data.push_front(5); + + Data::const_reverse_iterator begin = data.crbegin(); + Data::const_reverse_iterator end = data.crbegin(); + + CHECK_EQUAL(0, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(1, *end); + ++end; + CHECK_EQUAL(1, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(2, *end); + ++end; + CHECK_EQUAL(2, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(3, *end); + ++end; + CHECK_EQUAL(3, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(4, *end); + ++end; + CHECK_EQUAL(4, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(5, *end); + ++begin; + CHECK_EQUAL(3, std::distance(begin, end)); + CHECK_EQUAL(2, *begin); + CHECK_EQUAL(5, *end); + ++begin; + CHECK_EQUAL(2, std::distance(begin, end)); + CHECK_EQUAL(3, *begin); + CHECK_EQUAL(5, *end); + ++begin; + CHECK_EQUAL(1, std::distance(begin, end)); + CHECK_EQUAL(4, *begin); + CHECK_EQUAL(5, *end); + begin -= 3; + CHECK_EQUAL(4, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(5, *end); + end -= 2; + CHECK_EQUAL(2, std::distance(begin, end)); + CHECK_EQUAL(1, *begin); + CHECK_EQUAL(3, *end); + } + + //************************************************************************* + TEST(IteratorsNegativeDistance) + { + CompareData original = { 2, 1, 0, 0, 0 }; + Data data(original.begin(), original.end()); + + CHECK_EQUAL(-5, std::distance(data.end(), data.begin())); + } + + //************************************************************************* + TEST(ConstIteratorsNegativeDistance) + { + CompareData original = { 2, 1, 0, 0, 0 }; + Data data(original.begin(), original.end()); + + CHECK_EQUAL(-5, std::distance(data.cend(), data.cbegin())); + } + + //************************************************************************* + TEST(ReverseIteratorsNegativeDistance) + { + CompareData original = { 2, 1, 0, 0, 0 }; + Data data(original.begin(), original.end()); + + CHECK_EQUAL(-5, std::distance(data.rend(), data.rbegin())); + } + + //************************************************************************* + TEST(ConstReverseIteratorsNegativeDistance) + { + CompareData original = { 2, 1, 0, 0, 0 }; + Data data(original.begin(), original.end()); + + CHECK_EQUAL(-5, std::distance(data.crend(), data.crbegin())); + } + + //************************************************************************* + TEST(IteratorsComparison) + { + Data data(6, 0); + + Data::iterator first = data.begin() + 1; + Data::iterator second = data.begin() + 4; + + CHECK(first < second); + CHECK(!(second < first)); + } + + //************************************************************************* + TEST(IteratorsComparisonRolloverRight) + { + Data data(6, 0); + + data.pop_front(); + data.pop_front(); + data.pop_front(); + data.push_back(1); + data.push_back(1); + data.push_back(1); + + Data::iterator first = data.begin() + 1; + Data::iterator second = data.begin() + 4; + + CHECK(first < second); + CHECK(!(second < first)); + } + + //************************************************************************* + TEST(ConstIteratorsComparison) + { + Data data(6, 0); + + Data::const_iterator first = data.cbegin() + 1; + Data::const_iterator second = data.cbegin() + 4; + + CHECK(first < second); + CHECK(!(second < first)); + } + + //************************************************************************* + TEST(ConstIteratorsComparisonRolloverRight) + { + Data data(6, 0); + + data.pop_front(); + data.pop_front(); + data.pop_front(); + data.push_back(1); + data.push_back(1); + data.push_back(1); + + Data::const_iterator first = data.cbegin() + 1; + Data::const_iterator second = data.cbegin() + 4; + + CHECK(first < second); + CHECK(!(second < first)); + } + + //************************************************************************* + TEST(ConstIteratorsComparisonRolloverLeft) + { + Data data(6, 0); + + data.pop_back(); + data.pop_back(); + data.pop_back(); + data.push_front(1); + data.push_front(1); + data.push_front(1); + + Data::const_iterator first = data.cbegin() + 1; + Data::const_iterator second = data.cbegin() + 4; + + CHECK(first < second); + CHECK(!(second < first)); + } + + //************************************************************************* + TEST(ReverseIteratorsComparison) + { + Data data(6, 0); + + Data::reverse_iterator first = data.rbegin() + 1; + Data::reverse_iterator second = data.rbegin() + 4; + + CHECK(first < second); + CHECK(!(second < first)); + } + + //************************************************************************* + TEST(ReverseIteratorsComparisonRolloverRight) + { + Data data(6, 0); + + data.pop_front(); + data.pop_front(); + data.pop_front(); + data.push_back(1); + data.push_back(1); + data.push_back(1); + + Data::reverse_iterator first = data.rbegin() + 1; + Data::reverse_iterator second = data.rbegin() + 4; + + CHECK(first < second); + CHECK(!(second < first)); + } + + //************************************************************************* + TEST(ReverseIteratorsComparisonRolloverLeft) + { + Data data(6, 0); + + data.pop_back(); + data.pop_back(); + data.pop_back(); + data.push_front(1); + data.push_front(1); + data.push_front(1); + + Data::reverse_iterator first = data.rbegin() + 1; + Data::reverse_iterator second = data.rbegin() + 4; + + CHECK(first < second); + CHECK(!(second < first)); + } + + //************************************************************************* + TEST(ConstReverseIteratorsComparison) + { + Data data(6, 0); + + Data::const_reverse_iterator first = data.crbegin() + 1; + Data::const_reverse_iterator second = data.crbegin() + 4; + + CHECK(first < second); + CHECK(!(second < first)); + } + + //************************************************************************* + TEST(ConstReverseIteratorsComparisonRolloverRight) + { + Data data(6, 0); + + data.pop_front(); + data.pop_front(); + data.pop_front(); + data.push_back(1); + data.push_back(1); + data.push_back(1); + + Data::const_reverse_iterator first = data.crbegin() + 1; + Data::const_reverse_iterator second = data.crbegin() + 4; + + CHECK(first < second); + CHECK(!(second < first)); + } + + //************************************************************************* + TEST(ConstReverseIteratorsComparisonRolloverLeft) + { + Data data(6, 0); + + data.pop_back(); + data.pop_back(); + data.pop_back(); + data.push_front(1); + data.push_front(1); + data.push_front(1); + + Data::const_reverse_iterator first = data.crbegin() + 1; + Data::const_reverse_iterator second = data.crbegin() + 4; + + CHECK(first < second); + CHECK(!(second < first)); + } + + //************************************************************************* + TEST(OperatorEqual) + { + CompareData original = { 1, 2, 3, 4, 5, 6 }; + CompareData modified = { 6, 5, 4, 3, 2, 1 }; + + Data testDeque1(original.begin(), original.end()); + Data testDeque2(testDeque1); + + CHECK(testDeque1 == testDeque2); + + // Change testDeque2's data. + std::copy(modified.begin(), modified.end(), testDeque2.begin()); + + CHECK(testDeque1 != testDeque2); + } + }; +} \ No newline at end of file