Avoid null PODArray<> issues in SparseSet and SparseArray<>.
Change-Id: Ibd21e4277c2855d8572762e6f6ea9b3f90159273
Reviewed-on: https://code-review.googlesource.com/c/37398
Reviewed-by: Paul Wankadia <junyer@google.com>
diff --git a/util/sparse_array.h b/util/sparse_array.h
index 0c085d5..c81c9f3 100644
--- a/util/sparse_array.h
+++ b/util/sparse_array.h
@@ -152,12 +152,15 @@
// Change the maximum size of the array.
// Invalidates all iterators.
- void resize(int max_size);
+ void resize(int new_max_size);
// Return the maximum size of the array.
// Indices can be in the range [0, max_size).
int max_size() const {
- return dense_.size();
+ if (dense_.data() != NULL)
+ return dense_.size();
+ else
+ return 0;
}
// Clear the array.
@@ -206,7 +209,7 @@
private:
iterator SetInternal(bool allow_existing, int i, const Value& v) {
DebugCheckInvariants();
- if (static_cast<uint32_t>(i) >= static_cast<uint32_t>(dense_.size())) {
+ if (static_cast<uint32_t>(i) >= static_cast<uint32_t>(max_size())) {
assert(false && "illegal index");
// Semantically, end() would be better here, but we already know
// the user did something stupid, so begin() insulates them from
@@ -265,10 +268,10 @@
template<typename Value>
SparseArray<Value>::SparseArray(const SparseArray& src)
: size_(src.size_),
- sparse_(src.sparse_.size()),
- dense_(src.dense_.size()) {
- std::copy_n(src.sparse_.data(), src.sparse_.size(), sparse_.data());
- std::copy_n(src.dense_.data(), src.dense_.size(), dense_.data());
+ sparse_(src.max_size()),
+ dense_(src.max_size()) {
+ std::copy_n(src.sparse_.data(), src.max_size(), sparse_.data());
+ std::copy_n(src.dense_.data(), src.max_size(), dense_.data());
}
template<typename Value>
@@ -282,14 +285,14 @@
template<typename Value>
SparseArray<Value>& SparseArray<Value>::operator=(const SparseArray& src) {
// Construct these first for exception safety.
- PODArray<int> a(src.sparse_.size());
- PODArray<IndexValue> b(src.dense_.size());
+ PODArray<int> a(src.max_size());
+ PODArray<IndexValue> b(src.max_size());
size_ = src.size_;
sparse_ = std::move(a);
dense_ = std::move(b);
- std::copy_n(src.sparse_.data(), src.sparse_.size(), sparse_.data());
- std::copy_n(src.dense_.data(), src.dense_.size(), dense_.data());
+ std::copy_n(src.sparse_.data(), src.max_size(), sparse_.data());
+ std::copy_n(src.dense_.data(), src.max_size(), dense_.data());
return *this;
}
@@ -319,28 +322,25 @@
// Change the maximum size of the array.
// Invalidates all iterators.
template<typename Value>
-void SparseArray<Value>::resize(int max_size) {
+void SparseArray<Value>::resize(int new_max_size) {
DebugCheckInvariants();
- if (max_size > dense_.size()) {
- const int old_max_size = dense_.size();
+ if (new_max_size > max_size()) {
+ const int old_max_size = max_size();
- PODArray<int> a(max_size);
- if (sparse_.data() != NULL) {
- std::copy_n(sparse_.data(), old_max_size, a.data());
- }
+ // Construct these first for exception safety.
+ PODArray<int> a(new_max_size);
+ PODArray<IndexValue> b(new_max_size);
- PODArray<IndexValue> b(max_size);
- if (dense_.data() != NULL) {
- std::copy_n(dense_.data(), old_max_size, b.data());
- }
+ std::copy_n(sparse_.data(), old_max_size, a.data());
+ std::copy_n(dense_.data(), old_max_size, b.data());
sparse_ = std::move(a);
dense_ = std::move(b);
- MaybeInitializeMemory(old_max_size, max_size);
+ MaybeInitializeMemory(old_max_size, new_max_size);
}
- if (size_ > max_size)
- size_ = max_size;
+ if (size_ > new_max_size)
+ size_ = new_max_size;
DebugCheckInvariants();
}
@@ -348,8 +348,8 @@
template<typename Value>
bool SparseArray<Value>::has_index(int i) const {
assert(i >= 0);
- assert(i < dense_.size());
- if (static_cast<uint32_t>(i) >= static_cast<uint32_t>(dense_.size())) {
+ assert(i < max_size());
+ if (static_cast<uint32_t>(i) >= static_cast<uint32_t>(max_size())) {
return false;
}
// Unsigned comparison avoids checking sparse_[i] < 0.
@@ -360,7 +360,7 @@
template<typename Value>
void SparseArray<Value>::create_index(int i) {
assert(!has_index(i));
- assert(size_ < dense_.size());
+ assert(size_ < max_size());
sparse_[i] = size_;
dense_[size_].index_ = i;
size_++;
@@ -378,9 +378,7 @@
template<typename Value> void SparseArray<Value>::DebugCheckInvariants() const {
assert(0 <= size_);
- assert(size_ <= dense_.size());
- assert(sparse_.size() == dense_.size());
- assert(size_ == 0 || dense_.data() != NULL);
+ assert(size_ <= max_size());
}
// Comparison function for sorting.
diff --git a/util/sparse_set.h b/util/sparse_set.h
index 6b1a8e5..0d5ad51 100644
--- a/util/sparse_set.h
+++ b/util/sparse_set.h
@@ -102,12 +102,15 @@
// Change the maximum size of the set.
// Invalidates all iterators.
- void resize(int max_size);
+ void resize(int new_max_size);
// Return the maximum size of the set.
// Indices can be in the range [0, max_size).
int max_size() const {
- return dense_.size();
+ if (dense_.data() != NULL)
+ return dense_.size();
+ else
+ return 0;
}
// Clear the set.
@@ -139,7 +142,7 @@
private:
iterator InsertInternal(bool allow_existing, int i) {
DebugCheckInvariants();
- if (static_cast<uint32_t>(i) >= static_cast<uint32_t>(dense_.size())) {
+ if (static_cast<uint32_t>(i) >= static_cast<uint32_t>(max_size())) {
assert(false && "illegal index");
// Semantically, end() would be better here, but we already know
// the user did something stupid, so begin() insulates them from
@@ -190,28 +193,25 @@
// Change the maximum size of the set.
// Invalidates all iterators.
template<typename Value>
-void SparseSetT<Value>::resize(int max_size) {
+void SparseSetT<Value>::resize(int new_max_size) {
DebugCheckInvariants();
- if (max_size > dense_.size()) {
- const int old_max_size = dense_.size();
+ if (new_max_size > max_size()) {
+ const int old_max_size = max_size();
- PODArray<int> a(max_size);
- if (sparse_.data() != NULL) {
- std::copy_n(sparse_.data(), old_max_size, a.data());
- }
+ // Construct these first for exception safety.
+ PODArray<int> a(new_max_size);
+ PODArray<int> b(new_max_size);
- PODArray<int> b(max_size);
- if (dense_.data() != NULL) {
- std::copy_n(dense_.data(), old_max_size, b.data());
- }
+ std::copy_n(sparse_.data(), old_max_size, a.data());
+ std::copy_n(dense_.data(), old_max_size, b.data());
sparse_ = std::move(a);
dense_ = std::move(b);
- MaybeInitializeMemory(old_max_size, max_size);
+ MaybeInitializeMemory(old_max_size, new_max_size);
}
- if (size_ > max_size)
- size_ = max_size;
+ if (size_ > new_max_size)
+ size_ = new_max_size;
DebugCheckInvariants();
}
@@ -219,8 +219,8 @@
template<typename Value>
bool SparseSetT<Value>::contains(int i) const {
assert(i >= 0);
- assert(i < dense_.size());
- if (static_cast<uint32_t>(i) >= static_cast<uint32_t>(dense_.size())) {
+ assert(i < max_size());
+ if (static_cast<uint32_t>(i) >= static_cast<uint32_t>(max_size())) {
return false;
}
// Unsigned comparison avoids checking sparse_[i] < 0.
@@ -231,7 +231,7 @@
template<typename Value>
void SparseSetT<Value>::create_index(int i) {
assert(!contains(i));
- assert(size_ < dense_.size());
+ assert(size_ < max_size());
sparse_[i] = size_;
dense_[size_] = i;
size_++;
@@ -249,9 +249,7 @@
template<typename Value> void SparseSetT<Value>::DebugCheckInvariants() const {
assert(0 <= size_);
- assert(size_ <= dense_.size());
- assert(sparse_.size() == dense_.size());
- assert(size_ == 0 || dense_.data() != NULL);
+ assert(size_ <= max_size());
}
// Comparison function for sorting.