// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later // Copyright 2010, SIL International, All rights reserved. // designed to have a limited subset of the std::vector api #pragma once #include #include #include #include #include #include "Main.h" namespace graphite2 { template inline ptrdiff_t distance(T* first, T* last) { return last-first; } template class Vector { T * m_first, *m_last, *m_end; public: typedef T & reference; typedef const T & const_reference; typedef T * iterator; typedef const T * const_iterator; Vector() : m_first(0), m_last(0), m_end(0) {} Vector(size_t n, const T& value = T()) : m_first(0), m_last(0), m_end(0) { insert(begin(), n, value); } Vector(const Vector &rhs) : m_first(0), m_last(0), m_end(0) { insert(begin(), rhs.begin(), rhs.end()); } template Vector(I first, const I last) : m_first(0), m_last(0), m_end(0) { insert(begin(), first, last); } ~Vector() { clear(); free(m_first); } iterator begin() { return m_first; } const_iterator begin() const { return m_first; } iterator end() { return m_last; } const_iterator end() const { return m_last; } bool empty() const { return m_first == m_last; } size_t size() const { return m_last - m_first; } size_t capacity() const{ return m_end - m_first; } void reserve(size_t n); void resize(size_t n, const T & v = T()); reference front() { assert(size() > 0); return *begin(); } const_reference front() const { assert(size() > 0); return *begin(); } reference back() { assert(size() > 0); return *(end()-1); } const_reference back() const { assert(size() > 0); return *(end()-1); } Vector & operator = (const Vector & rhs) { assign(rhs.begin(), rhs.end()); return *this; } reference operator [] (size_t n) { assert(size() > n); return m_first[n]; } const_reference operator [] (size_t n) const { assert(size() > n); return m_first[n]; } void assign(size_t n, const T& u) { clear(); insert(begin(), n, u); } void assign(const_iterator first, const_iterator last) { clear(); insert(begin(), first, last); } iterator insert(iterator p, const T & x) { p = _insert_default(p, 1); new (p) T(x); return p; } void insert(iterator p, size_t n, const T & x); void insert(iterator p, const_iterator first, const_iterator last); void pop_back() { assert(size() > 0); --m_last; } void push_back(const T &v) { if (m_last == m_end) reserve(size()+1); new (m_last++) T(v); } void clear() { erase(begin(), end()); } iterator erase(iterator p) { return erase(p, p+1); } iterator erase(iterator first, iterator last); private: iterator _insert_default(iterator p, size_t n); }; template inline void Vector::reserve(size_t n) { if (n > capacity()) { const ptrdiff_t sz = size(); size_t requested; if (checked_mul(n,sizeof(T), requested)) std::abort(); m_first = static_cast(realloc(m_first, requested)); if (!m_first) std::abort(); m_last = m_first + sz; m_end = m_first + n; } } template inline void Vector::resize(size_t n, const T & v) { const ptrdiff_t d = n-size(); if (d < 0) erase(end()+d, end()); else if (d > 0) insert(end(), d, v); } template inline typename Vector::iterator Vector::_insert_default(iterator p, size_t n) { assert(begin() <= p && p <= end()); const ptrdiff_t i = p - begin(); reserve(((size() + n + 7) >> 3) << 3); p = begin() + i; // Move tail if there is one if (p != end()) memmove(p + n, p, distance(p,end())*sizeof(T)); m_last += n; return p; } template inline void Vector::insert(iterator p, size_t n, const T & x) { p = _insert_default(p, n); // Copy in elements for (; n; --n, ++p) { new (p) T(x); } } template inline void Vector::insert(iterator p, const_iterator first, const_iterator last) { p = _insert_default(p, distance(first, last)); // Copy in elements for (;first != last; ++first, ++p) { new (p) T(*first); } } template inline typename Vector::iterator Vector::erase(iterator first, iterator last) { for (iterator e = first; e != last; ++e) e->~T(); const size_t sz = distance(first, last); if (m_last != last) memmove(first, last, distance(last,end())*sizeof(T)); m_last -= sz; return first; } } // namespace graphite2