bitvect: fix some issues observed on 32bit architectures.

* src/misc/bitvect.cc, src/misc/bitvect.hh: Do
not assume the two bitvect with the same size have
the same number of allocated blocks.  Fix an
assertion in extra_range().
This commit is contained in:
Alexandre Duret-Lutz 2014-01-15 15:52:11 +01:00
parent 534edd4d1c
commit 522373984c
2 changed files with 35 additions and 14 deletions

View file

@ -120,7 +120,10 @@ namespace spot
block_t res = fnv<sizeof(block_t)>::init(); block_t res = fnv<sizeof(block_t)>::init();
size_t i; size_t i;
for (i = 0; i < block_count_ - 1; ++i) size_t m = used_blocks();
if (m == 0)
return res;
for (i = 0; i < m - 1; ++i)
{ {
res ^= storage_[i]; res ^= storage_[i];
res *= fnv<sizeof(block_t)>::prime(); res *= fnv<sizeof(block_t)>::prime();

View file

@ -25,7 +25,9 @@
# include <cstdlib> # include <cstdlib>
# include <cassert> # include <cassert>
# include <iosfwd> # include <iosfwd>
# include <iostream> # include <iostream>
# include <algorithm>
namespace spot namespace spot
{ {
/// \addtogroup misc_tools /// \addtogroup misc_tools
@ -125,6 +127,13 @@ namespace spot
} }
public: public:
size_t used_blocks() const
{
const size_t bpb = 8 * sizeof(block_t);
return (size_ - 1) / bpb + 1;
}
/// Append one bit. /// Append one bit.
void push_back(bool val) void push_back(bool val)
{ {
@ -256,24 +265,27 @@ namespace spot
bitvect& operator|=(const bitvect& other) bitvect& operator|=(const bitvect& other)
{ {
assert(other.block_count_ <= block_count_); assert(other.size_ <= size_);
for (size_t i = 0; i < other.block_count_; ++i) unsigned m = std::min(other.block_count_, block_count_);
for (size_t i = 0; i < m; ++i)
storage_[i] |= other.storage_[i]; storage_[i] |= other.storage_[i];
return *this; return *this;
} }
bitvect& operator&=(const bitvect& other) bitvect& operator&=(const bitvect& other)
{ {
assert(other.block_count_ <= block_count_); assert(other.size_ <= size_);
for (size_t i = 0; i < other.block_count_; ++i) unsigned m = std::min(other.block_count_, block_count_);
for (size_t i = 0; i < m; ++i)
storage_[i] &= other.storage_[i]; storage_[i] &= other.storage_[i];
return *this; return *this;
} }
bitvect& operator^=(const bitvect& other) bitvect& operator^=(const bitvect& other)
{ {
assert(other.block_count_ <= block_count_); assert(other.size_ <= size_);
for (size_t i = 0; i < other.block_count_; ++i) unsigned m = std::min(other.block_count_, block_count_);
for (size_t i = 0; i < m; ++i)
storage_[i] ^= other.storage_[i]; storage_[i] ^= other.storage_[i];
return *this; return *this;
} }
@ -288,10 +300,13 @@ namespace spot
bool operator==(const bitvect& other) const bool operator==(const bitvect& other) const
{ {
if (other.block_count_ != block_count_) if (other.size_ != size_)
return false; return false;
if (size_ == 0)
return true;
size_t i; size_t i;
for (i = 0; i < other.block_count_ - 1; ++i) size_t m = other.used_blocks();
for (i = 0; i < m - 1; ++i)
if (storage_[i] != other.storage_[i]) if (storage_[i] != other.storage_[i])
return false; return false;
// The last block might not be fully used, compare only the // The last block might not be fully used, compare only the
@ -308,10 +323,13 @@ namespace spot
bool operator<(const bitvect& other) const bool operator<(const bitvect& other) const
{ {
if (block_count_ != other.block_count_) if (size_ != other.size_)
return block_count_ < other.block_count_; return size_ < other.size_;
if (size_ == 0)
return false;
size_t i; size_t i;
for (i = 0; i < other.block_count_ - 1; ++i) size_t m = other.used_blocks();
for (i = 0; i < m - 1; ++i)
if (storage_[i] > other.storage_[i]) if (storage_[i] > other.storage_[i])
return false; return false;
// The last block might not be fully used, compare only the // The last block might not be fully used, compare only the
@ -374,7 +392,7 @@ namespace spot
++indexb; ++indexb;
res->push_back(storage_[indexb], bpb); res->push_back(storage_[indexb], bpb);
count -= bpb; count -= bpb;
assert(indexb != indexe || bpb == 0); assert(indexb != indexe || count == 0);
} }
if (count > 0) if (count > 0)
{ {