8#ifndef SkTArray_DEFINED
9#define SkTArray_DEFINED
28#include <initializer_list>
40template <
typename T,
bool MEM_MOVE = sk_is_trivially_relocatable_v<T>>
class TArray {
60 if (that.fOwnMemory) {
64 this->initData(that.fSize);
67 this->changeSize(that.fSize);
77 this->initData(
count);
96 this->checkRealloc(that.
size(), kExactFit);
97 this->changeSize(that.fSize);
98 this->
copy(that.fData);
107 if (that.fOwnMemory) {
113 fData = std::exchange(that.fData,
nullptr);
116 fCapacity = that.fCapacity;
121 this->changeSize(that.fSize);
124 this->checkRealloc(that.size(), kExactFit);
125 this->changeSize(that.fSize);
147 this->checkRealloc(n, kExactFit);
149 for (
int i = 0;
i < this->
size(); ++
i) {
160 this->checkRealloc(
count, kExactFit);
161 this->changeSize(
count);
172 if (n > this->
size()) {
173 this->checkRealloc(n - this->
size(), kGrowing);
183 if (n > this->
size()) {
184 this->checkRealloc(n - this->
size(), kExactFit);
190 int newCount = fSize - 1;
193 this->move(n, newCount);
195 this->changeSize(newCount);
199 bool empty()
const {
return fSize == 0; }
206 void* newT = this->push_back_raw(1);
207 return *
new (newT)
T;
219 newT =
new (fData + fSize)
T(t);
221 newT = this->growAndConstructAtEnd(t);
224 this->changeSize(fSize + 1);
236 newT =
new (fData + fSize)
T(std::move(t));
238 newT = this->growAndConstructAtEnd(std::move(t));
241 this->changeSize(fSize + 1);
253 newT =
new (fData + fSize)
T(std::forward<Args>(
args)...);
255 newT = this->growAndConstructAtEnd(std::forward<Args>(
args)...);
258 this->changeSize(fSize + 1);
269 T* newTs = TCast(this->push_back_raw(n));
270 for (
int i = 0;
i < n; ++
i) {
282 T* newTs = TCast(this->push_back_raw(n));
283 for (
int i = 0;
i < n; ++
i) {
284 new (&newTs[
i])
T(t);
286 return static_cast<T*
>(newTs);
295 this->checkRealloc(n, kGrowing);
297 this->changeSize(fSize + n);
298 for (
int i = 0;
i < n; ++
i) {
309 this->checkRealloc(n, kGrowing);
311 this->changeSize(fSize + n);
312 for (
int i = 0;
i < n; ++
i) {
313 new (
end +
i)
T(std::move(t[
i]));
323 fData[fSize - 1].~T();
324 this->changeSize(fSize - 1);
334 while (
i-- > fSize - n) {
337 this->changeSize(fSize - n);
345 if (newCount > this->
size()) {
348 this->checkRealloc(newCount, kExactFit);
351 }
else if (newCount < this->
size()) {
363 if (fOwnMemory && that.fOwnMemory) {
364 swap(fData, that.fData);
365 swap(fSize, that.fSize);
368 auto allocCount = fCapacity;
369 fCapacity = that.fCapacity;
370 that.fCapacity = allocCount;
374 that = std::move(*
this);
375 *
this = std::move(
copy);
384 if (that.
empty() || &that ==
this) {
387 void*
dst = this->push_back_raw(that.
size());
408 if (fData ==
nullptr) {
411 return fData + fSize;
414 if (fData ==
nullptr) {
417 return fData + fSize;
420 const T*
data()
const {
return fData; }
421 int size()
const {
return fSize; }
431 if (!fOwnMemory || fSize == fCapacity) {
441 this->move(TCast(allocation.
data()));
446 this->setDataFromBytes(allocation);
462 const T&
at(
int i)
const {
return (*
this)[
i]; }
482 return fData[fSize - 1];
487 return fData[fSize - 1];
494 return (*
this)[fSize -
i - 1];
498 return (*
this)[fSize -
i - 1];
502 int leftCount = this->
size();
503 if (leftCount != right.size()) {
506 for (
int index = 0; index < leftCount; ++index) {
507 if (fData[index] != right.fData[index]) {
515 return !(*
this == right);
525 template <
int InitialCapacity>
527 static_assert(InitialCapacity >= 0);
530 if (
size > InitialCapacity) {
531 this->initData(
size);
533 this->setDataFromBytes(*storage);
534 this->changeSize(
size);
544 template <
int InitialCapacity>
549 template <
int InitialCapacity>
557 static constexpr double kExactFit = 1.0;
558 static constexpr double kGrowing = 1.5;
560 static constexpr int kMinHeapAllocCount = 8;
561 static_assert(
SkIsPow2(kMinHeapAllocCount),
"min alloc count not power of two.");
565 static constexpr int kMaxCapacity =
SkToInt(
std::min(SIZE_MAX /
sizeof(
T), (
size_t)INT_MAX));
580 fData = array.
data();
588#ifdef SK_SANITIZE_ADDRESS
597#ifdef SK_SANITIZE_ADDRESS
598 if (fData && fCapacity > fSize) {
605 void changeSize(
int n) {
619 static
T* TCast(
void*
buffer) {
623 static size_t Bytes(
int n) {
632 void initData(
int count) {
633 this->setDataFromBytes(Allocate(
count));
634 this->changeSize(
count);
638 if (!this->
empty()) {
639 T* cursor = this->
begin();
644 }
while (cursor <
end);
652 if constexpr (std::is_trivially_copyable_v<T>) {
653 if (!this->
empty() && src !=
nullptr) {
657 for (
int i = 0;
i < this->
size(); ++
i) {
658 new (fData +
i)
T(
src[
i]);
663 void move(
int dst,
int src) {
664 if constexpr (MEM_MOVE) {
665 memcpy(
static_cast<void*
>(&fData[
dst]),
666 static_cast<const void*
>(&fData[
src]),
669 new (&fData[
dst])
T(std::move(fData[
src]));
674 void move(
void*
dst) {
675 if constexpr (MEM_MOVE) {
678 for (
int i = 0;
i < this->
size(); ++
i) {
679 new (
static_cast<char*
>(
dst) + Bytes(
i))
T(std::move(fData[
i]));
687 void* push_back_raw(
int n) {
688 this->checkRealloc(n, kGrowing);
689 void* ptr = fData + fSize;
690 this->changeSize(fSize + n);
694 template <
typename... Args>
697 T* newT =
new (TCast(
buffer.data()) + fSize)
T(std::forward<Args>(
args)...);
698 this->installDataAndUpdateCapacity(
buffer);
703 void checkRealloc(
int delta,
double growthFactor) {
711 this->installDataAndUpdateCapacity(this->preallocateNewData(
delta, growthFactor));
724 if (
delta > kMaxCapacity - fSize) {
727 const int newCount = fSize +
delta;
729 return Allocate(newCount, growthFactor);
733 this->move(TCast(allocation.
data()));
737 this->setDataFromBytes(allocation);
743 uint32_t fOwnMemory : 1;
744 uint32_t fCapacity : 31;
752template <
int Nreq,
typename T,
bool MEM_MOVE = sk_is_trivially_relocatable_v<T>>
754 public TArray<T, MEM_MOVE> {
757 static constexpr int N = SkContainerAllocator::RoundUp<T>(Nreq);
758 static_assert(Nreq > 0);
759 static_assert(
N >= Nreq);
790 :
STArray() { *
this = std::move(that); }
793 :
STArray() { *
this = std::move(that); }
static void sk_asan_poison_memory_region(void const volatile *addr, size_t size)
static void sk_asan_unpoison_memory_region(void const volatile *addr, size_t size)
SK_API void sk_collection_not_empty(bool empty)
SK_API T sk_collection_check_bounds(T i, T size)
#define SK_CLANG_NO_SANITIZE(A)
SK_SPI void sk_report_container_overflow_and_die()
SK_API void sk_free(void *)
static void * sk_careful_memcpy(void *dst, const void *src, size_t len)
constexpr bool SkIsPow2(T value)
void swap(sk_sp< T > &a, sk_sp< T > &b)
constexpr size_t SkToSizeT(S x)
constexpr int SkToInt(S x)
constexpr uint32_t SkToU32(S x)
SkSpan< std::byte > allocate(int capacity, double growthFactor=1.0)
constexpr T * data() const
constexpr T * begin() const
constexpr size_t size() const
STArray(const STArray &that)
STArray(SkSpan< const T > data)
STArray & operator=(TArray< T, MEM_MOVE > &&that)
STArray & operator=(const TArray< T, MEM_MOVE > &that)
STArray(std::initializer_list< T > data)
STArray & operator=(STArray &&that)
STArray & operator=(const STArray &that)
STArray(int reserveCount)
STArray(const TArray< T, MEM_MOVE > &that)
STArray(TArray< T, MEM_MOVE > &&that)
STArray(const T *array, int count)
TArray(const TArray &that)
T * push_back_n(int n, const T &t)
T * push_back_n(int n, const T t[])
TArray(SkAlignedSTStorage< InitialCapacity, T > *storage, int size=0)
size_t size_bytes() const
void move_back(TArray &that)
void reset(const T *array, int count)
void resize_back(int newCount)
TArray(SkSpan< const T > data, SkAlignedSTStorage< InitialCapacity, T > *storage)
const T & at(int i) const
TArray(const T *array, int count)
const T & fromBack(int i) const
void resize(size_t count)
TArray & operator=(TArray &&that)
T * move_back_n(int n, T *t)
void removeShuffle(int n)
TArray(SkSpan< const T > data)
T & push_back(const T &t)
bool operator!=(const TArray< T, MEM_MOVE > &right) const
void reserve_exact(int n)
bool operator==(const TArray< T, MEM_MOVE > &right) const
T & emplace_back(Args &&... args)
TArray(std::initializer_list< T > data)
TArray & operator=(const TArray &that)
TArray(const T *array, int size, SkAlignedSTStorage< InitialCapacity, T > *storage)
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
static float min(float r, float g, float b)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
static void swap(TArray< T, M > &a, TArray< T, M > &b)