#pragma once #include "utility.h" #include #include namespace container { using CapacityType = EntityIndex; using BoolArrayType = u8; template 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* const 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 CapacityType 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(data_type* const 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 CapacityType 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(const Array&) = 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; } const_pointer cosntData() const { return m_data; } reference operator[](const CapacityType index) { return m_data[index]; } const_reference operator[](const 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); } ConstIterator begin() const { return ConstIterator(m_data); } ConstIterator end() const { return ConstIterator(m_data + capacity); } private: pointer m_data; }; template class Array { public: class reference; class const_reference; using data_type = BoolArrayType; 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* const ptr_in, const data_type 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=(const bool input) { switch ((int)input) { case true: *m_ptr |= m_mask; break; case false: *m_ptr &= m_mask; break; } return *this; } reference& operator=(const reference& other) { return *this = bool(other); } void flip() { *m_ptr ^= m_mask; } private: data_type* const m_ptr; const data_type m_mask; }; class const_reference { friend class Array; const_reference(const data_type* ptr_in, const data_type 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; private: const data_type* const m_ptr; const data_type m_mask; }; class Iterator { public: Iterator(data_type* const input, const 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; } } bool operator[](const int) = delete; 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 ConstIterator { public: ConstIterator(const data_type* input, const data_type index) : m_ptr(input) , m_bitIndex(index) { } ConstIterator& operator++() { switch (m_bitIndex++) { case 7: m_bitIndex = 0; m_ptr++; return *this; break; default: return *this; } } ConstIterator operator++(int) { auto it = *this; switch (m_bitIndex++) { case 7: m_bitIndex = 0; m_ptr++; return it; break; default: return it; } } ConstIterator& operator--() { switch (m_bitIndex--) { case 0: m_bitIndex = 7; m_ptr--; return *this; break; default: return *this; } } ConstIterator operator--(int) { auto it = *this; switch (m_bitIndex--) { case 0: m_bitIndex = 7; m_ptr--; return it; break; default: return it; } } bool operator[](const int) = delete; const_reference operator*() const { return const_reference(m_ptr, 1 << m_bitIndex); } bool operator==(const ConstIterator& other) const { return (m_ptr == other.m_ptr) && (m_bitIndex == other.m_bitIndex); } bool operator!=(const ConstIterator& 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 / 8) + 1]; } ~Array() { delete[] m_data; } Array(const Array&) = 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; } //use readAt() instead reference operator[](const CapacityType index) { return reference(m_data + (index / 8), 1 << (index % 8)); } const_reference operator[](const CapacityType index) const { return reference(m_data + (index / 8), 1 << (index % 8)); } inline constexpr CapacityType size() { return capacity; } bool readAt(const CapacityType index) const { return m_data[index / 8] & (1 << (index % 8)); } void changeAt(const CapacityType index, const bool input) { switch ((int)input) { case true: m_data[index / 8] |= (1 << (index % 8)); break; case false: m_data[index / 8] &= ~(1 << (index % 8)); break; } } Iterator begin() { return Iterator(m_data, 0); } Iterator end() { return Iterator(m_data + (capacity / 8), capacity % 8); } ConstIterator begin() const { return ConstIterator(m_data, 0); } ConstIterator end() const { return ConstIterator(m_data + (capacity / 8), capacity % 8); } private: data_type* m_data; }; }//namespace