Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/libsnes/bsnes/nall/reference_array.hpp
2 views
1
#ifndef NALL_REFERENCE_ARRAY_HPP
2
#define NALL_REFERENCE_ARRAY_HPP
3
4
#include <algorithm>
5
#include <type_traits>
6
#include <nall/bit.hpp>
7
8
namespace nall {
9
template<typename T> struct reference_array {
10
struct exception_out_of_bounds{};
11
12
protected:
13
typedef typename std::remove_reference<T>::type type_t;
14
type_t **pool;
15
unsigned poolsize, buffersize;
16
17
public:
18
unsigned size() const { return buffersize; }
19
unsigned capacity() const { return poolsize; }
20
21
void reset() {
22
if(pool) free(pool);
23
pool = nullptr;
24
poolsize = 0;
25
buffersize = 0;
26
}
27
28
void reserve(unsigned newsize) {
29
if(newsize == poolsize) return;
30
31
pool = (type_t**)realloc(pool, sizeof(type_t*) * newsize);
32
poolsize = newsize;
33
buffersize = min(buffersize, newsize);
34
}
35
36
void resize(unsigned newsize) {
37
if(newsize > poolsize) reserve(bit::round(newsize));
38
buffersize = newsize;
39
}
40
41
template<typename... Args>
42
bool append(type_t& data, Args&&... args) {
43
bool result = append(data);
44
append(std::forward<Args>(args)...);
45
return result;
46
}
47
48
bool append(type_t& data) {
49
for(unsigned index = 0; index < buffersize; index++) {
50
if(pool[index] == &data) return false;
51
}
52
53
unsigned index = buffersize++;
54
if(index >= poolsize) resize(index + 1);
55
pool[index] = &data;
56
return true;
57
}
58
59
bool remove(type_t& data) {
60
for(unsigned index = 0; index < buffersize; index++) {
61
if(pool[index] == &data) {
62
for(unsigned i = index; i < buffersize - 1; i++) pool[i] = pool[i + 1];
63
resize(buffersize - 1);
64
return true;
65
}
66
}
67
return false;
68
}
69
70
template<typename... Args> reference_array(Args&... args) : pool(nullptr), poolsize(0), buffersize(0) {
71
construct(args...);
72
}
73
74
~reference_array() {
75
reset();
76
}
77
78
reference_array& operator=(const reference_array &source) {
79
if(pool) free(pool);
80
buffersize = source.buffersize;
81
poolsize = source.poolsize;
82
pool = (type_t**)malloc(sizeof(type_t*) * poolsize);
83
memcpy(pool, source.pool, sizeof(type_t*) * buffersize);
84
return *this;
85
}
86
87
reference_array& operator=(const reference_array &&source) {
88
if(pool) free(pool);
89
pool = source.pool;
90
poolsize = source.poolsize;
91
buffersize = source.buffersize;
92
source.pool = nullptr;
93
source.reset();
94
return *this;
95
}
96
97
inline type_t& operator[](unsigned index) {
98
if(index >= buffersize) throw exception_out_of_bounds();
99
return *pool[index];
100
}
101
102
inline type_t& operator[](unsigned index) const {
103
if(index >= buffersize) throw exception_out_of_bounds();
104
return *pool[index];
105
}
106
107
//iteration
108
struct iterator {
109
bool operator!=(const iterator &source) const { return index != source.index; }
110
type_t& operator*() { return array.operator[](index); }
111
iterator& operator++() { index++; return *this; }
112
iterator(const reference_array &array, unsigned index) : array(array), index(index) {}
113
private:
114
const reference_array &array;
115
unsigned index;
116
};
117
118
iterator begin() { return iterator(*this, 0); }
119
iterator end() { return iterator(*this, buffersize); }
120
const iterator begin() const { return iterator(*this, 0); }
121
const iterator end() const { return iterator(*this, buffersize); }
122
123
private:
124
void construct() {
125
}
126
127
void construct(const reference_array &source) {
128
operator=(source);
129
}
130
131
void construct(const reference_array &&source) {
132
operator=(std::move(source));
133
}
134
135
template<typename... Args> void construct(T data, Args&... args) {
136
append(data);
137
construct(args...);
138
}
139
};
140
}
141
142
#endif
143
144