334 lines
6.1 KiB
C++
Executable File
334 lines
6.1 KiB
C++
Executable File
// License: Modified MIT (NON-AI)
|
|
// See the LICENSE file in the root directory for license information.
|
|
// Copyright 2025 Timothy Prepscius
|
|
|
|
#pragma once
|
|
|
|
#include "../assert/debug_assert.h"
|
|
#include "../assert/handle_assert.hpp"
|
|
#include "../algorithm/mem_copy.hpp"
|
|
|
|
#include "../exception/OutOfBounds.hpp"
|
|
|
|
#include <cstring> // for memcpy
|
|
|
|
namespace tjp {
|
|
namespace core {
|
|
|
|
template<typename T, size_t N>
|
|
InPlaceArray<T, N>::InPlaceArray (size_t size, T t)
|
|
{
|
|
resize(size, t);
|
|
}
|
|
|
|
template<typename T, size_t N>
|
|
InPlaceArray<T, N>::InPlaceArray ()
|
|
{
|
|
}
|
|
|
|
template<typename T, size_t N>
|
|
//template<size_t N2>
|
|
InPlaceArray<T, N>::InPlaceArray(const InPlaceArray<T, N> &rhs)
|
|
{
|
|
append(rhs.begin(), rhs.end());
|
|
}
|
|
|
|
template<typename T, size_t N>
|
|
//template<size_t N2>
|
|
InPlaceArray<T, N>::InPlaceArray(const T *begin, const T *end)
|
|
{
|
|
append(begin, end);
|
|
}
|
|
|
|
template<typename T, size_t N>
|
|
//template<size_t N2>
|
|
InPlaceArray<T, N>::InPlaceArray(const T *data, size_t size)
|
|
{
|
|
append(data, data + size);
|
|
}
|
|
|
|
|
|
//template<typename T, size_t N>
|
|
//InPlaceArray<T, N>::InPlaceArray(InPlaceArray<T, N> &&rhs)
|
|
//{
|
|
// append(rhs.begin(), rhs.end());
|
|
//}
|
|
|
|
template<typename T, size_t N>
|
|
//template<size_t N2>
|
|
InPlaceArray<T,N> &InPlaceArray<T, N>::operator =(const InPlaceArray<T, N> &rhs)
|
|
{
|
|
if (this == &rhs)
|
|
return *this;
|
|
|
|
clear();
|
|
append(rhs.begin(), rhs.end());
|
|
|
|
return *this;
|
|
}
|
|
|
|
template<typename T, size_t N>
|
|
//template<size_t N2>
|
|
InPlaceArray<T,N> &InPlaceArray<T, N>::operator =(const Array &rhs)
|
|
{
|
|
if (&v.array != &rhs)
|
|
v.array = rhs;
|
|
|
|
length = N;
|
|
|
|
return *this;
|
|
}
|
|
|
|
template<typename T, size_t N>
|
|
InPlaceArray<T, N>::InPlaceArray(const std::initializer_list<T> &rhs)
|
|
{
|
|
for (auto &element: rhs)
|
|
push_back(element);
|
|
}
|
|
|
|
template<typename T, size_t N>
|
|
void InPlaceArray<T, N>::append_block(const T *begin_, const T *end_)
|
|
{
|
|
auto size = (end_ - begin_);
|
|
|
|
handle_assert(length + size <= N) {
|
|
throw exceptions::OutOfBounds();
|
|
}
|
|
|
|
mem_copy((char *)end(), (char *)begin_, size * sizeof(T));
|
|
length += size;
|
|
}
|
|
|
|
template<typename T, size_t N>
|
|
void InPlaceArray<T, N>::append_items(const T *begin_, const T *end_)
|
|
{
|
|
for (auto i = begin_; i!=end_; ++i)
|
|
push_back(*i);
|
|
}
|
|
|
|
template<typename T, size_t N>
|
|
void InPlaceArray<T, N>::emplace_items(T *begin_, T *end_)
|
|
{
|
|
for (auto i = begin_; i!=end_; ++i)
|
|
emplace_back(std::move(*i));
|
|
}
|
|
|
|
template<typename T, size_t N>
|
|
void InPlaceArray<T, N>::append(const T *begin, const T *end)
|
|
{
|
|
if constexpr (std::is_trivially_copyable<T>::value)
|
|
return append_block(begin, end);
|
|
else
|
|
return append_items(begin, end);
|
|
}
|
|
|
|
template<typename T, size_t N>
|
|
void InPlaceArray<T, N>::emplace(T *begin, T *end)
|
|
{
|
|
if constexpr (std::is_trivially_copyable<T>::value)
|
|
return append_block(begin, end);
|
|
else
|
|
return emplace_items(begin, end);
|
|
}
|
|
|
|
template<typename T, size_t N>
|
|
InPlaceArray<T, N>::~InPlaceArray ()
|
|
{
|
|
clear();
|
|
}
|
|
|
|
template<typename T, size_t N>
|
|
void InPlaceArray<T, N>::shorten_items(size_t length_)
|
|
{
|
|
while (length > length_)
|
|
pop_back();
|
|
}
|
|
|
|
template<typename T, size_t N>
|
|
void InPlaceArray<T, N>::shorten_block(size_t length_)
|
|
{
|
|
if (length > length_)
|
|
length = (Size)length_;
|
|
}
|
|
|
|
template<typename T, size_t N>
|
|
void InPlaceArray<T, N>::shorten(size_t length_)
|
|
{
|
|
if constexpr (std::is_trivially_destructible<T>::value)
|
|
return shorten_block(length_);
|
|
else
|
|
return shorten_items(length_);
|
|
}
|
|
|
|
template<typename T, size_t N>
|
|
void InPlaceArray<T, N>::resize(size_t length_, T t)
|
|
{
|
|
shorten(length_);
|
|
|
|
handle_assert(length_ <= N) {
|
|
throw exceptions::OutOfBounds();
|
|
}
|
|
|
|
if constexpr (std::is_trivially_copyable<T>::value)
|
|
{
|
|
if (length < length_)
|
|
{
|
|
auto *data_ = data();
|
|
auto *begin = data_ + length;
|
|
auto *end = data_ + length_;
|
|
|
|
std::fill(begin, end, t);
|
|
length = (Size)length_;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
while (length < length_)
|
|
push_back(t);
|
|
}
|
|
}
|
|
|
|
template<typename T, size_t N>
|
|
void InPlaceArray<T, N>::push_back (const T &element)
|
|
{
|
|
handle_assert(length < N) {
|
|
throw exceptions::OutOfBounds();
|
|
}
|
|
|
|
++length;
|
|
|
|
if constexpr (std::is_trivially_copyable<T>::value)
|
|
{
|
|
back() = element;
|
|
}
|
|
else
|
|
{
|
|
construct(&back(), element);
|
|
}
|
|
}
|
|
|
|
template<typename T, size_t N>
|
|
void InPlaceArray<T, N>::push_back (T &&element)
|
|
{
|
|
handle_assert(length < N) {
|
|
throw exceptions::OutOfBounds();
|
|
}
|
|
|
|
++length;
|
|
construct(&back(), std::move(element));
|
|
}
|
|
|
|
template<typename T, size_t N>
|
|
void InPlaceArray<T, N>::pop_back ()
|
|
{
|
|
debug_assert (length > 0);
|
|
|
|
// decrease length
|
|
if (length > 0)
|
|
{
|
|
--length;
|
|
destruct(&v.array[length]);
|
|
}
|
|
}
|
|
|
|
template<typename T, size_t N>
|
|
template<typename ... Args>
|
|
T &InPlaceArray<T, N>::emplace_back (Args&& ...element)
|
|
{
|
|
handle_assert(length < N) {
|
|
throw exceptions::OutOfBounds();
|
|
}
|
|
|
|
++length;
|
|
auto &t = back();
|
|
construct(&t, std::forward<Args>(element)...);
|
|
return t;
|
|
}
|
|
|
|
template<typename T, size_t N>
|
|
const T &InPlaceArray<T, N>::at(size_t i) const
|
|
{
|
|
return v.array[i];
|
|
}
|
|
|
|
template<typename T, size_t N>
|
|
T &InPlaceArray<T, N>::at(size_t i)
|
|
{
|
|
return v.array[i];
|
|
}
|
|
|
|
template<typename T, size_t N>
|
|
const T &InPlaceArray<T, N>::operator[] (size_t i) const
|
|
{
|
|
return at(i);
|
|
}
|
|
|
|
template<typename T, size_t N>
|
|
T &InPlaceArray<T, N>::operator[] (size_t i)
|
|
{
|
|
return at(i);
|
|
}
|
|
|
|
template<typename T, size_t N>
|
|
size_t InPlaceArray<T, N>::size () const
|
|
{
|
|
return length;
|
|
}
|
|
|
|
template<typename T, size_t N>
|
|
void InPlaceArray<T, N>::clear ()
|
|
{
|
|
shorten(0);
|
|
}
|
|
|
|
template<typename T, size_t N>
|
|
bool InPlaceArray<T, N>::empty () const
|
|
{
|
|
return length == 0;
|
|
}
|
|
|
|
template<typename T, size_t N>
|
|
bool operator <(const InPlaceArray<T, N> &lhs, const InPlaceArray<T, N> &rhs)
|
|
{
|
|
auto max = std::min(lhs.size(), rhs.size());
|
|
|
|
for (auto i=0; i<max; ++i)
|
|
{
|
|
auto &l = lhs.at(i);
|
|
auto &r = rhs.at(i);
|
|
|
|
if (l != r)
|
|
return l < r;
|
|
}
|
|
|
|
return lhs.size() < rhs.size();
|
|
}
|
|
|
|
template<typename T, size_t N>
|
|
bool operator ==(const InPlaceArray<T, N> &lhs, const InPlaceArray<T, N> &rhs)
|
|
{
|
|
if (lhs.size() != rhs.size())
|
|
return false;
|
|
|
|
for (auto i=0; i<lhs.size(); ++i)
|
|
{
|
|
auto &l = lhs.at(i);
|
|
auto &r = rhs.at(i);
|
|
|
|
if (l != r)
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
template<typename T, size_t N>
|
|
bool operator !=(const InPlaceArray<T, N> &lhs, const InPlaceArray<T, N> &rhs)
|
|
{
|
|
return !(lhs == rhs);
|
|
}
|
|
|
|
} // namespace utilities
|
|
} // namespace
|
|
|