Files
Commonwealth-Online-Public/plugin/lib/commonlibf4/include/RE/N/NiTArray.h
T
2026-05-30 18:33:24 +12:00

201 lines
5.1 KiB
C++

#pragma once
#include "RE/N/NiMemManager.h"
namespace RE
{
template <class T, class Allocator>
class NiTArray
{
public:
using value_type = T;
using allocator_type = Allocator;
using size_type = std::uint16_t;
using reference = value_type&;
using const_reference = const value_type&;
using pointer = value_type*;
using const_pointer = const value_type*;
template <class U>
class iterator_base
{
public:
using difference_type = std::ptrdiff_t;
using value_type = std::remove_const_t<U>;
using pointer = value_type*;
using reference = value_type&;
using iterator_category = std::bidirectional_iterator_tag;
~iterator_base() noexcept = default;
iterator_base() noexcept = default;
iterator_base(const volatile iterator_base&) = delete;
iterator_base& operator=(const volatile iterator_base&) = delete;
template <class V>
iterator_base(const iterator_base<V>& a_rhs) //
requires(std::convertible_to<typename iterator_base<V>::reference, reference>)
:
_pos(a_rhs._pos),
_head(a_rhs._head),
_tail(a_rhs._tail)
{}
template <class V>
iterator_base& operator=(const iterator_base<V>& a_rhs) //
requires(std::convertible_to<typename iterator_base<V>::reference, reference>)
{
_pos = a_rhs._pos;
_head = a_rhs._head;
_tail = a_rhs._tail;
return *this;
}
[[nodiscard]] reference operator*() const noexcept
{
assert(validate());
return *_pos;
}
[[nodiscard]] pointer operator->() const noexcept
{
return std::pointer_traits<pointer>::pointer_to(operator*());
}
template <class V>
[[nodiscard]] bool operator==(const iterator_base<V>& a_rhs) const noexcept
{
assert(_head == a_rhs._head);
assert(_tail == a_rhs._tail);
return _pos == a_rhs._pos;
}
template <class V>
[[nodiscard]] bool operator!=(const iterator_base<V>& a_rhs) const noexcept
{
return !operator==(a_rhs);
}
iterator_base& operator++() noexcept
{
assert(validate());
do {
++_pos;
} while (_pos < _tail && !slot_filled());
return *this;
}
iterator_base operator++(int) noexcept
{
iterator_base tmp{ *this };
operator++();
return tmp;
}
iterator_base& operator--() noexcept
{
assert(validate());
do {
--_pos;
} while (_head <= _pos && !slot_filled());
return *this;
}
iterator_base operator--(int) noexcept
{
iterator_base tmp{ *this };
operator--();
return tmp;
}
private:
friend iterator_base;
friend NiTArray;
explicit iterator_base(pointer a_pos, pointer a_head, pointer a_tail) noexcept :
_pos(a_pos),
_head(a_head),
_tail(a_tail)
{}
[[nodiscard]] bool validate() const noexcept
{
return _pos != nullptr &&
_head != nullptr &&
_tail != nullptr &&
_head <= _pos && _pos < _tail;
}
[[nodiscard]] bool slot_filled() const noexcept
{
assert(validate());
return static_cast<bool>(*_pos);
}
pointer _pos{ nullptr };
pointer _head{ nullptr };
pointer _tail{ nullptr };
};
public:
using iterator = iterator_base<value_type>;
using const_iterator = iterator_base<const value_type>;
explicit NiTArray(std::uint32_t a_maxSize = 0, std::uint32_t a_growBy = 1) :
_capacity(static_cast<std::uint16_t>(a_maxSize)),
_growthSize(static_cast<std::uint16_t>(a_growBy))
{
if (capacity() > 0) {
_data = allocator_type::allocate(capacity());
}
}
virtual ~NiTArray() { allocator_type::deallocate(_data); } // 00
[[nodiscard]] reference operator[](size_type a_pos) noexcept
{
assert(a_pos < capacity());
return _data[a_pos];
}
[[nodiscard]] const_reference operator[](size_type a_pos) const noexcept
{
assert(a_pos < capacity());
return _data[a_pos];
}
[[nodiscard]] const_pointer data() const noexcept { return _data; }
[[nodiscard]] iterator begin() noexcept { return make_iterator<iterator>(0); }
[[nodiscard]] const_iterator begin() const noexcept { return make_iterator<const_iterator>(0); }
[[nodiscard]] const_iterator cbegin() const noexcept { return make_iterator<const_iterator>(0); }
[[nodiscard]] iterator end() noexcept { return make_iterator<iterator>(_capacity); }
[[nodiscard]] const_iterator end() const noexcept { return make_iterator<const_iterator>(_capacity); }
[[nodiscard]] const_iterator cend() const noexcept { return make_iterator<const_iterator>(_capacity); }
[[nodiscard]] bool empty() const noexcept { return size() == 0; }
[[nodiscard]] size_type size() const noexcept { return _size; }
[[nodiscard]] size_type capacity() const noexcept { return _capacity; }
private:
template <class U>
[[nodiscard]] U make_iterator(size_type a_pos) const noexcept
{
return U(_data + a_pos, _data, _data + _capacity);
}
// members
pointer _data{ nullptr }; // 08
size_type _capacity{ 0 }; // 10
size_type _freeIdx{ 0 }; // 12
size_type _size{ 0 }; // 14
size_type _growthSize{ 0 }; // 16
};
template <class T>
using NiTObjectArray = NiTArray<T, NiTNewInterface<T>>;
template <class T>
using NiTPrimitiveArray = NiTArray<T, NiTMallocInterface<T>>;
}