aboutsummaryrefslogtreecommitdiff
path: root/src/deps/skia/include/private/SkTDArray.h
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <jarred@jarredsumner.com> 2022-04-03 16:34:10 -0700
committerGravatar Jarred Sumner <jarred@jarredsumner.com> 2022-04-03 16:34:10 -0700
commita87508008dfa1604baf2d4e39bf44704c00f261c (patch)
tree0be2ade96772037a02803b30e157c367d931e3d9 /src/deps/skia/include/private/SkTDArray.h
parent4a19a3f07f1887903e5638a3be167f0c7b377ba3 (diff)
downloadbun-a87508008dfa1604baf2d4e39bf44704c00f261c.tar.gz
bun-a87508008dfa1604baf2d4e39bf44704c00f261c.tar.zst
bun-a87508008dfa1604baf2d4e39bf44704c00f261c.zip
Diffstat (limited to 'src/deps/skia/include/private/SkTDArray.h')
-rw-r--r--src/deps/skia/include/private/SkTDArray.h385
1 files changed, 385 insertions, 0 deletions
diff --git a/src/deps/skia/include/private/SkTDArray.h b/src/deps/skia/include/private/SkTDArray.h
new file mode 100644
index 000000000..d06b46f72
--- /dev/null
+++ b/src/deps/skia/include/private/SkTDArray.h
@@ -0,0 +1,385 @@
+/*
+ * 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/core/SkTypes.h"
+#include "include/private/SkMalloc.h"
+#include "include/private/SkTo.h"
+
+#include <algorithm>
+#include <initializer_list>
+#include <utility>
+
+/** 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.
+
+ In most cases, std::vector<T> can provide a similar level of performance for POD objects when
+ used with appropriate care. In new code, consider std::vector<T> instead.
+*/
+template <typename T> class SkTDArray {
+public:
+ SkTDArray() : fArray(nullptr), fReserve(0), fCount(0) {}
+ SkTDArray(const T src[], int count) {
+ SkASSERT(src || count == 0);
+
+ fReserve = fCount = 0;
+ fArray = nullptr;
+ if (count) {
+ fArray = (T*)sk_malloc_throw(SkToSizeT(count) * sizeof(T));
+ memcpy(fArray, src, sizeof(T) * SkToSizeT(count));
+ fReserve = fCount = count;
+ }
+ }
+ SkTDArray(const std::initializer_list<T>& list) : SkTDArray(list.begin(), list.size()) {}
+ SkTDArray(const SkTDArray<T>& src) : fArray(nullptr), fReserve(0), fCount(0) {
+ SkTDArray<T> tmp(src.fArray, src.fCount);
+ this->swap(tmp);
+ }
+ SkTDArray(SkTDArray<T>&& src) : fArray(nullptr), fReserve(0), fCount(0) {
+ this->swap(src);
+ }
+ ~SkTDArray() {
+ sk_free(fArray);
+ }
+
+ SkTDArray<T>& operator=(const SkTDArray<T>& src) {
+ if (this != &src) {
+ if (src.fCount > fReserve) {
+ SkTDArray<T> tmp(src.fArray, src.fCount);
+ this->swap(tmp);
+ } else {
+ sk_careful_memcpy(fArray, src.fArray, sizeof(T) * SkToSizeT(src.fCount));
+ fCount = src.fCount;
+ }
+ }
+ return *this;
+ }
+ SkTDArray<T>& operator=(SkTDArray<T>&& src) {
+ if (this != &src) {
+ this->swap(src);
+ src.reset();
+ }
+ return *this;
+ }
+
+ friend bool operator==(const SkTDArray<T>& a, const SkTDArray<T>& b) {
+ return a.fCount == b.fCount &&
+ (a.fCount == 0 ||
+ !memcmp(a.fArray, b.fArray, SkToSizeT(a.fCount) * sizeof(T)));
+ }
+ friend bool operator!=(const SkTDArray<T>& a, const SkTDArray<T>& b) {
+ return !(a == b);
+ }
+
+ void swap(SkTDArray<T>& that) {
+ using std::swap;
+ swap(fArray, that.fArray);
+ swap(fReserve, that.fReserve);
+ swap(fCount, that.fCount);
+ }
+
+ bool isEmpty() const { return fCount == 0; }
+ bool empty() const { return this->isEmpty(); }
+
+ /**
+ * Return the number of elements in the array
+ */
+ int count() const { return fCount; }
+ size_t size() const { return fCount; }
+
+ /**
+ * Return the total number of elements allocated.
+ * reserved() - count() gives you the number of elements you can add
+ * without causing an allocation.
+ */
+ int reserved() const { return fReserve; }
+
+ /**
+ * return the number of bytes in the array: count * sizeof(T)
+ */
+ size_t bytes() const { return fCount * sizeof(T); }
+
+ T* begin() { return fArray; }
+ const T* begin() const { return fArray; }
+ T* end() { return fArray ? fArray + fCount : nullptr; }
+ const T* end() const { return fArray ? fArray + fCount : nullptr; }
+
+ T& operator[](int index) {
+ SkASSERT(index < fCount);
+ return fArray[index];
+ }
+ const T& operator[](int index) const {
+ SkASSERT(index < fCount);
+ return fArray[index];
+ }
+
+ T& getAt(int index) {
+ return (*this)[index];
+ }
+
+ const T& back() const { SkASSERT(fCount > 0); return fArray[fCount-1]; }
+ T& back() { SkASSERT(fCount > 0); return fArray[fCount-1]; }
+
+ void reset() {
+ if (fArray) {
+ sk_free(fArray);
+ fArray = nullptr;
+ fReserve = fCount = 0;
+ } else {
+ SkASSERT(fReserve == 0 && fCount == 0);
+ }
+ }
+
+ void rewind() {
+ // same as setCount(0)
+ fCount = 0;
+ }
+
+ /**
+ * 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 setCount(int count) {
+ SkASSERT(count >= 0);
+ if (count > fReserve) {
+ this->resizeStorageToAtLeast(count);
+ }
+ fCount = count;
+ }
+
+ void setReserve(int reserve) {
+ SkASSERT(reserve >= 0);
+ if (reserve > fReserve) {
+ this->resizeStorageToAtLeast(reserve);
+ }
+ }
+ void reserve(size_t n) {
+ SkASSERT_RELEASE(SkTFitsIn<int>(n));
+ this->setReserve(SkToInt(n));
+ }
+
+ T* prepend() {
+ this->adjustCount(1);
+ memmove(fArray + 1, fArray, (fCount - 1) * sizeof(T));
+ return fArray;
+ }
+
+ T* append() {
+ return this->append(1, nullptr);
+ }
+ T* append(int count, const T* src = nullptr) {
+ int oldCount = fCount;
+ if (count) {
+ SkASSERT(src == nullptr || fArray == nullptr ||
+ src + count <= fArray || fArray + oldCount <= src);
+
+ this->adjustCount(count);
+ if (src) {
+ memcpy(fArray + oldCount, src, sizeof(T) * count);
+ }
+ }
+ return fArray + oldCount;
+ }
+
+ T* insert(int index) {
+ return this->insert(index, 1, nullptr);
+ }
+ T* insert(int index, int count, const T* src = nullptr) {
+ SkASSERT(count);
+ SkASSERT(index <= fCount);
+ size_t oldCount = fCount;
+ this->adjustCount(count);
+ T* dst = fArray + index;
+ memmove(dst + count, dst, sizeof(T) * (oldCount - index));
+ if (src) {
+ memcpy(dst, src, sizeof(T) * count);
+ }
+ return dst;
+ }
+
+ void remove(int index, int count = 1) {
+ SkASSERT(index + count <= fCount);
+ fCount = fCount - count;
+ memmove(fArray + index, fArray + index + count, sizeof(T) * (fCount - index));
+ }
+
+ void removeShuffle(int index) {
+ SkASSERT(index < fCount);
+ int newCount = fCount - 1;
+ fCount = newCount;
+ if (index != newCount) {
+ memcpy(fArray + index, fArray + newCount, sizeof(T));
+ }
+ }
+
+ int find(const T& elem) const {
+ const T* iter = fArray;
+ const T* stop = fArray + fCount;
+
+ for (; iter < stop; iter++) {
+ if (*iter == elem) {
+ return SkToInt(iter - fArray);
+ }
+ }
+ return -1;
+ }
+
+ int rfind(const T& elem) const {
+ const T* iter = fArray + fCount;
+ const T* stop = fArray;
+
+ while (iter > stop) {
+ if (*--iter == elem) {
+ return SkToInt(iter - stop);
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Returns true iff the array contains this element.
+ */
+ bool contains(const T& elem) const {
+ return (this->find(elem) >= 0);
+ }
+
+ /**
+ * Copies up to max elements into dst. The number of items copied is
+ * capped by count - index. The actual number copied is returned.
+ */
+ int copyRange(T* dst, int index, int max) const {
+ SkASSERT(max >= 0);
+ SkASSERT(!max || dst);
+ if (index >= fCount) {
+ return 0;
+ }
+ int count = std::min(max, fCount - index);
+ memcpy(dst, fArray + index, sizeof(T) * count);
+ return count;
+ }
+
+ void copy(T* dst) const {
+ this->copyRange(dst, 0, fCount);
+ }
+
+ // routines to treat the array like a stack
+ void push_back(const T& v) { *this->append() = v; }
+ T* push() { return this->append(); }
+ const T& top() const { return (*this)[fCount - 1]; }
+ T& top() { return (*this)[fCount - 1]; }
+ void pop(T* elem) { SkASSERT(fCount > 0); if (elem) *elem = (*this)[fCount - 1]; --fCount; }
+ void pop() { SkASSERT(fCount > 0); --fCount; }
+
+ void deleteAll() {
+ T* iter = fArray;
+ T* stop = fArray + fCount;
+ while (iter < stop) {
+ delete *iter;
+ iter += 1;
+ }
+ this->reset();
+ }
+
+ void freeAll() {
+ T* iter = fArray;
+ T* stop = fArray + fCount;
+ while (iter < stop) {
+ sk_free(*iter);
+ iter += 1;
+ }
+ this->reset();
+ }
+
+ void unrefAll() {
+ T* iter = fArray;
+ T* stop = fArray + fCount;
+ while (iter < stop) {
+ (*iter)->unref();
+ iter += 1;
+ }
+ this->reset();
+ }
+
+ void safeUnrefAll() {
+ T* iter = fArray;
+ T* stop = fArray + fCount;
+ while (iter < stop) {
+ SkSafeUnref(*iter);
+ iter += 1;
+ }
+ this->reset();
+ }
+
+#ifdef SK_DEBUG
+ void validate() const {
+ SkASSERT((fReserve == 0 && fArray == nullptr) ||
+ (fReserve > 0 && fArray != nullptr));
+ SkASSERT(fCount <= fReserve);
+ }
+#endif
+
+ void shrinkToFit() {
+ if (fReserve != fCount) {
+ SkASSERT(fReserve > fCount);
+ fReserve = fCount;
+ fArray = (T*)sk_realloc_throw(fArray, fReserve * sizeof(T));
+ }
+ }
+
+private:
+ T* fArray;
+ int fReserve; // size of the allocation in fArray (#elements)
+ int fCount; // logical number of elements (fCount <= fReserve)
+
+ /**
+ * Adjusts the number of elements in the array.
+ * This is the same as calling setCount(count() + delta).
+ */
+ void adjustCount(int delta) {
+ SkASSERT(delta > 0);
+
+ // We take care to avoid overflow here.
+ // The sum of fCount and delta is at most 4294967294, which fits fine in uint32_t.
+ uint32_t count = (uint32_t)fCount + (uint32_t)delta;
+ SkASSERT_RELEASE( SkTFitsIn<int>(count) );
+
+ this->setCount(SkTo<int>(count));
+ }
+
+ /**
+ * Increase the storage allocation such that it can hold (fCount + extra)
+ * elements.
+ * It never shrinks the allocation, and it may increase the allocation by
+ * more than is strictly required, based on a private growth heuristic.
+ *
+ * note: does NOT modify fCount
+ */
+ void resizeStorageToAtLeast(int count) {
+ SkASSERT(count > fReserve);
+
+ // We take care to avoid overflow here.
+ // The maximum value we can get for reserve here is 2684354563, which fits in uint32_t.
+ uint32_t reserve = (uint32_t)count + 4;
+ reserve += reserve / 4;
+ SkASSERT_RELEASE( SkTFitsIn<int>(reserve) );
+
+ fReserve = SkTo<int>(reserve);
+ fArray = (T*)sk_realloc_throw(fArray, (size_t)fReserve * sizeof(T));
+ }
+};
+
+template <typename T> static inline void swap(SkTDArray<T>& a, SkTDArray<T>& b) {
+ a.swap(b);
+}
+
+#endif