2d-platformer/include/SwapBackVector.hpp

237 lines
5.2 KiB
C++

#pragma once
#include "Globals.h"
#include <Entities/Entity.h>
#include <SwapBackVectorIterator.hpp>
#include <bitset>
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <iterator>
#include <ostream>
template<typename T, EntityIndex capacity_in = Global::MAX_ENTITIES>
class SwapBackVector
{
public:
//iterator typedefs
using iterator_category = std::forward_iterator_tag;
using difference_type = std::ptrdiff_t;
using data_type = T;
using iterator = SwapBackVectorIterator<SwapBackVector<T, capacity_in>>;
using const_iterator = SwapBackVectorConstIterator<SwapBackVector<T, capacity_in>>;
public:
SwapBackVector()
{
m_data = new T[capacity_in];
}
~SwapBackVector()
{
delete[] m_data;
}
SwapBackVector(const SwapBackVector<T>& other)
{
m_nextValidIndex = other.m_nextValidIndex;
for (int i = 0; i < m_nextValidIndex; i++)
{
m_data[i] = other.m_data[i];
}
}
SwapBackVector(SwapBackVector<T>&& other)
{
m_data = other.m_data;
other.m_data = nullptr;
m_nextValidIndex = other.m_nextValidIndex;
}
SwapBackVector<T>& operator=(const SwapBackVector<T>& rhs)
{
if (this == &rhs) return this;
m_nextValidIndex = rhs.m_nextValidIndex;
for (int i = 0; i < m_nextValidIndex; i++)
{
m_data[i] = rhs.m_data[i];
}
return *this;
}
SwapBackVector<T>& operator=(SwapBackVector<T>&& rhs)
{
if (this == &rhs) return this;
delete[] m_data;
m_data = rhs.m_data;
rhs.m_data = nullptr;
return *this;
}
public:
T& operator[](EntityIndex index)
{
assert(index < m_nextValidIndex && "ASSERT ERROR -> SwapBackVector.hpp: attempting to index beyond next valid index");
return m_data[index];
}
const T& operator[](EntityIndex index) const
{
assert(index < m_nextValidIndex && "ASSERT ERROR -> SwapBackVector.hpp: attempting to index beyond next valid index");
return m_data[index];
}
public:
T* data() { return m_data; }
const T* data() const { return m_data; }
void remove(EntityIndex index)
{
if (index >= m_nextValidIndex) return;
m_data[index] = m_data[m_nextValidIndex - 1];
m_nextValidIndex--;
}
void push()
{
assert(capacity_in > m_nextValidIndex);
m_data[m_nextValidIndex] = T();
m_nextValidIndex++;
}
void push(const T& data)
{
assert(capacity_in > m_nextValidIndex);
m_data[m_nextValidIndex] = data;
m_nextValidIndex++;
}
inline EntityIndex size() const { return m_nextValidIndex; }
inline constexpr EntityIndex capacity() const { return capacity_in; }
iterator begin() { return iterator(m_data); }
iterator end() { return iterator(m_data + m_nextValidIndex); }
const_iterator cbegin() const { return const_iterator(m_data); }
const_iterator cend() const { return const_iterator(m_data + m_nextValidIndex); }
private:
T* m_data;
EntityIndex m_nextValidIndex{};
};
//bool specialization
template<EntityIndex capacity_in>
class SwapBackVector<bool, capacity_in>
{
public:
SwapBackVector()
{
m_data = new uint8_t[(capacity_in / 8) + 1];
}
~SwapBackVector()
{
delete[] m_data;
}
SwapBackVector(const SwapBackVector& other) = delete;
SwapBackVector(SwapBackVector&& other) = delete;
SwapBackVector& operator=(const SwapBackVector& rhs) = delete;
SwapBackVector& operator=(SwapBackVector&& rhs) = delete;
public:
bool operator[](EntityIndex index)
{
//assert(index < m_nextValidIndex && "ASSERT ERROR -> SwapBackVector.hpp: attempting to index beyond next valid index");
EntityIndex clusterIndex = index / 8u;
EntityIndex stateIndex = index % 8u;
return m_data[clusterIndex] & (1 << stateIndex);
}
friend std::ostream& operator<<(std::ostream&, const SwapBackVector<bool>&);
public:
void remove(EntityIndex index)
{
if (index >= m_nextValidIndex) return;
readAt(m_nextValidIndex - 1) ? setTrueAt(index) : setFalseAt(index);
m_nextValidIndex--;
}
void push()
{
assert(capacity_in > m_nextValidIndex);
setFalseAt(m_nextValidIndex);
m_nextValidIndex++;
}
void push(bool state)
{
assert(capacity_in > m_nextValidIndex);
state ? setTrueAt(m_nextValidIndex) : setFalseAt(m_nextValidIndex);
m_nextValidIndex++;
}
bool readAt(EntityIndex index) const
{
EntityIndex clusterIndex = index / 8u;
EntityIndex stateIndex = index % 8u;
return m_data[clusterIndex] & 1 << stateIndex;
}
void setTrueAt(EntityIndex index)
{
EntityIndex clusterIndex = index / 8u;
EntityIndex stateIndex = index % 8u;
m_data[clusterIndex] |= 1 << stateIndex;
}
void setFalseAt(EntityIndex index)
{
EntityIndex clusterIndex = index / 8u;
EntityIndex stateIndex = index % 8u;
m_data[clusterIndex] &= ~(1 << stateIndex);
}
inline EntityIndex size() const { return m_nextValidIndex; }
inline constexpr EntityIndex capacity() const { return capacity_in; }
private:
uint8_t* m_data;
EntityIndex m_nextValidIndex{};
};
inline std::ostream& operator<<(std::ostream& out, const SwapBackVector<bool>& vec)
{
for(size_t i = 0; i < (vec.size() / 8) + 1; i++)
{
out << std::bitset<8>(vec.m_data[i]) << " ";
}
out << "\n";
return out;
}
//Entity specialization
template<EntityIndex capacity_in>
class SwapBackVector<Entity, capacity_in>
{
};