blob: e9660d88b7704919021cc0c226fc92b87cadb0bc [file] [log] [blame]
/*
* 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 "SkTypes.h"
#include <vector>
// SkTDArray is now a thin wrapper over std::vector.
// Please feel free to use either.
// Implementation notes:
// 1) We take care to use SkToInt(size_t) and SkToSizeT(int) to do conversions that
// assert the value fits either direction. The SkToInt(size_t) should be obvious,
// but even SkToSizeT(int) has caught negative values passed in where you'd expect
// >= 0.
//
// 2) We try to add yet-undefined items to the array with default initialization.
// This can look funny, as the only really good way to get that is to write
// "T v;", a T default-intialized on the stack, often meaning uninitialized.
// This avoids the slightly more expensive value initialization (like, floats
// to 0.0f) that std::vector normally provides.
//
// 3) See the end of the file for how we avoid std::vector<bool>.
template <typename T>
class SkTDArray {
public:
SkTDArray() = default;
~SkTDArray() = default;
SkTDArray(const SkTDArray&) = default;
SkTDArray(SkTDArray&&) = default;
SkTDArray& operator=(const SkTDArray&) = default;
SkTDArray& operator=(SkTDArray&&) = default;
SkTDArray(const T* src, int n) : fVec(src, src+SkToSizeT(n)) {}
friend bool operator==(const SkTDArray& a, const SkTDArray& b) { return a.fVec == b.fVec; }
friend bool operator!=(const SkTDArray& a, const SkTDArray& b) { return a.fVec != b.fVec; }
void swap(SkTDArray& that) { std::swap(fVec, that.fVec); }
bool isEmpty() const { return fVec.empty(); }
int count() const { return SkToInt(fVec.size()); }
int reserved() const { return SkToInt(fVec.capacity()); }
size_t bytes() const { return sizeof(T) * fVec.size(); }
const T* begin() const { return fVec.data(); }
T* begin() { return fVec.data(); }
const T* end() const { return this->begin() + fVec.size(); }
T* end() { return this->begin() + fVec.size(); }
const T& operator[](int k) const { return fVec[SkToSizeT(k)]; }
T& operator[](int k) { return fVec[SkToSizeT(k)]; }
const T& getAt(int k) const { return fVec[SkToSizeT(k)]; }
T& getAt(int k) { return fVec[SkToSizeT(k)]; }
void reset() { this->~SkTDArray(); new (this) SkTDArray(); }
void rewind() { fVec.clear(); }
void setCount (int n) { T v; fVec.resize(SkToSizeT(n), v); }
void setReserve(int n) { fVec.reserve(SkToSizeT(n)); }
void shrinkToFit() { fVec.shrink_to_fit(); }
T* append(int n = 1, const T* src = nullptr) {
return this->insert(this->count(), n, src);
}
T* insert(int ix, int n = 1, const T* src = nullptr) {
if (src) {
return &*fVec.insert(fVec.begin() + SkToSizeT(ix), src, src+SkToSizeT(n));
}
T v;
return &*fVec.insert(fVec.begin() + SkToSizeT(ix), SkToSizeT(n), v);
}
void remove(int ix, int n = 1) {
fVec.erase(fVec.begin() + SkToSizeT(ix),
fVec.begin() + SkToSizeT(ix) + SkToSizeT(n));
}
void removeShuffle(int ix) {
std::swap(fVec[SkToSizeT(ix)], fVec.back());
fVec.pop_back();
}
int find(const T& value) const {
for (int i = 0; i < this->count(); i++) {
if (fVec[i] == value) {
return i;
}
}
return -1;
}
bool contains(const T& value) const {
return this->find(value) >= 0;
}
void push(const T& value) { fVec.push_back(value); }
T* push() { T v; fVec.push_back(v); return &fVec.back(); }
void pop(T* value = nullptr) { if (value) { *value = fVec.back(); } fVec.pop_back(); }
const T& top() const { return fVec.back(); }
T& top() { return fVec.back(); }
void deleteAll() { for (T ptr : fVec) { delete ptr; } this->reset(); }
void freeAll() { for (T ptr : fVec) { sk_free(ptr); } this->reset(); }
void unrefAll() { for (T ptr : fVec) { ptr->unref(); } this->reset(); }
void safeUnrefAll() { for (T ptr : fVec) { SkSafeUnref(ptr); } this->reset(); }
#if defined(SK_DEBUG)
void validate() const {}
#endif
private:
std::vector<T> fVec;
};
// Avoid using std::vector<bool> (annoying weird bitvector specialization).
struct SkTDArray_bool {
bool value;
SkTDArray_bool() = default;
SkTDArray_bool(bool v) : value(v) {}
operator bool() const { return value; }
};
template <>
class SkTDArray<bool> : public SkTDArray<SkTDArray_bool> {};
#endif