1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2000-2015 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 #ifndef _Common_vector_HH
9 #define _Common_vector_HH
13 * Inclusion of the STL vector header file prevents the Sun Forte 6.2 C++
14 * compiler from a mysterious internal error.
21 #include "../common/memory.h"
22 #include <string.h> // for memmove
25 * Container optimized to store elements sequentially,
26 * and access them randomly, referenced by indices.
28 * Accessing an element has constant time cost.
29 * Adding an element at the end has amortized constant time const.
30 * Other operations (adding at the beginning, replacing/deleting elements)
31 * have linear time cost.
33 * If there aren't elements in the buffer, then no space is allocated.
34 * If there are, the size of the allocated buffer is the smallest power of 2
35 * that is not smaller than the number of elements (num_e).
37 * The container stores pointers to objects of type T; it doesn't own them.
38 * It is the responsibility of the caller to create and destroy the objects
39 * and supply the pointers to the container.
51 static const size_t initial_size = 1, increment_factor = 2;
53 /** Copy constructor: DO NOT IMPLEMENT! */
54 vector(const vector&);
55 /** Copy assignment: DO NOT IMPLEMENT! */
56 vector& operator=(const vector&);
60 static const size_t max_vector_length = -1;
62 /** Creates an empty vector. */
63 vector() : num_e(0), e_ptr(NULL) { }
65 /** Deallocates its memory. If the container is not empty,
66 * FATAL_ERROR occurs, so before destructing, clear() must be
70 if (num_e > 0) FATAL_ERROR("vector::~vector(): vector is not empty");
74 /** Returns the number of elements in the container. */
75 size_t size() const { return num_e; }
77 /** Returns true if the container has no elements. */
78 bool empty() const { return num_e == 0; }
80 /** Erases the entire container. */
87 /** Appends the \a elem to the end of vector. */
90 e_ptr = static_cast<T**>(Malloc(initial_size * sizeof(*e_ptr)));
92 size_t max_e = initial_size;
93 while (max_e < num_e) max_e *= increment_factor;
95 if (max_e >= max_vector_length / increment_factor)
96 FATAL_ERROR("vector::add(): vector index overflow");
97 e_ptr = static_cast<T**>
98 (Realloc(e_ptr, max_e * increment_factor * sizeof(*e_ptr)));
101 e_ptr[num_e++] = elem;
104 /** Inserts the \a elem to the beginning of vector. */
105 void add_front(T *elem) {
107 e_ptr = static_cast<T**>(Malloc(initial_size * sizeof(*e_ptr)));
109 size_t max_e = initial_size;
110 while (max_e < num_e) max_e *= increment_factor;
111 if (max_e <= num_e) {
112 if (max_e >= max_vector_length / increment_factor)
113 FATAL_ERROR("vector::add_front(): vector index overflow");
114 e_ptr = static_cast<T**>
115 (Realloc(e_ptr, max_e * increment_factor * sizeof(*e_ptr)));
118 memmove(e_ptr + 1, e_ptr, num_e * sizeof(*e_ptr));
123 /** Returns the <em>n</em>th element. The index of the first element is
124 * zero. If no such index, then FATAL_ERROR occurs. */
125 T* operator[](size_t n) const {
127 FATAL_ERROR("vector::operator[](size_t) const: index overflow");
131 /** Returns the <em>n</em>th element. The index of the first element is
132 * zero. If no such index, then FATAL_ERROR occurs. */
133 T*& operator[](size_t n) {
135 FATAL_ERROR("vector::operator[](size_t): index overflow");
139 /** Replaces \a n elements beginning from position \a pos
140 * with elements in \a v. If \a pos+n > size() then FATAL_ERROR occurs.
141 * If \a v == NULL then deletes the elements.
143 void replace(size_t pos, size_t n, const vector *v = NULL) {
144 if (pos > num_e) FATAL_ERROR("vector::replace(): position points over " \
146 else if (n > num_e - pos) FATAL_ERROR("vector::replace(): not enough " \
147 "elements after the start position");
148 else if (v == this) FATAL_ERROR("vector::replace(): trying to replace " \
149 "the original vector");
150 size_t v_len = v != NULL ? v->num_e : 0;
151 if (v_len > max_vector_length - num_e + n)
152 FATAL_ERROR("vector::replace(): resulting vector size exceeds maximal " \
154 size_t new_len = num_e - n + v_len;
155 if (new_len > num_e) {
156 size_t max_e = initial_size;
158 while (max_e < new_len) max_e *= increment_factor;
159 e_ptr = static_cast<T**>(Malloc(max_e * sizeof(*e_ptr)));
161 while (max_e < num_e) max_e *= increment_factor;
162 if (new_len > max_e) {
163 while (max_e < new_len) max_e *= increment_factor;
164 e_ptr = static_cast<T**>(Realloc(e_ptr, max_e * sizeof(*e_ptr)));
168 if (pos + n < num_e && v_len != n) memmove(e_ptr + pos + v_len,
169 e_ptr + pos + n, (num_e - pos - n) * sizeof(*e_ptr));
170 if (v_len > 0) memcpy(e_ptr + pos, v->e_ptr, v_len * sizeof(*e_ptr));
171 if (new_len < num_e) {
176 size_t max_e = initial_size;
177 while (max_e < num_e) max_e *= increment_factor;
178 size_t max_e2 = initial_size;
179 while (max_e2 < new_len) max_e2 *= increment_factor;
181 e_ptr = static_cast<T**>(Realloc(e_ptr, max_e2 * sizeof(*e_ptr)));
188 * Copies a part of the vector to a new vector. The part is
189 * specified by the starting position (<em>pos</em>) and the number
190 * of elements (<em>n</em>) to copy. If <em>n</em> is greater than
191 * the number of elements beginning from the given <em>pos</em>,
192 * then the returned vector contains less elements.
194 * \note The pointers are copied, the objects they refer to will not
197 vector* subvector(size_t pos = 0, size_t n = max_vector_length) const
199 if (pos > num_e) FATAL_ERROR("vector::subvector(): position points " \
200 "over last vector element");
201 if (n > num_e - pos) n = num_e - pos;
202 vector *tmp_vector = new vector;
204 size_t max_e = initial_size;
205 while (max_e < n) max_e *= increment_factor;
206 tmp_vector->e_ptr = static_cast<T**>(Malloc(max_e * sizeof(*e_ptr)));
207 memcpy(tmp_vector->e_ptr, e_ptr + pos, n * sizeof(*e_ptr));
208 tmp_vector->num_e = n;
216 * Container to store simple types (can have constructor, but it should be fast)
217 * that are simple and small, stores the objects and not the pointers (copy
218 * constructor must be implemented). The capacity is increased to be always the
219 * power of two, the container capacity is never decreased. An initial
220 * capacity value can be supplied to the constructor, this can be used to avoid
221 * any further memory allocations during the life of the container.
224 class dynamic_array {
227 size_t capacity; // 0,1,2,4,8,...
231 void copy_content(const dynamic_array& other);
234 dynamic_array() : count(0), capacity(0), data(NULL) {}
235 // to avoid reallocations and copying
236 dynamic_array(size_t init_capacity) : count(0), capacity(init_capacity), data(NULL)
237 { if (capacity>0) data = new T[capacity]; }
238 dynamic_array(const dynamic_array& other) : count(0), capacity(0), data(NULL) { copy_content(other); }
239 dynamic_array& operator=(const dynamic_array& other) { clean_up(); copy_content(other); return *this; }
240 ~dynamic_array() { clean_up(); }
242 bool operator==(const dynamic_array& other) const;
243 bool operator!=(const dynamic_array& other) const { return (!(*this==other)); }
245 /** Returns the number of elements in the container. */
246 size_t size() const { return count; }
248 /** Erases the entire container. */
249 void clear() { clean_up(); }
251 /** Appends the \a elem to the end of vector. */
252 void add(const T& elem);
254 /** Removes an element that is at index \a idx */
255 void remove(size_t idx);
257 /** Returns the <em>n</em>th element. The index of the first element is
258 * zero. If no such index, then FATAL_ERROR occurs. */
259 const T& operator[](size_t n) const {
260 if (n>=count) FATAL_ERROR("dynamic_array::operator[] const: index overflow");
264 /** Returns the <em>n</em>th element. The index of the first element is
265 * zero. If no such index, then FATAL_ERROR occurs. */
266 T& operator[](size_t n) {
267 if (n>=count) FATAL_ERROR("dynamic_array::operator[]: index overflow");
270 }; // class dynamic_array
273 void dynamic_array<T>::clean_up()
282 void dynamic_array<T>::copy_content(const dynamic_array<T>& other)
284 capacity = other.capacity;
287 data = new T[capacity];
288 for (size_t i=0; i<count; i++) data[i] = other.data[i];
293 bool dynamic_array<T>::operator==(const dynamic_array<T>& other) const
295 if (count!=other.count) return false;
296 for (size_t i=0; i<count; i++) if (!(data[i]==other.data[i])) return false;
301 void dynamic_array<T>::add(const T& elem)
309 if (count<capacity) {
313 // no more room, need to allocate new memory
314 if (capacity==0) FATAL_ERROR("dynamic_array::add()");
316 T* new_data = new T[capacity];
317 for (size_t i=0; i<count; i++) new_data[i] = data[i];
327 void dynamic_array<T>::remove(size_t idx)
329 if (idx>=count) FATAL_ERROR("dynamic_array::remove(): index overflow");
330 for (size_t i=idx+1; i<count; i++) data[i-1] = data[i];
334 #endif // _Common_vector_HH