Serenity Operating System
at master 138 lines 4.0 kB view raw
1/* 2 * Copyright (c) 2020, the SerenityOS developers. 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#pragma once 8 9#include <AK/Iterator.h> 10#include <AK/Span.h> 11#include <AK/StdLibExtras.h> 12#include <AK/TypedTransfer.h> 13 14namespace AK { 15 16template<typename T, size_t Size> 17struct Array { 18 using ValueType = T; 19 20 // This is a static function because constructors mess up Array's POD-ness. 21 static Array from_span(Span<T> span) 22 { 23 Array array; 24 VERIFY(span.size() == Size); 25 TypedTransfer<T>::copy(array.data(), span.data(), Size); 26 return array; 27 } 28 29 [[nodiscard]] constexpr T const* data() const { return __data; } 30 [[nodiscard]] constexpr T* data() { return __data; } 31 32 [[nodiscard]] constexpr size_t size() const { return Size; } 33 34 [[nodiscard]] constexpr ReadonlySpan<T> span() const { return { __data, Size }; } 35 [[nodiscard]] constexpr Span<T> span() { return { __data, Size }; } 36 37 [[nodiscard]] constexpr T const& at(size_t index) const 38 { 39 VERIFY(index < size()); 40 return __data[index]; 41 } 42 [[nodiscard]] constexpr T& at(size_t index) 43 { 44 VERIFY(index < size()); 45 return __data[index]; 46 } 47 48 [[nodiscard]] constexpr T const& first() const { return at(0); } 49 [[nodiscard]] constexpr T& first() { return at(0); } 50 51 [[nodiscard]] constexpr T const& last() const 52 requires(Size > 0) 53 { 54 return at(Size - 1); 55 } 56 [[nodiscard]] constexpr T& last() 57 requires(Size > 0) 58 { 59 return at(Size - 1); 60 } 61 62 [[nodiscard]] constexpr bool is_empty() const { return size() == 0; } 63 64 [[nodiscard]] constexpr T const& operator[](size_t index) const { return at(index); } 65 [[nodiscard]] constexpr T& operator[](size_t index) { return at(index); } 66 67 template<typename T2, size_t Size2> 68 [[nodiscard]] constexpr bool operator==(Array<T2, Size2> const& other) const { return span() == other.span(); } 69 70 using ConstIterator = SimpleIterator<Array const, T const>; 71 using Iterator = SimpleIterator<Array, T>; 72 73 [[nodiscard]] constexpr ConstIterator begin() const { return ConstIterator::begin(*this); } 74 [[nodiscard]] constexpr Iterator begin() { return Iterator::begin(*this); } 75 76 [[nodiscard]] constexpr ConstIterator end() const { return ConstIterator::end(*this); } 77 [[nodiscard]] constexpr Iterator end() { return Iterator::end(*this); } 78 79 [[nodiscard]] constexpr operator ReadonlySpan<T>() const { return span(); } 80 [[nodiscard]] constexpr operator Span<T>() { return span(); } 81 82 constexpr size_t fill(T const& value) 83 { 84 for (size_t idx = 0; idx < Size; ++idx) 85 __data[idx] = value; 86 87 return Size; 88 } 89 90 [[nodiscard]] constexpr T max() const 91 requires(requires(T x, T y) { x < y; }) 92 { 93 static_assert(Size > 0, "No values to max() over"); 94 95 T value = __data[0]; 96 for (size_t i = 1; i < Size; ++i) 97 value = AK::max(__data[i], value); 98 return value; 99 } 100 101 [[nodiscard]] constexpr T min() const 102 requires(requires(T x, T y) { x > y; }) 103 { 104 static_assert(Size > 0, "No values to min() over"); 105 106 T value = __data[0]; 107 for (size_t i = 1; i < Size; ++i) 108 value = AK::min(__data[i], value); 109 return value; 110 } 111 112 T __data[Size]; 113}; 114 115template<typename T, typename... Types> 116Array(T, Types...) -> Array<T, sizeof...(Types) + 1>; 117 118namespace Detail { 119template<typename T, size_t... Is> 120constexpr auto integer_sequence_generate_array([[maybe_unused]] T const offset, IntegerSequence<T, Is...>) -> Array<T, sizeof...(Is)> 121{ 122 return { { (offset + Is)... } }; 123} 124} 125 126template<typename T, T N> 127constexpr static auto iota_array(T const offset = {}) 128{ 129 static_assert(N >= T {}, "Negative sizes not allowed in iota_array()"); 130 return Detail::integer_sequence_generate_array<T>(offset, MakeIntegerSequence<T, N>()); 131} 132 133} 134 135#if USING_AK_GLOBALLY 136using AK::Array; 137using AK::iota_array; 138#endif