2d-platformer/include/Containers/Array.h

451 lines
7.9 KiB
C++

#pragma once
#include "utility.h"
#include <cstddef>
#include <iterator>
namespace container
{
template<typename T, EntityIndex capacity>
class Array
{
public:
using data_type = T;
using pointer = data_type*;
using reference = data_type&;
using const_pointer = const pointer;
using const_reference = const data_type&;
using difference_type = std::ptrdiff_t;
using iterator_category = std::forward_iterator_tag;
public:
class Iterator
{
public:
Iterator(const_pointer input)
: m_ptr(input)
{ }
Iterator& operator++()
{
m_ptr++;
return *this;
}
Iterator operator++(int)
{
auto it = *this;
m_ptr++;
return it;
}
Iterator& operator--()
{
m_ptr--;
return *this;
}
Iterator operator--(int)
{
auto it = *this;
m_ptr++;
return it;
}
reference operator[](const int index) const { return m_ptr[index]; }
pointer operator->() const { return m_ptr; }
reference operator*() const { return *m_ptr; }
bool operator==(const Iterator& other) const { return m_ptr == other.m_ptr; }
bool operator!=(const Iterator& other) const { return m_ptr != other.m_ptr; }
private:
pointer m_ptr;
};
class ConstIterator
{
public:
ConstIterator(const_pointer input)
: m_ptr(input)
{ }
ConstIterator& operator++()
{
m_ptr++;
return *this;
}
ConstIterator operator++(int)
{
auto it = *this;
m_ptr++;
return it;
}
ConstIterator& operator--()
{
m_ptr--;
return *this;
}
ConstIterator operator--(int)
{
auto it = *this;
m_ptr++;
return it;
}
const_reference operator[](const int index) const { return m_ptr[index]; }
const_pointer operator->() const { return m_ptr; }
const_reference operator*() const { return *m_ptr; }
bool operator==(const ConstIterator& other) const { return m_ptr == other.m_ptr; }
bool operator!=(const ConstIterator& other) const { return m_ptr != other.m_ptr; }
private:
pointer m_ptr;
};
public:
Array() { m_data = new T[capacity]; }
~Array() { delete[] m_data; }
Array<T, capacity>(const Array<T, capacity>&) = delete;
Array(Array&& other)
: m_data(other.m_data)
{
other.m_data = nullptr;
}
Array& operator=(Array&& other)
{
if (this != &other)
{
delete[] m_data;
m_data = other.m_data;
other.m_data = nullptr;
}
return *this;
}
pointer data() { return m_data; }
reference operator[](const int index) { return m_data[index]; }
const_reference operator[](const int index) const { return m_data[index]; }
inline constexpr EntityIndex size() { return capacity; }
Iterator begin() { return Iterator(m_data); }
Iterator end() { return Iterator(m_data + capacity); }
ConstIterator cbegin() const { return ConstIterator(m_data); }
ConstIterator cend() const { return ConstIterator(m_data + capacity); }
private:
pointer m_data;
};
template <EntityIndex capacity>
class Array<bool, capacity>
{
public:
class reference;
class const_reference;
using data_type = u8;
using pointer = reference;
using const_pointer = const_reference;
using difference_type = std::ptrdiff_t;
using iterator_category = std::forward_iterator_tag;
public:
class reference
{
friend class Array;
reference(data_type* ptr_in, u8 mask_in)
: m_ptr(ptr_in)
, m_mask(mask_in)
{
}
public:
~reference()
{ }
reference(const reference&) = default;
operator bool () const
{
return !!(*m_ptr & m_mask);
}
reference& operator=(bool input)
{
if (input)
{
*m_ptr |= m_mask;
}
else
{
*m_ptr &= m_mask;
}
return *this;
}
reference& operator=(const reference& other)
{
return *this = bool(other);
}
void flip()
{
*m_ptr ^= m_mask;
}
private:
data_type* m_ptr;
u8 m_mask;
};
class const_reference
{
friend class Array;
const_reference(data_type* ptr_in, u8 mask_in)
: m_ptr(ptr_in)
, m_mask(mask_in)
{ }
public:
~const_reference()
{ }
const_reference(const const_reference&) = delete;
operator bool () const { return !!(*m_ptr & m_mask); }
const_reference& operator=(bool) = delete;
const_reference& operator=(const const_reference& other) = delete;
const_reference& operator=(const reference& other) = delete;
void flip() = delete;
private:
const data_type* m_ptr;
u8 m_mask;
};
class Iterator
{
public:
Iterator(data_type* input, u8 index)
: m_ptr(input)
, m_currentClusterIndex(index)
{ }
Iterator& operator++()
{
if (m_currentClusterIndex++ == 7)
{
m_currentClusterIndex = 0;
m_ptr++;
}
return *this;
}
Iterator operator++(int)
{
auto it = *this;
if (m_currentClusterIndex++ == 7)
{
m_ptr++;
m_currentClusterIndex = 0;
}
return it;
}
Iterator& operator--()
{
if (m_currentClusterIndex-- == 0)
{
m_ptr--;
m_currentClusterIndex = 7;
}
return *this;
}
Iterator operator--(int)
{
auto it = *this;
if (m_currentClusterIndex-- == 0)
{
m_ptr--;
m_currentClusterIndex = 7;
}
return it;
}
bool operator[](const int) = delete;
reference operator*() const
{
return reference(m_ptr, 1 << m_currentClusterIndex);
}
bool operator==(const Iterator& other) const
{
return (m_ptr == other.m_ptr) && (m_currentClusterIndex == other.m_currentClusterIndex);
}
bool operator!=(const Iterator& other) const
{
return (m_ptr != other.m_ptr) || (m_currentClusterIndex != other.m_currentClusterIndex);
}
private:
data_type* m_ptr;
u8 m_currentClusterIndex{};
};
class ConstIterator
{
public:
ConstIterator(const data_type* input, u8 index)
: m_ptr(input)
, m_currentClusterIndex(index)
{ }
ConstIterator& operator++()
{
if (m_currentClusterIndex++ == 7)
{
m_currentClusterIndex = 0;
m_ptr++;
}
return *this;
}
ConstIterator operator++(int)
{
auto it = *this;
if (m_currentClusterIndex++ == 7)
{
m_ptr++;
m_currentClusterIndex = 0;
}
return it;
}
ConstIterator& operator--()
{
if (m_currentClusterIndex-- == 0)
{
m_ptr--;
m_currentClusterIndex = 7;
}
return *this;
}
ConstIterator operator--(int)
{
auto it = *this;
if (m_currentClusterIndex-- == 0)
{
m_ptr--;
m_currentClusterIndex = 7;
}
return it;
}
bool operator[](const int) = delete;
const_reference operator*() const
{
return const_reference(m_ptr, 1 << m_currentClusterIndex);
}
bool operator==(const ConstIterator& other) const
{ return (m_ptr == other.m_ptr) && (m_currentClusterIndex == other.m_currentClusterIndex); }
bool operator!=(const ConstIterator& other) const
{ return (m_ptr != other.m_ptr) || (m_currentClusterIndex != other.m_currentClusterIndex); }
private:
const data_type* m_ptr;
u8 m_currentClusterIndex{};
};
public:
Array() { m_data = new data_type[(capacity / 8) + 1]; }
~Array() { delete[] m_data; }
Array<bool, capacity>(const Array<bool, capacity>&) = delete;
Array(Array&& other)
: m_data(other.m_data)
{
other.m_data = nullptr;
}
Array& operator=(Array&& other)
{
if (this != &other)
{
delete[] m_data;
m_data = other.m_data;
other.m_data = nullptr;
}
return *this;
}
data_type* data() { return m_data; }
//use readAt() instead
reference operator[](int index)
{
return reference(m_data + (index / 8), 1 << (index % 8));
}
inline constexpr EntityIndex size() { return capacity; }
bool readAt(const int index) const { return m_data[index / 8] & (1 << (index % 8)); }
void setTrueAt(const int index) { m_data[index / 8] |= (1 << (index % 8)); }
void setFalseAt(const int index) { m_data[index / 8] &= ~(1 << (index % 8)); }
Iterator begin() { return Iterator(m_data, 0); }
Iterator end() { return Iterator(m_data + (capacity / 8), capacity % 8); }
ConstIterator cbegin() const { return ConstIterator(m_data, 0); }
ConstIterator cend() const { return ConstIterator(m_data + (capacity / 8), capacity % 8); }
private:
data_type* m_data;
};
}//namespace