//------------------------------------------------------------------------------ /* This file is part of Beast: https://github.com/vinniefalco/Beast Copyright 2013, Vinnie Falco Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ //============================================================================== #ifndef BEAST_CORE_CONTAINERS_DYNAMICARRAY_H_INCLUDED #define BEAST_CORE_CONTAINERS_DYNAMICARRAY_H_INCLUDED template class DynamicArray; namespace detail { template class DynamicArrayIterator : public std::iterator { public: typedef typename copyconst ::type value_type; typedef value_type* pointer; typedef value_type& reference; typedef std::ptrdiff_t difference_type; typedef typename V::size_type size_type; DynamicArrayIterator (V* v = nullptr, size_type pos = 0) noexcept : m_v (v) , m_pos (pos) { } template DynamicArrayIterator (DynamicArrayIterator const& u) noexcept : m_v (u.m_v) , m_pos (u.m_pos) { } template DynamicArrayIterator& operator= (DynamicArrayIterator const& u) noexcept { m_v = u.m_v; m_pos = u.m_pos; return *this; } template bool operator== (DynamicArrayIterator const& u) const noexcept { return (m_v == u.m_v) && (m_pos == u.m_pos); } template bool operator!= (DynamicArrayIterator const& u) const noexcept { return ! ((*this) == u); } reference operator* () const noexcept { return dereference (); } pointer operator-> () const noexcept { return &dereference (); } DynamicArrayIterator& operator++ () noexcept { increment (1); return *this; } DynamicArrayIterator operator++ (int) noexcept { DynamicArrayIterator const result (*this); increment (1); return result; } DynamicArrayIterator& operator-- () noexcept { decrement (1); return *this; } DynamicArrayIterator operator-- (int) noexcept { DynamicArrayIterator const result (*this); decrement (1); return result; } DynamicArrayIterator& operator+= (difference_type n) noexcept { increment (n); return *this; } DynamicArrayIterator& operator-= (difference_type n) noexcept { decrement (n); return *this; } DynamicArrayIterator operator+ (difference_type n) noexcept { return DynamicArrayIterator (m_v, m_pos + n); } DynamicArrayIterator operator- (difference_type n) noexcept { return DynamicArrayIterator (m_v, m_pos - n); } template difference_type operator- (DynamicArrayIterator const& rhs) const noexcept { return m_pos - rhs.m_pos; } template bool operator< (DynamicArrayIterator const& rhs) const noexcept { return m_pos < rhs.m_pos; } template bool operator> (DynamicArrayIterator const& rhs) const noexcept { return m_pos > rhs.m_pos; } template bool operator<= (DynamicArrayIterator const& rhs) const noexcept { return m_pos <= rhs.m_pos; } template bool operator>= (DynamicArrayIterator const& rhs) const noexcept { return m_pos >= rhs.m_pos; } reference operator[] (difference_type n) noexcept { return (*m_v)[m_pos + n]; } private: reference dereference () const noexcept { return (*m_v) [m_pos]; } void increment (difference_type n) noexcept { m_pos += n; } void decrement (difference_type n) noexcept { m_pos -= n; } private: template friend class DynamicArrayIterator; V* m_v; size_type m_pos; }; //------------------------------------------------------------------------------ template DynamicArrayIterator operator+ ( typename DynamicArrayIterator ::difference_type n, DynamicArrayIterator iter) noexcept { return iter + n; } template DynamicArrayIterator operator- ( typename DynamicArrayIterator ::difference_type n, DynamicArrayIterator iter) noexcept { return iter - n; } //------------------------------------------------------------------------------ template class DynamicArrayReverseIterator : public std::iterator { public: typedef typename copyconst ::type value_type; typedef value_type* pointer; typedef value_type& reference; typedef std::ptrdiff_t difference_type; typedef typename V::size_type size_type; DynamicArrayReverseIterator (V* v = nullptr, difference_type pos = 0) noexcept : m_v (v) , m_pos (pos) { } template DynamicArrayReverseIterator (DynamicArrayReverseIterator const& u) noexcept : m_v (u.m_v) , m_pos (u.m_pos) { } template DynamicArrayReverseIterator& operator= (DynamicArrayReverseIterator const& u) noexcept { m_v = u.m_v; m_pos = u.m_pos; return *this; } template bool operator== (DynamicArrayReverseIterator const& u) const noexcept { return (m_v == u.m_v) && (m_pos == u.m_pos); } template bool operator!= (DynamicArrayReverseIterator const& u) const noexcept { return ! ((*this) == u); } reference operator* () const noexcept { return dereference (); } pointer operator-> () const noexcept { return &dereference (); } DynamicArrayReverseIterator& operator++ () noexcept { increment (1); return *this; } DynamicArrayReverseIterator operator++ (int) noexcept { DynamicArrayReverseIterator const result (*this); increment (1); return result; } DynamicArrayReverseIterator& operator-- () noexcept { decrement (1); return *this; } DynamicArrayReverseIterator operator-- (int) noexcept { DynamicArrayReverseIterator const result (*this); decrement (1); return result; } DynamicArrayReverseIterator& operator+= (difference_type n) noexcept { increment (n); return *this; } DynamicArrayReverseIterator& operator-= (difference_type n) noexcept { decrement (n); return *this; } DynamicArrayReverseIterator operator+ (difference_type n) noexcept { return DynamicArrayReverseIterator (m_v, m_pos - n); } DynamicArrayReverseIterator operator- (difference_type n) noexcept { return DynamicArrayReverseIterator (m_v, m_pos + n); } template difference_type operator- (DynamicArrayReverseIterator const& rhs) const noexcept { return rhs.m_pos - m_pos; } template bool operator< (DynamicArrayReverseIterator const& rhs) const noexcept { return m_pos > rhs.m_pos; } template bool operator> (DynamicArrayReverseIterator const& rhs) const noexcept { return m_pos < rhs.m_pos; } template bool operator<= (DynamicArrayReverseIterator const& rhs) const noexcept { return m_pos >= rhs.m_pos; } template bool operator>= (DynamicArrayReverseIterator const& rhs) const noexcept { return m_pos <= rhs.m_pos; } reference operator[] (difference_type n) noexcept { return (*m_v)[(m_pos - 1) - n]; } private: template friend class DynamicArrayReverseIterator; reference dereference () const noexcept { return (*m_v) [m_pos - 1]; } void increment (difference_type n) noexcept { m_pos -= n; } void decrement (difference_type n) noexcept { m_pos += n; } V* m_v; difference_type m_pos; }; //------------------------------------------------------------------------------ template DynamicArrayReverseIterator operator+ ( typename DynamicArrayReverseIterator ::difference_type n, DynamicArrayReverseIterator iter) noexcept { return iter + n; } template DynamicArrayReverseIterator operator- ( typename DynamicArrayReverseIterator ::difference_type n, DynamicArrayReverseIterator iter) noexcept { return iter - n; } } //------------------------------------------------------------------------------ template > class DynamicArray { private: typedef PARAMETER_TYPE (T) TParam; typedef std::vector handles_t; public: enum { defaultBlocksize = 1000, growthPercentage = 10 }; typedef T value_type; typedef Allocator allocator_type; typedef std::size_t size_type; typedef std::ptrdiff_t difference_type; typedef value_type* pointer; typedef value_type& reference; typedef value_type const* const_pointer; typedef value_type const& const_reference; typedef detail::DynamicArrayIterator > iterator; typedef detail::DynamicArrayIterator const> const_iterator; typedef detail::DynamicArrayReverseIterator > reverse_iterator; typedef detail::DynamicArrayReverseIterator const> const_reverse_iterator; //-------------------------------------------------------------------------- explicit DynamicArray (size_type blocksize = defaultBlocksize) noexcept : m_blocksize (blocksize) , m_capacity (0) , m_size (0) { } ~DynamicArray() { clear (); shrink_to_fit (); } /** Replace the array with 'count' copies of a default-constructed T. */ void assign (size_type count) { clear (); resize (count); } //-------------------------------------------------------------------------- reference at (size_type pos) { if (pos >= size ()) Throw (std::out_of_range ("bad pos"), __FILE__, __LINE__); return get (pos); } const_reference at (size_type pos) const { if (pos >= size ()) Throw (std::out_of_range ("bad pos"), __FILE__, __LINE__); return get (pos); } reference operator[] (size_type pos) noexcept { return get (pos); } const_reference operator[] (size_type pos) const noexcept { return get (pos); } reference front () noexcept { return get (0); } const_reference front () const noexcept { return get (0); } reference back () noexcept { return get (size () - 1); } const_reference back () const noexcept { return get (size () - 1); } //-------------------------------------------------------------------------- iterator begin () noexcept { return iterator (this, 0); } const_iterator begin () const noexcept { return const_iterator (this, 0); } const_iterator cbegin () const noexcept { return const_iterator (this, 0); } iterator end () noexcept { return iterator (this, size ()); } const_iterator end () const noexcept { return const_iterator (this, size ()); } const_iterator cend () const noexcept { return const_iterator (this, size ()); } reverse_iterator rbegin () noexcept { return reverse_iterator (this, size ()); } const_reverse_iterator rbegin () const noexcept { return const_reverse_iterator (this, size ()); } const_reverse_iterator crbegin () const noexcept { return const_reverse_iterator (this, size ()); } reverse_iterator rend () noexcept { return reverse_iterator (this, 0); } const_reverse_iterator rend () const noexcept { return const_reverse_iterator (this, 0); } const_reverse_iterator crend () const noexcept { return const_reverse_iterator (this, 0); } //-------------------------------------------------------------------------- bool empty () const noexcept { return m_size == 0; } size_type size () const noexcept { return m_size; } size_type max_size () const noexcept { return std::numeric_limits ::max (); } void reserve (size_type new_cap) { new_cap = m_blocksize * ( (new_cap + m_blocksize - 1) / m_blocksize); if (new_cap > max_size ()) Throw (std::length_error ("new_cap > max_size"), __FILE__, __LINE__); if (new_cap <= m_capacity) return; size_type const n (new_cap / m_blocksize); m_handles.reserve (n); for (size_type i = m_handles.size (); i < n; ++i) m_handles.push_back (static_cast (std::malloc ( m_blocksize * sizeof (T)))); m_capacity = new_cap; } size_type capacity () const noexcept { return m_capacity; } void shrink_to_fit () { size_type const handles ( (size () + m_blocksize - 1) / m_blocksize); m_capacity = handles * m_blocksize; for (size_type i = m_handles.size (); i-- > handles;) { std::free (m_handles [i]); m_handles.erase (m_handles.begin () + i); } } //-------------------------------------------------------------------------- void clear () { resize (0); } iterator push_back (TParam value) { ::new (alloc ()) T (value); return iterator (this, size () - 1); } iterator emplace_back () { ::new (alloc ()) T (); return iterator (this, size () - 1); } template iterator emplace_back (A1 a1) { ::new (alloc ()) T (a1); return iterator (this, size () - 1); } template iterator emplace_back (A1 a1, A2 a2) { ::new (alloc ()) T (a1, a2); return iterator (this, size () - 1); } template iterator emplace_back (A1 a1, A2 a2, A3 a3) { ::new (alloc ()) T (a1, a2, a3); return iterator (this, size () - 1); } template iterator emplace_back (A1 a1, A2 a2, A3 a3, A4 a4) { ::new (alloc ()) T (a1, a2, a3, a4); return iterator (this, size () - 1); } template iterator emplace_back (A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) { ::new (alloc ()) T (a1, a2, a3, a4, a5); return iterator (this, size () - 1); } void pop_back () { resize (size () - 1); } void resize (size_type count) { while (count > size ()) ::new (alloc ()) T; while (count < size ()) get (--m_size).~T (); } void resize (size_type count, TParam value) { while (count > size ()) ::new (alloc ()) T (value); while (count < size ()) get (--m_size).~T (); } void swap (DynamicArray& other) { std::swap (m_blocksize, other.m_blocksize); std::swap (m_size, other.m_size); std::swap (m_capacity, other.m_capacity); std::swap (m_handles, other.m_handles); } private: reference get (size_type pos) noexcept { size_type const index (pos / m_blocksize); size_type const offset (pos % m_blocksize); return m_handles [index] [offset]; } const_reference get (size_type pos) const noexcept { size_type const index (pos / m_blocksize); size_type const offset (pos % m_blocksize); return m_handles [index] [offset]; } T* alloc () noexcept { size_type const needed (size () + 1); if (capacity () < needed) reserve ((needed * (100 + growthPercentage) + 99) / 100); return &get (m_size++); } private: Allocator m_allocator; size_type m_blocksize; size_type m_capacity; size_type m_size; handles_t m_handles; }; #endif