From f84431d7043342c2deacde00c33fc8d1128773a8 Mon Sep 17 00:00:00 2001 From: GeorgH93 Date: Thu, 29 Oct 2020 15:26:04 +0100 Subject: [PATCH] Add Array.hpp --- openVulkanoCpp/Data/Containers/Array.hpp | 285 +++++++++++++++++++++++ 1 file changed, 285 insertions(+) create mode 100644 openVulkanoCpp/Data/Containers/Array.hpp diff --git a/openVulkanoCpp/Data/Containers/Array.hpp b/openVulkanoCpp/Data/Containers/Array.hpp new file mode 100644 index 0000000..6864985 --- /dev/null +++ b/openVulkanoCpp/Data/Containers/Array.hpp @@ -0,0 +1,285 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include +#include +#include +#include + +namespace openVulkanoCpp +{ + /** + * Heap allocated array. For all these times you need a fixed size data structure, but don't know the size at compile time. + * @tparam T The type to be used + */ + template + class Array + { + size_t size; + T* data; + + public: + using iterator = T*; + using const_iterator = const T*; + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; + + Array() noexcept: size(0), data(nullptr) + {} + + explicit Array(size_t size) : size(size), data(new T[size]()) + {} + + Array(const std::initializer_list& list) : size(list.size()), data(static_cast(::operator new(sizeof(T) * list.Size()))) + { + std::copy(list.begin(), list.end(), Begin()); + } + + Array(const Array& other) : size(other.Size()), data(static_cast(::operator new(sizeof(T) * other.Size()))) + { + std::copy(other.begin(), other.end(), Begin()); + } + + Array(Array&& other) noexcept: + size(other.size()), data(other.data()) + { + other.data = nullptr; + other.size = 0; + } + + explicit Array(const std::vector& vector) : size(vector.size()), data(static_cast(::operator new(sizeof(T) * size))) + { + std::copy(vector.begin(), vector.end(), Begin()); + } + + Array(size_t size, const T& defaultValue) : size(size), data(static_cast(::operator new(sizeof(T) * size))) + { + Fill(defaultValue); + } + + ~Array() noexcept + { + delete[] data; + } + + Array& operator=(const Array& rhs) + { + if (this == &rhs) return *this; + Resize(rhs.size()); + std::copy(rhs.begin(), rhs.end(), Begin()); + return *this; + } + + Array& operator=(const std::initializer_list& list) + { + Resize(list.size()); + std::copy(list.begin(), list.end(), Begin()); + return *this; + } + + Array& operator=(Array&& rhs) noexcept + { + if (this != &rhs) + { + Array(std::move(rhs)).Swap(*this); + } + return *this; + } + + T& operator[](size_t n) noexcept + { + return data[n]; + } + + const T& operator[](size_t n) const noexcept + { + return data[n]; + } + + operator bool() const noexcept + { + return data; + } + + iterator Begin() noexcept + { + return data; + } + + const_iterator Begin() const noexcept + { + return data; + } + + iterator End() noexcept + { + return Begin() + Size(); + } + + const_iterator End() const noexcept + { + return Begin() + Size(); + } + + reverse_iterator ReverseBegin() noexcept + { + return reverse_iterator(End()); + } + + const_reverse_iterator ReverseBegin() const noexcept + { + return const_reverse_iterator(End()); + } + + reverse_iterator ReverseEnd() noexcept + { + return reverse_iterator(Begin()); + } + + const_reverse_iterator ReverseEnd() const noexcept + { + return const_reverse_iterator(Begin()); + } + + const_iterator ConstBegin() const noexcept + { + return Begin(); + } + + const_iterator ConstEnd() const noexcept + { + return End(); + } + + const_reverse_iterator ConstReverseBegin() const noexcept + { + return ReverseBegin(); + } + + const_reverse_iterator ConstReverseEnd() const noexcept + { + return ReverseEnd(); + } + + [[nodiscard]] size_t Size() const noexcept + { + return size; + } + + [[nodiscard]] size_t MaxSize() const noexcept + { + return size; + } + + [[nodiscard]] bool Empty() const noexcept + { + return Size() == 0; + } + + T& At(size_t n) + { + if (n >= Size()) throw std::out_of_range("Index " + std::to_string(n) + " is out of bounds."); + return data[n]; + } + + const T& At(size_t n) const + { + return const_cast(this)->at(n); + } + + T& Front() noexcept + { + return *Begin(); + } + + const T& Front() const noexcept + { + return *ConstBegin(); + } + + T& Back() noexcept + { + return *(End() - 1); + } + + const T& Back() const noexcept + { + return *(ConstEnd() - 1); + } + + T* Data() noexcept + { + return data; + } + + const T* Data() const noexcept + { + return data; + } + + void Fill(const T& value) noexcept(noexcept(std::fill(Begin(), End(), value))) + { + std::fill(Begin(), End(), value); + } + + void Swap(Array& other) noexcept + { + std::swap(data, other.data); + std::swap(size, other.size); + } + + private: + void Resize(size_t newSize) + { + if (Size() != newSize) + { + size = 0; + delete[] data; + data = nullptr; + data = new T[newSize]; + size = newSize; + } + } + }; + + template + inline bool operator==(const Array& lhs, const Array& rhs) + { + return lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin()); + } + + template + inline bool operator!=(const Array& lhs, const Array& rhs) + { + return !(lhs == rhs); + } + + template + inline bool operator<(const Array& lhs, const Array& rhs) + { + return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end()); + } + + template + inline bool operator>(const Array& lhs, const Array& rhs) + { + return rhs < lhs; + } + + template + inline bool operator>=(const Array& lhs, const Array& rhs) + { + return !(lhs < rhs); + } + + template + inline bool operator<=(const Array& lhs, const Array& rhs) + { + return !(rhs < lhs); + } +} \ No newline at end of file