Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/libsnes/bsnes/nall/array.hpp
2 views
1
#ifndef NALL_ARRAY_HPP
2
#define NALL_ARRAY_HPP
3
4
#include <stdlib.h>
5
#include <algorithm>
6
#include <initializer_list>
7
#include <utility>
8
#include <nall/algorithm.hpp>
9
#include <nall/bit.hpp>
10
#include <nall/sort.hpp>
11
#include <nall/type_traits.hpp>
12
#include <nall/utility.hpp>
13
14
namespace nall {
15
16
template<typename T, typename Enable = void> struct array;
17
18
//non-reference array
19
//===================
20
21
template<typename T> struct array<T, typename std::enable_if<!std::is_reference<T>::value>::type> {
22
struct exception_out_of_bounds{};
23
24
protected:
25
T *pool;
26
unsigned poolsize, objectsize;
27
28
public:
29
unsigned size() const { return objectsize; }
30
unsigned capacity() const { return poolsize; }
31
32
void reset() {
33
if(pool) free(pool);
34
pool = nullptr;
35
poolsize = 0;
36
objectsize = 0;
37
}
38
39
void reserve(unsigned newsize) {
40
if(newsize == poolsize) return;
41
42
pool = (T*)realloc(pool, newsize * sizeof(T));
43
poolsize = newsize;
44
objectsize = min(objectsize, newsize);
45
}
46
47
void resize(unsigned newsize) {
48
if(newsize > poolsize) reserve(bit::round(newsize)); //round reserve size up to power of 2
49
objectsize = newsize;
50
}
51
52
T* get(unsigned minsize = 0) {
53
if(minsize > objectsize) resize(minsize);
54
return pool;
55
}
56
57
void append(const T data) {
58
operator()(objectsize) = data;
59
}
60
61
void append(const T data[], unsigned length) {
62
for(unsigned n = 0; n < length; n++) operator()(objectsize) = data[n];
63
}
64
65
void remove() {
66
if(size > 0) resize(size - 1); //remove last element only
67
}
68
69
void remove(unsigned index, unsigned count = 1) {
70
for(unsigned i = index; count + i < objectsize; i++) {
71
pool[i] = pool[count + i];
72
}
73
if(count + index >= objectsize) resize(index); //every element >= index was removed
74
else resize(objectsize - count);
75
}
76
77
void sort() {
78
nall::sort(pool, objectsize);
79
}
80
81
template<typename Comparator> void sort(const Comparator &lessthan) {
82
nall::sort(pool, objectsize, lessthan);
83
}
84
85
optional<unsigned> find(const T data) {
86
for(unsigned n = 0; n < size(); n++) if(pool[n] == data) return { true, n };
87
return { false, 0u };
88
}
89
90
void clear() {
91
memset(pool, 0, objectsize * sizeof(T));
92
}
93
94
array() : pool(nullptr), poolsize(0), objectsize(0) {
95
}
96
97
array(std::initializer_list<T> list) : pool(nullptr), poolsize(0), objectsize(0) {
98
for(auto &data : list) append(data);
99
}
100
101
~array() {
102
reset();
103
}
104
105
//copy
106
array& operator=(const array &source) {
107
if(pool) free(pool);
108
objectsize = source.objectsize;
109
poolsize = source.poolsize;
110
pool = (T*)malloc(sizeof(T) * poolsize); //allocate entire pool size,
111
memcpy(pool, source.pool, sizeof(T) * objectsize); //... but only copy used pool objects
112
return *this;
113
}
114
115
array(const array &source) : pool(nullptr), poolsize(0), objectsize(0) {
116
operator=(source);
117
}
118
119
//move
120
array& operator=(array &&source) {
121
if(pool) free(pool);
122
pool = source.pool;
123
poolsize = source.poolsize;
124
objectsize = source.objectsize;
125
source.pool = nullptr;
126
source.reset();
127
return *this;
128
}
129
130
array(array &&source) : pool(nullptr), poolsize(0), objectsize(0) {
131
operator=(std::move(source));
132
}
133
134
//access
135
inline T& operator[](unsigned position) {
136
if(position >= objectsize) throw exception_out_of_bounds();
137
return pool[position];
138
}
139
140
inline const T& operator[](unsigned position) const {
141
if(position >= objectsize) throw exception_out_of_bounds();
142
return pool[position];
143
}
144
145
inline T& operator()(unsigned position) {
146
if(position >= objectsize) resize(position + 1);
147
return pool[position];
148
}
149
150
inline const T& operator()(unsigned position, const T& data) {
151
if(position >= objectsize) return data;
152
return pool[position];
153
}
154
155
//iteration
156
T* begin() { return &pool[0]; }
157
T* end() { return &pool[objectsize]; }
158
const T* begin() const { return &pool[0]; }
159
const T* end() const { return &pool[objectsize]; }
160
};
161
162
//reference array
163
//===============
164
165
template<typename TR> struct array<TR, typename std::enable_if<std::is_reference<TR>::value>::type> {
166
struct exception_out_of_bounds{};
167
168
protected:
169
typedef typename std::remove_reference<TR>::type T;
170
T **pool;
171
unsigned poolsize, objectsize;
172
173
public:
174
unsigned size() const { return objectsize; }
175
unsigned capacity() const { return poolsize; }
176
177
void reset() {
178
if(pool) free(pool);
179
pool = nullptr;
180
poolsize = 0;
181
objectsize = 0;
182
}
183
184
void reserve(unsigned newsize) {
185
if(newsize == poolsize) return;
186
187
pool = (T**)realloc(pool, sizeof(T*) * newsize);
188
poolsize = newsize;
189
objectsize = min(objectsize, newsize);
190
}
191
192
void resize(unsigned newsize) {
193
if(newsize > poolsize) reserve(bit::round(newsize));
194
objectsize = newsize;
195
}
196
197
template<typename... Args>
198
bool append(T& data, Args&&... args) {
199
bool result = append(data);
200
append(std::forward<Args>(args)...);
201
return result;
202
}
203
204
bool append(T& data) {
205
if(find(data)) return false;
206
unsigned offset = objectsize++;
207
if(offset >= poolsize) resize(offset + 1);
208
pool[offset] = &data;
209
return true;
210
}
211
212
bool remove(T& data) {
213
if(auto position = find(data)) {
214
for(signed i = position(); i < objectsize - 1; i++) pool[i] = pool[i + 1];
215
resize(objectsize - 1);
216
return true;
217
}
218
return false;
219
}
220
221
optional<unsigned> find(const T& data) {
222
for(unsigned n = 0; n < objectsize; n++) if(pool[n] == &data) return { true, n };
223
return { false, 0u };
224
}
225
226
template<typename... Args> array(Args&&... args) : pool(nullptr), poolsize(0), objectsize(0) {
227
construct(std::forward<Args>(args)...);
228
}
229
230
~array() {
231
reset();
232
}
233
234
array& operator=(const array &source) {
235
if(pool) free(pool);
236
objectsize = source.objectsize;
237
poolsize = source.poolsize;
238
pool = (T**)malloc(sizeof(T*) * poolsize);
239
memcpy(pool, source.pool, sizeof(T*) * objectsize);
240
return *this;
241
}
242
243
array& operator=(const array &&source) {
244
if(pool) free(pool);
245
pool = source.pool;
246
poolsize = source.poolsize;
247
objectsize = source.objectsize;
248
source.pool = nullptr;
249
source.reset();
250
return *this;
251
}
252
253
T& operator[](unsigned position) const {
254
if(position >= objectsize) throw exception_out_of_bounds();
255
return *pool[position];
256
}
257
258
//iteration
259
struct iterator {
260
bool operator!=(const iterator &source) const { return position != source.position; }
261
T& operator*() { return source.operator[](position); }
262
iterator& operator++() { position++; return *this; }
263
iterator(const array &source, unsigned position) : source(source), position(position) {}
264
private:
265
const array &source;
266
unsigned position;
267
};
268
269
iterator begin() { return iterator(*this, 0); }
270
iterator end() { return iterator(*this, objectsize); }
271
const iterator begin() const { return iterator(*this, 0); }
272
const iterator end() const { return iterator(*this, objectsize); }
273
274
private:
275
void construct() {
276
}
277
278
void construct(const array& source) { operator=(source); }
279
void construct(const array&& source) { operator=(std::move(source)); }
280
281
template<typename... Args> void construct(T& data, Args&&... args) {
282
append(data);
283
construct(std::forward<Args>(args)...);
284
}
285
};
286
287
}
288
289
#endif
290
291