Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/core/templates/vector.h
9973 views
1
/**************************************************************************/
2
/* vector.h */
3
/**************************************************************************/
4
/* This file is part of: */
5
/* GODOT ENGINE */
6
/* https://godotengine.org */
7
/**************************************************************************/
8
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10
/* */
11
/* Permission is hereby granted, free of charge, to any person obtaining */
12
/* a copy of this software and associated documentation files (the */
13
/* "Software"), to deal in the Software without restriction, including */
14
/* without limitation the rights to use, copy, modify, merge, publish, */
15
/* distribute, sublicense, and/or sell copies of the Software, and to */
16
/* permit persons to whom the Software is furnished to do so, subject to */
17
/* the following conditions: */
18
/* */
19
/* The above copyright notice and this permission notice shall be */
20
/* included in all copies or substantial portions of the Software. */
21
/* */
22
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29
/**************************************************************************/
30
31
#pragma once
32
33
/**
34
* @class Vector
35
* Vector container. Simple copy-on-write container.
36
*
37
* LocalVector is an alternative available for internal use when COW is not
38
* required.
39
*/
40
41
#include "core/error/error_macros.h"
42
#include "core/templates/cowdata.h"
43
#include "core/templates/sort_array.h"
44
45
#include <initializer_list>
46
47
template <typename T>
48
class Vector;
49
50
template <typename T>
51
class VectorWriteProxy {
52
public:
53
_FORCE_INLINE_ T &operator[](typename CowData<T>::Size p_index) {
54
CRASH_BAD_INDEX(p_index, ((Vector<T> *)(this))->_cowdata.size());
55
56
return ((Vector<T> *)(this))->_cowdata.ptrw()[p_index];
57
}
58
};
59
60
template <typename T>
61
class Vector {
62
friend class VectorWriteProxy<T>;
63
64
public:
65
VectorWriteProxy<T> write;
66
typedef typename CowData<T>::Size Size;
67
68
private:
69
CowData<T> _cowdata;
70
71
public:
72
// Must take a copy instead of a reference (see GH-31736).
73
bool push_back(T p_elem);
74
_FORCE_INLINE_ bool append(const T &p_elem) { return push_back(p_elem); } //alias
75
void fill(T p_elem);
76
77
void remove_at(Size p_index) { _cowdata.remove_at(p_index); }
78
_FORCE_INLINE_ bool erase(const T &p_val) {
79
Size idx = find(p_val);
80
if (idx >= 0) {
81
remove_at(idx);
82
return true;
83
}
84
return false;
85
}
86
87
void reverse();
88
89
_FORCE_INLINE_ T *ptrw() { return _cowdata.ptrw(); }
90
_FORCE_INLINE_ const T *ptr() const { return _cowdata.ptr(); }
91
_FORCE_INLINE_ Size size() const { return _cowdata.size(); }
92
93
_FORCE_INLINE_ operator Span<T>() const { return _cowdata.span(); }
94
_FORCE_INLINE_ Span<T> span() const { return _cowdata.span(); }
95
96
_FORCE_INLINE_ void clear() { _cowdata.clear(); }
97
_FORCE_INLINE_ bool is_empty() const { return _cowdata.is_empty(); }
98
99
_FORCE_INLINE_ T get(Size p_index) { return _cowdata.get(p_index); }
100
_FORCE_INLINE_ const T &get(Size p_index) const { return _cowdata.get(p_index); }
101
_FORCE_INLINE_ void set(Size p_index, const T &p_elem) { _cowdata.set(p_index, p_elem); }
102
103
/// Resize the vector.
104
/// Elements are initialized (or not) depending on what the default C++ behavior for this type is.
105
_FORCE_INLINE_ Error resize(Size p_size) {
106
return _cowdata.template resize<!std::is_trivially_constructible_v<T>>(p_size);
107
}
108
109
/// Resize and set all values to 0 / false / nullptr.
110
/// This is only available for zero constructible types.
111
_FORCE_INLINE_ Error resize_initialized(Size p_size) {
112
return _cowdata.template resize<true>(p_size);
113
}
114
115
/// Resize and set all values to 0 / false / nullptr.
116
/// This is only available for trivially destructible types (otherwise, trivial resize might be UB).
117
_FORCE_INLINE_ Error resize_uninitialized(Size p_size) {
118
// resize() statically asserts that T is compatible, no need to do it ourselves.
119
return _cowdata.template resize<false>(p_size);
120
}
121
122
_FORCE_INLINE_ const T &operator[](Size p_index) const { return _cowdata.get(p_index); }
123
// Must take a copy instead of a reference (see GH-31736).
124
Error insert(Size p_pos, T p_val) { return _cowdata.insert(p_pos, p_val); }
125
Size find(const T &p_val, Size p_from = 0) const {
126
if (p_from < 0) {
127
p_from = size() + p_from;
128
}
129
if (p_from < 0 || p_from >= size()) {
130
return -1;
131
}
132
return span().find(p_val, p_from);
133
}
134
Size rfind(const T &p_val, Size p_from = -1) const {
135
if (p_from < 0) {
136
p_from = size() + p_from;
137
}
138
if (p_from < 0 || p_from >= size()) {
139
return -1;
140
}
141
return span().rfind(p_val, p_from);
142
}
143
Size count(const T &p_val) const { return span().count(p_val); }
144
145
// Must take a copy instead of a reference (see GH-31736).
146
void append_array(Vector<T> p_other);
147
148
_FORCE_INLINE_ bool has(const T &p_val) const { return find(p_val) != -1; }
149
150
void sort() {
151
sort_custom<Comparator<T>>();
152
}
153
154
template <typename Comparator, bool Validate = SORT_ARRAY_VALIDATE_ENABLED, typename... Args>
155
void sort_custom(Args &&...args) {
156
Size len = _cowdata.size();
157
if (len == 0) {
158
return;
159
}
160
161
T *data = ptrw();
162
SortArray<T, Comparator, Validate> sorter{ args... };
163
sorter.sort(data, len);
164
}
165
166
Size bsearch(const T &p_value, bool p_before) {
167
return bsearch_custom<Comparator<T>>(p_value, p_before);
168
}
169
170
template <typename Comparator, typename Value, typename... Args>
171
Size bsearch_custom(const Value &p_value, bool p_before, Args &&...args) {
172
return span().bisect(p_value, p_before, Comparator{ args... });
173
}
174
175
Vector<T> duplicate() {
176
return *this;
177
}
178
179
void ordered_insert(const T &p_val) {
180
Size i;
181
for (i = 0; i < _cowdata.size(); i++) {
182
if (p_val < operator[](i)) {
183
break;
184
}
185
}
186
insert(i, p_val);
187
}
188
189
void operator=(const Vector &p_from) { _cowdata = p_from._cowdata; }
190
void operator=(Vector &&p_from) { _cowdata = std::move(p_from._cowdata); }
191
192
Vector<uint8_t> to_byte_array() const {
193
Vector<uint8_t> ret;
194
if (is_empty()) {
195
return ret;
196
}
197
size_t alloc_size = size() * sizeof(T);
198
ret.resize(alloc_size);
199
if (alloc_size) {
200
memcpy(ret.ptrw(), ptr(), alloc_size);
201
}
202
return ret;
203
}
204
205
Vector<T> slice(Size p_begin, Size p_end = CowData<T>::MAX_INT) const {
206
Vector<T> result;
207
208
const Size s = size();
209
210
Size begin = CLAMP(p_begin, -s, s);
211
if (begin < 0) {
212
begin += s;
213
}
214
Size end = CLAMP(p_end, -s, s);
215
if (end < 0) {
216
end += s;
217
}
218
219
ERR_FAIL_COND_V(begin > end, result);
220
221
Size result_size = end - begin;
222
result.resize(result_size);
223
224
const T *const r = ptr();
225
T *const w = result.ptrw();
226
for (Size i = 0; i < result_size; ++i) {
227
w[i] = r[begin + i];
228
}
229
230
return result;
231
}
232
233
bool operator==(const Vector<T> &p_arr) const {
234
Size s = size();
235
if (s != p_arr.size()) {
236
return false;
237
}
238
for (Size i = 0; i < s; i++) {
239
if (operator[](i) != p_arr[i]) {
240
return false;
241
}
242
}
243
return true;
244
}
245
246
bool operator!=(const Vector<T> &p_arr) const {
247
Size s = size();
248
if (s != p_arr.size()) {
249
return true;
250
}
251
for (Size i = 0; i < s; i++) {
252
if (operator[](i) != p_arr[i]) {
253
return true;
254
}
255
}
256
return false;
257
}
258
259
struct Iterator {
260
_FORCE_INLINE_ T &operator*() const {
261
return *elem_ptr;
262
}
263
_FORCE_INLINE_ T *operator->() const { return elem_ptr; }
264
_FORCE_INLINE_ Iterator &operator++() {
265
elem_ptr++;
266
return *this;
267
}
268
_FORCE_INLINE_ Iterator &operator--() {
269
elem_ptr--;
270
return *this;
271
}
272
273
_FORCE_INLINE_ bool operator==(const Iterator &b) const { return elem_ptr == b.elem_ptr; }
274
_FORCE_INLINE_ bool operator!=(const Iterator &b) const { return elem_ptr != b.elem_ptr; }
275
276
Iterator(T *p_ptr) { elem_ptr = p_ptr; }
277
Iterator() {}
278
Iterator(const Iterator &p_it) { elem_ptr = p_it.elem_ptr; }
279
280
private:
281
T *elem_ptr = nullptr;
282
};
283
284
struct ConstIterator {
285
_FORCE_INLINE_ const T &operator*() const {
286
return *elem_ptr;
287
}
288
_FORCE_INLINE_ const T *operator->() const { return elem_ptr; }
289
_FORCE_INLINE_ ConstIterator &operator++() {
290
elem_ptr++;
291
return *this;
292
}
293
_FORCE_INLINE_ ConstIterator &operator--() {
294
elem_ptr--;
295
return *this;
296
}
297
298
_FORCE_INLINE_ bool operator==(const ConstIterator &b) const { return elem_ptr == b.elem_ptr; }
299
_FORCE_INLINE_ bool operator!=(const ConstIterator &b) const { return elem_ptr != b.elem_ptr; }
300
301
ConstIterator(const T *p_ptr) { elem_ptr = p_ptr; }
302
ConstIterator() {}
303
ConstIterator(const ConstIterator &p_it) { elem_ptr = p_it.elem_ptr; }
304
305
private:
306
const T *elem_ptr = nullptr;
307
};
308
309
_FORCE_INLINE_ Iterator begin() {
310
return Iterator(ptrw());
311
}
312
_FORCE_INLINE_ Iterator end() {
313
return Iterator(ptrw() + size());
314
}
315
316
_FORCE_INLINE_ ConstIterator begin() const {
317
return ConstIterator(ptr());
318
}
319
_FORCE_INLINE_ ConstIterator end() const {
320
return ConstIterator(ptr() + size());
321
}
322
323
_FORCE_INLINE_ Vector() {}
324
_FORCE_INLINE_ Vector(std::initializer_list<T> p_init) :
325
_cowdata(p_init) {}
326
_FORCE_INLINE_ Vector(const Vector &p_from) = default;
327
_FORCE_INLINE_ Vector(Vector &&p_from) = default;
328
329
_FORCE_INLINE_ ~Vector() {}
330
};
331
332
template <typename T>
333
void Vector<T>::reverse() {
334
T *p = ptrw();
335
for (Size i = 0; i < size() / 2; i++) {
336
SWAP(p[i], p[size() - i - 1]);
337
}
338
}
339
340
template <typename T>
341
void Vector<T>::append_array(Vector<T> p_other) {
342
const Size ds = p_other.size();
343
if (ds == 0) {
344
return;
345
}
346
const Size bs = size();
347
resize(bs + ds);
348
T *p = ptrw();
349
for (Size i = 0; i < ds; ++i) {
350
p[bs + i] = p_other[i];
351
}
352
}
353
354
template <typename T>
355
bool Vector<T>::push_back(T p_elem) {
356
Error err = resize(size() + 1);
357
ERR_FAIL_COND_V(err, true);
358
set(size() - 1, p_elem);
359
360
return false;
361
}
362
363
template <typename T>
364
void Vector<T>::fill(T p_elem) {
365
T *p = ptrw();
366
for (Size i = 0; i < size(); i++) {
367
p[i] = p_elem;
368
}
369
}
370
371
// Zero-constructing Vector initializes CowData.ptr() to nullptr and thus empty.
372
template <typename T>
373
struct is_zero_constructible<Vector<T>> : std::true_type {};
374
375