1*c8dee2aaSAndroid Build Coastguard Worker /* 2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2024 Google LLC 3*c8dee2aaSAndroid Build Coastguard Worker * 4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be 5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file. 6*c8dee2aaSAndroid Build Coastguard Worker */ 7*c8dee2aaSAndroid Build Coastguard Worker 8*c8dee2aaSAndroid Build Coastguard Worker #ifndef SkTFixedArray_DEFINED 9*c8dee2aaSAndroid Build Coastguard Worker #define SkTFixedArray_DEFINED 10*c8dee2aaSAndroid Build Coastguard Worker 11*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkAssert.h" 12*c8dee2aaSAndroid Build Coastguard Worker 13*c8dee2aaSAndroid Build Coastguard Worker #include <cstdint> 14*c8dee2aaSAndroid Build Coastguard Worker #include <cstring> 15*c8dee2aaSAndroid Build Coastguard Worker #include <initializer_list> 16*c8dee2aaSAndroid Build Coastguard Worker #include <type_traits> // IWYU pragma: keep for std::is_trivial_v 17*c8dee2aaSAndroid Build Coastguard Worker 18*c8dee2aaSAndroid Build Coastguard Worker namespace skia_private { 19*c8dee2aaSAndroid Build Coastguard Worker 20*c8dee2aaSAndroid Build Coastguard Worker /** 21*c8dee2aaSAndroid Build Coastguard Worker * Represents an array of `T` (must be a trivial type) that cannot grow past a fixed size `N`. 22*c8dee2aaSAndroid Build Coastguard Worker * The fixed-size restriction allows for tighter codegen and a smaller memory footprint. 23*c8dee2aaSAndroid Build Coastguard Worker * Missing methods from TArray (e.g. `fromBack`) can be added on demand. 24*c8dee2aaSAndroid Build Coastguard Worker * 25*c8dee2aaSAndroid Build Coastguard Worker * The trivial-type restriction is only to simplify implementation; if there is a need, we can 26*c8dee2aaSAndroid Build Coastguard Worker * adopt proper move/copy semantics in this class as well. 27*c8dee2aaSAndroid Build Coastguard Worker */ 28*c8dee2aaSAndroid Build Coastguard Worker template <int N, typename T> 29*c8dee2aaSAndroid Build Coastguard Worker class FixedArray { 30*c8dee2aaSAndroid Build Coastguard Worker public: 31*c8dee2aaSAndroid Build Coastguard Worker using value_type = T; 32*c8dee2aaSAndroid Build Coastguard Worker 33*c8dee2aaSAndroid Build Coastguard Worker FixedArray() = default; 34*c8dee2aaSAndroid Build Coastguard Worker FixedArray(std::initializer_list<T> values)35*c8dee2aaSAndroid Build Coastguard Worker FixedArray(std::initializer_list<T> values) { 36*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(values.size() <= N); 37*c8dee2aaSAndroid Build Coastguard Worker for (T value : values) { 38*c8dee2aaSAndroid Build Coastguard Worker fData[fSize++] = value; 39*c8dee2aaSAndroid Build Coastguard Worker } 40*c8dee2aaSAndroid Build Coastguard Worker } 41*c8dee2aaSAndroid Build Coastguard Worker FixedArray(int reserveCount)42*c8dee2aaSAndroid Build Coastguard Worker FixedArray(int reserveCount) { 43*c8dee2aaSAndroid Build Coastguard Worker // This is here to satisfy the TArray interface. Setting a reserve count on a fixed array 44*c8dee2aaSAndroid Build Coastguard Worker // isn't useful. 45*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(reserveCount >= 0); 46*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(reserveCount <= N); 47*c8dee2aaSAndroid Build Coastguard Worker } 48*c8dee2aaSAndroid Build Coastguard Worker FixedArray(const T * array,int count)49*c8dee2aaSAndroid Build Coastguard Worker FixedArray(const T* array, int count) { 50*c8dee2aaSAndroid Build Coastguard Worker this->reset(array, count); 51*c8dee2aaSAndroid Build Coastguard Worker } 52*c8dee2aaSAndroid Build Coastguard Worker FixedArray(const FixedArray<N,T> & that)53*c8dee2aaSAndroid Build Coastguard Worker FixedArray(const FixedArray<N, T>& that) { 54*c8dee2aaSAndroid Build Coastguard Worker this->reset(that.data(), that.size()); 55*c8dee2aaSAndroid Build Coastguard Worker } 56*c8dee2aaSAndroid Build Coastguard Worker 57*c8dee2aaSAndroid Build Coastguard Worker FixedArray<N, T>& operator=(const FixedArray<N, T>& that) { 58*c8dee2aaSAndroid Build Coastguard Worker if (this != &that) { 59*c8dee2aaSAndroid Build Coastguard Worker this->reset(that.data(), that.size()); 60*c8dee2aaSAndroid Build Coastguard Worker } 61*c8dee2aaSAndroid Build Coastguard Worker return *this; 62*c8dee2aaSAndroid Build Coastguard Worker } 63*c8dee2aaSAndroid Build Coastguard Worker 64*c8dee2aaSAndroid Build Coastguard Worker T& operator[](size_t index) { 65*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(index < fSize); 66*c8dee2aaSAndroid Build Coastguard Worker return fData[index]; 67*c8dee2aaSAndroid Build Coastguard Worker } 68*c8dee2aaSAndroid Build Coastguard Worker 69*c8dee2aaSAndroid Build Coastguard Worker const T& operator[](size_t index) const { 70*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(index < fSize); 71*c8dee2aaSAndroid Build Coastguard Worker return fData[index]; 72*c8dee2aaSAndroid Build Coastguard Worker } 73*c8dee2aaSAndroid Build Coastguard Worker 74*c8dee2aaSAndroid Build Coastguard Worker bool operator==(const FixedArray<N, T>& that) const { 75*c8dee2aaSAndroid Build Coastguard Worker return fSize == that.fSize && (0 == memcmp(fData, that.fData, fSize * sizeof(T))); 76*c8dee2aaSAndroid Build Coastguard Worker } 77*c8dee2aaSAndroid Build Coastguard Worker 78*c8dee2aaSAndroid Build Coastguard Worker bool operator!=(const FixedArray<N, T>& that) const { 79*c8dee2aaSAndroid Build Coastguard Worker return !this->operator==(that); 80*c8dee2aaSAndroid Build Coastguard Worker } 81*c8dee2aaSAndroid Build Coastguard Worker size()82*c8dee2aaSAndroid Build Coastguard Worker int size() const { 83*c8dee2aaSAndroid Build Coastguard Worker return fSize; 84*c8dee2aaSAndroid Build Coastguard Worker } 85*c8dee2aaSAndroid Build Coastguard Worker empty()86*c8dee2aaSAndroid Build Coastguard Worker bool empty() const { 87*c8dee2aaSAndroid Build Coastguard Worker return fSize == 0; 88*c8dee2aaSAndroid Build Coastguard Worker } 89*c8dee2aaSAndroid Build Coastguard Worker clear()90*c8dee2aaSAndroid Build Coastguard Worker void clear() { 91*c8dee2aaSAndroid Build Coastguard Worker fSize = 0; 92*c8dee2aaSAndroid Build Coastguard Worker } 93*c8dee2aaSAndroid Build Coastguard Worker reset(const T * array,int count)94*c8dee2aaSAndroid Build Coastguard Worker void reset(const T* array, int count) { 95*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(count >= 0); 96*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(count <= N); 97*c8dee2aaSAndroid Build Coastguard Worker fSize = count; 98*c8dee2aaSAndroid Build Coastguard Worker std::memcpy(fData, array, count * sizeof(T)); 99*c8dee2aaSAndroid Build Coastguard Worker } 100*c8dee2aaSAndroid Build Coastguard Worker resize(int newSize)101*c8dee2aaSAndroid Build Coastguard Worker void resize(int newSize) { 102*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(newSize >= 0); 103*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(newSize <= N); 104*c8dee2aaSAndroid Build Coastguard Worker 105*c8dee2aaSAndroid Build Coastguard Worker if (fSize > newSize) { 106*c8dee2aaSAndroid Build Coastguard Worker fSize = newSize; 107*c8dee2aaSAndroid Build Coastguard Worker } else { 108*c8dee2aaSAndroid Build Coastguard Worker while (fSize < newSize) { 109*c8dee2aaSAndroid Build Coastguard Worker fData[fSize++] = T(); 110*c8dee2aaSAndroid Build Coastguard Worker } 111*c8dee2aaSAndroid Build Coastguard Worker } 112*c8dee2aaSAndroid Build Coastguard Worker } 113*c8dee2aaSAndroid Build Coastguard Worker push_back()114*c8dee2aaSAndroid Build Coastguard Worker T& push_back() { 115*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(fSize < N); 116*c8dee2aaSAndroid Build Coastguard Worker T& ref = fData[fSize++]; 117*c8dee2aaSAndroid Build Coastguard Worker ref = T(); 118*c8dee2aaSAndroid Build Coastguard Worker return ref; 119*c8dee2aaSAndroid Build Coastguard Worker } 120*c8dee2aaSAndroid Build Coastguard Worker push_back(T x)121*c8dee2aaSAndroid Build Coastguard Worker void push_back(T x) { 122*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(fSize < N); 123*c8dee2aaSAndroid Build Coastguard Worker fData[fSize++] = x; 124*c8dee2aaSAndroid Build Coastguard Worker } 125*c8dee2aaSAndroid Build Coastguard Worker push_back_n(int n)126*c8dee2aaSAndroid Build Coastguard Worker T* push_back_n(int n) { 127*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(n >= 0); 128*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(fSize + n <= N); 129*c8dee2aaSAndroid Build Coastguard Worker T* ptr = fData + fSize; 130*c8dee2aaSAndroid Build Coastguard Worker for (int index = 0; index < n; ++index) { 131*c8dee2aaSAndroid Build Coastguard Worker ptr[index] = T(); 132*c8dee2aaSAndroid Build Coastguard Worker } 133*c8dee2aaSAndroid Build Coastguard Worker fSize += n; 134*c8dee2aaSAndroid Build Coastguard Worker return ptr; 135*c8dee2aaSAndroid Build Coastguard Worker } 136*c8dee2aaSAndroid Build Coastguard Worker push_back_n(int n,const T & t)137*c8dee2aaSAndroid Build Coastguard Worker T* push_back_n(int n, const T& t) { 138*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(n >= 0); 139*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(fSize + n <= N); 140*c8dee2aaSAndroid Build Coastguard Worker T* ptr = fData + fSize; 141*c8dee2aaSAndroid Build Coastguard Worker for (int index = 0; index < n; ++index) { 142*c8dee2aaSAndroid Build Coastguard Worker ptr[index] = t; 143*c8dee2aaSAndroid Build Coastguard Worker } 144*c8dee2aaSAndroid Build Coastguard Worker fSize += n; 145*c8dee2aaSAndroid Build Coastguard Worker return ptr; 146*c8dee2aaSAndroid Build Coastguard Worker } 147*c8dee2aaSAndroid Build Coastguard Worker pop_back()148*c8dee2aaSAndroid Build Coastguard Worker void pop_back() { 149*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(fSize >= 1); 150*c8dee2aaSAndroid Build Coastguard Worker --fSize; 151*c8dee2aaSAndroid Build Coastguard Worker } 152*c8dee2aaSAndroid Build Coastguard Worker pop_back_n(int n)153*c8dee2aaSAndroid Build Coastguard Worker void pop_back_n(int n) { 154*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(fSize >= n); 155*c8dee2aaSAndroid Build Coastguard Worker fSize -= n; 156*c8dee2aaSAndroid Build Coastguard Worker } 157*c8dee2aaSAndroid Build Coastguard Worker removeShuffle(int n)158*c8dee2aaSAndroid Build Coastguard Worker void removeShuffle(int n) { 159*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(n < fSize); 160*c8dee2aaSAndroid Build Coastguard Worker int last = fSize - 1; 161*c8dee2aaSAndroid Build Coastguard Worker if (n != last) { 162*c8dee2aaSAndroid Build Coastguard Worker fData[n] = fData[last]; 163*c8dee2aaSAndroid Build Coastguard Worker } 164*c8dee2aaSAndroid Build Coastguard Worker fSize = last; 165*c8dee2aaSAndroid Build Coastguard Worker } 166*c8dee2aaSAndroid Build Coastguard Worker data()167*c8dee2aaSAndroid Build Coastguard Worker T* data() { 168*c8dee2aaSAndroid Build Coastguard Worker return fData; 169*c8dee2aaSAndroid Build Coastguard Worker } 170*c8dee2aaSAndroid Build Coastguard Worker data()171*c8dee2aaSAndroid Build Coastguard Worker const T* data() const { 172*c8dee2aaSAndroid Build Coastguard Worker return fData; 173*c8dee2aaSAndroid Build Coastguard Worker } 174*c8dee2aaSAndroid Build Coastguard Worker begin()175*c8dee2aaSAndroid Build Coastguard Worker T* begin() { 176*c8dee2aaSAndroid Build Coastguard Worker return fData; 177*c8dee2aaSAndroid Build Coastguard Worker } 178*c8dee2aaSAndroid Build Coastguard Worker begin()179*c8dee2aaSAndroid Build Coastguard Worker const T* begin() const { 180*c8dee2aaSAndroid Build Coastguard Worker return fData; 181*c8dee2aaSAndroid Build Coastguard Worker } 182*c8dee2aaSAndroid Build Coastguard Worker end()183*c8dee2aaSAndroid Build Coastguard Worker T* end() { 184*c8dee2aaSAndroid Build Coastguard Worker return fData + fSize; 185*c8dee2aaSAndroid Build Coastguard Worker } 186*c8dee2aaSAndroid Build Coastguard Worker end()187*c8dee2aaSAndroid Build Coastguard Worker const T* end() const { 188*c8dee2aaSAndroid Build Coastguard Worker return fData + fSize; 189*c8dee2aaSAndroid Build Coastguard Worker } 190*c8dee2aaSAndroid Build Coastguard Worker front()191*c8dee2aaSAndroid Build Coastguard Worker T& front() { 192*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(fSize > 0); 193*c8dee2aaSAndroid Build Coastguard Worker return fData[0]; 194*c8dee2aaSAndroid Build Coastguard Worker } 195*c8dee2aaSAndroid Build Coastguard Worker front()196*c8dee2aaSAndroid Build Coastguard Worker const T& front() const { 197*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(fSize > 0); 198*c8dee2aaSAndroid Build Coastguard Worker return fData[0]; 199*c8dee2aaSAndroid Build Coastguard Worker } 200*c8dee2aaSAndroid Build Coastguard Worker back()201*c8dee2aaSAndroid Build Coastguard Worker T& back() { 202*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(fSize > 0); 203*c8dee2aaSAndroid Build Coastguard Worker return fData[fSize - 1]; 204*c8dee2aaSAndroid Build Coastguard Worker } 205*c8dee2aaSAndroid Build Coastguard Worker back()206*c8dee2aaSAndroid Build Coastguard Worker const T& back() const { 207*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(fSize > 0); 208*c8dee2aaSAndroid Build Coastguard Worker return fData[fSize - 1]; 209*c8dee2aaSAndroid Build Coastguard Worker } 210*c8dee2aaSAndroid Build Coastguard Worker reserve(int size)211*c8dee2aaSAndroid Build Coastguard Worker void reserve(int size) { 212*c8dee2aaSAndroid Build Coastguard Worker // This is here to satisfy the TArray interface. 213*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(size >= 0); 214*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(size <= N); 215*c8dee2aaSAndroid Build Coastguard Worker } 216*c8dee2aaSAndroid Build Coastguard Worker capacity()217*c8dee2aaSAndroid Build Coastguard Worker constexpr int capacity() const { 218*c8dee2aaSAndroid Build Coastguard Worker return N; 219*c8dee2aaSAndroid Build Coastguard Worker } 220*c8dee2aaSAndroid Build Coastguard Worker 221*c8dee2aaSAndroid Build Coastguard Worker private: 222*c8dee2aaSAndroid Build Coastguard Worker static_assert(std::is_trivial_v<T>); 223*c8dee2aaSAndroid Build Coastguard Worker static_assert(N > 0); 224*c8dee2aaSAndroid Build Coastguard Worker static_assert(N < 256); // limited by `uint8_t fSize` 225*c8dee2aaSAndroid Build Coastguard Worker 226*c8dee2aaSAndroid Build Coastguard Worker T fData[N]; 227*c8dee2aaSAndroid Build Coastguard Worker uint8_t fSize = 0; 228*c8dee2aaSAndroid Build Coastguard Worker }; 229*c8dee2aaSAndroid Build Coastguard Worker 230*c8dee2aaSAndroid Build Coastguard Worker } // namespace skia_private 231*c8dee2aaSAndroid Build Coastguard Worker 232*c8dee2aaSAndroid Build Coastguard Worker #endif 233