Adjusted workflow.
This commit is contained in:
435
include/ehs/Array.h
Normal file
435
include/ehs/Array.h
Normal file
@@ -0,0 +1,435 @@
|
||||
#pragma once
|
||||
|
||||
#include "Types.h"
|
||||
#include "BaseObj.h"
|
||||
|
||||
#include <initializer_list>
|
||||
#include <algorithm>
|
||||
|
||||
namespace ehs
|
||||
{
|
||||
/// A helper class for C-style arrays.
|
||||
/// @tparam T Array data type to use.
|
||||
/// @tparam N Number data type to use.
|
||||
template<typename T, typename N = UInt_64>
|
||||
class Array : public BaseObj
|
||||
{
|
||||
protected:
|
||||
T* data;
|
||||
N size;
|
||||
|
||||
public:
|
||||
/// Frees any data created on the heap.
|
||||
~Array() override
|
||||
{
|
||||
delete[] data;
|
||||
}
|
||||
|
||||
/// Default members initialization.
|
||||
Array()
|
||||
: data(nullptr), size(0)
|
||||
{
|
||||
AddType("Array");
|
||||
}
|
||||
|
||||
/// Initializes an empty array with the given size.
|
||||
/// @note Data must be assigned manually using an index.
|
||||
explicit Array(const N size)
|
||||
: data(new T[size]), size(size)
|
||||
{
|
||||
AddType("Array");
|
||||
}
|
||||
|
||||
/// Initializes this array with an initializer list object.
|
||||
/// @param [in] list The given initializer list.
|
||||
Array(std::initializer_list<T> list)
|
||||
: data(new T[list.size()]), size(list.size())
|
||||
{
|
||||
AddType("Array");
|
||||
|
||||
N i = 0;
|
||||
for (auto v = list.begin(); v != list.end(); ++v)
|
||||
data[i++] = std::move(*v);
|
||||
}
|
||||
|
||||
/// Initializes members with given C-style array.
|
||||
/// @param [in] data The C-style array.
|
||||
/// @param [in] size The size of the given C-style array.
|
||||
Array(const T* const data, const N size)
|
||||
: data(new T[size]), size(size)
|
||||
{
|
||||
AddType("Array");
|
||||
|
||||
for (N i = 0; i < size; ++i)
|
||||
this->data[i] = data[i];
|
||||
}
|
||||
|
||||
Array(Array&& array) noexcept
|
||||
: BaseObj(array), data(array.data), size(array.size)
|
||||
{
|
||||
array.data = nullptr;
|
||||
array.size = 0;
|
||||
}
|
||||
|
||||
/// Copies all members from the given array object.
|
||||
/// @param [in] array The array object to copy from.
|
||||
Array(const Array& array)
|
||||
: BaseObj((BaseObj&&)array), data(new T[array.size]), size(array.size)
|
||||
{
|
||||
for (N i = 0; i < size; ++i)
|
||||
data[i] = array.data[i];
|
||||
}
|
||||
|
||||
Array<T, N>& operator=(Array&& array) noexcept
|
||||
{
|
||||
if (this == &array)
|
||||
return *this;
|
||||
|
||||
BaseObj::operator=((BaseObj&&)array);
|
||||
|
||||
delete[] data;
|
||||
data = array.data;
|
||||
size = array.size;
|
||||
|
||||
array.data = nullptr;
|
||||
array.size = 0;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Copies all members from the given array object.
|
||||
/// @param [in] array The array object to copy from.
|
||||
/// @returns The array that has been assigned to.
|
||||
Array<T, N>& operator=(const Array& array)
|
||||
{
|
||||
if (this == &array)
|
||||
return *this;
|
||||
|
||||
BaseObj::operator=(array);
|
||||
|
||||
delete[] data;
|
||||
data = new T[array.size];
|
||||
for (N i = 0; i < array.size; ++i)
|
||||
data[i] = array.data[i];
|
||||
|
||||
size = array.size;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Copies all members from the given initializer list object.
|
||||
/// @param [in] list The initializer list object to copy from.
|
||||
/// @returns The array that has been assigned to.
|
||||
Array& operator=(std::initializer_list<T> list)
|
||||
{
|
||||
delete[] data;
|
||||
data = new T[list.size];
|
||||
|
||||
N i = 0;
|
||||
for (auto v = list.begin(); v != list.end(); ++v)
|
||||
data[i++] = std::move(*v);
|
||||
|
||||
size = list.size();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Adds a given array object at the end of the array.
|
||||
/// @param [in] value The given array object to push to the end of the array.
|
||||
Array& operator+=(Array value)
|
||||
{
|
||||
T* result = new T[size + value.size];
|
||||
|
||||
for (N i = 0; i < size; ++i)
|
||||
result[i] = std::move(data[i]);
|
||||
|
||||
for (N i = 0; i < value.size; ++i)
|
||||
result[size + i] = std::move(value[i]);
|
||||
|
||||
delete[] data;
|
||||
|
||||
data = result;
|
||||
size += value.size;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const Array& in) const
|
||||
{
|
||||
if (size != in.size)
|
||||
return false;
|
||||
|
||||
return Util::Compare(data, in.data, size);
|
||||
}
|
||||
|
||||
bool operator!=(const Array& in) const
|
||||
{
|
||||
if (size != in.size)
|
||||
return true;
|
||||
|
||||
return !Util::Compare(data, in.data, size);
|
||||
}
|
||||
|
||||
/// Adds a given array object at the end of the array.
|
||||
/// @param [in] value The given initializer list to push to the end of the array.
|
||||
Array& operator+=(std::initializer_list<T> value)
|
||||
{
|
||||
T* result = new T[size + value.size()];
|
||||
|
||||
for (N i = 0; i < size; ++i)
|
||||
result[i] = std::move(data[i]);
|
||||
|
||||
N i = 0;
|
||||
for (auto v = value.begin(); v != value.end(); ++v)
|
||||
result[size + i++] = std::move(*v);
|
||||
|
||||
delete[] data;
|
||||
|
||||
data = result;
|
||||
size += value.size();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Adds a given value at the end of the array.
|
||||
/// @param [in] value The given value to push to the end of the array.
|
||||
Array& operator+=(const T value)
|
||||
{
|
||||
T* result = new T[size + 1];
|
||||
|
||||
for (N i = 0; i < size; ++i)
|
||||
result[i] = std::move(data[i]);
|
||||
|
||||
result[size] = std::move(value);
|
||||
|
||||
delete[] data;
|
||||
|
||||
data = result;
|
||||
++size;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Retrieves the raw C-style array from casting an array object.
|
||||
operator T* () const
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
/// Swaps two values in the array.
|
||||
/// @param a The first index to swap with.
|
||||
/// @param b The second index to swap with.
|
||||
void Swap(N a, N b) const
|
||||
{
|
||||
T tmp = std::move(data[a]);
|
||||
|
||||
data[a] = std::move(data[b]);
|
||||
data[b] = std::move(tmp);
|
||||
}
|
||||
|
||||
/// Inserts a value at the specified index.
|
||||
/// @param [in] index The index to insert the value at.
|
||||
/// @param [in] value The value to add.
|
||||
void Insert(const N index, const T value)
|
||||
{
|
||||
N newSize = 0;
|
||||
if (index > size - 1)
|
||||
newSize = size + ((index + 1) - size);
|
||||
else
|
||||
newSize = size + 1;
|
||||
|
||||
T* result = new T[newSize];
|
||||
|
||||
for (N i = 0; i < index; ++i)
|
||||
result[i] = std::move(data[i]);
|
||||
|
||||
result[index] = std::move(value);
|
||||
|
||||
for (N i = index; i < size; ++i)
|
||||
result[i + 1] = std::move(data[i]);
|
||||
|
||||
delete[] data;
|
||||
data = result;
|
||||
|
||||
size = newSize;
|
||||
}
|
||||
|
||||
/// Removes a value at the specified index.
|
||||
/// @param [in] index The index to remove a value.
|
||||
/// @returns The value that was removed.
|
||||
T Remove(const N index)
|
||||
{
|
||||
T popped = {};
|
||||
|
||||
if (!size || index >= size)
|
||||
return popped;
|
||||
|
||||
popped = std::move(data[index]);
|
||||
|
||||
N newSize = size - 1;
|
||||
T* result = new T[newSize];
|
||||
|
||||
for (N i = 0; i < index; ++i)
|
||||
result[i] = std::move(data[i]);
|
||||
|
||||
for (N i = index + 1; i < size; ++i)
|
||||
result[i - 1] = std::move(data[i]);
|
||||
|
||||
delete[] data;
|
||||
data = result;
|
||||
size = newSize;
|
||||
|
||||
return popped;
|
||||
}
|
||||
|
||||
/// Adds a given C-style array at the end of the array.
|
||||
/// @param [in] value The given C-style array to push to the end of the array.
|
||||
/// @param [in] size The size of the given C-style array.
|
||||
void Push(const T* const value, const N size)
|
||||
{
|
||||
T* result = new T[this->size + size];
|
||||
|
||||
for (N i = 0; i < this->size; ++i)
|
||||
result[i] = std::move(this->data[i]);
|
||||
|
||||
for (N i = 0; i < size; ++i)
|
||||
result[this->size + i] = value[i];
|
||||
|
||||
delete[] data;
|
||||
|
||||
this->data = result;
|
||||
this->size += size;
|
||||
}
|
||||
|
||||
/// Adds a given array object at the end of the array.
|
||||
/// @param [in] value The given array object to push to the end of the array.
|
||||
void Push(Array value)
|
||||
{
|
||||
T* result = new T[size + value.size];
|
||||
|
||||
for (N i = 0; i < size; ++i)
|
||||
result[i] = std::move(data[i]);
|
||||
|
||||
for (N i = 0; i < value.size; ++i)
|
||||
result[size + i] = std::move(value[i]);
|
||||
|
||||
delete[] data;
|
||||
|
||||
data = result;
|
||||
size += value.size;
|
||||
}
|
||||
|
||||
/// Adds a given array object at the end of the array.
|
||||
/// @param [in] value The given initializer list to push to the end of the array.
|
||||
void Push(std::initializer_list<T> value)
|
||||
{
|
||||
T* result = new T[size + value.size()];
|
||||
|
||||
for (N i = 0; i < size; ++i)
|
||||
result[i] = std::move(data[i]);
|
||||
|
||||
N i = 0;
|
||||
for (auto v = value.begin(); v != value.end(); ++v)
|
||||
result[size + i++] = std::move(*v);
|
||||
|
||||
delete[] data;
|
||||
|
||||
data = result;
|
||||
size += value.size();
|
||||
}
|
||||
|
||||
/// Adds a given value at the end of the array.
|
||||
/// @param [in] value The given value to push to the end of the array.
|
||||
void Push(T value)
|
||||
{
|
||||
T* result = new T[size + 1];
|
||||
|
||||
for (N i = 0; i < size; ++i)
|
||||
result[i] = std::move(data[i]);
|
||||
|
||||
result[size] = std::move(value);
|
||||
|
||||
delete[] data;
|
||||
|
||||
data = result;
|
||||
++size;
|
||||
}
|
||||
|
||||
/// Removes a value at the end of the array.
|
||||
/// @returns The value that was popped.
|
||||
T Pop()
|
||||
{
|
||||
T* result = new T[--size];
|
||||
|
||||
T popped = (T&&)data[size];
|
||||
|
||||
for (N i = 0; i < size; ++i)
|
||||
result[i] = (T&&)data[i];
|
||||
|
||||
delete[] data;
|
||||
|
||||
data = result;
|
||||
|
||||
return popped;
|
||||
}
|
||||
|
||||
/// Will swap the value at the given index with the value at the end of the array and pops it.
|
||||
/// @param [in] index The index of the value to swap with.
|
||||
/// @returns The removed value.
|
||||
T Pop(const N index)
|
||||
{
|
||||
if (!size)
|
||||
return {};
|
||||
|
||||
N lastIndex = size - 1;
|
||||
|
||||
if (index < lastIndex)
|
||||
Swap(index, lastIndex);
|
||||
|
||||
return Pop();
|
||||
}
|
||||
|
||||
/// Releases the resources of the array.
|
||||
void Clear()
|
||||
{
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
delete[] data;
|
||||
data = nullptr;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
/// Resizes the array.
|
||||
/// @param [in] newSize The size to change to.
|
||||
void Resize(const N newSize)
|
||||
{
|
||||
if (size == newSize)
|
||||
return;
|
||||
|
||||
T* result = new T[newSize];
|
||||
|
||||
for (N i = 0; i < newSize && i < size; ++i)
|
||||
result[i] = std::move(data[i]);
|
||||
|
||||
delete[] data;
|
||||
|
||||
data = result;
|
||||
size = newSize;
|
||||
}
|
||||
|
||||
/// Retrieves the size of the array.
|
||||
/// @returns The resulting size.
|
||||
N Size() const
|
||||
{
|
||||
return size;
|
||||
}
|
||||
|
||||
/// Retrieves the index at the end of the array.
|
||||
/// @returns The index.
|
||||
N End() const
|
||||
{
|
||||
return size - 1;
|
||||
}
|
||||
};
|
||||
}
|
Reference in New Issue
Block a user