copy BitArray by reference

This commit is contained in:
David Rose 2006-06-08 00:21:08 +00:00
parent 8933f78230
commit bf6bb54c31
3 changed files with 44 additions and 8 deletions

View File

@ -518,3 +518,20 @@ operator >> (int shift) const {
result >>= shift;
return result;
}
////////////////////////////////////////////////////////////////////
// Function: BitArray::copy_on_write
// Access: Private
// Description: Called internally just before writing to the _array
// member, this makes a new copy of _array if it appears
// to be shared with any other objects--thus achieving
// copy-on-write.
////////////////////////////////////////////////////////////////////
INLINE void BitArray::
copy_on_write() {
if (_array.get_ref_count() > 1) {
PTA(MaskType) new_array;
new_array.v() = _array.v();
_array = new_array;
}
}

View File

@ -35,7 +35,7 @@ is_zero() const {
}
// Start from the high end, since that's more likely to be nonzero.
Array::const_reverse_iterator ai;
Array::reverse_iterator ai;
for (ai = _array.rbegin(); ai != _array.rend(); ++ai) {
if ((*ai) != 0) {
return false;
@ -157,6 +157,7 @@ clear_range(int low_bit, int size) {
void BitArray::
invert_in_place() {
_highest_bits = !_highest_bits;
copy_on_write();
Array::iterator ai;
for (ai = _array.begin(); ai != _array.end(); ++ai) {
(*ai) = ~(*ai);
@ -328,6 +329,8 @@ void BitArray::
operator &= (const BitArray &other) {
size_t num_common_words = min(_array.size(), other._array.size());
copy_on_write();
// Consider the words that are on top of either array.
if (other._array.size() < _array.size() && !other._highest_bits) {
// The other array has fewer actual words, and the top n words of
@ -365,6 +368,8 @@ void BitArray::
operator |= (const BitArray &other) {
size_t num_common_words = min(_array.size(), other._array.size());
copy_on_write();
// Consider the words that are on top of either array.
if (other._array.size() < _array.size() && other._highest_bits) {
// The other array has fewer actual words, and the top n words of
@ -402,6 +407,8 @@ void BitArray::
operator ^= (const BitArray &other) {
size_t num_common_words = min(_array.size(), other._array.size());
copy_on_write();
// Consider the words that are on top of either array.
if (other._array.size() < _array.size() && other._highest_bits) {
// The other array has fewer actual words, and the top n words of
@ -478,7 +485,7 @@ operator <<= (int shift) {
for (ai = _array.begin(); ai != _array.end(); ++ai) {
new_array.push_back(*ai);
}
_array.swap(new_array);
_array = new_array;
} else {
// Harder case--we have to shuffle bits between words.
@ -508,7 +515,7 @@ operator <<= (int shift) {
next_bits |= ~MaskType::lower_on(b);
}
new_array.push_back(next_bits);
_array.swap(new_array);
_array = new_array;
}
normalize();
@ -549,7 +556,7 @@ operator >>= (int shift) {
for (ai = _array.begin() + w; ai != _array.end(); ++ai) {
new_array.push_back(*ai);
}
_array.swap(new_array);
_array = new_array;
} else {
// Harder case--we have to shuffle bits between words.
@ -576,7 +583,7 @@ operator >>= (int shift) {
next_bits |= ~MaskType::lower_on(upshift_count);
}
new_array.push_back(next_bits);
_array.swap(new_array);
_array = new_array;
}
normalize();
@ -604,6 +611,8 @@ generate_hash(ChecksumHashGenerator &hashgen) const {
////////////////////////////////////////////////////////////////////
void BitArray::
ensure_has_word(int n) {
copy_on_write();
if (_highest_bits) {
while (n >= (int)_array.size()) {
_array.push_back(MaskType::all_on());
@ -625,12 +634,20 @@ ensure_has_word(int n) {
void BitArray::
normalize() {
if (_highest_bits) {
while (!_array.empty() && _array.back() == MaskType::all_on()) {
if (!_array.empty() && _array.back() == MaskType::all_on()) {
copy_on_write();
_array.pop_back();
while (!_array.empty() && _array.back() == MaskType::all_on()) {
_array.pop_back();
}
}
} else {
while (!_array.empty() && _array.back().is_zero()) {
if (!_array.empty() && _array.back().is_zero()) {
copy_on_write();
_array.pop_back();
while (!_array.empty() && _array.back().is_zero()) {
_array.pop_back();
}
}
}
}

View File

@ -25,6 +25,7 @@
#include "numeric_types.h"
#include "typedObject.h"
#include "indent.h"
#include "pointerToArray.h"
#include "checksumHashGenerator.h"
@ -121,11 +122,12 @@ public:
void generate_hash(ChecksumHashGenerator &hashgen) const;
private:
INLINE void copy_on_write();
void ensure_has_word(int n);
void normalize();
private:
typedef pvector<MaskType> Array;
typedef PTA(MaskType) Array;
Array _array;
int _highest_bits; // Either 0 or 1.