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

430 lines
7.9 KiB
C++

#pragma once
#include "utility.h"
//#include <cstddef>
#include <iterator>
namespace container
{
using CapacityType = index_t;
using BoolArrayType = u8;
template<typename T, CapacityType capacity>
class Array
{
public:
using data_type = T;
using pointer = data_type*;
using reference = data_type&;
using const_pointer = const data_type*;
using const_reference = const data_type&;
using difference_type = std::ptrdiff_t;
using iterator_category = std::forward_iterator_tag;
public:
class iterator
{
public:
iterator(data_type* 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[](CapacityType index) const { return m_ptr[index]; }
pointer operator->() const { return m_ptr; }
reference operator*() const { return *m_ptr; }
bool operator==(iterator other) const { return m_ptr == other.m_ptr; }
bool operator!=(iterator other) const { return m_ptr != other.m_ptr; }
private:
pointer m_ptr;
};
class const_iterator
{
public:
const_iterator(data_type* input)
: m_ptr(input)
{ }
const_iterator& operator++()
{ m_ptr++; return *this; }
const_iterator operator++(int)
{ auto it = *this; m_ptr++; return it; }
const_iterator& operator--()
{ m_ptr--; return *this; }
const_iterator operator--(int)
{ auto it = *this; m_ptr++; return it; }
const_reference operator[](CapacityType index) const { return m_ptr[index]; }
const_pointer operator->() const { return m_ptr; }
const_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:
const_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)
{
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[](CapacityType index) { return m_data[index]; }
const_reference operator[](CapacityType index) const { return m_data[index]; }
pointer operator->() { return m_data; }
const_pointer operator->() const { return m_data; }
reference operator*() { return *m_data; }
const_reference operator*() const { return *m_data; }
inline constexpr CapacityType size() const { return capacity; }
iterator begin() { return iterator(m_data); }
iterator end() { return iterator(m_data + capacity); }
const_iterator begin() const { return const_iterator(m_data); }
const_iterator end() const { return const_iterator(m_data + capacity); }
private:
pointer m_data;
};
template <CapacityType capacity>
class Array<bool, capacity>
{
public:
class reference;
using pointer = reference;
using const_reference = bool;
using data_type = BoolArrayType;
using difference_type = std::ptrdiff_t;
using iterator_category = std::forward_iterator_tag;
public:
class reference
{
public:
reference(data_type* ptr_in, data_type mask_in)
: m_ptr(ptr_in)
, m_mask(mask_in)
{ }
~reference()
{ }
reference(reference&) = default;
operator bool () const
{ return !!(*m_ptr & m_mask); }
reference& operator=(bool input)
{
if (input == true)
{
*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; }
void setTrue()
{ *m_ptr |= m_mask; }
void setFalse()
{ *m_ptr &= ~m_mask; }
private:
data_type* const m_ptr;
const data_type m_mask;
};
class iterator
{
public:
iterator(data_type* input, data_type index)
: m_ptr(input)
, m_bitIndex(index)
{ }
iterator& operator++()
{
switch (m_bitIndex++)
{
case 7:
m_bitIndex = 0;
m_ptr++;
return *this;
break;
default:
return *this;
}
}
iterator operator++(int)
{
auto it = *this;
switch (m_bitIndex++)
{
case 7:
m_bitIndex = 0;
m_ptr++;
return it;
break;
default:
return it;
}
}
iterator& operator--()
{
switch (m_bitIndex--)
{
case 0:
m_bitIndex = 7;
m_ptr--;
return *this;
break;
default:
return *this;
}
}
iterator operator--(int)
{
auto it = *this;
switch (m_bitIndex--)
{
case 0:
m_bitIndex = 7;
m_ptr--;
return it;
break;
default:
return it;
}
}
reference operator[](CapacityType index)
{ return reference(m_ptr + (index / 7), m_bitIndex + (index % 8)); }
reference operator*() const
{ return reference(m_ptr, 1 << m_bitIndex); }
bool operator==(const iterator& other) const
{ return (m_ptr == other.m_ptr) && (m_bitIndex == other.m_bitIndex); }
bool operator!=(const iterator& other) const
{ return (m_ptr != other.m_ptr) || (m_bitIndex != other.m_bitIndex); }
private:
data_type* m_ptr;
data_type m_bitIndex{};
};
class const_iterator
{
public:
const_iterator(const data_type* input, data_type index)
: m_ptr(input)
, m_bitIndex(index)
{ }
const_iterator& operator++()
{
switch (m_bitIndex++)
{
case 7:
m_bitIndex = 0;
m_ptr++;
return *this;
break;
default:
return *this;
}
}
const_iterator operator++(int)
{
auto it = *this;
switch (m_bitIndex++)
{
case 7:
m_bitIndex = 0;
m_ptr++;
return it;
break;
default:
return it;
}
}
const_iterator& operator--()
{
switch (m_bitIndex--)
{
case 0:
m_bitIndex = 7;
m_ptr--;
return *this;
break;
default:
return *this;
}
}
const_iterator operator--(int)
{
auto it = *this;
switch (m_bitIndex--)
{
case 0:
m_bitIndex = 7;
m_ptr--;
return it;
break;
default:
return it;
}
}
const_reference operator[](CapacityType index) const
{ return (*m_ptr + (index / 8)) & (1 << (index % 8)); }
const_reference operator*() const
{ return *m_ptr & (1 << m_bitIndex); }
bool operator==(const const_iterator& other) const
{ return (m_ptr == other.m_ptr) && (m_bitIndex == other.m_bitIndex); }
bool operator!=(const const_iterator& other) const
{ return (m_ptr != other.m_ptr) || (m_bitIndex != other.m_bitIndex); }
private:
const data_type* m_ptr;
data_type m_bitIndex{};
};
public:
Array() { m_data = new data_type[(capacity / 9) + 1]{}; }
~Array() { delete[] m_data; }
Array<bool, capacity>(const Array<bool, capacity>&) = delete;
Array(Array&& other)
: m_data(other.m_data)
{
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;
}
reference operator[](CapacityType index)
{ return reference(m_data + (index / 8), 1 << (index % 8)); }
const_reference operator[](CapacityType index) const
{ return m_data[index / 8] & (1 << (index % 8)); }
inline constexpr CapacityType size() { return capacity; }
const_reference readAt(CapacityType index) const
{ return m_data[index / 8] & (1 << (index % 8)); }
void setTrueAt(CapacityType index)
{ m_data[index / 8] |= (1 << (index % 8)); }
void setFalseAt(CapacityType 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); }
const_iterator begin() const { return const_iterator(m_data, 0); }
const_iterator end() const { return const_iterator(m_data + (capacity / 8), capacity % 8); }
private:
data_type* m_data;
};
}//namespace