Commit | Line | Data |
---|---|---|
970ed795 EL |
1 | /////////////////////////////////////////////////////////////////////////////// |
2 | // Copyright (c) 2000-2014 Ericsson Telecom AB | |
3 | // All rights reserved. This program and the accompanying materials | |
4 | // are made available under the terms of the Eclipse Public License v1.0 | |
5 | // which accompanies this distribution, and is available at | |
6 | // http://www.eclipse.org/legal/epl-v10.html | |
7 | /////////////////////////////////////////////////////////////////////////////// | |
8 | ||
9 | #ifndef TITANVECTOR_H_ | |
10 | #define TITANVECTOR_H_ | |
11 | ||
12 | #include <stddef.h> | |
13 | ||
14 | #include "Error.hh" | |
15 | ||
16 | // Not invented here | |
17 | template<typename T> | |
18 | class Vector { | |
19 | private: | |
20 | size_t cap; | |
21 | size_t nof_elem; | |
22 | T* data; | |
23 | ||
24 | void copy(const Vector<T>&); | |
25 | public: | |
26 | explicit Vector(size_t p_capacity = 4); | |
27 | ||
28 | explicit Vector(const Vector<T>& other); | |
29 | ~Vector(); | |
30 | ||
31 | Vector<T>& operator=(const Vector<T>& rhs); | |
32 | ||
33 | // Capacity | |
34 | size_t size() const { return nof_elem; } | |
35 | void resize(size_t new_size, T element = T()); | |
36 | size_t capacity() const { return cap; } | |
37 | bool empty() const { return nof_elem == 0; } | |
38 | void reserve(size_t n); | |
39 | void shrink_to_fit(); | |
40 | ||
41 | // Element access | |
42 | T& operator[](size_t idx); | |
43 | const T& operator[](size_t idx) const; | |
44 | T& at(size_t idx); | |
45 | const T& at(size_t idx) const; | |
46 | T& front() { return at(0); } | |
47 | const T& front() const { return at(0); } | |
48 | T& back() { return at(nof_elem - 1); } | |
49 | const T& back() const { return at(nof_elem - 1); } | |
50 | // This could be used better with iterators | |
51 | void erase_at(size_t idx); | |
52 | ||
53 | // Modifiers | |
54 | void push_back(const T& element); | |
55 | void pop_back(); | |
56 | void clear(); | |
57 | }; | |
58 | ||
59 | template<typename T> | |
60 | Vector<T>::Vector(size_t p_capacity) | |
61 | : cap(p_capacity), nof_elem(0) { | |
62 | ||
63 | data = new T[cap]; | |
64 | if (!data) { | |
65 | TTCN_error("Internal error: new returned NULL"); | |
66 | } | |
67 | } | |
68 | ||
69 | template<typename T> | |
70 | Vector<T>::Vector(const Vector<T>& other) { | |
71 | copy(other); | |
72 | } | |
73 | ||
74 | template<typename T> | |
75 | Vector<T>& Vector<T>::operator=(const Vector<T>& rhs) { | |
76 | if (this == &rhs) { | |
77 | return *this; | |
78 | } | |
79 | ||
80 | clear(); | |
81 | delete[] data; | |
82 | ||
83 | copy(rhs); | |
84 | ||
85 | return *this; | |
86 | } | |
87 | ||
88 | template<typename T> | |
89 | void Vector<T>::copy(const Vector<T>& other) { | |
90 | cap = other.cap; | |
91 | data = new T[cap]; | |
92 | if (!data) { | |
93 | TTCN_error("Internal error: new returned NULL"); | |
94 | } | |
95 | ||
96 | for (size_t i = 0; i < other.nof_elem; ++i) { | |
97 | data[i] = other.data[i]; | |
98 | } | |
99 | ||
100 | nof_elem = other.nof_elem; | |
101 | } | |
102 | ||
103 | template<typename T> | |
104 | Vector<T>::~Vector() { | |
105 | clear(); | |
106 | delete[] data; | |
107 | } | |
108 | ||
109 | template<typename T> | |
110 | void Vector<T>::resize(size_t new_size, T element) { | |
111 | if (new_size > nof_elem) { | |
112 | reserve(new_size); | |
113 | while (nof_elem < new_size) { | |
114 | data[nof_elem++] = element; | |
115 | } | |
116 | return; | |
117 | } | |
118 | ||
119 | nof_elem = new_size; | |
120 | } | |
121 | ||
122 | template<typename T> | |
123 | void Vector<T>::reserve(size_t new_size) { | |
124 | if (new_size <= cap) { | |
125 | return; | |
126 | } | |
127 | ||
128 | cap = new_size; | |
129 | T* data_tmp = new T[cap]; | |
130 | if (!data_tmp) { | |
131 | TTCN_error("Internal error: new returned NULL"); | |
132 | } | |
133 | for (size_t i = 0; i < nof_elem; ++i) { | |
134 | data_tmp[i] = data[i]; | |
135 | } | |
136 | ||
137 | delete[] data; | |
138 | data = data_tmp; | |
139 | } | |
140 | ||
141 | // Modifiers | |
142 | template<typename T> | |
143 | void Vector<T>::push_back(const T& element) { | |
144 | if (nof_elem == cap) { | |
145 | size_t new_cap = (cap == 0 ? 4 : (cap * 2)); | |
146 | reserve(new_cap); | |
147 | } | |
148 | ||
149 | data[nof_elem++] = element; | |
150 | } | |
151 | ||
152 | template<typename T> | |
153 | const T& Vector<T>::at(size_t idx) const { | |
154 | if (idx >= nof_elem) { | |
155 | TTCN_error("Internal error: Vector over-indexing."); | |
156 | } | |
157 | ||
158 | return data[idx]; | |
159 | } | |
160 | ||
161 | template<typename T> | |
162 | T& Vector<T>::at(size_t idx) { | |
163 | if (idx >= nof_elem) { | |
164 | TTCN_error("Internal error: Vector over-indexing."); | |
165 | } | |
166 | ||
167 | return data[idx]; | |
168 | } | |
169 | ||
170 | template<typename T> | |
171 | const T& Vector<T>::operator[](size_t idx) const { | |
172 | return at(idx); | |
173 | } | |
174 | ||
175 | template<typename T> | |
176 | T& Vector<T>::operator[](size_t idx) { | |
177 | return at(idx); | |
178 | } | |
179 | ||
180 | template<typename T> | |
181 | void Vector<T>::erase_at(size_t idx) { | |
182 | if (idx >= nof_elem) { | |
183 | TTCN_error("Internal error: Vector over-indexing."); | |
184 | } | |
185 | ||
186 | while (idx < nof_elem - 1) { | |
187 | data[idx] = data[idx + 1]; | |
188 | ++idx; | |
189 | } | |
190 | ||
191 | --nof_elem; | |
192 | } | |
193 | ||
194 | template<typename T> | |
195 | void Vector<T>::shrink_to_fit() { | |
196 | if (nof_elem == cap) { | |
197 | return; | |
198 | } | |
199 | ||
200 | cap = nof_elem; | |
201 | T* data_tmp = new T[nof_elem]; | |
202 | if (!data_tmp) { | |
203 | TTCN_error("Internal error: new returned NULL"); | |
204 | } | |
205 | for (size_t i = 0; i < nof_elem; ++i) { | |
206 | data_tmp[i] = data[i]; | |
207 | } | |
208 | delete[] data; | |
209 | data = data_tmp; | |
210 | } | |
211 | ||
212 | template<typename T> | |
213 | void Vector<T>::clear() { | |
214 | nof_elem = 0; | |
215 | } | |
216 | ||
217 | #endif /* TITANVECTOR_H_ */ |