1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2006 The Android Open Source Project
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 SkTDArray_DEFINED
9*c8dee2aaSAndroid Build Coastguard Worker #define SkTDArray_DEFINED
10*c8dee2aaSAndroid Build Coastguard Worker
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkAPI.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkAssert.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkDebug.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTo.h"
15*c8dee2aaSAndroid Build Coastguard Worker
16*c8dee2aaSAndroid Build Coastguard Worker #include <algorithm>
17*c8dee2aaSAndroid Build Coastguard Worker #include <cstddef>
18*c8dee2aaSAndroid Build Coastguard Worker #include <initializer_list>
19*c8dee2aaSAndroid Build Coastguard Worker
20*c8dee2aaSAndroid Build Coastguard Worker class SK_SPI SkTDStorage {
21*c8dee2aaSAndroid Build Coastguard Worker public:
22*c8dee2aaSAndroid Build Coastguard Worker explicit SkTDStorage(int sizeOfT);
23*c8dee2aaSAndroid Build Coastguard Worker SkTDStorage(const void* src, int size, int sizeOfT);
24*c8dee2aaSAndroid Build Coastguard Worker
25*c8dee2aaSAndroid Build Coastguard Worker // Copy
26*c8dee2aaSAndroid Build Coastguard Worker SkTDStorage(const SkTDStorage& that);
27*c8dee2aaSAndroid Build Coastguard Worker SkTDStorage& operator= (const SkTDStorage& that);
28*c8dee2aaSAndroid Build Coastguard Worker
29*c8dee2aaSAndroid Build Coastguard Worker // Move
30*c8dee2aaSAndroid Build Coastguard Worker SkTDStorage(SkTDStorage&& that);
31*c8dee2aaSAndroid Build Coastguard Worker SkTDStorage& operator= (SkTDStorage&& that);
32*c8dee2aaSAndroid Build Coastguard Worker
33*c8dee2aaSAndroid Build Coastguard Worker ~SkTDStorage();
34*c8dee2aaSAndroid Build Coastguard Worker
35*c8dee2aaSAndroid Build Coastguard Worker void reset();
36*c8dee2aaSAndroid Build Coastguard Worker void swap(SkTDStorage& that);
37*c8dee2aaSAndroid Build Coastguard Worker
38*c8dee2aaSAndroid Build Coastguard Worker // Size routines
empty()39*c8dee2aaSAndroid Build Coastguard Worker bool empty() const { return fSize == 0; }
clear()40*c8dee2aaSAndroid Build Coastguard Worker void clear() { fSize = 0; }
size()41*c8dee2aaSAndroid Build Coastguard Worker int size() const { return fSize; }
42*c8dee2aaSAndroid Build Coastguard Worker void resize(int newSize);
size_bytes()43*c8dee2aaSAndroid Build Coastguard Worker size_t size_bytes() const { return this->bytes(fSize); }
44*c8dee2aaSAndroid Build Coastguard Worker
45*c8dee2aaSAndroid Build Coastguard Worker // Capacity routines
capacity()46*c8dee2aaSAndroid Build Coastguard Worker int capacity() const { return fCapacity; }
47*c8dee2aaSAndroid Build Coastguard Worker void reserve(int newCapacity);
48*c8dee2aaSAndroid Build Coastguard Worker void shrink_to_fit();
49*c8dee2aaSAndroid Build Coastguard Worker
data()50*c8dee2aaSAndroid Build Coastguard Worker void* data() { return fStorage; }
data()51*c8dee2aaSAndroid Build Coastguard Worker const void* data() const { return fStorage; }
52*c8dee2aaSAndroid Build Coastguard Worker
53*c8dee2aaSAndroid Build Coastguard Worker // Deletion routines
54*c8dee2aaSAndroid Build Coastguard Worker void erase(int index, int count);
55*c8dee2aaSAndroid Build Coastguard Worker // Removes the entry at 'index' and replaces it with the last array element
56*c8dee2aaSAndroid Build Coastguard Worker void removeShuffle(int index);
57*c8dee2aaSAndroid Build Coastguard Worker
58*c8dee2aaSAndroid Build Coastguard Worker // Insertion routines
59*c8dee2aaSAndroid Build Coastguard Worker void* prepend();
60*c8dee2aaSAndroid Build Coastguard Worker
61*c8dee2aaSAndroid Build Coastguard Worker void append();
62*c8dee2aaSAndroid Build Coastguard Worker void append(int count);
63*c8dee2aaSAndroid Build Coastguard Worker void* append(const void* src, int count);
64*c8dee2aaSAndroid Build Coastguard Worker
65*c8dee2aaSAndroid Build Coastguard Worker void* insert(int index);
66*c8dee2aaSAndroid Build Coastguard Worker void* insert(int index, int count, const void* src);
67*c8dee2aaSAndroid Build Coastguard Worker
pop_back()68*c8dee2aaSAndroid Build Coastguard Worker void pop_back() {
69*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(fSize > 0);
70*c8dee2aaSAndroid Build Coastguard Worker fSize--;
71*c8dee2aaSAndroid Build Coastguard Worker }
72*c8dee2aaSAndroid Build Coastguard Worker
73*c8dee2aaSAndroid Build Coastguard Worker friend bool operator==(const SkTDStorage& a, const SkTDStorage& b);
74*c8dee2aaSAndroid Build Coastguard Worker friend bool operator!=(const SkTDStorage& a, const SkTDStorage& b) {
75*c8dee2aaSAndroid Build Coastguard Worker return !(a == b);
76*c8dee2aaSAndroid Build Coastguard Worker }
77*c8dee2aaSAndroid Build Coastguard Worker
78*c8dee2aaSAndroid Build Coastguard Worker private:
bytes(int n)79*c8dee2aaSAndroid Build Coastguard Worker size_t bytes(int n) const { return SkToSizeT(n * fSizeOfT); }
address(int n)80*c8dee2aaSAndroid Build Coastguard Worker void* address(int n) { return fStorage + this->bytes(n); }
81*c8dee2aaSAndroid Build Coastguard Worker
82*c8dee2aaSAndroid Build Coastguard Worker // Adds delta to fSize. Crash if outside [0, INT_MAX]
83*c8dee2aaSAndroid Build Coastguard Worker int calculateSizeOrDie(int delta);
84*c8dee2aaSAndroid Build Coastguard Worker
85*c8dee2aaSAndroid Build Coastguard Worker // Move the tail of the array defined by the indexes tailStart and tailEnd to dstIndex. The
86*c8dee2aaSAndroid Build Coastguard Worker // elements at dstIndex are overwritten by the tail.
87*c8dee2aaSAndroid Build Coastguard Worker void moveTail(int dstIndex, int tailStart, int tailEnd);
88*c8dee2aaSAndroid Build Coastguard Worker
89*c8dee2aaSAndroid Build Coastguard Worker // Copy src into the array at dstIndex.
90*c8dee2aaSAndroid Build Coastguard Worker void copySrc(int dstIndex, const void* src, int count);
91*c8dee2aaSAndroid Build Coastguard Worker
92*c8dee2aaSAndroid Build Coastguard Worker const int fSizeOfT;
93*c8dee2aaSAndroid Build Coastguard Worker std::byte* fStorage{nullptr};
94*c8dee2aaSAndroid Build Coastguard Worker int fCapacity{0}; // size of the allocation in fArray (#elements)
95*c8dee2aaSAndroid Build Coastguard Worker int fSize{0}; // logical number of elements (fSize <= fCapacity)
96*c8dee2aaSAndroid Build Coastguard Worker };
97*c8dee2aaSAndroid Build Coastguard Worker
swap(SkTDStorage & a,SkTDStorage & b)98*c8dee2aaSAndroid Build Coastguard Worker static inline void swap(SkTDStorage& a, SkTDStorage& b) {
99*c8dee2aaSAndroid Build Coastguard Worker a.swap(b);
100*c8dee2aaSAndroid Build Coastguard Worker }
101*c8dee2aaSAndroid Build Coastguard Worker
102*c8dee2aaSAndroid Build Coastguard Worker // SkTDArray<T> implements a std::vector-like array for raw data-only objects that do not require
103*c8dee2aaSAndroid Build Coastguard Worker // construction or destruction. The constructor and destructor for T will not be called; T objects
104*c8dee2aaSAndroid Build Coastguard Worker // will always be moved via raw memcpy. Newly created T objects will contain uninitialized memory.
105*c8dee2aaSAndroid Build Coastguard Worker template <typename T> class SkTDArray {
106*c8dee2aaSAndroid Build Coastguard Worker public:
SkTDArray()107*c8dee2aaSAndroid Build Coastguard Worker SkTDArray() : fStorage{sizeof(T)} {}
SkTDArray(const T src[],int count)108*c8dee2aaSAndroid Build Coastguard Worker SkTDArray(const T src[], int count) : fStorage{src, count, sizeof(T)} { }
SkTDArray(const std::initializer_list<T> & list)109*c8dee2aaSAndroid Build Coastguard Worker SkTDArray(const std::initializer_list<T>& list) : SkTDArray(list.begin(), list.size()) {}
110*c8dee2aaSAndroid Build Coastguard Worker
111*c8dee2aaSAndroid Build Coastguard Worker // Copy
SkTDArray(const SkTDArray<T> & src)112*c8dee2aaSAndroid Build Coastguard Worker SkTDArray(const SkTDArray<T>& src) : SkTDArray(src.data(), src.size()) {}
113*c8dee2aaSAndroid Build Coastguard Worker SkTDArray<T>& operator=(const SkTDArray<T>& src) {
114*c8dee2aaSAndroid Build Coastguard Worker fStorage = src.fStorage;
115*c8dee2aaSAndroid Build Coastguard Worker return *this;
116*c8dee2aaSAndroid Build Coastguard Worker }
117*c8dee2aaSAndroid Build Coastguard Worker
118*c8dee2aaSAndroid Build Coastguard Worker // Move
SkTDArray(SkTDArray<T> && src)119*c8dee2aaSAndroid Build Coastguard Worker SkTDArray(SkTDArray<T>&& src) : fStorage{std::move(src.fStorage)} {}
120*c8dee2aaSAndroid Build Coastguard Worker SkTDArray<T>& operator=(SkTDArray<T>&& src) {
121*c8dee2aaSAndroid Build Coastguard Worker fStorage = std::move(src.fStorage);
122*c8dee2aaSAndroid Build Coastguard Worker return *this;
123*c8dee2aaSAndroid Build Coastguard Worker }
124*c8dee2aaSAndroid Build Coastguard Worker
125*c8dee2aaSAndroid Build Coastguard Worker friend bool operator==(const SkTDArray<T>& a, const SkTDArray<T>& b) {
126*c8dee2aaSAndroid Build Coastguard Worker return a.fStorage == b.fStorage;
127*c8dee2aaSAndroid Build Coastguard Worker }
128*c8dee2aaSAndroid Build Coastguard Worker friend bool operator!=(const SkTDArray<T>& a, const SkTDArray<T>& b) { return !(a == b); }
129*c8dee2aaSAndroid Build Coastguard Worker
swap(SkTDArray<T> & that)130*c8dee2aaSAndroid Build Coastguard Worker void swap(SkTDArray<T>& that) {
131*c8dee2aaSAndroid Build Coastguard Worker using std::swap;
132*c8dee2aaSAndroid Build Coastguard Worker swap(fStorage, that.fStorage);
133*c8dee2aaSAndroid Build Coastguard Worker }
134*c8dee2aaSAndroid Build Coastguard Worker
empty()135*c8dee2aaSAndroid Build Coastguard Worker bool empty() const { return fStorage.empty(); }
136*c8dee2aaSAndroid Build Coastguard Worker
137*c8dee2aaSAndroid Build Coastguard Worker // Return the number of elements in the array
size()138*c8dee2aaSAndroid Build Coastguard Worker int size() const { return fStorage.size(); }
139*c8dee2aaSAndroid Build Coastguard Worker
140*c8dee2aaSAndroid Build Coastguard Worker // Return the total number of elements allocated.
141*c8dee2aaSAndroid Build Coastguard Worker // Note: capacity() - size() gives you the number of elements you can add without causing an
142*c8dee2aaSAndroid Build Coastguard Worker // allocation.
capacity()143*c8dee2aaSAndroid Build Coastguard Worker int capacity() const { return fStorage.capacity(); }
144*c8dee2aaSAndroid Build Coastguard Worker
145*c8dee2aaSAndroid Build Coastguard Worker // return the number of bytes in the array: count * sizeof(T)
size_bytes()146*c8dee2aaSAndroid Build Coastguard Worker size_t size_bytes() const { return fStorage.size_bytes(); }
147*c8dee2aaSAndroid Build Coastguard Worker
data()148*c8dee2aaSAndroid Build Coastguard Worker T* data() { return static_cast<T*>(fStorage.data()); }
data()149*c8dee2aaSAndroid Build Coastguard Worker const T* data() const { return static_cast<const T*>(fStorage.data()); }
begin()150*c8dee2aaSAndroid Build Coastguard Worker T* begin() { return this->data(); }
begin()151*c8dee2aaSAndroid Build Coastguard Worker const T* begin() const { return this->data(); }
end()152*c8dee2aaSAndroid Build Coastguard Worker T* end() { return this->data() + this->size(); }
end()153*c8dee2aaSAndroid Build Coastguard Worker const T* end() const { return this->data() + this->size(); }
154*c8dee2aaSAndroid Build Coastguard Worker
155*c8dee2aaSAndroid Build Coastguard Worker T& operator[](int index) {
156*c8dee2aaSAndroid Build Coastguard Worker return this->data()[sk_collection_check_bounds(index, this->size())];
157*c8dee2aaSAndroid Build Coastguard Worker }
158*c8dee2aaSAndroid Build Coastguard Worker const T& operator[](int index) const {
159*c8dee2aaSAndroid Build Coastguard Worker return this->data()[sk_collection_check_bounds(index, this->size())];
160*c8dee2aaSAndroid Build Coastguard Worker }
161*c8dee2aaSAndroid Build Coastguard Worker
back()162*c8dee2aaSAndroid Build Coastguard Worker const T& back() const {
163*c8dee2aaSAndroid Build Coastguard Worker sk_collection_not_empty(this->empty());
164*c8dee2aaSAndroid Build Coastguard Worker return this->data()[this->size() - 1];
165*c8dee2aaSAndroid Build Coastguard Worker }
back()166*c8dee2aaSAndroid Build Coastguard Worker T& back() {
167*c8dee2aaSAndroid Build Coastguard Worker sk_collection_not_empty(this->empty());
168*c8dee2aaSAndroid Build Coastguard Worker return this->data()[this->size() - 1];
169*c8dee2aaSAndroid Build Coastguard Worker }
170*c8dee2aaSAndroid Build Coastguard Worker
reset()171*c8dee2aaSAndroid Build Coastguard Worker void reset() {
172*c8dee2aaSAndroid Build Coastguard Worker fStorage.reset();
173*c8dee2aaSAndroid Build Coastguard Worker }
174*c8dee2aaSAndroid Build Coastguard Worker
clear()175*c8dee2aaSAndroid Build Coastguard Worker void clear() {
176*c8dee2aaSAndroid Build Coastguard Worker fStorage.clear();
177*c8dee2aaSAndroid Build Coastguard Worker }
178*c8dee2aaSAndroid Build Coastguard Worker
179*c8dee2aaSAndroid Build Coastguard Worker // Sets the number of elements in the array.
180*c8dee2aaSAndroid Build Coastguard Worker // If the array does not have space for count elements, it will increase
181*c8dee2aaSAndroid Build Coastguard Worker // the storage allocated to some amount greater than that required.
182*c8dee2aaSAndroid Build Coastguard Worker // It will never shrink the storage.
resize(int count)183*c8dee2aaSAndroid Build Coastguard Worker void resize(int count) {
184*c8dee2aaSAndroid Build Coastguard Worker fStorage.resize(count);
185*c8dee2aaSAndroid Build Coastguard Worker }
186*c8dee2aaSAndroid Build Coastguard Worker
reserve(int n)187*c8dee2aaSAndroid Build Coastguard Worker void reserve(int n) {
188*c8dee2aaSAndroid Build Coastguard Worker fStorage.reserve(n);
189*c8dee2aaSAndroid Build Coastguard Worker }
190*c8dee2aaSAndroid Build Coastguard Worker
append()191*c8dee2aaSAndroid Build Coastguard Worker T* append() {
192*c8dee2aaSAndroid Build Coastguard Worker fStorage.append();
193*c8dee2aaSAndroid Build Coastguard Worker return this->end() - 1;
194*c8dee2aaSAndroid Build Coastguard Worker }
append(int count)195*c8dee2aaSAndroid Build Coastguard Worker T* append(int count) {
196*c8dee2aaSAndroid Build Coastguard Worker fStorage.append(count);
197*c8dee2aaSAndroid Build Coastguard Worker return this->end() - count;
198*c8dee2aaSAndroid Build Coastguard Worker }
append(int count,const T * src)199*c8dee2aaSAndroid Build Coastguard Worker T* append(int count, const T* src) {
200*c8dee2aaSAndroid Build Coastguard Worker return static_cast<T*>(fStorage.append(src, count));
201*c8dee2aaSAndroid Build Coastguard Worker }
202*c8dee2aaSAndroid Build Coastguard Worker
insert(int index)203*c8dee2aaSAndroid Build Coastguard Worker T* insert(int index) {
204*c8dee2aaSAndroid Build Coastguard Worker return static_cast<T*>(fStorage.insert(index));
205*c8dee2aaSAndroid Build Coastguard Worker }
206*c8dee2aaSAndroid Build Coastguard Worker T* insert(int index, int count, const T* src = nullptr) {
207*c8dee2aaSAndroid Build Coastguard Worker return static_cast<T*>(fStorage.insert(index, count, src));
208*c8dee2aaSAndroid Build Coastguard Worker }
209*c8dee2aaSAndroid Build Coastguard Worker
210*c8dee2aaSAndroid Build Coastguard Worker void remove(int index, int count = 1) {
211*c8dee2aaSAndroid Build Coastguard Worker fStorage.erase(index, count);
212*c8dee2aaSAndroid Build Coastguard Worker }
213*c8dee2aaSAndroid Build Coastguard Worker
removeShuffle(int index)214*c8dee2aaSAndroid Build Coastguard Worker void removeShuffle(int index) {
215*c8dee2aaSAndroid Build Coastguard Worker fStorage.removeShuffle(index);
216*c8dee2aaSAndroid Build Coastguard Worker }
217*c8dee2aaSAndroid Build Coastguard Worker
218*c8dee2aaSAndroid Build Coastguard Worker // routines to treat the array like a stack
push_back(const T & v)219*c8dee2aaSAndroid Build Coastguard Worker void push_back(const T& v) {
220*c8dee2aaSAndroid Build Coastguard Worker this->append();
221*c8dee2aaSAndroid Build Coastguard Worker this->back() = v;
222*c8dee2aaSAndroid Build Coastguard Worker }
pop_back()223*c8dee2aaSAndroid Build Coastguard Worker void pop_back() { fStorage.pop_back(); }
224*c8dee2aaSAndroid Build Coastguard Worker
shrink_to_fit()225*c8dee2aaSAndroid Build Coastguard Worker void shrink_to_fit() {
226*c8dee2aaSAndroid Build Coastguard Worker fStorage.shrink_to_fit();
227*c8dee2aaSAndroid Build Coastguard Worker }
228*c8dee2aaSAndroid Build Coastguard Worker
229*c8dee2aaSAndroid Build Coastguard Worker private:
230*c8dee2aaSAndroid Build Coastguard Worker SkTDStorage fStorage;
231*c8dee2aaSAndroid Build Coastguard Worker };
232*c8dee2aaSAndroid Build Coastguard Worker
swap(SkTDArray<T> & a,SkTDArray<T> & b)233*c8dee2aaSAndroid Build Coastguard Worker template <typename T> static inline void swap(SkTDArray<T>& a, SkTDArray<T>& b) { a.swap(b); }
234*c8dee2aaSAndroid Build Coastguard Worker
235*c8dee2aaSAndroid Build Coastguard Worker #endif
236