Scanframe Modular Application 0.1.0
Loading...
Searching...
No Matches
TDynamicBuffer.h
Go to the documentation of this file.
1#pragma once
2#include <cassert>
3#include <malloc.h>
4#include <misc/gen/dbgutils.h>
5#include <misc/global.h>
6
7namespace sf
8{
9
14{
18 typedef int handle_t;
19
23 static void* allocmem(handle_t&, size_t sz)
24 {
25 auto rv = ::malloc(sz);
26 assert(rv);
27 return rv;
28 }
29
33 static void* reallocmem(handle_t&, void* p, size_t sz)
34 {
35 auto rv = ::realloc(p, sz);
36 assert(rv);
37 return rv;
38 }
39
43 static void freemem(handle_t, void*& p)
44 {
45 ::free(p);
46 p = nullptr;
47 }
48};
49
55template<typename Alloc = Allocator>
57{
58 public:
63
68
72 explicit TDynamicBuffer(size_t sz);
73
78
82 void reserve(size_t sz, bool shrink = false);
83
90 void resize(size_t sz, bool shrink = false);
91
95 void offset(size_t ofs);
96
100 [[nodiscard]] size_t offset() const;
101
105 size_t size();
106
110 [[nodiscard]] size_t size() const;
111
115 [[nodiscard]] size_t reserved() const;
116
120 void* data();
121
125 [[nodiscard]] const void* data() const;
126
130 char* c_str();
131
135 [[nodiscard]] const char* c_str() const;
136
140 template<typename T>
141 T* ptr(size_t offset = 0)
142 {
143 return reinterpret_cast<T*>(static_cast<char*>(_reference->_data) + (offset + _reference->_offset));
144 }
145
149 template<typename T>
150 const T* ptr(size_t offset = 0) const
151 {
152 return reinterpret_cast<T*>(static_cast<char*>(_reference->_data) + (offset + _reference->_offset));
153 }
154
158 void grow(size_t sz);
159
163 void zero(bool reserved = false);
164
169 void set(int c = 0, bool reserved = false);
170
174 void* data(size_t offset);
175
179 [[nodiscard]] const void* data(size_t offset) const;
180
184 explicit operator void*();
185
189 explicit operator const char*() const;
190
194 explicit operator char*();
195
199 explicit operator const void*() const;
200
204 char& operator[](size_t i);
205
209 char operator[](size_t i) const;
210
215
216 private:
220 struct Reference
221 {
222 typename Alloc::handle_t Handle;
223 // Determines if a destructor frees the memory.
224 unsigned _usage;
225 // Reported size of the buffer.
226 size_t _size;
227 // Actual allocated size of memory.
228 size_t _allocated;
229 // Byte offset to the data.
230 size_t _offset;
231 // Pointer to the allocated chunk of memory.
232 void* _data;
233 }* _reference;
234};
235
236template<typename Alloc>
238{
239 return _reference->_size - _reference->_offset;
240}
241
242template<typename Alloc>
243inline size_t TDynamicBuffer<Alloc>::size() const
244{
245 return _reference->_size - _reference->_offset;
246}
247
248template<typename Alloc>
250{
251 return static_cast<char*>(_reference->_data) + _reference->_offset;
252}
253
254template<typename Alloc>
255inline const void* TDynamicBuffer<Alloc>::data() const
256{
257 return static_cast<char*>(_reference->_data) + _reference->_offset;
258}
259
260template<typename Alloc>
262{
263 return static_cast<char*>(_reference->_data) + _reference->_offset;
264}
265
266template<typename Alloc>
267inline const char* TDynamicBuffer<Alloc>::c_str() const
268{
269 return static_cast<char*>(_reference->_data) + _reference->_offset;
270}
271
272template<typename Alloc>
273inline void* TDynamicBuffer<Alloc>::data(size_t offset)
274{
275 // Compensate for the offset.
276 offset += _reference->_offset;
277 return &(static_cast<char*>(_reference->_data))[offset];
278}
279
280template<typename Alloc>
281inline const void* TDynamicBuffer<Alloc>::data(size_t offset) const
282{
283 // Compensate for the offset.
284 offset += _reference->_offset;
285 return &(static_cast<char*>(_reference->_data))[offset];
286}
287
288template<typename Alloc>
289inline char TDynamicBuffer<Alloc>::operator[](size_t i) const
290{
291 // Compensate for the offset.
292 i += _reference->_offset;
293 if (i > _reference->_size)
294 {
295 throw std::out_of_range("Index out of range!");
296 }
297 // Make sure that no data is accessed beyond its real size.
298 return (static_cast<char*>(_reference->_data))[i];
299}
300
301template<typename Alloc>
303{
304 if (i > _reference->_size)
305 {
306 throw std::out_of_range("Index out of range!");
307 }
308 // Make sure that no dta is accessed beyond its real size.
309 return (static_cast<char*>(_reference->_data))[i];
310}
311
312template<typename Alloc>
314{
315 // Prevent self copying.
316 if (this == &db)
317 {
318 return *this;
319 }
320 // Avoid assigning same instance.
321 if (_reference == db._reference)
322 {
323 return *this;
324 }
325 // Decrease usage count.
326 _reference->_usage--;
327 // If the usage is zero the reference and data buffer in it must be deleted.
328 if (_reference->_usage == 0)
329 {
330 Alloc::freemem(_reference->Handle, _reference->_data);
331 delete _reference;
332 }
333 // Assign reference of passed instance.
334 _reference = db._reference;
335 // Increment usage count.
336 _reference->_usage++;
337 // Return myself.
338 return *this;
339}
340
341template<typename Alloc>
343{
344 return _reference->_data;
345}
346
347template<typename Alloc>
348inline TDynamicBuffer<Alloc>::operator const void*() const
349{
350 return _reference->_data;
351}
352
353template<typename Alloc>
355{
356 return _reference->_data;
357}
358
359template<typename Alloc>
360inline TDynamicBuffer<Alloc>::operator const char*() const
361{
362 return _reference->_data;
363}
364
365template<typename Alloc>
367{
368 _reference = new Reference;
369 _reference->_size = 0;
370 _reference->_allocated = 0;
371 _reference->_offset = 0;
372 _reference->_data = nullptr;
373 _reference->_usage = 1;
374}
375
376template<typename Alloc>
378{
379 _reference = db._reference;
380 _reference->_usage++;
381}
382
383template<typename Alloc>
385{
386 _reference = new Reference;
387 _reference->_size = 0;
388 _reference->_allocated = 0;
389 _reference->_offset = 0;
390 _reference->_data = nullptr;
391 _reference->_usage = 1;
392 resize(sz);
393}
394
395template<typename Alloc>
397{
398 _reference->_usage--;
399 // If the usage is zero the reference and data buffer in it must be deleted.
400 if (_reference->_usage == 0)
401 {
402 if (_reference->_data)
403 {
404 Alloc::freemem(_reference->Handle, _reference->_data);
405 }
406 delete _reference;
407 }
408}
409
410template<typename Alloc>
411void TDynamicBuffer<Alloc>::reserve(size_t sz, bool shrink)
412{
413 if (sz == 0)
414 {
415 if (shrink)
416 {
417 _reference->_allocated = 0;
418 _reference->_offset = 0;
419 if (_reference->_data)
420 {
421 Alloc::freemem(_reference->Handle, _reference->_data);
422 }
423 }
424 }
425 else
426 {
427 // Compensate for the offset.
428 sz += _reference->_offset;
429 // Only allocate memory when the requested size is larger or
430 // if the buffer size is allowed to shrink and the new size is smaller.
431 if ((sz > _reference->_allocated) || (sz < _reference->_allocated && shrink))
432 {// Determine what is to be called.
433 if (_reference->_data)
434 {
435 _reference->_data = Alloc::reallocmem(_reference->Handle, _reference->_data, sz);
436 }
437 else
438 {
439 _reference->_data = Alloc::allocmem(_reference->Handle, sz);
440 }
441 // Adjust the real size member.
442 _reference->_allocated = sz;
443 }
444 }
445}
446
447template<typename Alloc>
448inline void TDynamicBuffer<Alloc>::offset(size_t ofs)
449{
450 // Assign the new offset.
451 _reference->_offset = ofs;
452}
453
454template<typename Alloc>
455inline size_t TDynamicBuffer<Alloc>::offset() const
456{
457 return _reference->_offset;
458}
459
460template<typename Alloc>
461void TDynamicBuffer<Alloc>::resize(size_t sz, bool shrink)
462{
463 // When resizing to zero the offset can ben cleared too.
464 if (sz)
465 {
466 sz += _reference->_offset;
467 }
468 else
469 {
470 _reference->_offset = 0;
471 }
472 // Make sure enough space is there.
473 reserve(sz, shrink);
474 // Assign the new virtual size of this buffer.
475 _reference->_size = sz;
476}
477
478template<typename Alloc>
480{
481 // Compensate with the offset.
482 sz += _reference->_offset;
483 // Only when there is a change.
484 if (sz != _reference->_size)
485 {
486 // Check if the current allocated space is sufficient.
487 if (sz <= _reference->_allocated)
488 {
489 // Assign the new virtual size.
490 _reference->_size = sz;
491 }
492 else
493 {
494 // Make a copy of the reference.
495 Reference ref = *_reference;
496 // Reset the reference to the initial values except the usage member.
497 _reference->_size = 0;
498 _reference->_allocated = 0;
499 _reference->_offset = 0;
500 _reference->_data = nullptr;
501 // Make resize fill the ref again and also allocate the new larger
502 // block of memory.
503 resize(sz - _reference->_offset);
504 // Copy the old data to the new allocated memory.
505#if IS_WIN
506 memcpy_s(_reference->_data, ref._size, ref._data, ref._size);
507#else
508 memcpy(_reference->_data, ref._data, ref._size);
509#endif
510 // Delete the previous allocated memory.
511 if (ref._data)
512 {
513 Alloc::freemem(ref.Handle, ref._data);
514 }
515 }
516 }
517}
518
519template<typename Alloc>
520inline void TDynamicBuffer<Alloc>::set(int c, bool reserved)
521{
522 memset(_reference->_data, c, reserved ? _reference->_allocated : _reference->_size);
523}
524
525template<typename Alloc>
526inline void TDynamicBuffer<Alloc>::zero(bool reserved)
527{
528 set(0, reserved);
529}
530
531template<typename Alloc>
533{
534 return _reference->_allocated - _reference->_offset;
535}
536
541
542}// namespace sf
Template for creating a dynamic buffer using an allocator.
Definition TDynamicBuffer.h:57
TDynamicBuffer(size_t sz)
Initializing constructor.
Definition TDynamicBuffer.h:384
char & operator[](size_t i)
Character array operator to access a single byte element.
Definition TDynamicBuffer.h:302
TDynamicBuffer(const TDynamicBuffer &db)
Copy constructor.
Definition TDynamicBuffer.h:377
void * data()
Gets a void pointer to the start of the buffer.
Definition TDynamicBuffer.h:249
void reserve(size_t sz, bool shrink=false)
Reserves the array but does leave the data in tact.
Definition TDynamicBuffer.h:411
const char * c_str() const
Gets a const character pointer to the start of the buffer.
Definition TDynamicBuffer.h:267
TDynamicBuffer()
Default constructor.
Definition TDynamicBuffer.h:366
T * ptr(size_t offset=0)
Gets a typed pointer to the specified given offset the start of the buffer.
Definition TDynamicBuffer.h:141
void grow(size_t sz)
Grows the array to the specified size but keeps the current data intact.
Definition TDynamicBuffer.h:479
TDynamicBuffer & operator=(const TDynamicBuffer &db)
Assignment operators.
Definition TDynamicBuffer.h:313
void offset(size_t ofs)
Sets an virtual offset to the buffer.
Definition TDynamicBuffer.h:448
char * c_str()
Gets a character pointer to the start of the buffer.
Definition TDynamicBuffer.h:261
size_t size() const
Returns the byte size of the buffer.
Definition TDynamicBuffer.h:243
const T * ptr(size_t offset=0) const
Gets a typed pointer to the specified given offset the start of the buffer.
Definition TDynamicBuffer.h:150
void * data(size_t offset)
Gets a void pointer with a byte offset from the start.
Definition TDynamicBuffer.h:273
const void * data() const
Definition TDynamicBuffer.h:255
void resize(size_t sz, bool shrink=false)
Resizes the array but does leave the data in tact.
Definition TDynamicBuffer.h:461
char operator[](size_t i) const
Const character array operator to access a single byte element.
Definition TDynamicBuffer.h:289
void set(int c=0, bool reserved=false)
Sets all memory to the given character. When reserved is true not only the current size but all of it...
Definition TDynamicBuffer.h:520
const void * data(size_t offset) const
Gets a const void pointer with a byte offset from the start.
Definition TDynamicBuffer.h:281
~TDynamicBuffer()
Destructor.
Definition TDynamicBuffer.h:396
void zero(bool reserved=false)
Definition TDynamicBuffer.h:526
size_t reserved() const
Gets the reserved size of this instance.
Definition TDynamicBuffer.h:532
size_t size()
Returns the byte size of the buffer.
Definition TDynamicBuffer.h:237
size_t offset() const
Returns the current offset.
Definition TDynamicBuffer.h:455
Definition Application.h:10
TDynamicBuffer< Allocator > DynamicBuffer
Actual specialized dynamic buffer type using the default allocator.
Definition TDynamicBuffer.h:540
Memory allocator class.
Definition TDynamicBuffer.h:14
int handle_t
Dummy type for allocators which need handles.
Definition TDynamicBuffer.h:18
static void * allocmem(handle_t &, size_t sz)
Allocates the memory for a dynamic buffer.
Definition TDynamicBuffer.h:23
static void * reallocmem(handle_t &, void *p, size_t sz)
Reallocates the memory for a dynamic buffer.
Definition TDynamicBuffer.h:33
static void freemem(handle_t, void *&p)
Frees the memory for a dynamic buffer.
Definition TDynamicBuffer.h:43