Commit | Line | Data |
---|---|---|
d44e3c4f | 1 | /****************************************************************************** |
2 | * Copyright (c) 2000-2016 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 | * Contributors: | |
9 | * Balasko, Jeno | |
10 | * Baranyi, Botond | |
11 | * Beres, Szabolcs | |
12 | * Kovacs, Ferenc | |
13 | * Raduly, Csaba | |
14 | * | |
15 | ******************************************************************************/ | |
970ed795 EL |
16 | |
17 | #ifndef TITANVECTOR_H_ | |
18 | #define TITANVECTOR_H_ | |
19 | ||
20 | #include <stddef.h> | |
21 | ||
3abe9331 | 22 | #ifndef PROF_MERGE |
970ed795 | 23 | #include "Error.hh" |
3abe9331 | 24 | #else |
25 | // there's no point in including Error.hh and all the includes that come with it | |
26 | // when building the profiler merge tool, just use this simple error function | |
27 | #include <stdio.h> | |
28 | #include <stdarg.h> | |
29 | void TTCN_error(const char *fmt, ...) | |
30 | { | |
31 | va_list parameters; | |
32 | va_start(parameters, fmt); | |
33 | vfprintf(stderr, fmt, parameters); | |
34 | va_end(parameters); | |
35 | putc('\n', stderr); | |
36 | fflush(stderr); | |
37 | } | |
38 | #endif | |
970ed795 EL |
39 | |
40 | // Not invented here | |
41 | template<typename T> | |
42 | class Vector { | |
43 | private: | |
44 | size_t cap; | |
45 | size_t nof_elem; | |
46 | T* data; | |
47 | ||
48 | void copy(const Vector<T>&); | |
49 | public: | |
50 | explicit Vector(size_t p_capacity = 4); | |
51 | ||
52 | explicit Vector(const Vector<T>& other); | |
53 | ~Vector(); | |
54 | ||
55 | Vector<T>& operator=(const Vector<T>& rhs); | |
56 | ||
57 | // Capacity | |
58 | size_t size() const { return nof_elem; } | |
59 | void resize(size_t new_size, T element = T()); | |
60 | size_t capacity() const { return cap; } | |
61 | bool empty() const { return nof_elem == 0; } | |
62 | void reserve(size_t n); | |
63 | void shrink_to_fit(); | |
64 | ||
65 | // Element access | |
66 | T& operator[](size_t idx); | |
67 | const T& operator[](size_t idx) const; | |
68 | T& at(size_t idx); | |
69 | const T& at(size_t idx) const; | |
70 | T& front() { return at(0); } | |
71 | const T& front() const { return at(0); } | |
72 | T& back() { return at(nof_elem - 1); } | |
73 | const T& back() const { return at(nof_elem - 1); } | |
74 | // This could be used better with iterators | |
75 | void erase_at(size_t idx); | |
76 | ||
77 | // Modifiers | |
78 | void push_back(const T& element); | |
79 | void pop_back(); | |
80 | void clear(); | |
81 | }; | |
82 | ||
83 | template<typename T> | |
84 | Vector<T>::Vector(size_t p_capacity) | |
85 | : cap(p_capacity), nof_elem(0) { | |
86 | ||
87 | data = new T[cap]; | |
88 | if (!data) { | |
89 | TTCN_error("Internal error: new returned NULL"); | |
90 | } | |
91 | } | |
92 | ||
93 | template<typename T> | |
94 | Vector<T>::Vector(const Vector<T>& other) { | |
95 | copy(other); | |
96 | } | |
97 | ||
98 | template<typename T> | |
99 | Vector<T>& Vector<T>::operator=(const Vector<T>& rhs) { | |
100 | if (this == &rhs) { | |
101 | return *this; | |
102 | } | |
103 | ||
104 | clear(); | |
105 | delete[] data; | |
106 | ||
107 | copy(rhs); | |
108 | ||
109 | return *this; | |
110 | } | |
111 | ||
112 | template<typename T> | |
113 | void Vector<T>::copy(const Vector<T>& other) { | |
114 | cap = other.cap; | |
115 | data = new T[cap]; | |
116 | if (!data) { | |
117 | TTCN_error("Internal error: new returned NULL"); | |
118 | } | |
119 | ||
120 | for (size_t i = 0; i < other.nof_elem; ++i) { | |
121 | data[i] = other.data[i]; | |
122 | } | |
123 | ||
124 | nof_elem = other.nof_elem; | |
125 | } | |
126 | ||
127 | template<typename T> | |
128 | Vector<T>::~Vector() { | |
129 | clear(); | |
130 | delete[] data; | |
131 | } | |
132 | ||
133 | template<typename T> | |
134 | void Vector<T>::resize(size_t new_size, T element) { | |
135 | if (new_size > nof_elem) { | |
136 | reserve(new_size); | |
137 | while (nof_elem < new_size) { | |
138 | data[nof_elem++] = element; | |
139 | } | |
140 | return; | |
141 | } | |
142 | ||
143 | nof_elem = new_size; | |
144 | } | |
145 | ||
146 | template<typename T> | |
147 | void Vector<T>::reserve(size_t new_size) { | |
148 | if (new_size <= cap) { | |
149 | return; | |
150 | } | |
151 | ||
152 | cap = new_size; | |
153 | T* data_tmp = new T[cap]; | |
154 | if (!data_tmp) { | |
155 | TTCN_error("Internal error: new returned NULL"); | |
156 | } | |
157 | for (size_t i = 0; i < nof_elem; ++i) { | |
158 | data_tmp[i] = data[i]; | |
159 | } | |
160 | ||
161 | delete[] data; | |
162 | data = data_tmp; | |
163 | } | |
164 | ||
165 | // Modifiers | |
166 | template<typename T> | |
167 | void Vector<T>::push_back(const T& element) { | |
168 | if (nof_elem == cap) { | |
169 | size_t new_cap = (cap == 0 ? 4 : (cap * 2)); | |
170 | reserve(new_cap); | |
171 | } | |
172 | ||
173 | data[nof_elem++] = element; | |
174 | } | |
175 | ||
176 | template<typename T> | |
177 | const T& Vector<T>::at(size_t idx) const { | |
178 | if (idx >= nof_elem) { | |
179 | TTCN_error("Internal error: Vector over-indexing."); | |
180 | } | |
181 | ||
182 | return data[idx]; | |
183 | } | |
184 | ||
185 | template<typename T> | |
186 | T& Vector<T>::at(size_t idx) { | |
187 | if (idx >= nof_elem) { | |
188 | TTCN_error("Internal error: Vector over-indexing."); | |
189 | } | |
190 | ||
191 | return data[idx]; | |
192 | } | |
193 | ||
194 | template<typename T> | |
195 | const T& Vector<T>::operator[](size_t idx) const { | |
196 | return at(idx); | |
197 | } | |
198 | ||
199 | template<typename T> | |
200 | T& Vector<T>::operator[](size_t idx) { | |
201 | return at(idx); | |
202 | } | |
203 | ||
204 | template<typename T> | |
205 | void Vector<T>::erase_at(size_t idx) { | |
206 | if (idx >= nof_elem) { | |
207 | TTCN_error("Internal error: Vector over-indexing."); | |
208 | } | |
209 | ||
210 | while (idx < nof_elem - 1) { | |
211 | data[idx] = data[idx + 1]; | |
212 | ++idx; | |
213 | } | |
214 | ||
215 | --nof_elem; | |
216 | } | |
217 | ||
218 | template<typename T> | |
219 | void Vector<T>::shrink_to_fit() { | |
220 | if (nof_elem == cap) { | |
221 | return; | |
222 | } | |
223 | ||
224 | cap = nof_elem; | |
225 | T* data_tmp = new T[nof_elem]; | |
226 | if (!data_tmp) { | |
227 | TTCN_error("Internal error: new returned NULL"); | |
228 | } | |
229 | for (size_t i = 0; i < nof_elem; ++i) { | |
230 | data_tmp[i] = data[i]; | |
231 | } | |
232 | delete[] data; | |
233 | data = data_tmp; | |
234 | } | |
235 | ||
236 | template<typename T> | |
237 | void Vector<T>::clear() { | |
238 | nof_elem = 0; | |
239 | } | |
240 | ||
241 | #endif /* TITANVECTOR_H_ */ |