|
1 /* GRAPHITE2 LICENSING |
|
2 |
|
3 Copyright 2010, SIL International |
|
4 All rights reserved. |
|
5 |
|
6 This library is free software; you can redistribute it and/or modify |
|
7 it under the terms of the GNU Lesser General Public License as published |
|
8 by the Free Software Foundation; either version 2.1 of License, or |
|
9 (at your option) any later version. |
|
10 |
|
11 This program is distributed in the hope that it will be useful, |
|
12 but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
14 Lesser General Public License for more details. |
|
15 |
|
16 You should also have received a copy of the GNU Lesser General Public |
|
17 License along with this library in the file named "LICENSE". |
|
18 If not, write to the Free Software Foundation, 51 Franklin Street, |
|
19 Suite 500, Boston, MA 02110-1335, USA or visit their web page on the |
|
20 internet at http://www.fsf.org/licenses/lgpl.html. |
|
21 |
|
22 Alternatively, the contents of this file may be used under the terms of the |
|
23 Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public |
|
24 License, as published by the Free Software Foundation, either version 2 |
|
25 of the License or (at your option) any later version. |
|
26 */ |
|
27 |
|
28 // designed to have a limited subset of the std::vector api |
|
29 #pragma once |
|
30 |
|
31 #include <cstddef> |
|
32 #include <cassert> |
|
33 #include <cstring> |
|
34 #include <cstdlib> |
|
35 #include <new> |
|
36 |
|
37 |
|
38 namespace graphite2 { |
|
39 |
|
40 template <typename T> |
|
41 inline |
|
42 ptrdiff_t distance(T* first, T* last) { return last-first; } |
|
43 |
|
44 |
|
45 template <typename T> |
|
46 class Vector |
|
47 { |
|
48 T * m_first, *m_last, *m_end; |
|
49 public: |
|
50 typedef T & reference; |
|
51 typedef const T & const_reference; |
|
52 typedef T * iterator; |
|
53 typedef const T * const_iterator; |
|
54 |
|
55 Vector() : m_first(0), m_last(0), m_end(0) {} |
|
56 Vector(size_t n, const T& value = T()) : m_first(0), m_last(0), m_end(0) { insert(begin(), n, value); } |
|
57 Vector(const Vector<T> &rhs) : m_first(0), m_last(0), m_end(0) { insert(begin(), rhs.begin(), rhs.end()); } |
|
58 template <typename I> |
|
59 Vector(I first, const I last) : m_first(0), m_last(0), m_end(0) { insert(begin(), first, last); } |
|
60 ~Vector() { clear(); free(m_first); } |
|
61 |
|
62 iterator begin() { return m_first; } |
|
63 const_iterator begin() const { return m_first; } |
|
64 |
|
65 iterator end() { return m_last; } |
|
66 const_iterator end() const { return m_last; } |
|
67 |
|
68 bool empty() const { return m_first == m_last; } |
|
69 size_t size() const { return m_last - m_first; } |
|
70 size_t capacity() const{ return m_end - m_first; } |
|
71 |
|
72 void reserve(size_t n); |
|
73 |
|
74 reference front() { assert(size() > 0); return *begin(); } |
|
75 const_reference front() const { assert(size() > 0); return *begin(); } |
|
76 reference back() { assert(size() > 0); return *(end()-1); } |
|
77 const_reference back() const { assert(size() > 0); return *(end()-1); } |
|
78 |
|
79 Vector<T> & operator = (const Vector<T> & rhs) { assign(rhs.begin(), rhs.end()); return *this; } |
|
80 reference operator [] (size_t n) { assert(size() > n); return m_first[n]; } |
|
81 const_reference operator [] (size_t n) const { assert(size() > n); return m_first[n]; } |
|
82 |
|
83 void assign(size_t n, const T& u) { clear(); insert(begin(), n, u); } |
|
84 void assign(const_iterator first, const_iterator last) { clear(); insert(begin(), first, last); } |
|
85 iterator insert(iterator p, const T & x) { p = _insert_default(p, 1); *p = x; return p; } |
|
86 void insert(iterator p, size_t n, const T & x); |
|
87 void insert(iterator p, const_iterator first, const_iterator last); |
|
88 void pop_back() { assert(size() > 0); --m_last; } |
|
89 void push_back(const T &v) { if (m_last == m_end) reserve(size()+1); new (m_last++) T(v); } |
|
90 |
|
91 void clear() { erase(begin(), end()); } |
|
92 iterator erase(iterator p) { return erase(p, p+1); } |
|
93 iterator erase(iterator first, iterator last); |
|
94 |
|
95 private: |
|
96 iterator _insert_default(iterator p, size_t n); |
|
97 }; |
|
98 |
|
99 template <typename T> |
|
100 inline |
|
101 void Vector<T>::reserve(size_t n) |
|
102 { |
|
103 if (n > capacity()) |
|
104 { |
|
105 const ptrdiff_t sz = size(); |
|
106 m_first = static_cast<T*>(realloc(m_first, n*sizeof(T))); |
|
107 m_last = m_first + sz; |
|
108 m_end = m_first + n; |
|
109 } |
|
110 } |
|
111 |
|
112 template<typename T> |
|
113 inline |
|
114 typename Vector<T>::iterator Vector<T>::_insert_default(iterator p, size_t n) |
|
115 { |
|
116 assert(begin() <= p && p <= end()); |
|
117 const ptrdiff_t i = p - begin(); |
|
118 reserve((size() + n + 7) >> 3 << 3); |
|
119 p = begin() + i; |
|
120 // Move tail if there is one |
|
121 if (p != end()) memmove(p + n, p, distance(p,end())*sizeof(T)); |
|
122 m_last += n; |
|
123 return p; |
|
124 } |
|
125 |
|
126 template<typename T> |
|
127 inline |
|
128 void Vector<T>::insert(iterator p, size_t n, const T & x) |
|
129 { |
|
130 p = _insert_default(p, n); |
|
131 // Copy in elements |
|
132 for (; n; --n, ++p) { new (p) T(x); } |
|
133 } |
|
134 |
|
135 template<typename T> |
|
136 inline |
|
137 void Vector<T>::insert(iterator p, const_iterator first, const_iterator last) |
|
138 { |
|
139 p = _insert_default(p, distance(first, last)); |
|
140 // Copy in elements |
|
141 for (;first != last; ++first, ++p) { new (p) T(*first); } |
|
142 } |
|
143 |
|
144 template<typename T> |
|
145 inline |
|
146 typename Vector<T>::iterator Vector<T>::erase(iterator first, iterator last) |
|
147 { |
|
148 for (iterator e = first; e != last; ++e) e->~T(); |
|
149 const size_t sz = distance(first, last); |
|
150 if (m_last != last) memmove(first, last, distance(last,end())*sizeof(T)); |
|
151 m_last -= sz; |
|
152 return first; |
|
153 } |
|
154 |
|
155 } // namespace graphite2 |