|
1
|
1 #pragma once
|
|
|
2
|
|
|
3 #include "primitives.h"
|
|
|
4
|
|
|
5 namespace pfc {
|
|
|
6
|
|
|
7 static void * raw_malloc(t_size p_size) {
|
|
|
8 return p_size > 0 ? new_ptr_check_t(malloc(p_size)) : NULL;
|
|
|
9 }
|
|
|
10
|
|
|
11 static void raw_free(void * p_block) throw() {free(p_block);}
|
|
|
12
|
|
|
13 inline void* raw_realloc(void * p_ptr,t_size p_size) {
|
|
|
14 if (p_size == 0) {raw_free(p_ptr); return NULL;}
|
|
|
15 else if (p_ptr == NULL) return raw_malloc(p_size);
|
|
|
16 else return pfc::new_ptr_check_t(::realloc(p_ptr,p_size));
|
|
|
17 }
|
|
|
18
|
|
|
19 inline bool raw_realloc_inplace(void * p_block,t_size p_size) throw() {
|
|
|
20 if (p_block == NULL) return p_size == 0;
|
|
|
21 #ifdef _MSC_VER
|
|
|
22 if (p_size == 0) return false;
|
|
|
23 return _expand(p_block,p_size) != NULL;
|
|
|
24 #else
|
|
|
25 return false;
|
|
|
26 #endif
|
|
|
27 }
|
|
|
28
|
|
|
29 template<typename T>
|
|
|
30 t_size calc_array_width(t_size p_width) {
|
|
|
31 return pfc::mul_safe_t<std::bad_alloc,t_size>(p_width,sizeof(T));
|
|
|
32 }
|
|
|
33
|
|
|
34 template<typename T>
|
|
|
35 T * __raw_malloc_t(t_size p_size) {
|
|
|
36 return reinterpret_cast<T*>(raw_malloc(calc_array_width<T>(p_size)));
|
|
|
37 }
|
|
|
38
|
|
|
39 template<typename T>
|
|
|
40 void __raw_free_t(T * p_block) throw() {
|
|
|
41 raw_free(reinterpret_cast<void*>(p_block));
|
|
|
42 }
|
|
|
43
|
|
|
44 template<typename T>
|
|
|
45 T * __raw_realloc_t(T * p_block,t_size p_size) {
|
|
|
46 return reinterpret_cast<T*>(raw_realloc(p_block,calc_array_width<T>(p_size)));
|
|
|
47 }
|
|
|
48
|
|
|
49 template<typename T>
|
|
|
50 bool __raw_realloc_inplace_t(T * p_block,t_size p_size) {
|
|
|
51 return raw_realloc_inplace(p_block,calc_array_width<T>(p_size));
|
|
|
52 }
|
|
|
53
|
|
|
54
|
|
|
55 template<typename t_exception,typename t_int>
|
|
|
56 inline t_int safe_shift_left_t(t_int p_val,t_size p_shift = 1) {
|
|
|
57 t_int newval = p_val << p_shift;
|
|
|
58 if (newval >> p_shift != p_val) throw t_exception();
|
|
|
59 return newval;
|
|
|
60 }
|
|
|
61
|
|
|
62 template<typename t_item> class alloc_dummy {
|
|
|
63 private: typedef alloc_dummy<t_item> t_self;
|
|
|
64 public:
|
|
|
65 alloc_dummy() {}
|
|
|
66 void set_size(t_size p_size) {throw pfc::exception_not_implemented();}
|
|
|
67 t_size get_size() const {throw pfc::exception_not_implemented();}
|
|
|
68 const t_item & operator[](t_size p_index) const {throw pfc::exception_not_implemented();}
|
|
|
69 t_item & operator[](t_size p_index) {throw pfc::exception_not_implemented();}
|
|
|
70
|
|
|
71 bool is_ptr_owned(const void * p_item) const {return false;}
|
|
|
72
|
|
|
73 //set to true when we prioritize speed over memory usage
|
|
|
74 enum { alloc_prioritizes_speed = false };
|
|
|
75
|
|
|
76 //not mandatory
|
|
|
77 const t_item * get_ptr() const {throw pfc::exception_not_implemented();}
|
|
|
78 t_item * get_ptr() {throw pfc::exception_not_implemented();}
|
|
|
79 void prealloc(t_size) {throw pfc::exception_not_implemented();}
|
|
|
80 void force_reset() {throw pfc::exception_not_implemented();}
|
|
|
81 void move_from(t_self &) {throw pfc::exception_not_implemented();}
|
|
|
82 private:
|
|
|
83 const t_self & operator=(const t_self &) {throw pfc::exception_not_implemented();}
|
|
|
84 alloc_dummy(const t_self&) {throw pfc::exception_not_implemented();}
|
|
|
85 };
|
|
|
86
|
|
|
87 template<typename t_item>
|
|
|
88 bool is_pointer_in_range(const t_item * p_buffer,t_size p_buffer_size,const void * p_pointer) {
|
|
|
89 return p_pointer >= reinterpret_cast<const void*>(p_buffer) && p_pointer < reinterpret_cast<const void*>(p_buffer + p_buffer_size);
|
|
|
90 }
|
|
|
91
|
|
|
92
|
|
|
93 //! Simple inefficient fully portable allocator.
|
|
|
94 template<typename t_item> class alloc_simple {
|
|
|
95 private: typedef alloc_simple<t_item> t_self;
|
|
|
96 public:
|
|
|
97 alloc_simple() : m_data(NULL), m_size(0) {}
|
|
|
98 void set_size(t_size p_size) {
|
|
|
99 if (p_size != m_size) {
|
|
|
100 t_item * l_data = NULL;
|
|
|
101 if (p_size > 0) l_data = new t_item[p_size];
|
|
|
102 try {
|
|
|
103 pfc::memcpy_t(l_data,m_data,pfc::min_t(m_size,p_size));
|
|
|
104 } catch(...) {
|
|
|
105 delete[] l_data;
|
|
|
106 throw;
|
|
|
107 }
|
|
|
108 delete[] m_data;
|
|
|
109 m_data = l_data;
|
|
|
110 m_size = p_size;
|
|
|
111 }
|
|
|
112 }
|
|
|
113 t_size get_size() const {return m_size;}
|
|
|
114 const t_item & operator[](t_size p_index) const {PFC_ASSERT(p_index < m_size); return m_data[p_index];}
|
|
|
115 t_item & operator[](t_size p_index) {PFC_ASSERT(p_index < m_size); return m_data[p_index];}
|
|
|
116 bool is_ptr_owned(const void * p_item) const {return is_pointer_in_range(get_ptr(),get_size(),p_item);}
|
|
|
117
|
|
|
118 enum { alloc_prioritizes_speed = false };
|
|
|
119
|
|
|
120 t_item * get_ptr() {return m_data;}
|
|
|
121 const t_item * get_ptr() const {return m_data;}
|
|
|
122
|
|
|
123 void prealloc(t_size) {}
|
|
|
124 void force_reset() {set_size(0);}
|
|
|
125
|
|
|
126 ~alloc_simple() {delete[] m_data;}
|
|
|
127
|
|
|
128 void move_from(t_self & other) noexcept {
|
|
|
129 delete[] m_data;
|
|
|
130 m_data = replace_null_t(other.m_data);
|
|
|
131 m_size = replace_null_t(other.m_size);
|
|
|
132 }
|
|
|
133 private:
|
|
|
134 const t_self & operator=(const t_self &) = delete;
|
|
|
135 alloc_simple(const t_self&) = delete;
|
|
|
136
|
|
|
137 t_item * m_data;
|
|
|
138 t_size m_size;
|
|
|
139 };
|
|
|
140
|
|
|
141 template<typename t_item> class __array_fast_helper_t {
|
|
|
142 private:
|
|
|
143 typedef __array_fast_helper_t<t_item> t_self;
|
|
|
144 public:
|
|
|
145 __array_fast_helper_t() : m_buffer(NULL), m_size(0), m_size_total(0) {}
|
|
|
146
|
|
|
147
|
|
|
148 void set_size(t_size p_size,t_size p_size_total) {
|
|
|
149 PFC_ASSERT(p_size <= p_size_total);
|
|
|
150 PFC_ASSERT(m_size <= m_size_total);
|
|
|
151 if (p_size_total > m_size_total) {
|
|
|
152 resize_storage(p_size_total);
|
|
|
153 resize_content(p_size);
|
|
|
154 } else {
|
|
|
155 resize_content(p_size);
|
|
|
156 resize_storage(p_size_total);
|
|
|
157 }
|
|
|
158 }
|
|
|
159
|
|
|
160
|
|
|
161
|
|
|
162 t_size get_size() const {return m_size;}
|
|
|
163 t_size get_size_total() const {return m_size_total;}
|
|
|
164 const t_item & operator[](t_size p_index) const {PFC_ASSERT(p_index < m_size); return m_buffer[p_index];}
|
|
|
165 t_item & operator[](t_size p_index) {PFC_ASSERT(p_index < m_size); return m_buffer[p_index];}
|
|
|
166 ~__array_fast_helper_t() {
|
|
|
167 set_size(0,0);
|
|
|
168 }
|
|
|
169 t_item * get_ptr() {return m_buffer;}
|
|
|
170 const t_item * get_ptr() const {return m_buffer;}
|
|
|
171 bool is_ptr_owned(const void * p_item) const {return is_pointer_in_range(m_buffer,m_size_total,p_item);}
|
|
|
172
|
|
|
173 void move_from(t_self & other) {
|
|
|
174 set_size(0,0);
|
|
|
175 m_buffer = replace_null_t(other.m_buffer);
|
|
|
176 m_size = replace_null_t(other.m_size);
|
|
|
177 m_size_total = replace_null_t(other.m_size_total);
|
|
|
178 }
|
|
|
179 private:
|
|
|
180 const t_self & operator=(const t_self &) = delete;
|
|
|
181 __array_fast_helper_t(const t_self &) = delete;
|
|
|
182
|
|
|
183
|
|
|
184 void resize_content(t_size p_size) {
|
|
|
185 if constexpr (traits_t<t_item>::needs_constructor || traits_t<t_item>::needs_destructor) {
|
|
|
186 if (p_size > m_size) {//expand
|
|
|
187 do {
|
|
|
188 __unsafe__in_place_constructor_t(m_buffer[m_size]);
|
|
|
189 m_size++;
|
|
|
190 } while(m_size < p_size);
|
|
|
191 } else if (p_size < m_size) {
|
|
|
192 __unsafe__in_place_destructor_array_t(m_buffer + p_size, m_size - p_size);
|
|
|
193 m_size = p_size;
|
|
|
194 }
|
|
|
195 } else {
|
|
|
196 m_size = p_size;
|
|
|
197 }
|
|
|
198 }
|
|
|
199
|
|
|
200 void resize_storage(t_size p_size) {
|
|
|
201 PFC_ASSERT( m_size <= m_size_total );
|
|
|
202 PFC_ASSERT( m_size <= p_size );
|
|
|
203 if (m_size_total != p_size) {
|
|
|
204 if constexpr (pfc::traits_t<t_item>::realloc_safe) {
|
|
|
205 m_buffer = pfc::__raw_realloc_t(m_buffer,p_size);
|
|
|
206 m_size_total = p_size;
|
|
|
207 } else if (__raw_realloc_inplace_t(m_buffer,p_size)) {
|
|
|
208 //success
|
|
|
209 m_size_total = p_size;
|
|
|
210 } else {
|
|
|
211 t_item * newbuffer = pfc::__raw_malloc_t<t_item>(p_size);
|
|
|
212 try {
|
|
|
213 pfc::__unsafe__in_place_constructor_array_copy_t(newbuffer,m_size,m_buffer);
|
|
|
214 } catch(...) {
|
|
|
215 pfc::__raw_free_t(newbuffer);
|
|
|
216 throw;
|
|
|
217 }
|
|
|
218 pfc::__unsafe__in_place_destructor_array_t(m_buffer,m_size);
|
|
|
219 pfc::__raw_free_t(m_buffer);
|
|
|
220 m_buffer = newbuffer;
|
|
|
221 m_size_total = p_size;
|
|
|
222 }
|
|
|
223 }
|
|
|
224 }
|
|
|
225
|
|
|
226 t_item * m_buffer;
|
|
|
227 t_size m_size,m_size_total;
|
|
|
228 };
|
|
|
229
|
|
|
230 template<typename t_item> class __array_lite_helper_t {
|
|
|
231 private:
|
|
|
232 typedef __array_lite_helper_t<t_item> t_self;
|
|
|
233 public:
|
|
|
234 __array_lite_helper_t() : m_buffer(NULL), m_size(0) {}
|
|
|
235
|
|
|
236
|
|
|
237 void set_size(t_size p_size) {
|
|
|
238 if (p_size > m_size) { // expand
|
|
|
239 resize_storage(p_size);
|
|
|
240 resize_content(p_size);
|
|
|
241 } else if (p_size < m_size) { // shrink
|
|
|
242 resize_content(p_size);
|
|
|
243 resize_storage(p_size);
|
|
|
244 }
|
|
|
245 }
|
|
|
246
|
|
|
247
|
|
|
248
|
|
|
249 t_size get_size() const {return m_size;}
|
|
|
250 const t_item & operator[](t_size p_index) const {PFC_ASSERT(p_index < m_size); return m_buffer[p_index];}
|
|
|
251 t_item & operator[](t_size p_index) {PFC_ASSERT(p_index < m_size); return m_buffer[p_index];}
|
|
|
252 ~__array_lite_helper_t() {
|
|
|
253 set_size(0);
|
|
|
254 }
|
|
|
255 t_item * get_ptr() {return m_buffer;}
|
|
|
256 const t_item * get_ptr() const {return m_buffer;}
|
|
|
257 bool is_ptr_owned(const void * p_item) const {return is_pointer_in_range(m_buffer,m_size,p_item);}
|
|
|
258
|
|
|
259 void move_from(t_self & other) {
|
|
|
260 set_size(0);
|
|
|
261 m_buffer = replace_null_t(other.m_buffer);
|
|
|
262 m_size = replace_null_t(other.m_size);
|
|
|
263 }
|
|
|
264 private:
|
|
|
265 const t_self & operator=(const t_self &) = delete;
|
|
|
266 __array_lite_helper_t(const t_self &) = delete;
|
|
|
267
|
|
|
268
|
|
|
269 void resize_content(t_size p_size) {
|
|
|
270 if constexpr (traits_t<t_item>::needs_constructor || traits_t<t_item>::needs_destructor) {
|
|
|
271 if (p_size > m_size) {//expand
|
|
|
272 do {
|
|
|
273 __unsafe__in_place_constructor_t(m_buffer[m_size]);
|
|
|
274 m_size++;
|
|
|
275 } while(m_size < p_size);
|
|
|
276 } else if (p_size < m_size) {
|
|
|
277 __unsafe__in_place_destructor_array_t(m_buffer + p_size, m_size - p_size);
|
|
|
278 m_size = p_size;
|
|
|
279 }
|
|
|
280 } else {
|
|
|
281 m_size = p_size;
|
|
|
282 }
|
|
|
283 }
|
|
|
284
|
|
|
285 void resize_storage(t_size p_size) {
|
|
|
286 PFC_ASSERT( m_size <= p_size );
|
|
|
287 if constexpr (pfc::traits_t<t_item>::realloc_safe) {
|
|
|
288 m_buffer = pfc::__raw_realloc_t(m_buffer,p_size);
|
|
|
289 //m_size_total = p_size;
|
|
|
290 } else if (__raw_realloc_inplace_t(m_buffer,p_size)) {
|
|
|
291 //success
|
|
|
292 //m_size_total = p_size;
|
|
|
293 } else {
|
|
|
294 t_item * newbuffer = pfc::__raw_malloc_t<t_item>(p_size);
|
|
|
295 try {
|
|
|
296 pfc::__unsafe__in_place_constructor_array_copy_t(newbuffer,m_size,m_buffer);
|
|
|
297 } catch(...) {
|
|
|
298 pfc::__raw_free_t(newbuffer);
|
|
|
299 throw;
|
|
|
300 }
|
|
|
301 pfc::__unsafe__in_place_destructor_array_t(m_buffer,m_size);
|
|
|
302 pfc::__raw_free_t(m_buffer);
|
|
|
303 m_buffer = newbuffer;
|
|
|
304 //m_size_total = p_size;
|
|
|
305 }
|
|
|
306 }
|
|
|
307
|
|
|
308 t_item * m_buffer;
|
|
|
309 t_size m_size;
|
|
|
310 };
|
|
|
311
|
|
|
312 template<typename t_item> class alloc_standard {
|
|
|
313 private: typedef alloc_standard<t_item> t_self;
|
|
|
314 public:
|
|
|
315 alloc_standard() {}
|
|
|
316 void set_size(t_size p_size) {m_content.set_size(p_size);}
|
|
|
317
|
|
|
318 t_size get_size() const {return m_content.get_size();}
|
|
|
319
|
|
|
320 const t_item & operator[](t_size p_index) const {return m_content[p_index];}
|
|
|
321 t_item & operator[](t_size p_index) {return m_content[p_index];}
|
|
|
322
|
|
|
323 const t_item * get_ptr() const {return m_content.get_ptr();}
|
|
|
324 t_item * get_ptr() {return m_content.get_ptr();}
|
|
|
325
|
|
|
326 bool is_ptr_owned(const void * p_item) const {return m_content.is_ptr_owned(p_item);}
|
|
|
327 void prealloc(t_size p_size) {}
|
|
|
328 void force_reset() {set_size(0);}
|
|
|
329
|
|
|
330 enum { alloc_prioritizes_speed = false };
|
|
|
331
|
|
|
332 void move_from(t_self & other) { m_content.move_from(other.m_content); }
|
|
|
333 private:
|
|
|
334 alloc_standard(const t_self &) = delete;
|
|
|
335 const t_self & operator=(const t_self&) = delete;
|
|
|
336
|
|
|
337 __array_lite_helper_t<t_item> m_content;
|
|
|
338 };
|
|
|
339
|
|
|
340 template<typename t_item> class alloc_fast {
|
|
|
341 private: typedef alloc_fast<t_item> t_self;
|
|
|
342 public:
|
|
|
343 alloc_fast() {}
|
|
|
344
|
|
|
345 void set_size(t_size p_size) {
|
|
|
346 t_size size_base = m_data.get_size_total();
|
|
|
347 if (size_base == 0) size_base = 1;
|
|
|
348 while(size_base < p_size) {
|
|
|
349 size_base = safe_shift_left_t<std::bad_alloc,t_size>(size_base,1);
|
|
|
350 }
|
|
|
351 while(size_base >> 2 > p_size) {
|
|
|
352 size_base >>= 1;
|
|
|
353 }
|
|
|
354 m_data.set_size(p_size,size_base);
|
|
|
355 }
|
|
|
356
|
|
|
357 t_size get_size() const {return m_data.get_size();}
|
|
|
358 const t_item & operator[](t_size p_index) const {return m_data[p_index];}
|
|
|
359 t_item & operator[](t_size p_index) {return m_data[p_index];}
|
|
|
360
|
|
|
361 const t_item * get_ptr() const {return m_data.get_ptr();}
|
|
|
362 t_item * get_ptr() {return m_data.get_ptr();}
|
|
|
363 bool is_ptr_owned(const void * p_item) const {return m_data.is_ptr_owned(p_item);}
|
|
|
364 void prealloc(t_size) {}
|
|
|
365 void force_reset() {m_data.set_size(0,0);}
|
|
|
366
|
|
|
367 enum { alloc_prioritizes_speed = true };
|
|
|
368
|
|
|
369 void move_from(t_self & other) { m_data.move_from(other.m_data); }
|
|
|
370 private:
|
|
|
371 alloc_fast(const t_self &) = delete;
|
|
|
372 const t_self & operator=(const t_self&) = delete;
|
|
|
373 __array_fast_helper_t<t_item> m_data;
|
|
|
374 };
|
|
|
375
|
|
|
376 template<typename t_item> class alloc_fast_aggressive {
|
|
|
377 private: typedef alloc_fast_aggressive<t_item> t_self;
|
|
|
378 public:
|
|
|
379 alloc_fast_aggressive() {}
|
|
|
380
|
|
|
381 void set_size(t_size p_size) {
|
|
|
382 t_size size_base = m_data.get_size_total();
|
|
|
383 if (size_base == 0) size_base = 1;
|
|
|
384 while(size_base < p_size) {
|
|
|
385 size_base = safe_shift_left_t<std::bad_alloc,t_size>(size_base,1);
|
|
|
386 }
|
|
|
387 m_data.set_size(p_size,size_base);
|
|
|
388 }
|
|
|
389
|
|
|
390 void prealloc(t_size p_size) {
|
|
|
391 if (p_size > 0) {
|
|
|
392 t_size size_base = m_data.get_size_total();
|
|
|
393 if (size_base == 0) size_base = 1;
|
|
|
394 while(size_base < p_size) {
|
|
|
395 size_base = safe_shift_left_t<std::bad_alloc,t_size>(size_base,1);
|
|
|
396 }
|
|
|
397 m_data.set_size(m_data.get_size(),size_base);
|
|
|
398 }
|
|
|
399 }
|
|
|
400
|
|
|
401 t_size get_size() const {return m_data.get_size();}
|
|
|
402 const t_item & operator[](t_size p_index) const {;return m_data[p_index];}
|
|
|
403 t_item & operator[](t_size p_index) {return m_data[p_index];}
|
|
|
404
|
|
|
405 const t_item * get_ptr() const {return m_data.get_ptr();}
|
|
|
406 t_item * get_ptr() {return m_data.get_ptr();}
|
|
|
407 bool is_ptr_owned(const void * p_item) const {return m_data.is_ptr_owned(p_item);}
|
|
|
408 void force_reset() {m_data.set_size(0,0);}
|
|
|
409
|
|
|
410 enum { alloc_prioritizes_speed = true };
|
|
|
411
|
|
|
412 void move_from(t_self & other) { m_data.move_from(other.m_data); }
|
|
|
413 private:
|
|
|
414 alloc_fast_aggressive(const t_self &) = delete;
|
|
|
415 const t_self & operator=(const t_self&) = delete;
|
|
|
416 __array_fast_helper_t<t_item> m_data;
|
|
|
417 };
|
|
|
418
|
|
|
419 template<t_size p_width> class alloc_fixed {
|
|
|
420 public:
|
|
|
421 template<typename t_item> class alloc {
|
|
|
422 private: typedef alloc<t_item> t_self;
|
|
|
423 public:
|
|
|
424 alloc() : m_size(0) {}
|
|
|
425
|
|
|
426 void set_size(t_size p_size) {
|
|
|
427 static_assert_t<sizeof(m_array) == sizeof(t_item[p_width])>();
|
|
|
428
|
|
|
429 if (p_size > p_width) throw pfc::exception_overflow();
|
|
|
430 else if (p_size > m_size) {
|
|
|
431 __unsafe__in_place_constructor_array_t(get_ptr()+m_size,p_size-m_size);
|
|
|
432 m_size = p_size;
|
|
|
433 } else if (p_size < m_size) {
|
|
|
434 __unsafe__in_place_destructor_array_t(get_ptr()+p_size,m_size-p_size);
|
|
|
435 m_size = p_size;
|
|
|
436 }
|
|
|
437 }
|
|
|
438
|
|
|
439 ~alloc() {
|
|
|
440 if constexpr (pfc::traits_t<t_item>::needs_destructor) set_size(0);
|
|
|
441 }
|
|
|
442
|
|
|
443 t_size get_size() const {return m_size;}
|
|
|
444
|
|
|
445 t_item * get_ptr() {return reinterpret_cast<t_item*>(&m_array);}
|
|
|
446 const t_item * get_ptr() const {return reinterpret_cast<const t_item*>(&m_array);}
|
|
|
447
|
|
|
448 const t_item & operator[](t_size n) const {return get_ptr()[n];}
|
|
|
449 t_item & operator[](t_size n) {return get_ptr()[n];}
|
|
|
450 bool is_ptr_owned(const void * p_item) const {return is_pointer_in_range(get_ptr(),p_width,p_item);}
|
|
|
451 void prealloc(t_size) {}
|
|
|
452 void force_reset() {set_size(0);}
|
|
|
453
|
|
|
454 enum { alloc_prioritizes_speed = false };
|
|
|
455
|
|
|
456 void move_from(t_self & other) {
|
|
|
457 const size_t count = other.get_size();
|
|
|
458 set_size( count );
|
|
|
459 for(size_t w = 0; w < count; ++w) this->get_ptr()[w] = other.get_ptr()[w];
|
|
|
460 }
|
|
|
461 private:
|
|
|
462 alloc(const t_self&) {throw pfc::exception_not_implemented();}
|
|
|
463 const t_self& operator=(const t_self&) {throw pfc::exception_not_implemented();}
|
|
|
464
|
|
|
465 t_uint8 m_array[sizeof(t_item[p_width])];
|
|
|
466 t_size m_size;
|
|
|
467 };
|
|
|
468 };
|
|
|
469
|
|
|
470 template<t_size p_width, template<typename> class t_alloc = alloc_standard > class alloc_hybrid {
|
|
|
471 public:
|
|
|
472 template<typename t_item> class alloc {
|
|
|
473 private: typedef alloc<t_item> t_self;
|
|
|
474 public:
|
|
|
475 alloc() {}
|
|
|
476
|
|
|
477 void set_size(t_size p_size) {
|
|
|
478 if (p_size > p_width) {
|
|
|
479 m_fixed.set_size(p_width);
|
|
|
480 m_variable.set_size(p_size - p_width);
|
|
|
481 } else {
|
|
|
482 m_fixed.set_size(p_size);
|
|
|
483 m_variable.set_size(0);
|
|
|
484 }
|
|
|
485 }
|
|
|
486
|
|
|
487 t_item & operator[](t_size p_index) {
|
|
|
488 PFC_ASSERT(p_index < get_size());
|
|
|
489 if (p_index < p_width) return m_fixed[p_index];
|
|
|
490 else return m_variable[p_index - p_width];
|
|
|
491 }
|
|
|
492
|
|
|
493 const t_item & operator[](t_size p_index) const {
|
|
|
494 PFC_ASSERT(p_index < get_size());
|
|
|
495 if (p_index < p_width) return m_fixed[p_index];
|
|
|
496 else return m_variable[p_index - p_width];
|
|
|
497 }
|
|
|
498
|
|
|
499 t_size get_size() const {return m_fixed.get_size() + m_variable.get_size();}
|
|
|
500 bool is_ptr_owned(const void * p_item) const {return m_fixed.is_ptr_owned(p_item) || m_variable.is_ptr_owned(p_item);}
|
|
|
501 void prealloc(t_size p_size) {
|
|
|
502 if (p_size > p_width) m_variable.prealloc(p_size - p_width);
|
|
|
503 }
|
|
|
504 void force_reset() {
|
|
|
505 m_fixed.force_reset(); m_variable.force_reset();
|
|
|
506 }
|
|
|
507 enum { alloc_prioritizes_speed = t_alloc<t_item>::alloc_prioritizes_speed };
|
|
|
508
|
|
|
509 void move_from(t_self & other) {
|
|
|
510 m_fixed.move_from(other.m_fixed);
|
|
|
511 m_variable.move_from(other.m_variable);
|
|
|
512 }
|
|
|
513 private:
|
|
|
514 alloc(const t_self&) {throw pfc::exception_not_implemented();}
|
|
|
515 const t_self& operator=(const t_self&) {throw pfc::exception_not_implemented();}
|
|
|
516
|
|
|
517 typename alloc_fixed<p_width>::template alloc<t_item> m_fixed;
|
|
|
518 t_alloc<t_item> m_variable;
|
|
|
519 };
|
|
|
520 };
|
|
|
521
|
|
|
522 template<typename t_item> class traits_t<alloc_simple<t_item> > : public traits_default_movable {};
|
|
|
523 template<typename t_item> class traits_t<__array_fast_helper_t<t_item> > : public traits_default_movable {};
|
|
|
524 template<typename t_item> class traits_t<alloc_standard<t_item> > : public pfc::traits_t<__array_fast_helper_t<t_item> > {};
|
|
|
525 template<typename t_item> class traits_t<alloc_fast<t_item> > : public pfc::traits_t<__array_fast_helper_t<t_item> > {};
|
|
|
526 template<typename t_item> class traits_t<alloc_fast_aggressive<t_item> > : public pfc::traits_t<__array_fast_helper_t<t_item> > {};
|
|
|
527
|
|
|
528 #if 0//not working (compiler bug?)
|
|
|
529 template<t_size p_width,typename t_item> class traits_t<typename alloc_fixed<p_width>::template alloc<t_item> > : public pfc::traits_t<t_item> {
|
|
|
530 public:
|
|
|
531 enum {
|
|
|
532 needs_constructor = true,
|
|
|
533 };
|
|
|
534 };
|
|
|
535
|
|
|
536 template<t_size p_width,template<typename> class t_alloc,typename t_item>
|
|
|
537 class traits_t<typename alloc_hybrid<p_width,t_alloc>::template alloc<t_item> > : public traits_combined<t_alloc,typename alloc_fixed<p_width>::template alloc<t_item> > {};
|
|
|
538 #endif
|
|
|
539
|
|
|
540
|
|
|
541 };
|