forked from simonask/ftl
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy patharray.hpp
127 lines (107 loc) · 3.03 KB
/
array.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#pragma once
#ifndef ARRAY_HPP_4KSK70IE
#define ARRAY_HPP_4KSK70IE
#include "utils.hpp"
#include "enumerable.hpp"
#include "array_enumerator.hpp"
#include "arrayref.hpp"
#include "allocator.hpp"
#include "allocator_utils.hpp"
namespace ftl {
template <typename T>
class Array : public Enumerable<Array<T>, ArrayEnumerator<T>> {
public:
typedef ArrayEnumerator<T> Enumerator; // used by wrapping types, such as Bag
Array() : _data(NULL), _size(0), _alloc_size(0) {}
Array(const ArrayRef<T>& other);
~Array();
Array<T>& operator=(const ArrayRef<T>& other);
operator ArrayRef<T>() const { return ArrayRef<T>(_data, _size); }
size_t size() const { return _size; }
void clear(bool unallocate = false);
void reserve(size_t new_alloc_size);
void fill(size_t new_size, const T& element = T());
T& push(const T& element);
T& push();
void pop();
void erase(size_t idx);
T& first() { FTL_ASSERT(_size); return _data[0]; }
const T& first() const { FTL_ASSERT(_size); return _data[0]; }
T& last() { FTL_ASSERT(_size); return _data[_size-1]; }
const T& last() const { FTL_ASSERT(_size); return _data[_size-1]; }
T& operator[](size_t idx) { FTL_ASSERT(idx < _size); return _data[idx]; }
const T& operator[](size_t idx) const { FTL_ASSERT(idx < _size); return _data[idx]; }
ArrayEnumerator<T> get_enumerator() const { return ArrayEnumerator<T>(_data, _data+_size); }
private:
T* _data;
size_t _size;
size_t _alloc_size;
};
template <typename T>
Array<T>::Array(const ArrayRef<T>& other) : _data(NULL), _size(0), _alloc_size(0) {
_size = other.size();
reserve(_size);
copy_construct_range(_data, other.data(), _size);
}
template <typename T>
Array<T>::~Array() {
clear(true);
}
template <typename T>
Array<T>& Array<T>::operator=(const ArrayRef<T>& other) {
clear();
_size = other.size();
reserve(_size);
copy_construct_range(_data, other.data(), _size);
}
template <typename T>
void Array<T>::clear(bool unallocate) {
destruct_range(_data, _size);
_size = 0;
if (unallocate) {
Allocator::free(_data);
_alloc_size = 0;
}
}
template <typename T>
void Array<T>::reserve(size_t new_size) {
if (new_size > _alloc_size) {
_data = AllocatorUtils<Allocator>::realloc(_data, new_size, _size);
}
}
template <typename T>
void Array<T>::fill(size_t new_size, const T& element) {
reserve(new_size);
for (size_t i = _size; i < new_size; ++i) {
push(element);
}
}
template <typename T>
T& Array<T>::push() {
reserve(_size+1);
T* p = _data + _size++;
new(p) T;
return *p;
}
template <typename T>
T& Array<T>::push(const T& element) {
reserve(_size+1);
T* p = _data + _size++;
new(p) T(element);
return *p;
}
template <typename T>
void Array<T>::pop() {
FTL_ASSERT(_size);
_data[_size--].~T();
}
template <typename T>
void Array<T>::erase(size_t idx) {
FTL_ASSERT(idx < _size);
_data[idx].~T();
size_t tail = idx + 1;
move_range(_data + idx, _data + tail, _size - tail);
--_size;
}
}
#endif /* end of include guard: ARRAY_HPP_4KSK70IE */