mirror of
https://github.com/thunderbrewhq/squall.git
synced 2025-12-12 02:22:30 +00:00
feat(array): add growable array template
This commit is contained in:
parent
23df793b34
commit
3d5794ed7c
3 changed files with 149 additions and 0 deletions
141
storm/array/TSGrowableArray.hpp
Normal file
141
storm/array/TSGrowableArray.hpp
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
#ifndef STORM_ARRAY_TS_GROWABLE_ARRAY_HPP
|
||||
#define STORM_ARRAY_TS_GROWABLE_ARRAY_HPP
|
||||
|
||||
#include "array/TSFixedArray.hpp"
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <new>
|
||||
|
||||
template<class T>
|
||||
class TSGrowableArray : public TSFixedArray<T> {
|
||||
public:
|
||||
uint32_t m_chunk = 0;
|
||||
|
||||
uint32_t Add(uint32_t count, const T* data);
|
||||
uint32_t Add(uint32_t count, uint32_t incr, const T* data);
|
||||
uint32_t CalcChunkSize(uint32_t count);
|
||||
void GrowToFit(uint32_t index, int32_t zero);
|
||||
T* New(void);
|
||||
void Reserve(uint32_t count, int32_t round);
|
||||
uint32_t RoundToChunk(uint32_t count, uint32_t chunk);
|
||||
void SetCount(uint32_t count);
|
||||
};
|
||||
|
||||
template<class T>
|
||||
uint32_t TSGrowableArray<T>::Add(uint32_t count, const T* data) {
|
||||
this->Reserve(count, 1);
|
||||
|
||||
for (int32_t i = 0; i < count; i++) {
|
||||
T* element = &this->m_data[this->m_count + i];
|
||||
*element = data[i];
|
||||
}
|
||||
|
||||
this->m_count += count;
|
||||
return this->m_count - count;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
uint32_t TSGrowableArray<T>::Add(uint32_t count, uint32_t incr, const T* data) {
|
||||
this->Reserve(count, 1);
|
||||
|
||||
const char* dataptr = reinterpret_cast<const char*>(data);
|
||||
|
||||
for (int32_t i = 0; i < count; i++) {
|
||||
T* element = &this->m_data[this->m_count + i];
|
||||
*element = *reinterpret_cast<const T*>(dataptr);
|
||||
dataptr += incr;
|
||||
}
|
||||
|
||||
this->m_count += count;
|
||||
return this->m_count - count;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
uint32_t TSGrowableArray<T>::CalcChunkSize(uint32_t count) {
|
||||
uint32_t maxChunk = std::max(static_cast<int32_t>(256 / sizeof(T)), 8);
|
||||
|
||||
if (count >= maxChunk) {
|
||||
this->m_chunk = maxChunk;
|
||||
return maxChunk;
|
||||
}
|
||||
|
||||
uint32_t result = count;
|
||||
|
||||
for (uint32_t i = count & (count - 1); i; i &= i - 1) {
|
||||
result = i;
|
||||
}
|
||||
|
||||
if (result < 1) {
|
||||
result = 1;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void TSGrowableArray<T>::GrowToFit(uint32_t index, int32_t zero) {
|
||||
uint32_t count = this->m_count;
|
||||
|
||||
if (index >= count) {
|
||||
this->Reserve(index - count + 1, 1);
|
||||
|
||||
if (zero) {
|
||||
memset(&this->m_data[count], 0, sizeof(T) * (index - count + 1));
|
||||
}
|
||||
|
||||
this->m_count = index + 1;
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
T* TSGrowableArray<T>::New() {
|
||||
this->Reserve(1, 1);
|
||||
void* element = &this->m_data[this->m_count++];
|
||||
return new (element) T();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void TSGrowableArray<T>::Reserve(uint32_t count, int32_t round) {
|
||||
if (count + this->m_count > this->m_alloc) {
|
||||
if (round) {
|
||||
uint32_t chunk = this->m_chunk;
|
||||
|
||||
if (!chunk) {
|
||||
chunk = this->CalcChunkSize(count + this->m_count);
|
||||
}
|
||||
|
||||
count = this->RoundToChunk(count, chunk);
|
||||
}
|
||||
|
||||
this->ReallocData(count + this->m_count);
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
uint32_t TSGrowableArray<T>::RoundToChunk(uint32_t count, uint32_t chunk) {
|
||||
if (count % chunk) {
|
||||
return chunk - count % chunk + count;
|
||||
} else {
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void TSGrowableArray<T>::SetCount(uint32_t count) {
|
||||
if (count > this->m_count) {
|
||||
// Expand size
|
||||
this->Reserve(count - this->m_count, 1);
|
||||
|
||||
T* element;
|
||||
|
||||
for (int32_t i = this->m_count; i < count; ++i) {
|
||||
element = &this->m_data[i];
|
||||
new (element) T();
|
||||
}
|
||||
}
|
||||
|
||||
this->m_count = count;
|
||||
}
|
||||
|
||||
#endif
|
||||
Loading…
Add table
Add a link
Reference in a new issue