summaryrefslogtreecommitdiffstats
path: root/gfx/skia/skia/include/private/base/SkTDArray.h
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/skia/skia/include/private/base/SkTDArray.h')
-rw-r--r--gfx/skia/skia/include/private/base/SkTDArray.h236
1 files changed, 236 insertions, 0 deletions
diff --git a/gfx/skia/skia/include/private/base/SkTDArray.h b/gfx/skia/skia/include/private/base/SkTDArray.h
new file mode 100644
index 0000000000..b08d285378
--- /dev/null
+++ b/gfx/skia/skia/include/private/base/SkTDArray.h
@@ -0,0 +1,236 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkTDArray_DEFINED
+#define SkTDArray_DEFINED
+
+#include "include/private/base/SkAPI.h"
+#include "include/private/base/SkAssert.h"
+#include "include/private/base/SkTo.h"
+
+#include <algorithm>
+#include <cstddef>
+#include <initializer_list>
+
+class SK_SPI SkTDStorage {
+public:
+ explicit SkTDStorage(int sizeOfT);
+ SkTDStorage(const void* src, int size, int sizeOfT);
+
+ // Copy
+ SkTDStorage(const SkTDStorage& that);
+ SkTDStorage& operator= (const SkTDStorage& that);
+
+ // Move
+ SkTDStorage(SkTDStorage&& that);
+ SkTDStorage& operator= (SkTDStorage&& that);
+
+ ~SkTDStorage();
+
+ void reset();
+ void swap(SkTDStorage& that);
+
+ // Size routines
+ bool empty() const { return fSize == 0; }
+ void clear() { fSize = 0; }
+ int size() const { return fSize; }
+ void resize(int newSize);
+ size_t size_bytes() const { return this->bytes(fSize); }
+
+ // Capacity routines
+ int capacity() const { return fCapacity; }
+ void reserve(int newCapacity);
+ void shrink_to_fit();
+
+ void* data() { return fStorage; }
+ const void* data() const { return fStorage; }
+
+ // Deletion routines
+ void erase(int index, int count);
+ // Removes the entry at 'index' and replaces it with the last array element
+ void removeShuffle(int index);
+
+ // Insertion routines
+ void* prepend();
+
+ void append();
+ void append(int count);
+ void* append(const void* src, int count);
+
+ void* insert(int index);
+ void* insert(int index, int count, const void* src);
+
+ void pop_back() {
+ SkASSERT(fSize > 0);
+ fSize--;
+ }
+
+ friend bool operator==(const SkTDStorage& a, const SkTDStorage& b);
+ friend bool operator!=(const SkTDStorage& a, const SkTDStorage& b) {
+ return !(a == b);
+ }
+
+private:
+ size_t bytes(int n) const { return SkToSizeT(n * fSizeOfT); }
+ void* address(int n) { return fStorage + this->bytes(n); }
+
+ // Adds delta to fSize. Crash if outside [0, INT_MAX]
+ int calculateSizeOrDie(int delta);
+
+ // Move the tail of the array defined by the indexes tailStart and tailEnd to dstIndex. The
+ // elements at dstIndex are overwritten by the tail.
+ void moveTail(int dstIndex, int tailStart, int tailEnd);
+
+ // Copy src into the array at dstIndex.
+ void copySrc(int dstIndex, const void* src, int count);
+
+ const int fSizeOfT;
+ std::byte* fStorage{nullptr};
+ int fCapacity{0}; // size of the allocation in fArray (#elements)
+ int fSize{0}; // logical number of elements (fSize <= fCapacity)
+};
+
+static inline void swap(SkTDStorage& a, SkTDStorage& b) {
+ a.swap(b);
+}
+
+// SkTDArray<T> implements a std::vector-like array for raw data-only objects that do not require
+// construction or destruction. The constructor and destructor for T will not be called; T objects
+// will always be moved via raw memcpy. Newly created T objects will contain uninitialized memory.
+template <typename T> class SkTDArray {
+public:
+ SkTDArray() : fStorage{sizeof(T)} {}
+ SkTDArray(const T src[], int count) : fStorage{src, count, sizeof(T)} { }
+ SkTDArray(const std::initializer_list<T>& list) : SkTDArray(list.begin(), list.size()) {}
+
+ // Copy
+ SkTDArray(const SkTDArray<T>& src) : SkTDArray(src.data(), src.size()) {}
+ SkTDArray<T>& operator=(const SkTDArray<T>& src) {
+ fStorage = src.fStorage;
+ return *this;
+ }
+
+ // Move
+ SkTDArray(SkTDArray<T>&& src) : fStorage{std::move(src.fStorage)} {}
+ SkTDArray<T>& operator=(SkTDArray<T>&& src) {
+ fStorage = std::move(src.fStorage);
+ return *this;
+ }
+
+ friend bool operator==(const SkTDArray<T>& a, const SkTDArray<T>& b) {
+ return a.fStorage == b.fStorage;
+ }
+ friend bool operator!=(const SkTDArray<T>& a, const SkTDArray<T>& b) { return !(a == b); }
+
+ void swap(SkTDArray<T>& that) {
+ using std::swap;
+ swap(fStorage, that.fStorage);
+ }
+
+ bool empty() const { return fStorage.empty(); }
+
+ // Return the number of elements in the array
+ int size() const { return fStorage.size(); }
+
+ // Return the total number of elements allocated.
+ // Note: capacity() - size() gives you the number of elements you can add without causing an
+ // allocation.
+ int capacity() const { return fStorage.capacity(); }
+
+ // return the number of bytes in the array: count * sizeof(T)
+ size_t size_bytes() const { return fStorage.size_bytes(); }
+
+ T* data() { return static_cast<T*>(fStorage.data()); }
+ const T* data() const { return static_cast<const T*>(fStorage.data()); }
+ T* begin() { return this->data(); }
+ const T* begin() const { return this->data(); }
+ T* end() { return this->data() + this->size(); }
+ const T* end() const { return this->data() + this->size(); }
+
+ T& operator[](int index) {
+ SkASSERT(index < this->size());
+ return this->data()[index];
+ }
+ const T& operator[](int index) const {
+ SkASSERT(index < this->size());
+ return this->data()[index];
+ }
+
+ const T& back() const {
+ SkASSERT(this->size() > 0);
+ return this->data()[this->size() - 1];
+ }
+ T& back() {
+ SkASSERT(this->size() > 0);
+ return this->data()[this->size() - 1];
+ }
+
+ void reset() {
+ fStorage.reset();
+ }
+
+ void clear() {
+ fStorage.clear();
+ }
+
+ // Sets the number of elements in the array.
+ // If the array does not have space for count elements, it will increase
+ // the storage allocated to some amount greater than that required.
+ // It will never shrink the storage.
+ void resize(int count) {
+ fStorage.resize(count);
+ }
+
+ void reserve(int n) {
+ fStorage.reserve(n);
+ }
+
+ T* append() {
+ fStorage.append();
+ return this->end() - 1;
+ }
+ T* append(int count) {
+ fStorage.append(count);
+ return this->end() - count;
+ }
+ T* append(int count, const T* src) {
+ return static_cast<T*>(fStorage.append(src, count));
+ }
+
+ T* insert(int index) {
+ return static_cast<T*>(fStorage.insert(index));
+ }
+ T* insert(int index, int count, const T* src = nullptr) {
+ return static_cast<T*>(fStorage.insert(index, count, src));
+ }
+
+ void remove(int index, int count = 1) {
+ fStorage.erase(index, count);
+ }
+
+ void removeShuffle(int index) {
+ fStorage.removeShuffle(index);
+ }
+
+ // routines to treat the array like a stack
+ void push_back(const T& v) {
+ this->append();
+ this->back() = v;
+ }
+ void pop_back() { fStorage.pop_back(); }
+
+ void shrink_to_fit() {
+ fStorage.shrink_to_fit();
+ }
+
+private:
+ SkTDStorage fStorage;
+};
+
+template <typename T> static inline void swap(SkTDArray<T>& a, SkTDArray<T>& b) { a.swap(b); }
+
+#endif