StableVector repetition fix.
This commit is contained in:
@@ -14,7 +14,7 @@
|
|||||||
namespace OpenVulkano
|
namespace OpenVulkano
|
||||||
{
|
{
|
||||||
template<typename K, typename V, template<typename, typename> class Pair = std::pair,
|
template<typename K, typename V, template<typename, typename> class Pair = std::pair,
|
||||||
template<typename> class Vec = std::vector, typename = std::enable_if_t<std::is_integral<K>::value>>
|
template<typename...> class Vec = std::vector, typename = std::enable_if_t<std::is_integral<K>::value>>
|
||||||
class BinSearchArrayMap
|
class BinSearchArrayMap
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -59,7 +59,7 @@ namespace OpenVulkano
|
|||||||
std::streamsize index = FindIndexInVector(key);
|
std::streamsize index = FindIndexInVector(key);
|
||||||
if (index < 0)
|
if (index < 0)
|
||||||
{
|
{
|
||||||
std::runtime_error("Key not found");
|
throw std::runtime_error("Key not found");
|
||||||
}
|
}
|
||||||
return m_data[index];
|
return m_data[index];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ namespace OpenVulkano
|
|||||||
*
|
*
|
||||||
* @throw Please know that this vector creates array gaps when you remove an element.
|
* @throw Please know that this vector creates array gaps when you remove an element.
|
||||||
*/
|
*/
|
||||||
template<typename T, size_t GROW_FACTOR = 2, size_t DEFAULT_CHUNK_SIZE = 32> class StableVector
|
template<typename T> class StableVector
|
||||||
{
|
{
|
||||||
struct VectorChunk
|
struct VectorChunk
|
||||||
{
|
{
|
||||||
@@ -174,10 +174,7 @@ namespace OpenVulkano
|
|||||||
return m_chunk == other.m_chunk && m_index == other.m_index;
|
return m_chunk == other.m_chunk && m_index == other.m_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator!=(const Iterator& other) const
|
bool operator!=(const Iterator& other) const { return !(*this == other); }
|
||||||
{
|
|
||||||
return m_chunk != other.m_chunk || m_index != other.m_index;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::streamsize GetIndex() const { return m_chunk->GetRealIndex(m_index); }
|
std::streamsize GetIndex() const { return m_chunk->GetRealIndex(m_index); }
|
||||||
VectorChunk* GetChunk() const { return m_chunk; }
|
VectorChunk* GetChunk() const { return m_chunk; }
|
||||||
@@ -285,143 +282,17 @@ namespace OpenVulkano
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PushBack(const T& value)
|
void PushBack(const T& value) { new (InsertBack()) T(value); }
|
||||||
{
|
void PushBack(T&& value) noexcept { new (InsertBack()) T(std::move(value)); }
|
||||||
if (m_lastChunk->m_nextIndex == m_lastChunk->m_capacity)
|
|
||||||
{
|
|
||||||
VectorChunk* newChunk = Grow(m_lastChunk->m_capacity * GROW_FACTOR);
|
|
||||||
m_capacity += m_lastChunk->m_capacity * GROW_FACTOR;
|
|
||||||
m_lastChunk->m_next = newChunk;
|
|
||||||
newChunk->m_prev = m_lastChunk;
|
|
||||||
m_lastChunk = newChunk;
|
|
||||||
}
|
|
||||||
|
|
||||||
new (&m_lastChunk->m_data[m_lastChunk->m_nextIndex]) T(value);
|
|
||||||
m_lastChunk->m_occupiedIndices[m_lastChunk->m_nextIndex] = true;
|
|
||||||
m_lastChunk->m_nextIndex++;
|
|
||||||
m_lastChunk->m_size++;
|
|
||||||
m_size++;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PushBack(T&& value) noexcept
|
|
||||||
{
|
|
||||||
if (m_lastChunk->m_nextIndex == m_lastChunk->m_capacity)
|
|
||||||
{
|
|
||||||
VectorChunk* newChunk = Grow(m_lastChunk->m_capacity * GROW_FACTOR);
|
|
||||||
m_capacity += m_lastChunk->m_capacity * GROW_FACTOR;
|
|
||||||
m_lastChunk->m_next = newChunk;
|
|
||||||
newChunk->m_prev = m_lastChunk;
|
|
||||||
m_lastChunk = newChunk;
|
|
||||||
}
|
|
||||||
|
|
||||||
new (&m_lastChunk->m_data[m_lastChunk->m_nextIndex]) T(std::move(value));
|
|
||||||
m_lastChunk->m_occupiedIndices[m_lastChunk->m_nextIndex] = true;
|
|
||||||
m_lastChunk->m_nextIndex++;
|
|
||||||
m_lastChunk->m_size++;
|
|
||||||
m_size++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Checks the first available gap and inserts. If no gap it works like push_back(const T& value)
|
|
||||||
void Push(const T& value)
|
|
||||||
{
|
|
||||||
VectorChunk* currentChunk = m_firstChunk;
|
|
||||||
while (currentChunk)
|
|
||||||
{
|
|
||||||
if (currentChunk->m_gapCount > 0) // If there is a gap check occupied indices to find the first gap
|
|
||||||
{
|
|
||||||
for (size_t i = 0; i < currentChunk->m_capacity; i++)
|
|
||||||
{
|
|
||||||
if (!currentChunk->m_occupiedIndices[i])
|
|
||||||
{
|
|
||||||
new (¤tChunk->m_data[i]) T(value);
|
|
||||||
currentChunk->m_occupiedIndices[i] = true;
|
|
||||||
currentChunk->m_size++;
|
|
||||||
currentChunk->m_gapCount--;
|
|
||||||
m_size++;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
currentChunk = currentChunk->m_next;
|
|
||||||
}
|
|
||||||
|
|
||||||
PushBack(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Checks the first available gap and inserts. If no gap it works like push_back(T&& value)
|
|
||||||
void Push(T&& value) noexcept
|
|
||||||
{
|
|
||||||
VectorChunk* currentChunk = m_firstChunk;
|
|
||||||
while (currentChunk)
|
|
||||||
{
|
|
||||||
if (currentChunk->m_gapCount > 0) // If there is a gap check occupied indices to find the first gap
|
|
||||||
{
|
|
||||||
for (size_t i = 0; i < currentChunk->m_capacity; i++)
|
|
||||||
{
|
|
||||||
if (!currentChunk->m_occupiedIndices[i])
|
|
||||||
{
|
|
||||||
new (¤tChunk->m_data[i]) T(std::move(value));
|
|
||||||
currentChunk->m_occupiedIndices[i] = true;
|
|
||||||
currentChunk->m_size++;
|
|
||||||
currentChunk->m_gapCount--;
|
|
||||||
m_size++;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
currentChunk = currentChunk->m_next;
|
|
||||||
}
|
|
||||||
|
|
||||||
PushBack(std::move(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename... Args> void EmplaceBack(Args&&... args)
|
template<typename... Args> void EmplaceBack(Args&&... args)
|
||||||
{
|
{
|
||||||
if (m_lastChunk->m_nextIndex == m_lastChunk->m_capacity)
|
new (InsertBack()) T(std::forward<Args>(args)...);
|
||||||
{
|
|
||||||
VectorChunk* newChunk = Grow(m_lastChunk->m_capacity * GROW_FACTOR);
|
|
||||||
m_capacity += m_lastChunk->m_capacity * GROW_FACTOR;
|
|
||||||
m_lastChunk->m_next = newChunk;
|
|
||||||
newChunk->m_prev = m_lastChunk;
|
|
||||||
m_lastChunk = newChunk;
|
|
||||||
}
|
|
||||||
|
|
||||||
new (&m_lastChunk->m_data[m_lastChunk->m_nextIndex]) T(std::forward<Args>(args)...);
|
|
||||||
m_lastChunk->m_occupiedIndices[m_lastChunk->m_nextIndex] = true;
|
|
||||||
m_lastChunk->m_nextIndex++;
|
|
||||||
m_lastChunk->m_size++;
|
|
||||||
m_size++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checks the first available gap and inserts. If no gap it works like emplace_back(Args&&... args)
|
void Push(const T& value) { new (Insert()) T(value); }
|
||||||
template<typename... Args> void Emplace(Args&&... args)
|
void Push(T&& value) noexcept { new (Insert()) T(std::move(value)); }
|
||||||
{
|
template<typename... Args> void Emplace(Args&&... args) { new (Insert()) T(std::forward<Args>(args)...); }
|
||||||
VectorChunk* currentChunk = m_firstChunk;
|
|
||||||
while (currentChunk)
|
|
||||||
{
|
|
||||||
if (currentChunk->m_gapCount > 0) // If there is a gap check occupied indices to find the first gap
|
|
||||||
{
|
|
||||||
for (size_t i = 0; i < currentChunk->m_capacity; i++)
|
|
||||||
{
|
|
||||||
if (!currentChunk->m_occupiedIndices[i])
|
|
||||||
{
|
|
||||||
new (¤tChunk->m_data[i]) T(std::forward<Args>(args)...);
|
|
||||||
currentChunk->m_occupiedIndices[i] = true;
|
|
||||||
currentChunk->m_size++;
|
|
||||||
currentChunk->m_gapCount--;
|
|
||||||
m_size++;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
currentChunk = currentChunk->m_next;
|
|
||||||
}
|
|
||||||
|
|
||||||
EmplaceBack(std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PopBack()
|
void PopBack()
|
||||||
{
|
{
|
||||||
@@ -580,11 +451,60 @@ namespace OpenVulkano
|
|||||||
throw std::out_of_range("Index out of range");
|
throw std::out_of_range("Index out of range");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
T* InsertBack()
|
||||||
|
{
|
||||||
|
if (m_lastChunk->m_nextIndex == m_lastChunk->m_capacity)
|
||||||
|
{
|
||||||
|
VectorChunk* newChunk = Grow(m_lastChunk->m_capacity * GROW_FACTOR);
|
||||||
|
m_capacity += m_lastChunk->m_capacity * GROW_FACTOR;
|
||||||
|
m_lastChunk->m_next = newChunk;
|
||||||
|
newChunk->m_prev = m_lastChunk;
|
||||||
|
m_lastChunk = newChunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_lastChunk->m_occupiedIndices[m_lastChunk->m_nextIndex] = true;
|
||||||
|
m_lastChunk->m_size++;
|
||||||
|
m_lastChunk->m_gapCount++;
|
||||||
|
m_size++;
|
||||||
|
return &m_lastChunk->m_data[m_lastChunk->m_nextIndex++];
|
||||||
|
}
|
||||||
|
|
||||||
|
T* Insert()
|
||||||
|
{
|
||||||
|
T* target = nullptr;
|
||||||
|
VectorChunk* currentChunk = m_firstChunk;
|
||||||
|
while (currentChunk)
|
||||||
|
{
|
||||||
|
if (currentChunk->m_gapCount > 0) // If there is a gap check occupied indices to find the first gap
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < currentChunk->m_capacity; i++)
|
||||||
|
{
|
||||||
|
if (!currentChunk->m_occupiedIndices[i])
|
||||||
|
{
|
||||||
|
target = ¤tChunk->m_data[i];
|
||||||
|
currentChunk->m_occupiedIndices[i] = true;
|
||||||
|
currentChunk->m_size++;
|
||||||
|
currentChunk->m_gapCount--;
|
||||||
|
m_size++;
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
currentChunk = currentChunk->m_next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return InsertBack();
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
VectorChunk* m_firstChunk;
|
VectorChunk* m_firstChunk;
|
||||||
VectorChunk* m_lastChunk;
|
VectorChunk* m_lastChunk;
|
||||||
size_t m_size;
|
size_t m_size;
|
||||||
size_t m_capacity;
|
size_t m_capacity;
|
||||||
|
|
||||||
|
static inline constexpr size_t DEFAULT_CHUNK_SIZE = 32;
|
||||||
|
static inline constexpr size_t GROW_FACTOR = 2;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user