michael@0: /* GRAPHITE2 LICENSING michael@0: michael@0: Copyright 2010, SIL International michael@0: All rights reserved. michael@0: michael@0: This library is free software; you can redistribute it and/or modify michael@0: it under the terms of the GNU Lesser General Public License as published michael@0: by the Free Software Foundation; either version 2.1 of License, or michael@0: (at your option) any later version. michael@0: michael@0: This program is distributed in the hope that it will be useful, michael@0: but WITHOUT ANY WARRANTY; without even the implied warranty of michael@0: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU michael@0: Lesser General Public License for more details. michael@0: michael@0: You should also have received a copy of the GNU Lesser General Public michael@0: License along with this library in the file named "LICENSE". michael@0: If not, write to the Free Software Foundation, 51 Franklin Street, michael@0: Suite 500, Boston, MA 02110-1335, USA or visit their web page on the michael@0: internet at http://www.fsf.org/licenses/lgpl.html. michael@0: michael@0: Alternatively, the contents of this file may be used under the terms of the michael@0: Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public michael@0: License, as published by the Free Software Foundation, either version 2 michael@0: of the License or (at your option) any later version. michael@0: */ michael@0: michael@0: // designed to have a limited subset of the std::vector api michael@0: #pragma once michael@0: michael@0: #include michael@0: #include michael@0: #include michael@0: #include michael@0: #include michael@0: michael@0: michael@0: namespace graphite2 { michael@0: michael@0: template michael@0: inline michael@0: ptrdiff_t distance(T* first, T* last) { return last-first; } michael@0: michael@0: michael@0: template michael@0: class Vector michael@0: { michael@0: T * m_first, *m_last, *m_end; michael@0: public: michael@0: typedef T & reference; michael@0: typedef const T & const_reference; michael@0: typedef T * iterator; michael@0: typedef const T * const_iterator; michael@0: michael@0: Vector() : m_first(0), m_last(0), m_end(0) {} michael@0: Vector(size_t n, const T& value = T()) : m_first(0), m_last(0), m_end(0) { insert(begin(), n, value); } michael@0: Vector(const Vector &rhs) : m_first(0), m_last(0), m_end(0) { insert(begin(), rhs.begin(), rhs.end()); } michael@0: template michael@0: Vector(I first, const I last) : m_first(0), m_last(0), m_end(0) { insert(begin(), first, last); } michael@0: ~Vector() { clear(); free(m_first); } michael@0: michael@0: iterator begin() { return m_first; } michael@0: const_iterator begin() const { return m_first; } michael@0: michael@0: iterator end() { return m_last; } michael@0: const_iterator end() const { return m_last; } michael@0: michael@0: bool empty() const { return m_first == m_last; } michael@0: size_t size() const { return m_last - m_first; } michael@0: size_t capacity() const{ return m_end - m_first; } michael@0: michael@0: void reserve(size_t n); michael@0: michael@0: reference front() { assert(size() > 0); return *begin(); } michael@0: const_reference front() const { assert(size() > 0); return *begin(); } michael@0: reference back() { assert(size() > 0); return *(end()-1); } michael@0: const_reference back() const { assert(size() > 0); return *(end()-1); } michael@0: michael@0: Vector & operator = (const Vector & rhs) { assign(rhs.begin(), rhs.end()); return *this; } michael@0: reference operator [] (size_t n) { assert(size() > n); return m_first[n]; } michael@0: const_reference operator [] (size_t n) const { assert(size() > n); return m_first[n]; } michael@0: michael@0: void assign(size_t n, const T& u) { clear(); insert(begin(), n, u); } michael@0: void assign(const_iterator first, const_iterator last) { clear(); insert(begin(), first, last); } michael@0: iterator insert(iterator p, const T & x) { p = _insert_default(p, 1); *p = x; return p; } michael@0: void insert(iterator p, size_t n, const T & x); michael@0: void insert(iterator p, const_iterator first, const_iterator last); michael@0: void pop_back() { assert(size() > 0); --m_last; } michael@0: void push_back(const T &v) { if (m_last == m_end) reserve(size()+1); new (m_last++) T(v); } michael@0: michael@0: void clear() { erase(begin(), end()); } michael@0: iterator erase(iterator p) { return erase(p, p+1); } michael@0: iterator erase(iterator first, iterator last); michael@0: michael@0: private: michael@0: iterator _insert_default(iterator p, size_t n); michael@0: }; michael@0: michael@0: template michael@0: inline michael@0: void Vector::reserve(size_t n) michael@0: { michael@0: if (n > capacity()) michael@0: { michael@0: const ptrdiff_t sz = size(); michael@0: m_first = static_cast(realloc(m_first, n*sizeof(T))); michael@0: m_last = m_first + sz; michael@0: m_end = m_first + n; michael@0: } michael@0: } michael@0: michael@0: template michael@0: inline michael@0: typename Vector::iterator Vector::_insert_default(iterator p, size_t n) michael@0: { michael@0: assert(begin() <= p && p <= end()); michael@0: const ptrdiff_t i = p - begin(); michael@0: reserve((size() + n + 7) >> 3 << 3); michael@0: p = begin() + i; michael@0: // Move tail if there is one michael@0: if (p != end()) memmove(p + n, p, distance(p,end())*sizeof(T)); michael@0: m_last += n; michael@0: return p; michael@0: } michael@0: michael@0: template michael@0: inline michael@0: void Vector::insert(iterator p, size_t n, const T & x) michael@0: { michael@0: p = _insert_default(p, n); michael@0: // Copy in elements michael@0: for (; n; --n, ++p) { new (p) T(x); } michael@0: } michael@0: michael@0: template michael@0: inline michael@0: void Vector::insert(iterator p, const_iterator first, const_iterator last) michael@0: { michael@0: p = _insert_default(p, distance(first, last)); michael@0: // Copy in elements michael@0: for (;first != last; ++first, ++p) { new (p) T(*first); } michael@0: } michael@0: michael@0: template michael@0: inline michael@0: typename Vector::iterator Vector::erase(iterator first, iterator last) michael@0: { michael@0: for (iterator e = first; e != last; ++e) e->~T(); michael@0: const size_t sz = distance(first, last); michael@0: if (m_last != last) memmove(first, last, distance(last,end())*sizeof(T)); michael@0: m_last -= sz; michael@0: return first; michael@0: } michael@0: michael@0: } // namespace graphite2