// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. // ==++== // // // // ==--== /*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XX XX XX vector XX XX XX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */ #pragma once #include "allocator.h" #include "iterator.h" namespace jitstd { template > class vector { public: typedef Allocator allocator_type; typedef T* pointer; typedef T& reference; typedef const T* const_pointer; typedef const T& const_reference; typedef size_t size_type; typedef ptrdiff_t difference_type; typedef T value_type; // nested classes class iterator : public jitstd::iterator { iterator(T* ptr); public: iterator(); iterator(const iterator& it); iterator& operator++(); iterator& operator++(int); iterator& operator--(); iterator& operator--(int); iterator operator+(difference_type n); iterator operator-(difference_type n); size_type operator-(const iterator& that); bool operator==(const iterator& it); bool operator!=(const iterator& it); T& operator*(); T* operator&(); operator T*(); private: friend class vector; pointer m_pElem; }; class const_iterator : public jitstd::iterator { private: const_iterator(T* ptr); const_iterator(); public: const_iterator(const const_iterator& it); const_iterator& operator++(); const_iterator& operator++(int); const_iterator& operator--(); const_iterator& operator--(int); const_iterator operator+(difference_type n); const_iterator operator-(difference_type n); size_type operator-(const const_iterator& that); bool operator==(const const_iterator& it) const; bool operator!=(const const_iterator& it) const; const T& operator*() const; const T* operator&() const; operator const T*() const; private: friend class vector; pointer m_pElem; }; class reverse_iterator : public jitstd::iterator { private: reverse_iterator(T* ptr); public: reverse_iterator(); reverse_iterator(const reverse_iterator& it); reverse_iterator& operator++(); reverse_iterator& operator++(int); reverse_iterator& operator--(); reverse_iterator& operator--(int); reverse_iterator operator+(difference_type n); reverse_iterator operator-(difference_type n); size_type operator-(const reverse_iterator& that); bool operator==(const reverse_iterator& it); bool operator!=(const reverse_iterator& it); T& operator*(); T* operator&(); operator T*(); private: friend class vector; pointer m_pElem; }; class const_reverse_iterator : public jitstd::iterator { private: const_reverse_iterator(T* ptr); public: const_reverse_iterator(); const_reverse_iterator(const const_reverse_iterator& it); const_reverse_iterator& operator++(); const_reverse_iterator& operator++(int); const_reverse_iterator& operator--(); const_reverse_iterator& operator--(int); const_reverse_iterator operator+(difference_type n); const_reverse_iterator operator-(difference_type n); size_type operator-(const const_reverse_iterator& that); bool operator==(const const_reverse_iterator& it) const; bool operator!=(const const_reverse_iterator& it) const; const T& operator*() const; const T* operator&() const; operator const T*() const; private: friend class vector; pointer m_pElem; }; // ctors explicit vector(const Allocator& allocator); explicit vector(size_type n, const T& value, const Allocator& allocator); template vector(InputIterator first, InputIterator last, const Allocator& allocator); // cctors vector(const vector& vec); template explicit vector(const vector& vec); // dtor ~vector(); template void assign(InputIterator first, InputIterator last); void assign(size_type size, const T& value); const_reference at(size_type n) const; reference at(size_type n); reference back(); const_reference back() const; iterator begin(); const_iterator begin() const; const_iterator cbegin() const; size_type capacity() const; void clear(); bool empty() const; iterator end(); const_iterator end() const; const_iterator cend() const; iterator erase(iterator position); iterator erase(iterator first, iterator last); reference front(); const_reference front() const; allocator_type get_allocator() const; iterator insert(iterator position, const T& value); void insert(iterator position, size_type size, const T& value); template void insert(iterator position, InputIterator first, InputIterator last); size_type max_size() const; vector& operator=(const vector& vec); template vector& operator=(const vector& vec); reference operator[](size_type n); const_reference operator[](size_type n) const; void pop_back(); void push_back(const T& value); reverse_iterator rbegin(); const_reverse_iterator rbegin() const; reverse_iterator rend(); const_reverse_iterator rend() const; void reserve(size_type n); void resize(size_type sz, const T&); size_type size() const; void swap(vector& vec); private: typename Allocator::template rebind::allocator m_allocator; T* m_pArray; size_type m_nSize; size_type m_nCapacity; inline bool ensure_capacity(size_type capacity); template void construct_helper(InputIterator first, InputIterator last, forward_iterator_tag); template void construct_helper(InputIterator first, InputIterator last, int_not_an_iterator_tag); void construct_helper(size_type size, const T& value); template void insert_helper(iterator iter, InputIterator first, InputIterator last, forward_iterator_tag); template void insert_helper(iterator iter, InputIterator first, InputIterator last, int_not_an_iterator_tag); void insert_elements_helper(iterator iter, size_type size, const T& value); template void assign_helper(InputIterator first, InputIterator last, forward_iterator_tag); template void assign_helper(InputIterator first, InputIterator last, int_not_an_iterator_tag); template friend class vector; }; }// namespace jit_std // Implementation of vector. namespace jitstd { namespace { template size_t iterator_difference(InputIterator first, const InputIterator& last) { size_t size = 0; for (; first != last; ++first, ++size); return size; } } template vector::vector(const Allocator& allocator) : m_allocator(allocator) , m_pArray(nullptr) , m_nSize(0) , m_nCapacity(0) { } template vector::vector(size_type size, const T& value, const Allocator& allocator) : m_allocator(allocator) , m_pArray(NULL) , m_nSize(0) , m_nCapacity(0) { construct_helper(size, value); } template template vector::vector(InputIterator first, InputIterator last, const Allocator& allocator) : m_allocator(allocator) , m_pArray(NULL) , m_nSize(0) , m_nCapacity(0) { construct_helper(first, last, iterator_traits::iterator_category()); } template template vector::vector(const vector& vec) : m_allocator(vec.m_allocator) , m_pArray(NULL) , m_nSize(0) , m_nCapacity(0) { ensure_capacity(vec.m_nSize); for (size_type i = 0, j = 0; i < vec.m_nSize; ++i, ++j) { new (m_pArray + i, placement_t()) T((T) vec.m_pArray[j]); } m_nSize = vec.m_nSize; } template vector::vector(const vector& vec) : m_allocator(vec.m_allocator) , m_pArray(NULL) , m_nSize(0) , m_nCapacity(0) { ensure_capacity(vec.m_nSize); for (size_type i = 0, j = 0; i < vec.m_nSize; ++i, ++j) { new (m_pArray + i, placement_t()) T(vec.m_pArray[j]); } m_nSize = vec.m_nSize; } template vector::~vector() { for (size_type i = 0; i < m_nSize; ++i) { m_pArray[i].~T(); } m_allocator.deallocate(m_pArray, m_nCapacity); m_nSize = 0; m_nCapacity = 0; } // public methods template template void vector::assign(InputIterator first, InputIterator last) { construct_helper(first, last, iterator_traits::iterator_category()); } template void vector::assign(size_type size, const T& value) { ensure_capacity(size); for (int i = 0; i < size; ++i) { m_pArray[i] = value; } m_nSize = size; } template typename vector::const_reference vector::at(size_type i) const { return operator[](i); } template typename vector::reference vector::at(size_type i) { return operator[](i); } template typename vector::reference vector::back() { return operator[](m_nSize - 1); } template typename vector::const_reference vector::back() const { return operator[](m_nSize - 1); } template typename vector::iterator vector::begin() { return iterator(m_pArray); } template typename vector::const_iterator vector::begin() const { return const_iterator(m_pArray); } template typename vector::const_iterator vector::cbegin() const { return const_iterator(m_pArray); } template typename vector::size_type vector::capacity() const { return m_nCapacity; } template void vector::clear() { for (size_type i = 0; i < m_nSize; ++i) { m_pArray[i].~T(); } m_nSize = 0; } template bool vector::empty() const { return m_nSize == 0; } template typename vector::iterator vector::end() { return iterator(m_pArray + m_nSize); } template typename vector::const_iterator vector::end() const { return const_iterator(m_pArray + m_nSize); } template typename vector::const_iterator vector::cend() const { return const_iterator(m_pArray + m_nSize); } template typename vector::iterator vector::erase( typename vector::iterator position) { return erase(position, position + 1); } template typename vector::iterator vector::erase( typename vector::iterator first, typename vector::iterator last) { assert(m_nSize > 0); assert(first.m_pElem >= m_pArray); assert(last.m_pElem >= m_pArray); assert(first.m_pElem <= m_pArray + m_nSize); assert(last.m_pElem <= m_pArray + m_nSize); assert(last.m_pElem > first.m_pElem); pointer fptr = first.m_pElem; pointer lptr = last.m_pElem; pointer eptr = m_pArray + m_nSize; for (; lptr != eptr; ++lptr, fptr++) { (*fptr).~T(); *fptr = *lptr; } m_nSize -= (size_type)(lptr - fptr); return first; } template typename vector::reference vector::front() { return operator[](0); } template typename vector::const_reference vector::front() const { return operator[](0); } template typename vector::allocator_type vector::get_allocator() const { return m_allocator; } template typename vector::iterator vector::insert( typename vector::iterator iter, const T& value) { size_type pos = (size_type) (iter.m_pElem - m_pArray); insert_elements_helper(iter, 1, value); return iterator(m_pArray + pos); } template void vector::insert( iterator iter, size_type size, const T& value) { insert_elements_helper(iter, size, value); } template template void vector::insert( iterator iter, InputIterator first, InputIterator last) { insert_helper(iter, first, last, iterator_traits::iterator_category()); } template typename vector::size_type vector::max_size() const { return ((size_type) -1) >> 1; } template template vector& vector::operator=(const vector& vec) { // We'll not observe copy-on-write for now. m_allocator = vec.m_allocator; ensure_capacity(vec.m_nSize); m_nSize = vec.m_nSize; for (size_type i = 0; i < m_nSize; ++i) { m_pArray[i] = (T) vec.m_pArray[i]; } return *this; } template vector& vector::operator=(const vector& vec) { // We'll not observe copy-on-write for now. m_allocator = vec.m_allocator; ensure_capacity(vec.m_nSize); m_nSize = vec.m_nSize; for (size_type i = 0; i < m_nSize; ++i) { new (m_pArray + i, placement_t()) T(vec.m_pArray[i]); } return *this; } template typename vector::reference vector::operator[](size_type n) { return m_pArray[n]; } template typename vector::const_reference vector::operator[](size_type n) const { return m_pArray[n]; } template void vector::pop_back() { m_pArray[m_nSize - 1].~T(); --m_nSize; } template void vector::push_back(const T& value) { ensure_capacity(m_nSize + 1); new (m_pArray + m_nSize, placement_t()) T(value); ++m_nSize; } template typename vector::reverse_iterator vector::rbegin() { return reverse_iterator(m_pArray + m_nSize - 1); } template typename vector::const_reverse_iterator vector::rbegin() const { return const_reverse_iterator(m_pArray + m_nSize - 1); } template typename vector::reverse_iterator vector::rend() { return reverse_iterator(m_pArray - 1); } template typename vector::const_reverse_iterator vector::rend() const { return const_reverse_iterator(m_pArray - 1); } template void vector::reserve(size_type n) { ensure_capacity(n); } template void vector::resize( size_type sz, const T& c) { for (; m_nSize > sz; m_nSize--) { m_pArray[m_nSize - 1].~T(); } ensure_capacity(sz); for (; m_nSize < sz; m_nSize++) { new (m_pArray + m_nSize, placement_t()) T(c); } } template typename vector::size_type vector::size() const { return m_nSize; } template void vector::swap(vector& vec) { jitstd::swap(m_pArray, vec.m_pArray); jitstd::swap(m_nSize, vec.m_nSize); jitstd::swap(m_nCapacity, vec.m_nCapacity); jitstd::swap(m_nCapacity, vec.m_nCapacity); jitstd::swap(m_allocator, vec.m_allocator); } // ======================================================================================= template void vector::construct_helper(size_type size, const T& value) { ensure_capacity(size); for (size_type i = 0; i < size; ++i) { new (m_pArray + i, placement_t()) T(value); } m_nSize = size; } template template void vector::construct_helper(InputIterator first, InputIterator last, int_not_an_iterator_tag) { construct_helper(first, last); } template template void vector::construct_helper(InputIterator first, InputIterator last, forward_iterator_tag) { size_type size = iterator_difference(first, last); ensure_capacity(size); for (size_type i = 0; i < size; ++i) { new (m_pArray + i, placement_t()) T(*first); first++; } m_nSize = size; } // ======================================================================================= template void vector::insert_elements_helper(iterator iter, size_type size, const T& value) { assert(size < max_size()); // m_pElem could be NULL then m_pArray would be NULL too. size_type pos = iter.m_pElem - m_pArray; assert(pos <= m_nSize); // <= could insert at end. assert(pos >= 0); ensure_capacity(m_nSize + size); for (int src = m_nSize - 1, dst = m_nSize + size - 1; src >= (int) pos; --src, --dst) { m_pArray[dst] = m_pArray[src]; } for (size_type i = 0; i < size; ++i) { new (m_pArray + pos + i, placement_t()) T(value); } m_nSize += size; } template template void vector::insert_helper(iterator iter, InputIterator first, InputIterator last, int_not_an_iterator_tag) { insert_elements_helper(iter, first, last); } template template void vector::insert_helper(iterator iter, InputIterator first, InputIterator last, forward_iterator_tag) { // m_pElem could be NULL then m_pArray would be NULL too. size_type pos = iter.m_pElem - m_pArray; assert(pos <= m_nSize); // <= could insert at end. assert(pos >= 0); size_type size = iterator_difference(first, last); assert(size < max_size()); ensure_capacity(m_nSize + size); pointer lst = m_pArray + m_nSize + size - 1; for (size_type i = pos; i < m_nSize; ++i) { *lst-- = m_pArray[i]; } for (size_type i = 0; i < size; ++i, ++first) { m_pArray[pos + i] = *first; } m_nSize += size; } // ======================================================================================= template template void vector::assign_helper(InputIterator first, InputIterator last, forward_iterator_tag) { size_type size = iterator_difference(first, last); ensure_capacity(size); for (size_type i = 0; i < size; ++i) { m_pArray[i] = *first; first++; } m_nSize = size; } template template void vector::assign_helper(InputIterator first, InputIterator last, int_not_an_iterator_tag) { assign_helper(first, last); } // ======================================================================================= template bool vector::ensure_capacity(size_type newCap) { if (newCap <= m_nCapacity) { return false; } // Double the alloc capacity based on size. size_type allocCap = m_nSize * 2; // Is it still not sufficient? if (allocCap < newCap) { allocCap = newCap; } // Allocate space. pointer ptr = m_allocator.allocate(allocCap); // Copy over. for (size_type i = 0; i < m_nSize; ++i) { new (ptr + i, placement_t()) T(m_pArray[i]); } // Deallocate currently allocated space. m_allocator.deallocate(m_pArray, m_nCapacity); // Update the pointers and capacity; m_pArray = ptr; m_nCapacity = allocCap; return true; } } // end of namespace jitstd. // Implementation of vector iterators namespace jitstd { // iterator template vector::iterator::iterator() : m_pElem(NULL) { } template vector::iterator::iterator(T* ptr) : m_pElem(ptr) { } template vector::iterator::iterator(const iterator& it) : m_pElem(it.m_pElem) { } template typename vector::iterator& vector::iterator::operator++() { ++m_pElem; return *this; } template typename vector::iterator& vector::iterator::operator++(int) { ++m_pElem; return *this; } template typename vector::iterator& vector::iterator::operator--() { --m_pElem; return *this; } template typename vector::iterator& vector::iterator::operator--(int) { --m_pElem; return *this; } template typename vector::iterator vector::iterator::operator+(difference_type n) { return iterator(m_pElem + n); } template typename vector::iterator vector::iterator::operator-(difference_type n) { return iterator(m_pElem - n); } template typename vector::size_type vector::iterator::operator-( const typename vector::iterator& that) { return m_pElem - that.m_pElem; } template bool vector::iterator::operator==(const iterator& it) { return (m_pElem == it.m_pElem); } template bool vector::iterator::operator!=(const iterator& it) { return !operator==(it); } template T& vector::iterator::operator*() { return *m_pElem; } template T* vector::iterator::operator&() { return &m_pElem; } template vector::iterator::operator T*() { return &m_pElem; } // const_iterator template vector::const_iterator::const_iterator() : m_pElem(NULL) { } template vector::const_iterator::const_iterator(T* ptr) : m_pElem(ptr) { } template vector::const_iterator::const_iterator(const const_iterator& it) : m_pElem(it.m_pElem) { } template typename vector::const_iterator& vector::const_iterator::operator++() { ++m_pElem; return *this; } template typename vector::const_iterator& vector::const_iterator::operator++(int) { ++m_pElem; return *this; } template typename vector::const_iterator& vector::const_iterator::operator--() { --m_pElem; return *this; } template typename vector::const_iterator& vector::const_iterator::operator--(int) { --m_pElem; return *this; } template typename vector::const_iterator vector::const_iterator::operator+(difference_type n) { return const_iterator(m_pElem + n); } template typename vector::const_iterator vector::const_iterator::operator-(difference_type n) { return const_iterator(m_pElem - n); } template typename vector::size_type vector::const_iterator::operator-( const typename vector::const_iterator& that) { return m_pElem - that.m_pElem; } template bool vector::const_iterator::operator==(const const_iterator& it) const { return (m_pElem == it.m_pElem); } template bool vector::const_iterator::operator!=(const const_iterator& it) const { return !operator==(it); } template const T& vector::const_iterator::operator*() const { return *m_pElem; } template const T* vector::const_iterator::operator&() const { return &m_pElem; } template vector::const_iterator::operator const T*() const { return &m_pElem; } // reverse_iterator template vector::reverse_iterator::reverse_iterator() : m_pElem(NULL) { } template vector::reverse_iterator::reverse_iterator(T* ptr) : m_pElem(ptr) { } template vector::reverse_iterator::reverse_iterator(const reverse_iterator& it) : m_pElem(it.m_pElem) { } template typename vector::reverse_iterator& vector::reverse_iterator::operator++() { --m_pElem; return *this; } template typename vector::reverse_iterator& vector::reverse_iterator::operator++(int) { --m_pElem; return *this; } template typename vector::reverse_iterator& vector::reverse_iterator::operator--() { ++m_pElem; return *this; } template typename vector::reverse_iterator& vector::reverse_iterator::operator--(int) { ++m_pElem; return *this; } template typename vector::reverse_iterator vector::reverse_iterator::operator+(difference_type n) { return reverse_iterator(m_pElem + n); } template typename vector::reverse_iterator vector::reverse_iterator::operator-(difference_type n) { return reverse_iterator(m_pElem - n); } template typename vector::size_type vector::reverse_iterator::operator-( const typename vector::reverse_iterator& that) { return m_pElem - that.m_pElem; } template bool vector::reverse_iterator::operator==(const reverse_iterator& it) { return (m_pElem == it.m_pElem); } template bool vector::reverse_iterator::operator!=(const reverse_iterator& it) { return !operator==(it); } template T& vector::reverse_iterator::operator*() { return *m_pElem; } template T* vector::reverse_iterator::operator&() { return &m_pElem; } template vector::reverse_iterator::operator T*() { return &m_pElem; } // const_reverse_iterator template vector::const_reverse_iterator::const_reverse_iterator() : m_pElem(NULL) { } template vector::const_reverse_iterator::const_reverse_iterator(T* ptr) : m_pElem(ptr) { } template vector::const_reverse_iterator::const_reverse_iterator(const const_reverse_iterator& it) : m_pElem(it.m_pElem) { } template typename vector::const_reverse_iterator& vector::const_reverse_iterator::operator++() { --m_pElem; return *this; } template typename vector::const_reverse_iterator& vector::const_reverse_iterator::operator++(int) { --m_pElem; return *this; } template typename vector::const_reverse_iterator& vector::const_reverse_iterator::operator--() { ++m_pElem; return *this; } template typename vector::const_reverse_iterator& vector::const_reverse_iterator::operator--(int) { ++m_pElem; return *this; } template typename vector::const_reverse_iterator vector::const_reverse_iterator::operator+(difference_type n) { return const_reverse_iterator(m_pElem + n); } template typename vector::const_reverse_iterator vector::const_reverse_iterator::operator-(difference_type n) { return const_reverse_iterator(m_pElem - n); } template typename vector::size_type vector::const_reverse_iterator::operator-( const typename vector::const_reverse_iterator& that) { return m_pElem - that.m_pElem; } template bool vector::const_reverse_iterator::operator==(const const_reverse_iterator& it) const { return (m_pElem == it.m_pElem); } template bool vector::const_reverse_iterator::operator!=(const const_reverse_iterator& it) const { return !operator==(it); } template const T& vector::const_reverse_iterator::operator*() const { return *m_pElem; } template const T* vector::const_reverse_iterator::operator&() const { return &m_pElem; } template vector::const_reverse_iterator::operator const T*() const { return &m_pElem; } }