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