acme
Foundational cross-platform layer of the ca2 framework
Loading...
Searching...
No Matches
block_array.h
1#pragma once
2
3
4template<typename TYPE, ::i32 t_iSize, enum_array t_earray, typename ARG_TYPE>
5class block_array :
6 public ::array_range < TYPE, ARG_TYPE >
7{
8public:
9
10
11 using ARRAY_RANGE = ::array_range < TYPE, ARG_TYPE >;
12 using BASE_RANGE = ::array_range < TYPE, ARG_TYPE >;
13 using RAW_BASE_ARRAY = block_array;
14 using BASE_RAW_RANGE = ::range < TYPE * >;
15 using BASE_TYPE = TYPE;
16
17 TYPE m_ta[t_iSize];
18
19
20 block_array() : ARRAY_RANGE (m_ta, m_ta){}
21 ~block_array() {}
22
23 TYPE *data() { return m_ta; }
24 const TYPE *data() const { return m_ta; }
25
26 ::collection::count storage_size() const { return t_iSize; }
27// ::collection::index get_upper_bound(::collection::index i = -1) const { return this->size() + i; }
28
29 template<pointer_not_castable_to<TYPE *> P>
30 ::collection::count allocate(::collection::count nNewSize, bool bShrink, bool bRaw, P &p)
31 {
32 TYPE t(p);
33 return _allocate(nNewSize, bShrink, bRaw, &t);
34 }
35 template<pointer_castable_to<TYPE *> T>
36 ::collection::count allocate(::collection::count nNewSize, bool bShrink, bool bRaw, T &t)
37 {
38 return _allocate(nNewSize, bShrink, bRaw, &t);
39 }
40
41 TYPE & add_new()
42 {
43
44 if (this->size() >= this->storage_size())
45 {
46
47 throw ::exception(error_wrong_state);
48
49 }
50
51 auto & t = m_ta[this->size()];
52
53 this->m_end++;
54
55 return t;
56
57 }
58
59
60 ::collection::index add(const TYPE & t)
61 {
62
63 if (this->size() >= this->storage_size())
64 {
65
66 throw ::exception(error_wrong_state);
67
68 }
69
70 auto i = this->size();
71
72 m_ta[i] = t;
73
74 this->m_end++;
75
76 return i;
77
78 }
79
80
81 block_array &operator+=(const TYPE &t)
82 {
83
84 add(t);
85
86 return *this;
87
88 }
89
90
91
92 constexpr bool is_raw_array() const { return t_earray & e_array_raw; }
93
97 void erase_at(::collection::index iErase, ::collection::count countErase = 1)
98 {
99
100 if (iErase < 0)
101 {
102
103 throw ::exception(error_bad_argument);
104
105 }
106 else if (iErase >= this->size())
107 {
108
109 throw ::exception(error_wrong_state);
110
111 }
112
113 if (iErase + countErase > this->size())
114 {
115
116 countErase = this->size() - iErase;
117
118 }
119
120 if (countErase <= 0)
121 {
122
123 return;
124
125 }
126
127 if constexpr (t_earray & e_array_raw)
128 {
129
130 auto nTransferCount = this->size() - (iErase + countErase);
131
132 auto i = iErase + countErase;
133
134 ::safe_memory_transfer2(&m_ta[i - countErase], nTransferCount, &m_ta[i], nTransferCount);
135
136 }
137 else
138 {
139
140 auto i = iErase + countErase;
141
142 for (; i < this->size(); i++)
143 {
144
145 m_ta[i - countErase] = m_ta[i];
146
147 }
148
149 i -= countErase;
150
151 for (; i < this->size(); i++)
152 {
153
154 m_ta[i].~TYPE();
155
156 new (&m_ta[i]) TYPE();
157
158 }
159
160 }
161
162 this->m_end -= countErase;
163
164 }
165
166 void erase_first(::collection::count count = 1) { this->erase_at(0, count);
167 }
168
169 void erase_last(::collection::count count = 1)
170 {
171 this->erase_at(this->size() - count, count);
172 }
173
174
175
176 ::collection::count _allocate(::collection::count nNewSize, bool bShrink, bool bRaw, const TYPE * ptype)
177 {
178
179 if (nNewSize >= this->storage_size())
180 {
181
182 throw ::exception(error_wrong_state);
183
184 }
185
186 auto nOldSize = this->size();
187
188 if (nNewSize > nOldSize)
189 {
190
191 for (auto i = nOldSize; i < nNewSize; i++)
192 {
193
194 if constexpr (t_earray & e_array_raw)
195 {
196
197 safe_memory_copy2(this->m_begin+ i, 1, ptype, 1);
198
199 }
200 else
201 {
202
203 this->m_begin[i] = *ptype;
204
205 }
206
207 }
208
209 }
210
211 this->m_end = this->m_begin + nNewSize;
212
213 return nNewSize;
214
215 }
216
217};
Definition array_range.h:15
void erase_at(::collection::index iErase, ::collection::count countErase=1)
attention, it doesn't actually destruct the object it just not regard it as part of the "filled" arra...
Definition block_array.h:97