diff --git a/ivector.h b/ivector.h new file mode 100644 index 00000000..a04a81c9 --- /dev/null +++ b/ivector.h @@ -0,0 +1,612 @@ +///\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_ivector__ +#define __etl_ivector__ +#define __etl_in_ivector_h__ + +#include +#include +#include +#include + +#include "vector_base.h" + +namespace etl +{ + //***************************************************************************== + /// The base class for specifically sized vectors. + /// Can be used as a reference type for all vectors containing a specific type. + //***************************************************************************== + template + class ivector : public vector_base + { + public: + + typedef T* iterator; + typedef const T* const_iterator; + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; + 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; + + //********************************************************************* + /// Returns an iterator to the beginning of the vector. + ///\return An iterator to the beginning of the vector. + //********************************************************************* + iterator begin() + { + return &buffer[0]; + } + + //********************************************************************* + /// Returns a const_iterator to the beginning of the vector. + ///\return A const iterator to the beginning of the vector. + //********************************************************************* + const_iterator begin() const + { + return &buffer[0]; + } + + //********************************************************************* + /// Returns a const_iterator to the beginning of the vector. + ///\return A const iterator to the beginning of the vector. + //********************************************************************* + const_iterator cbegin() const + { + return &buffer[0]; + } + + //********************************************************************* + /// Returns an reverse iterator to the reverse beginning of the vector. + ///\return Iterator to the reverse beginning of the vector. + //********************************************************************* + reverse_iterator rbegin() + { + return reverse_iterator(end()); + } + + //********************************************************************* + /// Returns a const reverse iterator to the reverse beginning of the vector. + ///\return Const iterator to the reverse beginning of the vector. + //********************************************************************* + const_reverse_iterator rbegin() const + { + return const_reverse_iterator(end()); + } + + //********************************************************************* + /// Returns a const reverse iterator to the reverse beginning of the vector. + ///\return Const reverse iterator to the reverse beginning of the vector. + //********************************************************************* + const_reverse_iterator crbegin() const + { + return const_reverse_iterator(cend()); + } + + //********************************************************************* + /// Returns an iterator to the end of the vector. + ///\return An iterator to the end of the vector. + //********************************************************************* + iterator end() + { + return &buffer[current_size]; + } + + //********************************************************************* + /// Returns a const_iterator to the end of the vector. + ///\return A const iterator to the end of the vector. + //********************************************************************* + const_iterator end() const + { + return &buffer[current_size]; + } + + //********************************************************************* + /// Returns a const_iterator to the end of the vector. + ///\return A const iterator to the end of the vector. + //********************************************************************* + const_iterator cend() const + { + return &buffer[current_size]; + } + + //********************************************************************* + /// Returns a reverse iterator to the end + 1 of the vector. + ///\return Reverse iterator to the end + 1 of the vector. + //********************************************************************* + reverse_iterator rend() + { + return reverse_iterator(begin()); + } + + //********************************************************************* + /// Returns a const reverse iterator to the end + 1 of the vector. + ///\return Const reverse iterator to the end + 1 of the vector. + //********************************************************************* + const_reverse_iterator rend() const + { + return const_reverse_iterator(begin()); + } + + //********************************************************************* + /// Returns a const reverse iterator to the end + 1 of the vector. + ///\return Const reverse iterator to the end + 1 of the vector. + //********************************************************************* + const_reverse_iterator crend() const + { + return const_reverse_iterator(cbegin()); + } + + //********************************************************************* + /// Resizes the vector. + /// If ETL_USE_EXCEPTIONS is defined and the new size is larger than the + /// maximum then a vector_full_exception is thrown. + ///\param newSize The new size. + ///\param value The value to fill new elements with. Default = default contructed value. + //********************************************************************* + void resize(size_t newSize, T value = T()) + { +#ifdef ETL_USE_EXCEPTIONS + if (newSize > MAX_SIZE) + { + throw vector_full_exception(); + } +#endif + + if (newSize > current_size) + { + std::fill(&buffer[current_size], &buffer[newSize], value); + } + + current_size = newSize; + } + + //********************************************************************* + /// Clears the vector. + /// Does not call the destructor for any elements. + //********************************************************************* + void clear() + { + current_size = 0; + } + + //********************************************************************* + /// Assigns values to the vector. + /// If ETL_USE_EXCEPTIONS is defined, throws vector_full_exception if the vector does not have enough free space. + /// If ETL_USE_EXCEPTIONS is defined, throws vector_iterator_exception if the iterators are reversed. + ///\param first The iterator to the first element. + ///\param last The iterator to the last element + 1. + //********************************************************************* + template + void assign(TIterator first, TIterator last) + { + difference_type count = std::distance(first, last); + + if (count < 0) + { +#ifdef ETL_USE_EXCEPTIONS + throw vector_iterator_exception(); +#endif + } + else if (static_cast(count) > MAX_SIZE) + { +#ifdef ETL_USE_EXCEPTIONS + throw vector_full_exception(); +#endif + } + else + { + // Safe to copy. + std::copy(first, last, begin()); + current_size = count; + } + } + + //********************************************************************* + /// Assigns values to the vector. + /// If ETL_USE_EXCEPTIONS is defined, throws vector_exception if the vector does not have enough free space. + ///\param n The number of elements to add. + ///\param value The value to insert for each element. + //********************************************************************* + void assign(size_t n, const T& value) + { + if (n > MAX_SIZE) + { +#ifdef ETL_USE_EXCEPTIONS + throw vector_full_exception(); +#endif + } + else + { + std::fill_n(begin(), n, value); + current_size = n; + } + } + + //********************************************************************* + /// Inserts a value to the vector. + /// If ETL_USE_EXCEPTIONS is defined, throws vector_exception if the vector is already full. + ///\param position The position to insert at. + ///\param value The value to insert. + //********************************************************************* + iterator insert(iterator position, const T& value) + { + if (position == end()) + { + push_back(value); + return iterator(&back()); + } + else + { + if ((current_size + 1) > MAX_SIZE) + { +#ifdef ETL_USE_EXCEPTIONS + throw vector_full_exception(); +#endif + } + else + { + ++current_size; + std::copy_backward(position, end() - 1, end()); + *position = value; + } + + return position; + } + } + + //********************************************************************* + /// Inserts 'n' values to the vector. + /// If ETL_USE_EXCEPTIONS is defined, throws vector_exception if the vector does not have enough free space. + ///\param position The position to insert at. + ///\param n The number of elements to add. + ///\param value The value to insert. + //********************************************************************* + void insert(iterator position, size_t n, const T& value) + { + if ((current_size + n) > MAX_SIZE) + { +#ifdef ETL_USE_EXCEPTIONS + throw vector_full_exception(); +#endif + } + else + { + current_size += n; + std::copy_backward(position, end() - n, end()); + std::fill_n(position, n, value); + } + } + + template + //********************************************************************* + /// Inserts a range of values to the vector. + /// If ETL_USE_EXCEPTIONS is defined, throws vector_exception if the vector does not have enough free space. + ///\param position The position to insert at. + ///\param first The first element to add. + ///\param last The last + 1 element to add. + //********************************************************************* + void insert(iterator position, TIterator first, TIterator last) + { + size_t count = std::distance(first, last); + + if ((current_size + count) > MAX_SIZE) + { + throw vector_full_exception(); + } + else + { + current_size += count; + std::copy_backward(position, end() - count, end()); + std::copy(first, first + count, position); + } + } + + //********************************************************************* + /// Inserts a value at the end of the vector. + /// If ETL_USE_EXCEPTIONS is defined, throws vector_exception if the vector is already full. + ///\param value The value to add. + //********************************************************************* + void push_back(const T& value) + { + if (current_size == MAX_SIZE) + { +#ifdef ETL_USE_EXCEPTIONS + throw vector_full_exception(); +#endif + } + else + { + buffer[current_size++] = value; + } + } + + //********************************************************************* + /// Increases the size of the vector by one, but does not initialise the new element. + /// If ETL_USE_EXCEPTIONS is defined, throws vector_exception if the vector is already full. + //********************************************************************* + void push_back() + { + if (current_size == MAX_SIZE) + { +#ifdef ETL_USE_EXCEPTIONS + throw vector_full_exception(); +#endif + } + else + { + ++current_size; + } + } + + //********************************************************************* + /// Removes an element from the end of the vector. + /// Does nothing if the vector is empty. + //********************************************************************* + void pop_back() + { + if (current_size > 0) + { + --current_size; + } + } + + //********************************************************************* + /// Erases an element. + ///\param iElement Iterator to the element. + ///\return An iterator pointing to the element that followed the erased element. + //********************************************************************* + iterator erase(iterator iElement) + { + std::copy(iElement + 1, end(), iElement); + --current_size; + + return iElement; + } + + //********************************************************************* + /// Erases a range of elements. + /// The range includes all the elements between first and last, including the + /// element pointed by first, but not the one pointed by last. + ///\param first Iterator to the first element. + ///\param last Iterator to the last element. + ///\return An iterator pointing to the element that followed the erased element. + //********************************************************************* + iterator erase(iterator first, iterator last) + { + std::copy(last, end(), first); + current_size -= std::distance(first, last); + + return first; + } + + //********************************************************************* + /// Returns a reference to the first element. + ///\return A reference to the first element. + //********************************************************************* + reference front() + { + return buffer[0]; + } + + //********************************************************************* + /// Returns a const reference to the first element. + ///\return A const reference to the first element. + //********************************************************************* + const_reference front() const + { + return buffer[0]; + } + + //********************************************************************* + /// Returns a reference to the last element. + ///\return A reference to the last element. + //********************************************************************* + reference back() + { + return buffer[current_size - 1]; + } + + //********************************************************************* + /// Returns a const reference to the last element. + ///\return A const reference to the last element. + //********************************************************************* + const_reference back() const + { + return buffer[current_size - 1]; + } + + //********************************************************************* + /// Returns a reference to the value at index 'i' + /// If ETL_USE_EXCEPTIONS is defined, throws a std::range_error if the index is out of range. + ///\param i The index. + ///\return A reference to the value at index 'i' + //********************************************************************* + reference at(size_t i) + { +#ifdef ETL_USE_EXCEPTIONS + if (i >= current_size) + { + throw vector_out_of_bounds_exception(); + } +#endif + + return buffer[i]; + } + + //********************************************************************* + /// Returns a const reference to the value at index 'i' + /// If ETL_USE_EXCEPTIONS is defined, throws a std::range_error if the index is out of range. + ///\param i The index. + ///\return A const reference to the value at index 'i' + //********************************************************************* + const_reference at(size_t i) const + { +#ifdef ETL_USE_EXCEPTIONS + if (i >= current_size) + { + throw vector_out_of_bounds_exception(); + } +#endif + + return buffer[i]; + } + + //********************************************************************* + /// Returns a reference to the value at index 'i' + ///\param i The index. + ///\return A reference to the value at index 'i' + //********************************************************************* + reference operator[](size_t i) + { + return buffer[i]; + } + + //********************************************************************* + /// Returns a const reference to the value at index 'i' + ///\param i The index. + ///\return A const reference to the value at index 'i' + //********************************************************************* + const_reference operator[](size_t i) const + { + return buffer[i]; + } + + //********************************************************************* + /// Assignment operator. + /// The source vector can be larger than the destination, but + /// only the elements that will fit in the destination will be copied. + ///\param other The other vector. + //********************************************************************* + ivector& operator = (ivector& other) + { + const size_t length = std::min(MAX_SIZE, other.size()); + + std::copy(other.begin(), other.begin() + length, buffer); + current_size = length; + + return *this; + } + + protected: + + //********************************************************************* + /// Constructor. + //********************************************************************* + ivector(T* buffer, size_t MAX_SIZE) + : vector_base(MAX_SIZE), + buffer(buffer) + { + } + + private: + + T* buffer; + }; + + //*************************************************************************** + /// 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 + //*************************************************************************** + template + bool operator ==(const etl::ivector& lhs, const etl::ivector& 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 + //*************************************************************************** + template + bool operator !=(const etl::ivector& lhs, const etl::ivector& 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 + //*************************************************************************** + template + bool operator <(const etl::ivector& lhs, const etl::ivector& 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 + //*************************************************************************** + template + bool operator >(const etl::ivector& lhs, const etl::ivector& 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 + //*************************************************************************** + template + bool operator <=(const etl::ivector& lhs, const etl::ivector& 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 + //*************************************************************************** + template + bool operator >=(const etl::ivector& lhs, const etl::ivector& rhs) + { + return !operator <(lhs, rhs); + } +} + +#undef __etl_in_ivector_h__ +#endif diff --git a/vector.h b/vector.h new file mode 100644 index 00000000..c3189e7e --- /dev/null +++ b/vector.h @@ -0,0 +1,117 @@ +///\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_vector__ +#define __etl_vector__ + +#include +#include + +#include "ivector.h" + +//***************************************************************************** +///\defgroup vector vector +/// A vector with the capacity defined at compile time. +///\note Uses a predefined array, so MAX_SIZE_ elements will be always be constructed. +///\ingroup containers +//***************************************************************************** + +namespace etl +{ + template + //*************************************************************************==== + /// A vector implementation that uses a fixed size buffer. + ///\note Uses a predefined array, so MAX_SIZE_ elements will be always be constructed. + ///\tparam T The element type. + ///\tparam MAX_SIZE_ The maximum number of elements that can be stored. + //*************************************************************************==== + class vector : public ivector + { + public: + + static const size_t MAX_SIZE = MAX_SIZE_; + + //************************************************************************* + /// Constructor. + //************************************************************************* + vector() + : ivector(buffer, MAX_SIZE) + { + } + + //************************************************************************* + /// Constructor, with size. + ///\param initialSize The initial size of the vector. + //************************************************************************* + explicit vector(size_t initialSize) + : ivector(buffer, MAX_SIZE) + { + ivector::resize(initialSize); + } + + //************************************************************************* + /// Constructor, from initial size and value. + ///\param initialSize The initial size of the vector. + ///\param value The value to fill the vector with. + //************************************************************************* + vector(size_t initialSize, const T& value) + : ivector(buffer, MAX_SIZE) + { + ivector::resize(initialSize, value); + } + + //************************************************************************* + /// Constructor, from an iterator range. + ///\tparam TIterator The iterator type. + ///\param first The iterator to the first element. + ///\param last The iterator to the last element + 1. + //************************************************************************* + template + vector(TIterator first, TIterator last) + : ivector(buffer, MAX_SIZE) + { + ivector::assign(first, last); + } + + //************************************************************************* + /// Assignment operator. + //************************************************************************* + vector& operator = (const vector& rhs) + { + ivector::assign(rhs.cbegin(), rhs.cend()); + + return *this; + } + + private: + + T buffer[MAX_SIZE]; /// + +#include "exception.h" + +namespace etl +{ +#ifdef ETL_USE_EXCEPTIONS + //*************************************************************************** + ///\ingroup vector + /// exception base for vectors + //*************************************************************************** + class vector_exception : public exception + { + public: + + vector_exception(const char* what) + : exception(what) + { + } + }; + + //*************************************************************************** + ///\ingroup vector + /// Vector full exception. + //*************************************************************************** + class vector_full_exception : public vector_exception + { + public: + + vector_full_exception() + : vector_exception("vector full") + { + } + }; + + //*************************************************************************** + ///\ingroup vector + /// Vector empty exception. + //*************************************************************************** + class vector_empty_exception : public vector_exception + { + public: + + vector_empty_exception() + : vector_exception("vector empty") + { + } + }; + + //*************************************************************************** + ///\ingroup vector + /// Vector out of bounds exception. + //*************************************************************************** + class vector_out_of_bounds_exception : public vector_exception + { + public: + + vector_out_of_bounds_exception() + : vector_exception("vector out of bounds") + { + } + }; + + //*************************************************************************** + ///\ingroup vector + /// Vector iterator exception. + //*************************************************************************** + class vector_iterator_exception : public vector_exception + { + public: + + vector_iterator_exception() + : vector_exception("vector iterator error") + { + } + }; +#endif + + //*************************************************************************** + ///\ingroup vector + /// The base class for all templated vector types. + //*************************************************************************** + class vector_base + { + public: + + typedef size_t size_type; + + //************************************************************************* + /// Gets the current size of the vector. + ///\return The current size of the vector. + //************************************************************************* + size_type size() const + { + return current_size; + } + + //************************************************************************* + /// Checks the 'empty' state of the vector. + ///\return true if empty. + //************************************************************************* + bool empty() const + { + return (current_size == 0); + } + + //************************************************************************* + /// Checks the 'full' state of the vector. + ///\return true if full. + //************************************************************************* + bool full() const + { + return current_size == MAX_SIZE; + } + + //************************************************************************* + /// Returns the capacity of the vector. + ///\return The capacity of the vector. + //************************************************************************* + size_type capacity() const + { + return MAX_SIZE; + } + + //************************************************************************* + /// Returns the maximum possible size of the vector. + ///\return The maximum size of the vector. + //************************************************************************* + size_type max_size() const + { + return MAX_SIZE; + } + + //************************************************************************* + /// Clears the vector. + //************************************************************************* + void clear() + { + current_size = 0; + } + + //************************************************************************* + /// Increases the size of the vector by one, but does not initialise the new element. + /// If ETL_USE_EXCEPTIONS is defined, throws a vector_full_exception if the vector is already full. + //************************************************************************* + void push_back() + { +#ifdef ETL_USE_EXCEPTIONS + if (current_size == MAX_SIZE) + { + throw vector_full_exception(); + } +#endif + + ++current_size; + } + + //************************************************************************* + /// Removes an element from the end of the vector. + /// Does nothing if the vector is empty. + //************************************************************************* + void pop_back() + { + if (current_size > 0) + { + --current_size; + } + } + + protected: + + //************************************************************************* + /// Constructor. + //************************************************************************* + vector_base(size_t max_size) + : current_size(0), + MAX_SIZE(max_size) + { + } + + size_type current_size; ///