The Pedigree Project 0.1
Vector.h
1/*
2 * Copyright (c) 2008-2014, Pedigree Developers
3 *
4 * Please see the CONTRIB file in the root of the source tree for a full
5 * list of contributors.
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#ifndef KERNEL_UTILITIES_VECTOR_H
21#define KERNEL_UTILITIES_VECTOR_H
22
23#include "pedigree/kernel/compiler.h"
24#include "pedigree/kernel/processor/types.h"
25#include "pedigree/kernel/utilities/utility.h"
26
32template <class T>
33class EXPORTED_PUBLIC Vector {
34 public:
36 typedef T* Iterator;
38 typedef T const* ConstIterator;
40 template <class T_>
42 T_ value;
43
45 --value;
46 return *this;
47 }
49 ++value;
50 return *this;
51 }
52
54 T_ origValue = value;
55 --value;
56 return ReverseIteratorContainer<T_>{.value = origValue};
57 }
59 T_ origValue = value;
60 ++value;
61 return ReverseIteratorContainer<T_>{.value = origValue};
62 }
63
64 operator T_() const {
65 return value;
66 }
67
68 typename pedigree_std::remove_pointer<T_>::type operator*() const {
69 return *value;
70 }
71
72 bool operator==(const ReverseIteratorContainer<T_>& other) {
73 return value == other.value;
74 }
75 };
78
83 explicit Vector(size_t size);
86 Vector(const Vector& x);
89
96 T& operator[](size_t index);
97 const T& operator[](size_t index) const;
98
101 size_t size() const;
104 size_t count() const;
107 void pushBack(const T& value);
109 template <class... Args>
110 void createBack(Args&&... args) {
111 reserve(m_Count + 1, true);
112
113 // If we've hit the end of the reserved space we can use, we need to move
114 // the existing entries (rather than this happening in each reserve).
115 if ((m_Start + m_Count + 1) > m_Size) {
116 pedigree_std::copy(m_Data, m_Data + m_Start, m_Count);
117 m_Start = 0;
118 }
119
120 m_Data[m_Start + m_Count++] = T(pedigree_std::forward<Args>(args)...);
121 }
124 void pushBack(T&& value);
130 void pushFront(const T& value);
133 void pushFront(T&& value);
138 void setAt(size_t idx, const T& value);
142 void swap(Vector& other) noexcept;
145 void insert(size_t index, const T& value);
146
152 void clear(bool freeMem = false);
154 void erase(size_t index);
158 ReverseIterator erase(ReverseIterator iter);
159
163 return m_Data + m_Start;
164 }
168 return m_Data + m_Start;
169 }
173 return m_Data + m_Start + m_Count;
174 }
178 return m_Data + m_Start + m_Count;
179 }
180
181 ReverseIterator rbegin() {
182 return ReverseIterator{.value = m_Data + m_Start + m_Count - 1};
183 }
184 ConstReverseIterator rbegin() const {
185 return ConstReverseIterator{.value = m_Data + m_Start + m_Count - 1};
186 }
187 ReverseIterator rend() {
188 return ReverseIterator{.value = m_Data + m_Start - 1};
189 }
190 ConstReverseIterator rend() const {
191 return ConstReverseIterator{.value = m_Data + m_Start - 1};
192 }
195 void assign(const Vector& x);
199 void reserve(size_t size, bool copy);
200 bool tryReserve(size_t size, bool copy = true);
201
202 private:
207 void reserve(size_t size, bool copy, bool free);
209 size_t m_Size;
211 size_t m_Count;
216 size_t m_Start;
220 static const int m_ReserveFactor = 2;
221};
222
223template <class T>
224Vector<T>::Vector() : m_Size(0), m_Count(0), m_Start(0), m_Data(0) {}
225
226template <class T>
227Vector<T>::Vector(size_t size) : m_Size(0), m_Count(0), m_Start(0), m_Data(0) {
228 reserve(size, false);
229}
230
231template <class T>
232Vector<T>::Vector(const Vector& x) : m_Size(0), m_Count(0), m_Start(0), m_Data(0) {
233 assign(x);
234}
235
236template <class T>
238 if (m_Data != 0)
239 delete[] m_Data;
240}
241
242template <class T>
244 assign(x);
245 return *this;
246}
247
248template <class T>
249T& Vector<T>::operator[](size_t index) {
250 static T outofbounds = T();
251 if (index >= m_Count)
252 return outofbounds;
253 return m_Data[m_Start + index];
254}
255
256template <class T>
257const T& Vector<T>::operator[](size_t index) const {
258 static const T outofbounds = T();
259 if (index >= m_Count)
260 return outofbounds;
261 return m_Data[m_Start + index];
262}
263
264template <class T>
265size_t Vector<T>::size() const {
266 return m_Size;
267}
268
269template <class T>
270size_t Vector<T>::count() const {
271 return m_Count;
272}
273
274template <class T>
275void Vector<T>::pushBack(const T& value) {
276 reserve(m_Count + 1, true);
277
278 // If we've hit the end of the reserved space we can use, we need to move
279 // the existing entries (rather than this happening in each reserve).
280 if ((m_Start + m_Count + 1) > m_Size) {
281 pedigree_std::copy(m_Data, m_Data + m_Start, m_Count);
282 m_Start = 0;
283 }
284
285 m_Data[m_Start + m_Count++] = value;
286}
287
288template <class T>
289void Vector<T>::pushBack(T&& value) {
290 reserve(m_Count + 1, true);
291
292 // If we've hit the end of the reserved space we can use, we need to move
293 // the existing entries (rather than this happening in each reserve).
294 if ((m_Start + m_Count + 1) > m_Size) {
295 pedigree_std::copy(m_Data, m_Data + m_Start, m_Count);
296 m_Start = 0;
297 }
298
299 m_Data[m_Start + m_Count++] = pedigree_std::move(value);
300}
301
302template <class T>
304 if (!m_Count) {
305 return T();
306 }
307
308 m_Count--;
309 return m_Data[m_Start + m_Count];
310}
311
312template <class T>
313void Vector<T>::pushFront(const T& value) {
314 const T* oldData = m_Data;
315
316 reserve(m_Count + 1, true, false);
317
318 if (m_Start && (m_Data == oldData)) {
319 m_Start--;
320 m_Data[m_Start] = value;
321 } else {
322 pedigree_std::copy(&m_Data[1], m_Data, m_Count);
323 m_Data[0] = value;
324 }
325
326 m_Count++;
327
328 // All finished with the previous buffer now.
329 if (m_Data != oldData) {
330 delete[] oldData;
331 }
332}
333
334template <class T>
335void Vector<T>::pushFront(T&& value) {
336 const T* oldData = m_Data;
337
338 reserve(m_Count + 1, true, false);
339
340 if (m_Start && (m_Data == oldData)) {
341 m_Start--;
342 m_Data[m_Start] = pedigree_std::move(value);
343 } else {
344 pedigree_std::copy(&m_Data[1], m_Data, m_Count);
345 m_Data[0] = pedigree_std::move(value);
346 }
347
348 m_Count++;
349
350 // All finished with the previous buffer now.
351 if (m_Data != oldData) {
352 delete[] oldData;
353 }
354}
355
356template <class T>
358 if (!m_Count) {
359 return T();
360 }
361
362 T ret = m_Data[m_Start];
363 m_Count--;
364 m_Start++;
365 if (!m_Count) {
366 m_Start = 0;
367 }
368 return ret;
369}
370
371template <class T>
372void Vector<T>::setAt(size_t idx, const T& value) {
373 if (idx < m_Count)
374 m_Data[m_Start + idx] = value;
375}
376
377template <class T>
378void Vector<T>::clear(bool freeMem) {
379 m_Count = 0;
380 m_Start = 0;
381 if (freeMem) {
382 m_Size = 0;
383 delete[] m_Data;
384 m_Data = 0;
385 }
386}
387
388template <class T>
389void Vector<T>::erase(size_t index) {
390 if (!m_Count) {
391 return;
392 } else if (index >= m_Count) {
393 return;
394 }
395
396 T* base = m_Data + m_Start;
397 pedigree_std::copy(base + index, base + index + 1, m_Count - index - 1);
398 m_Count--;
399}
400
401template <class T>
403 erase(static_cast<size_t>(iter - begin()));
404 return iter;
405}
406
407template <class T>
409 erase(static_cast<size_t>(iter.value - (m_Data + m_Start)));
410 return iter;
411}
412
413template <class T>
414void Vector<T>::assign(const Vector& x) {
415 if (this == &x) {
416 return;
417 }
418
419 reserve(x.size(), false);
420 pedigree_std::copy(m_Data, x.begin(), x.m_Count);
421 m_Count = x.count();
422 m_Start = 0;
423}
424
425template <class T>
426bool Vector<T>::tryReserve(size_t size, bool copy) {
427 if (size <= m_Size) {
428 return true;
429 }
430 const size_t maximum = ~size_t{0} / sizeof(T);
431 if (size > maximum) {
432 return false;
433 }
434 if (m_Size <= maximum / m_ReserveFactor && size < m_Size * m_ReserveFactor) {
435 size = m_Size * m_ReserveFactor;
436 }
437 T* replacement = new T[size];
438 if (!replacement) {
439 return false;
440 }
441 if (copy && m_Count) {
442 pedigree_std::copy(replacement, m_Data + m_Start, m_Count);
443 }
444 T* old = m_Data;
445 m_Data = replacement;
446 m_Size = size;
447 m_Start = 0;
448 delete[] old;
449 return true;
450}
451
452template <class T>
453void Vector<T>::reserve(size_t size, bool copy) {
454 reserve(size, copy, true);
455}
456
457template <class T>
458void Vector<T>::reserve(size_t size, bool copy, bool free) {
459 if (size <= m_Size) {
460 return;
461 } else if (size < (m_Size * m_ReserveFactor)) {
462 // Grow exponentially.
463 size = m_Size * m_ReserveFactor;
464 }
465
466 T* tmp = m_Data;
467 m_Data = new T[size];
468 if (tmp != 0) {
469 if ((copy == true) && m_Count) {
470 pedigree_std::copy(m_Data, tmp + m_Start, m_Count);
471 m_Start = 0;
472 }
473 if (free) {
474 delete[] tmp;
475 }
476 }
477 m_Size = size;
478}
479
480template <class T>
482 if (a == b)
483 return;
484 else if (a < begin() || a >= end())
485 return;
486 else if (b < begin() || b >= end())
487 return;
488
489 // Perform the swap.
490 T tmp = *a;
491 *a = *b;
492 *b = tmp;
493}
494
495template <class T>
496void Vector<T>::insert(size_t index, const T& value) {
497 if (index >= m_Count) {
498 pushBack(value);
499 return;
500 } else if (index == 0) {
501 pushFront(value);
502 return;
503 }
504
505 reserve(m_Count + 1, true);
506
507 pedigree_std::copy(m_Data + m_Start + index + 1, m_Data + m_Start + index, m_Count - index);
508
509 m_Data[m_Start + index] = value;
510 ++m_Count;
511}
512
513extern template class Vector<void*>; // IWYU pragma: keep
514extern template class Vector<uint64_t>; // IWYU pragma: keep
515extern template class Vector<uint32_t>; // IWYU pragma: keep
516extern template class Vector<uint16_t>; // IWYU pragma: keep
517extern template class Vector<uint8_t>; // IWYU pragma: keep
518extern template class Vector<int64_t>; // IWYU pragma: keep
519extern template class Vector<int32_t>; // IWYU pragma: keep
520extern template class Vector<int16_t>; // IWYU pragma: keep
521extern template class Vector<int8_t>; // IWYU pragma: keep
522
525template <class T>
526void Vector<T>::swap(Vector& other) noexcept {
527 const size_t size = m_Size, count = m_Count, start = m_Start;
528 T* data = m_Data;
529 m_Size = other.m_Size;
530 m_Count = other.m_Count;
531 m_Start = other.m_Start;
532 m_Data = other.m_Data;
533 other.m_Size = size;
534 other.m_Count = count;
535 other.m_Start = start;
536 other.m_Data = data;
537}
538
539#endif
An iterator applicable for many data structures.
Definition Iterator.h:41
A vector / dynamic array.
Definition Vector.h:33
void swap(Vector &other) noexcept
Definition Vector.h:526
size_t m_Start
Definition Vector.h:216
void createBack(Args &&... args)
Definition Vector.h:110
ConstIterator end() const
Definition Vector.h:177
Iterator end()
Definition Vector.h:172
size_t m_Count
Definition Vector.h:211
ConstIterator begin() const
Definition Vector.h:167
T * Iterator
Definition Vector.h:36
Iterator begin()
Definition Vector.h:162
T * m_Data
Definition Vector.h:218
T const * ConstIterator
Definition Vector.h:38
size_t m_Size
Definition Vector.h:209
T operator--(T &x, int)
Global postdecrement operator for types with overloaded predecrement operator.
Definition template.h:53
Vector(size_t size)
Definition Vector.h:227
Vector(const Vector &x)
Definition Vector.h:232
Vector & operator=(const Vector &x)
Definition Vector.h:243
void assign(const Vector &x)
Definition Vector.h:414
T & operator[](size_t index)
Definition Vector.h:249
ReverseIterator erase(ReverseIterator iter)
Definition Vector.h:408
void erase(size_t index)
Definition Vector.h:389
Vector()
Definition Vector.h:224
void setAt(size_t idx, const T &value)
Definition Vector.h:372
void pushBack(T &&value)
Definition Vector.h:289
T operator++(T &x, int)
Global postincrement operator for types with overloaded preincrement operator.
Definition template.h:43
void insert(size_t index, const T &value)
Definition Vector.h:496
void reserve(size_t size, bool copy)
Definition Vector.h:453
void pushFront(T &&value)
Definition Vector.h:335
void pushFront(const T &value)
Definition Vector.h:313
T popBack()
Definition Vector.h:303
void reserve(size_t size, bool copy, bool free)
Definition Vector.h:458
void pushBack(const T &value)
Definition Vector.h:275
void clear(bool freeMem=false)
Definition Vector.h:378
size_t size() const
Definition Vector.h:265
T popFront()
Definition Vector.h:357
Iterator erase(Iterator iter)
Definition Vector.h:402
void swap(Iterator a, Iterator b)
Definition Vector.h:481
size_t count() const
Definition Vector.h:270
~Vector()
Definition Vector.h:237
bool operator==(const Iterator< originalT, Struct, FunctionPrev, FunctionNext, T1 > &x1, const Iterator< originalT, Struct, FunctionPrev, FunctionNext, T2 > &x2)
Definition Iterator.h:256
One node in the list.
Definition List.h:37