/*** Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. File: auArray.hpp Date: 2022-2-1 Author: Reece ***/ #pragma once #if defined(_AURORA_AVOID_EXTREMLY_DUMB_STL_TYPES) && !defined(_AURORA_FORCE_STD_ARRAY) // following the conventions set out in other out of ecosystem macro-test cases for identifying aurora types in portable header libraries #define AU_AuArray AuArray template struct AuArray { T elements[Count] {}; static const AuUInt kElementCount = Count; using value_type = T; using size_type = AuUInt; using difference_type = AuSInt; using pointer = value_type *; using const_pointer = const value_type *; using reference = value_type &; using const_reference = const value_type &; using iterator = pointer; using const_iterator = const_pointer; using reverse_iterator = AuReverseIterator; using const_reverse_iterator = AuReverseIterator; void fill(const T &value) { if constexpr (AuIsSame_v || AuIsSame_v) { AuMemset(this->elements, value, sizeof(this->elements)); } else { for (AU_ITERATE_N(i, kElementCount)) { this->elements[i] = value; } } } void Fill(const T &value) { this->fill(value); } void swap(AuArray &other) { AuArray temp; if constexpr (AuIsTriviallyCopyable_v) { AuMemcpy(temp.elements, this->elements, sizeof(this->elements)); AuMemcpy(this->elements, other.elements, sizeof(this->elements)); AuMemcpy(other.elements, temp.elements, sizeof(this->elements)); } else { AuArray temp; for (AU_ITERATE_N(i, kElementCount)) { temp[i] = AuMove(this->elements[i]); } for (AU_ITERATE_N(i, kElementCount)) { this->elements[i] = AuMove(other.elements[i]); } for (AU_ITERATE_N(i, kElementCount)) { other.elements[i] = AuMove(temp[i]); } } } void Swap(AuArray &other) { this->swap(other); } constexpr iterator begin() { return this->elements; } constexpr const_iterator begin() const { return this->elements; } constexpr iterator Begin() { return this->elements; } constexpr const_iterator Begin() const { return this->elements; } constexpr iterator end() { return this->elements + kElementCount; } constexpr const_iterator end() const { return this->elements + kElementCount; } constexpr iterator End() { return this->elements + kElementCount; } constexpr const_iterator End() const { return this->elements + kElementCount; } constexpr const_iterator cbegin() const { return begin(); } constexpr const_iterator cend() const { return end(); } constexpr const_iterator CBegin() const { return begin(); } constexpr const_iterator CEnd() const { return end(); } constexpr const_reverse_iterator rbegin() const { return reverse_iterator(end()); } constexpr reverse_iterator RBegin() { return reverse_iterator(end()); } constexpr const_reverse_iterator RBegin() const { return const_reverse_iterator(end()); } constexpr reverse_iterator rend() { return reverse_iterator(begin()); } constexpr const_reverse_iterator rend() const { return reverse_iterator(begin()); } constexpr reverse_iterator REnd() { return const_reverse_iterator(begin()); } constexpr const_reverse_iterator REnd() const { return const_reverse_iterator(begin()); } constexpr const_reverse_iterator crbegin() const { return const_reverse_iterator(end()); } constexpr const_reverse_iterator crend() const { return const_reverse_iterator(begin()); } constexpr const_reverse_iterator CRBegin() const { return const_reverse_iterator(end()); } constexpr const_reverse_iterator CREnd() const { return const_reverse_iterator(begin()); } constexpr size_type size() const { return kElementCount; } constexpr size_type Size() const { return kElementCount; } constexpr size_type max_size() const { return kElementCount; } constexpr size_type MaxSize() const { return kElementCount; } constexpr bool empty() const { return false; } constexpr bool Empty() const { return false; } reference at(size_type pos) { #if defined(AU_CFG_ID_DEBUG) if (pos >= kElementCount) { AuMemoryPanic("out of bounds access"); } #endif return this->elements[pos]; } constexpr const_reference at(size_type pos) const { #if defined(AU_CFG_ID_DEBUG) if (pos >= kElementCount) { AuMemoryPanic("out of bounds access"); } #endif return this->elements[pos]; } reference At(size_type pos) { #if defined(AU_CFG_ID_DEBUG) if (pos >= kElementCount) { AuMemoryPanic("out of bounds access"); } #endif return this->elements[pos]; } constexpr const_reference At(size_type pos) const { #if defined(AU_CFG_ID_DEBUG) if (pos >= kElementCount) { AuMemoryPanic("out of bounds access"); } #endif return this->elements[pos]; } reference operator[](size_type pos) { #if defined(AU_CFG_ID_DEBUG) if (pos >= kElementCount) { AuMemoryPanic("out of bounds access"); } #endif return this->elements[pos]; } constexpr const_reference operator[](size_type pos) const { #if defined(AU_CFG_ID_DEBUG) if (pos >= Count) { AuMemoryPanic("out of bounds access"); } #endif return this->elements[pos]; } constexpr reference front() { return this->elements[0]; } constexpr const_reference front() const { return this->elements[0]; } constexpr reference back() { return this->elements[Count - 1]; } constexpr const_reference back() const { return this->elements[Count - 1]; } constexpr reference Front() { return this->elements[0]; } constexpr const_reference Front() const { return this->elements[0]; } constexpr reference Back() { return this->elements[Count - 1]; } constexpr const_reference Back() const { return this->elements[Count - 1]; } constexpr T *data() { return this->elements; } constexpr const T *data() const { return this->elements; } constexpr T *Data() { return this->elements; } constexpr const T *Data() const { return this->elements; } // oh look, its that feature in that nearly 30 year old programming language intended to replace xerox alto's OOP language for the internet era. AuUInt HashCode() const { AuUInt uRet {}; if constexpr (AuIsTriviallyCopyable_v) { return AuFnv1aRuntime(this->elements, sizeof(this->elements)); } else { for (AU_ITERATE_N(i, kElementCount)) { uRet ^= AuHashCode(this->elements[i]); } } return uRet; } }; template bool operator==(const AuArray &lhs, const AuArray &rhs) { for (AU_ITERATE_N(i, N)) { if (lhs[i] != rhs[i]) { return false; } } return true; } template bool operator!=(const AuArray &lhs, const AuArray &rhs) { for (AU_ITERATE_N(i, N)) { if (lhs[i] != rhs[i]) { return true; } } return false; } #else #if !defined(AURORA_RUNTIME_AU_ARRAY) #define AURORA_RUNTIME_AU_ARRAY std::array #endif template using AuArray = AURORA_RUNTIME_AU_ARRAY; #endif