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
|
|
@ -3,5 +3,6 @@
|
||||||
|
|
||||||
#include "array/TSBaseArray.hpp"
|
#include "array/TSBaseArray.hpp"
|
||||||
#include "array/TSFixedArray.hpp"
|
#include "array/TSFixedArray.hpp"
|
||||||
|
#include "array/TSGrowableArray.hpp"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
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
|
||||||
|
|
@ -14,3 +14,10 @@ TEST_CASE("TSFixedArray", "[list]") {
|
||||||
REQUIRE(array.Count() == 0);
|
REQUIRE(array.Count() == 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("TSGrowableArray", "[list]") {
|
||||||
|
SECTION("constructs correctly") {
|
||||||
|
TSGrowableArray<uint32_t> array;
|
||||||
|
REQUIRE(array.Count() == 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue