blob: b841eaf6d38835a1aae06bdd72d51270d00101a2 [file] [log] [blame]
reed@android.com8a1c16f2008-12-17 15:59:43 +00001/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00002 * Copyright 2006 The Android Open Source Project
reed@android.com8a1c16f2008-12-17 15:59:43 +00003 *
epoger@google.comec3ed6a2011-07-28 14:26:00 +00004 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
reed@android.com8a1c16f2008-12-17 15:59:43 +00006 */
7
epoger@google.comec3ed6a2011-07-28 14:26:00 +00008
reed@android.com8a1c16f2008-12-17 15:59:43 +00009#ifndef SkTDArray_DEFINED
10#define SkTDArray_DEFINED
11
12#include "SkTypes.h"
Mike Klein80e1d562018-03-22 11:36:52 -040013#include <vector>
reed@android.com8a1c16f2008-12-17 15:59:43 +000014
Mike Klein80e1d562018-03-22 11:36:52 -040015// SkTDArray is now a thin wrapper over std::vector.
16// Please feel free to use either.
17
18// Implementation notes:
19// 1) We take care to use SkToInt(size_t) and SkToSizeT(int) to do conversions that
20// assert the value fits either direction. The SkToInt(size_t) should be obvious,
21// but even SkToSizeT(int) has caught negative values passed in where you'd expect
22// >= 0.
23//
24// 2) We try to add yet-undefined items to the array with default initialization.
25// This can look funny, as the only really good way to get that is to write
26// "T v;", a T default-intialized on the stack, often meaning uninitialized.
27// This avoids the slightly more expensive value initialization (like, floats
28// to 0.0f) that std::vector normally provides.
29//
30// 3) See the end of the file for how we avoid std::vector<bool>.
31
32template <typename T>
33class SkTDArray {
reed@android.com8a1c16f2008-12-17 15:59:43 +000034public:
Mike Klein80e1d562018-03-22 11:36:52 -040035 SkTDArray() = default;
36 ~SkTDArray() = default;
37 SkTDArray(const SkTDArray&) = default;
38 SkTDArray(SkTDArray&&) = default;
39 SkTDArray& operator=(const SkTDArray&) = default;
40 SkTDArray& operator=(SkTDArray&&) = default;
reed@android.com8a1c16f2008-12-17 15:59:43 +000041
Mike Klein80e1d562018-03-22 11:36:52 -040042 SkTDArray(const T* src, int n) : fVec(src, src+SkToSizeT(n)) {}
reed@android.com8a1c16f2008-12-17 15:59:43 +000043
Mike Klein80e1d562018-03-22 11:36:52 -040044 friend bool operator==(const SkTDArray& a, const SkTDArray& b) { return a.fVec == b.fVec; }
45 friend bool operator!=(const SkTDArray& a, const SkTDArray& b) { return a.fVec != b.fVec; }
reed@android.com8a1c16f2008-12-17 15:59:43 +000046
Mike Klein80e1d562018-03-22 11:36:52 -040047 void swap(SkTDArray& that) { std::swap(fVec, that.fVec); }
48
49 bool isEmpty() const { return fVec.empty(); }
50 int count() const { return SkToInt(fVec.size()); }
51 int reserved() const { return SkToInt(fVec.capacity()); }
52 size_t bytes() const { return sizeof(T) * fVec.size(); }
53
54 const T* begin() const { return fVec.data(); }
55 T* begin() { return fVec.data(); }
56 const T* end() const { return this->begin() + fVec.size(); }
57 T* end() { return this->begin() + fVec.size(); }
58
59 const T& operator[](int k) const { return fVec[SkToSizeT(k)]; }
60 T& operator[](int k) { return fVec[SkToSizeT(k)]; }
61 const T& getAt(int k) const { return fVec[SkToSizeT(k)]; }
62 T& getAt(int k) { return fVec[SkToSizeT(k)]; }
63
64 void reset() { this->~SkTDArray(); new (this) SkTDArray(); }
65 void rewind() { fVec.clear(); }
66 void setCount (int n) { T v; fVec.resize(SkToSizeT(n), v); }
67 void setReserve(int n) { fVec.reserve(SkToSizeT(n)); }
68 void shrinkToFit() { fVec.shrink_to_fit(); }
69
70 T* append(int n = 1, const T* src = nullptr) {
71 return this->insert(this->count(), n, src);
reed@android.com8a1c16f2008-12-17 15:59:43 +000072 }
Mike Klein80e1d562018-03-22 11:36:52 -040073 T* insert(int ix, int n = 1, const T* src = nullptr) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000074 if (src) {
Mike Klein7dd8ee92018-04-02 12:26:51 -040075 fVec.insert(fVec.begin() + SkToSizeT(ix), src, src+SkToSizeT(n));
76 } else {
77 T v;
78 fVec.insert(fVec.begin() + SkToSizeT(ix), SkToSizeT(n), v);
reed@android.com8a1c16f2008-12-17 15:59:43 +000079 }
Mike Klein7dd8ee92018-04-02 12:26:51 -040080 return &this->getAt(ix);
reed@android.com8a1c16f2008-12-17 15:59:43 +000081 }
82
Mike Klein80e1d562018-03-22 11:36:52 -040083 void remove(int ix, int n = 1) {
84 fVec.erase(fVec.begin() + SkToSizeT(ix),
85 fVec.begin() + SkToSizeT(ix) + SkToSizeT(n));
86 }
87 void removeShuffle(int ix) {
88 std::swap(fVec[SkToSizeT(ix)], fVec.back());
89 fVec.pop_back();
reed@android.com8a1c16f2008-12-17 15:59:43 +000090 }
91
Mike Klein80e1d562018-03-22 11:36:52 -040092 int find(const T& value) const {
93 for (int i = 0; i < this->count(); i++) {
94 if (fVec[i] == value) {
95 return i;
reed22b2af12016-08-29 07:52:13 -070096 }
97 }
98 return -1;
99 }
Mike Klein80e1d562018-03-22 11:36:52 -0400100 bool contains(const T& value) const {
101 return this->find(value) >= 0;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000102 }
103
Mike Klein80e1d562018-03-22 11:36:52 -0400104 void push(const T& value) { fVec.push_back(value); }
105 T* push() { T v; fVec.push_back(v); return &fVec.back(); }
106 void pop(T* value = nullptr) { if (value) { *value = fVec.back(); } fVec.pop_back(); }
107 const T& top() const { return fVec.back(); }
108 T& top() { return fVec.back(); }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000109
Mike Klein80e1d562018-03-22 11:36:52 -0400110 void deleteAll() { for (T ptr : fVec) { delete ptr; } this->reset(); }
111 void freeAll() { for (T ptr : fVec) { sk_free(ptr); } this->reset(); }
112 void unrefAll() { for (T ptr : fVec) { ptr->unref(); } this->reset(); }
113 void safeUnrefAll() { for (T ptr : fVec) { SkSafeUnref(ptr); } this->reset(); }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000114
Mike Klein80e1d562018-03-22 11:36:52 -0400115#if defined(SK_DEBUG)
116 void validate() const {}
reed@android.com8a1c16f2008-12-17 15:59:43 +0000117#endif
118
119private:
Mike Klein80e1d562018-03-22 11:36:52 -0400120 std::vector<T> fVec;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000121};
122
Mike Klein80e1d562018-03-22 11:36:52 -0400123// Avoid using std::vector<bool> (annoying weird bitvector specialization).
124
125struct SkTDArray_bool {
126 bool value;
127
128 SkTDArray_bool() = default;
129 SkTDArray_bool(bool v) : value(v) {}
130 operator bool() const { return value; }
131};
132
133template <>
134class SkTDArray<bool> : public SkTDArray<SkTDArray_bool> {};
135
reed@android.com8a1c16f2008-12-17 15:59:43 +0000136#endif