blob: e9660d88b7704919021cc0c226fc92b87cadb0bc [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 Klein80e1d562018-03-22 11:36:52 -040075 return &*fVec.insert(fVec.begin() + SkToSizeT(ix), src, src+SkToSizeT(n));
reed@android.com8a1c16f2008-12-17 15:59:43 +000076 }
Mike Klein80e1d562018-03-22 11:36:52 -040077 T v;
78 return &*fVec.insert(fVec.begin() + SkToSizeT(ix), SkToSizeT(n), v);
reed@android.com8a1c16f2008-12-17 15:59:43 +000079 }
80
Mike Klein80e1d562018-03-22 11:36:52 -040081 void remove(int ix, int n = 1) {
82 fVec.erase(fVec.begin() + SkToSizeT(ix),
83 fVec.begin() + SkToSizeT(ix) + SkToSizeT(n));
84 }
85 void removeShuffle(int ix) {
86 std::swap(fVec[SkToSizeT(ix)], fVec.back());
87 fVec.pop_back();
reed@android.com8a1c16f2008-12-17 15:59:43 +000088 }
89
Mike Klein80e1d562018-03-22 11:36:52 -040090 int find(const T& value) const {
91 for (int i = 0; i < this->count(); i++) {
92 if (fVec[i] == value) {
93 return i;
reed22b2af12016-08-29 07:52:13 -070094 }
95 }
96 return -1;
97 }
Mike Klein80e1d562018-03-22 11:36:52 -040098 bool contains(const T& value) const {
99 return this->find(value) >= 0;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000100 }
101
Mike Klein80e1d562018-03-22 11:36:52 -0400102 void push(const T& value) { fVec.push_back(value); }
103 T* push() { T v; fVec.push_back(v); return &fVec.back(); }
104 void pop(T* value = nullptr) { if (value) { *value = fVec.back(); } fVec.pop_back(); }
105 const T& top() const { return fVec.back(); }
106 T& top() { return fVec.back(); }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000107
Mike Klein80e1d562018-03-22 11:36:52 -0400108 void deleteAll() { for (T ptr : fVec) { delete ptr; } this->reset(); }
109 void freeAll() { for (T ptr : fVec) { sk_free(ptr); } this->reset(); }
110 void unrefAll() { for (T ptr : fVec) { ptr->unref(); } this->reset(); }
111 void safeUnrefAll() { for (T ptr : fVec) { SkSafeUnref(ptr); } this->reset(); }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000112
Mike Klein80e1d562018-03-22 11:36:52 -0400113#if defined(SK_DEBUG)
114 void validate() const {}
reed@android.com8a1c16f2008-12-17 15:59:43 +0000115#endif
116
117private:
Mike Klein80e1d562018-03-22 11:36:52 -0400118 std::vector<T> fVec;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000119};
120
Mike Klein80e1d562018-03-22 11:36:52 -0400121// Avoid using std::vector<bool> (annoying weird bitvector specialization).
122
123struct SkTDArray_bool {
124 bool value;
125
126 SkTDArray_bool() = default;
127 SkTDArray_bool(bool v) : value(v) {}
128 operator bool() const { return value; }
129};
130
131template <>
132class SkTDArray<bool> : public SkTDArray<SkTDArray_bool> {};
133
reed@android.com8a1c16f2008-12-17 15:59:43 +0000134#endif