reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 1 | /* |
epoger@google.com | ec3ed6a | 2011-07-28 14:26:00 +0000 | [diff] [blame] | 2 | * Copyright 2006 The Android Open Source Project |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 3 | * |
epoger@google.com | ec3ed6a | 2011-07-28 14:26:00 +0000 | [diff] [blame] | 4 | * Use of this source code is governed by a BSD-style license that can be |
| 5 | * found in the LICENSE file. |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 6 | */ |
| 7 | |
epoger@google.com | ec3ed6a | 2011-07-28 14:26:00 +0000 | [diff] [blame] | 8 | |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 9 | #ifndef SkTDArray_DEFINED |
| 10 | #define SkTDArray_DEFINED |
| 11 | |
| 12 | #include "SkTypes.h" |
Mike Klein | 80e1d56 | 2018-03-22 11:36:52 -0400 | [diff] [blame^] | 13 | #include <vector> |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 14 | |
Mike Klein | 80e1d56 | 2018-03-22 11:36:52 -0400 | [diff] [blame^] | 15 | // 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 | |
| 32 | template <typename T> |
| 33 | class SkTDArray { |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 34 | public: |
Mike Klein | 80e1d56 | 2018-03-22 11:36:52 -0400 | [diff] [blame^] | 35 | 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.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 41 | |
Mike Klein | 80e1d56 | 2018-03-22 11:36:52 -0400 | [diff] [blame^] | 42 | SkTDArray(const T* src, int n) : fVec(src, src+SkToSizeT(n)) {} |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 43 | |
Mike Klein | 80e1d56 | 2018-03-22 11:36:52 -0400 | [diff] [blame^] | 44 | 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.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 46 | |
Mike Klein | 80e1d56 | 2018-03-22 11:36:52 -0400 | [diff] [blame^] | 47 | 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.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 72 | } |
Mike Klein | 80e1d56 | 2018-03-22 11:36:52 -0400 | [diff] [blame^] | 73 | T* insert(int ix, int n = 1, const T* src = nullptr) { |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 74 | if (src) { |
Mike Klein | 80e1d56 | 2018-03-22 11:36:52 -0400 | [diff] [blame^] | 75 | return &*fVec.insert(fVec.begin() + SkToSizeT(ix), src, src+SkToSizeT(n)); |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 76 | } |
Mike Klein | 80e1d56 | 2018-03-22 11:36:52 -0400 | [diff] [blame^] | 77 | T v; |
| 78 | return &*fVec.insert(fVec.begin() + SkToSizeT(ix), SkToSizeT(n), v); |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 79 | } |
| 80 | |
Mike Klein | 80e1d56 | 2018-03-22 11:36:52 -0400 | [diff] [blame^] | 81 | 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.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 88 | } |
| 89 | |
Mike Klein | 80e1d56 | 2018-03-22 11:36:52 -0400 | [diff] [blame^] | 90 | int find(const T& value) const { |
| 91 | for (int i = 0; i < this->count(); i++) { |
| 92 | if (fVec[i] == value) { |
| 93 | return i; |
reed | 22b2af1 | 2016-08-29 07:52:13 -0700 | [diff] [blame] | 94 | } |
| 95 | } |
| 96 | return -1; |
| 97 | } |
Mike Klein | 80e1d56 | 2018-03-22 11:36:52 -0400 | [diff] [blame^] | 98 | bool contains(const T& value) const { |
| 99 | return this->find(value) >= 0; |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 100 | } |
| 101 | |
Mike Klein | 80e1d56 | 2018-03-22 11:36:52 -0400 | [diff] [blame^] | 102 | 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.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 107 | |
Mike Klein | 80e1d56 | 2018-03-22 11:36:52 -0400 | [diff] [blame^] | 108 | 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.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 112 | |
Mike Klein | 80e1d56 | 2018-03-22 11:36:52 -0400 | [diff] [blame^] | 113 | #if defined(SK_DEBUG) |
| 114 | void validate() const {} |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 115 | #endif |
| 116 | |
| 117 | private: |
Mike Klein | 80e1d56 | 2018-03-22 11:36:52 -0400 | [diff] [blame^] | 118 | std::vector<T> fVec; |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 119 | }; |
| 120 | |
Mike Klein | 80e1d56 | 2018-03-22 11:36:52 -0400 | [diff] [blame^] | 121 | // Avoid using std::vector<bool> (annoying weird bitvector specialization). |
| 122 | |
| 123 | struct 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 | |
| 131 | template <> |
| 132 | class SkTDArray<bool> : public SkTDArray<SkTDArray_bool> {}; |
| 133 | |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 134 | #endif |