2009-06-15 00:11:06 +00:00
|
|
|
/*
|
2014-01-19 01:09:44 +00:00
|
|
|
* This file Copyright (C) 2008-2014 Mnemosyne LLC
|
2009-06-15 00:11:06 +00:00
|
|
|
*
|
2014-01-21 03:10:30 +00:00
|
|
|
* It may be used under the GNU GPL versions 2 or 3
|
2014-01-19 01:09:44 +00:00
|
|
|
* or any future license endorsed by Mnemosyne LLC.
|
2009-06-15 00:11:06 +00:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2021-09-19 20:41:35 +00:00
|
|
|
#include <algorithm>
|
2021-10-16 14:04:19 +00:00
|
|
|
#include <iterator> // std::back_inserter
|
|
|
|
#include <numeric> // std::accumulate
|
2009-06-15 00:11:06 +00:00
|
|
|
|
|
|
|
#include "transmission.h"
|
|
|
|
#include "bitfield.h"
|
2017-06-08 07:24:12 +00:00
|
|
|
#include "tr-assert.h"
|
2021-10-16 14:04:19 +00:00
|
|
|
#include "span.h"
|
2011-02-23 03:54:04 +00:00
|
|
|
|
2011-03-28 16:31:05 +00:00
|
|
|
/****
|
|
|
|
*****
|
|
|
|
****/
|
|
|
|
|
2021-10-16 14:04:19 +00:00
|
|
|
std::array<int8_t const, 256> Bitfield::true_bits_lookup_ = {
|
2021-08-15 09:41:48 +00:00
|
|
|
0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, //
|
|
|
|
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, //
|
|
|
|
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, //
|
|
|
|
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, //
|
|
|
|
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, //
|
|
|
|
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, //
|
|
|
|
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, //
|
|
|
|
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, //
|
|
|
|
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, //
|
|
|
|
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, //
|
|
|
|
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, //
|
|
|
|
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, //
|
|
|
|
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, //
|
|
|
|
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, //
|
|
|
|
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, //
|
|
|
|
4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, //
|
2011-03-28 16:31:05 +00:00
|
|
|
};
|
|
|
|
|
2021-10-16 14:04:19 +00:00
|
|
|
size_t Bitfield::countArray() const
|
2011-03-30 04:14:57 +00:00
|
|
|
{
|
2021-10-16 14:04:19 +00:00
|
|
|
return std::accumulate(
|
|
|
|
std::begin(bits_),
|
|
|
|
std::end(bits_),
|
|
|
|
0,
|
|
|
|
[](auto acc, auto item) { return acc + true_bits_lookup_[item]; });
|
2011-03-30 04:14:57 +00:00
|
|
|
}
|
|
|
|
|
2021-10-11 17:29:14 +00:00
|
|
|
size_t Bitfield::countRangeImpl(size_t begin, size_t end) const
|
2011-03-28 16:31:05 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
size_t ret = 0;
|
2019-03-17 04:07:48 +00:00
|
|
|
size_t const first_byte = begin >> 3U;
|
|
|
|
size_t const last_byte = (end - 1) >> 3U;
|
2012-12-05 17:29:46 +00:00
|
|
|
|
2021-10-16 14:04:19 +00:00
|
|
|
if (bit_count_ == 0)
|
2017-04-19 12:04:45 +00:00
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
2011-03-28 16:31:05 +00:00
|
|
|
|
2021-10-16 14:04:19 +00:00
|
|
|
if (first_byte >= std::size(bits_))
|
2017-04-19 12:04:45 +00:00
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
2011-03-29 16:39:30 +00:00
|
|
|
|
2017-06-08 07:24:12 +00:00
|
|
|
TR_ASSERT(begin < end);
|
2011-03-28 16:31:05 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
if (first_byte == last_byte)
|
2011-03-28 16:31:05 +00:00
|
|
|
{
|
2021-10-16 14:04:19 +00:00
|
|
|
uint8_t val = bits_[first_byte];
|
2011-03-28 16:31:05 +00:00
|
|
|
|
2021-10-06 22:24:04 +00:00
|
|
|
int i = begin - (first_byte * 8);
|
2017-04-19 12:04:45 +00:00
|
|
|
val <<= i;
|
|
|
|
val >>= i;
|
|
|
|
i = (last_byte + 1) * 8 - end;
|
|
|
|
val >>= i;
|
|
|
|
val <<= i;
|
2011-03-28 16:31:05 +00:00
|
|
|
|
2021-10-16 14:04:19 +00:00
|
|
|
ret += true_bits_lookup_[val];
|
2011-03-28 16:31:05 +00:00
|
|
|
}
|
2017-04-19 12:04:45 +00:00
|
|
|
else
|
2011-03-28 16:31:05 +00:00
|
|
|
{
|
2021-10-16 14:04:19 +00:00
|
|
|
size_t const walk_end = std::min(std::size(bits_), last_byte);
|
2017-04-19 12:04:45 +00:00
|
|
|
|
|
|
|
/* first byte */
|
2017-05-13 22:38:31 +00:00
|
|
|
size_t const first_shift = begin - (first_byte * 8);
|
2021-10-16 14:04:19 +00:00
|
|
|
uint8_t val = bits_[first_byte];
|
2017-05-13 22:38:31 +00:00
|
|
|
val <<= first_shift;
|
|
|
|
val >>= first_shift;
|
2021-10-16 14:04:19 +00:00
|
|
|
ret += true_bits_lookup_[val];
|
2017-04-19 12:04:45 +00:00
|
|
|
|
|
|
|
/* middle bytes */
|
2017-05-13 22:38:31 +00:00
|
|
|
for (size_t i = first_byte + 1; i < walk_end; ++i)
|
2017-04-19 12:04:45 +00:00
|
|
|
{
|
2021-10-16 14:04:19 +00:00
|
|
|
ret += true_bits_lookup_[bits_[i]];
|
2017-04-19 12:04:45 +00:00
|
|
|
}
|
2012-12-05 17:29:46 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
/* last byte */
|
2021-10-16 14:04:19 +00:00
|
|
|
if (last_byte < std::size(bits_))
|
2012-12-05 17:29:46 +00:00
|
|
|
{
|
2017-05-13 22:38:31 +00:00
|
|
|
size_t const last_shift = (last_byte + 1) * 8 - end;
|
2021-10-16 14:04:19 +00:00
|
|
|
val = bits_[last_byte];
|
2017-05-13 22:38:31 +00:00
|
|
|
val >>= last_shift;
|
|
|
|
val <<= last_shift;
|
2021-10-16 14:04:19 +00:00
|
|
|
ret += true_bits_lookup_[val];
|
2011-03-30 04:14:57 +00:00
|
|
|
}
|
2011-03-28 16:31:05 +00:00
|
|
|
}
|
|
|
|
|
2021-10-16 14:04:19 +00:00
|
|
|
TR_ASSERT(ret <= (end - begin));
|
2017-04-19 12:04:45 +00:00
|
|
|
return ret;
|
2009-06-15 00:11:06 +00:00
|
|
|
}
|
|
|
|
|
2021-10-11 17:29:14 +00:00
|
|
|
bool Bitfield::readBit(size_t n) const
|
2011-03-28 16:31:05 +00:00
|
|
|
{
|
2021-10-16 14:04:19 +00:00
|
|
|
switch (mode_)
|
2017-04-19 12:04:45 +00:00
|
|
|
{
|
2021-10-16 14:04:19 +00:00
|
|
|
case OperationMode::Normal:
|
|
|
|
{
|
|
|
|
auto const byte_offset = n >> 3;
|
2012-12-13 02:00:45 +00:00
|
|
|
|
2021-10-16 14:04:19 +00:00
|
|
|
if (byte_offset >= std::size(bits_))
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2012-12-13 02:00:45 +00:00
|
|
|
|
2021-10-16 14:04:19 +00:00
|
|
|
return ((bits_[byte_offset] << (n & 7)) & 0x80) != 0;
|
|
|
|
}
|
|
|
|
case OperationMode::All:
|
|
|
|
return true;
|
|
|
|
case OperationMode::None:
|
2017-04-19 12:04:45 +00:00
|
|
|
return false;
|
2021-10-16 14:04:19 +00:00
|
|
|
case OperationMode::Start:
|
|
|
|
TR_UNREACHABLE();
|
2017-04-19 12:04:45 +00:00
|
|
|
}
|
2021-10-16 14:04:19 +00:00
|
|
|
return false;
|
2012-12-13 02:00:45 +00:00
|
|
|
}
|
|
|
|
|
2011-03-28 16:31:05 +00:00
|
|
|
/***
|
|
|
|
****
|
|
|
|
***/
|
|
|
|
|
2017-06-08 07:24:12 +00:00
|
|
|
#ifdef TR_ENABLE_ASSERTS
|
2015-05-31 22:13:31 +00:00
|
|
|
|
2021-10-11 17:29:14 +00:00
|
|
|
bool Bitfield::isValid() const
|
2011-03-28 16:31:05 +00:00
|
|
|
{
|
2021-10-16 14:04:19 +00:00
|
|
|
TR_ASSERT_MSG(
|
|
|
|
std::size(bits_) == 0 || true_count_ == countArray(),
|
|
|
|
"Invalid Bitfield state: bits.size()=%zu bit_count=%zu true_count=%zu countArray()=%zu",
|
|
|
|
std::size(bits_),
|
|
|
|
bit_count_,
|
|
|
|
true_count_,
|
|
|
|
countArray());
|
2012-12-05 17:29:46 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
return true;
|
2011-03-30 04:14:57 +00:00
|
|
|
}
|
|
|
|
|
2015-05-31 22:13:31 +00:00
|
|
|
#endif
|
|
|
|
|
2021-10-11 17:29:14 +00:00
|
|
|
size_t Bitfield::countBits() const
|
2011-04-05 00:29:42 +00:00
|
|
|
{
|
2021-10-16 14:04:19 +00:00
|
|
|
TR_ASSERT(isValid());
|
2012-12-05 17:29:46 +00:00
|
|
|
|
2021-10-16 14:04:19 +00:00
|
|
|
return true_count_;
|
2011-04-05 00:29:42 +00:00
|
|
|
}
|
|
|
|
|
2021-10-16 14:04:19 +00:00
|
|
|
void Bitfield::setBitsInArray(std::vector<uint8_t>& array, size_t bit_count)
|
2011-03-30 04:14:57 +00:00
|
|
|
{
|
2021-10-16 14:04:19 +00:00
|
|
|
TR_ASSERT(getStorageSize(bit_count) == std::size(array));
|
2012-12-05 17:29:46 +00:00
|
|
|
|
2021-10-16 14:04:19 +00:00
|
|
|
if (!std::empty(array) && bit_count > 0)
|
2013-07-29 04:19:15 +00:00
|
|
|
{
|
2021-10-16 14:04:19 +00:00
|
|
|
auto const last_byte_index = getStorageSize(bit_count) - 1;
|
2012-12-05 17:29:46 +00:00
|
|
|
|
2021-10-16 14:04:19 +00:00
|
|
|
std::fill_n(std::begin(array), last_byte_index, 0xFF);
|
|
|
|
array[last_byte_index] = 0xFF << (last_byte_index * 8 - bit_count);
|
2013-07-29 04:19:15 +00:00
|
|
|
}
|
2011-03-28 16:31:05 +00:00
|
|
|
}
|
|
|
|
|
2021-10-16 14:04:19 +00:00
|
|
|
std::vector<uint8_t> Bitfield::getRaw() const
|
2009-06-15 00:11:06 +00:00
|
|
|
{
|
2021-10-16 14:04:19 +00:00
|
|
|
TR_ASSERT(bit_count_ > 0);
|
2011-03-28 16:31:05 +00:00
|
|
|
|
2021-10-16 14:04:19 +00:00
|
|
|
size_t const n = getStorageSize(bit_count_);
|
|
|
|
auto new_bits = std::vector<uint8_t>(n);
|
2011-03-30 04:14:57 +00:00
|
|
|
|
2021-10-16 14:04:19 +00:00
|
|
|
if (!std::empty(bits_))
|
2011-03-30 04:14:57 +00:00
|
|
|
{
|
2021-10-16 14:04:19 +00:00
|
|
|
TR_ASSERT(std::size(bits_) <= n);
|
|
|
|
std::copy(std::cbegin(bits_), std::cend(bits_), std::back_inserter(new_bits));
|
2011-03-30 04:14:57 +00:00
|
|
|
}
|
2021-10-16 14:04:19 +00:00
|
|
|
else if (hasAll())
|
2017-04-19 12:04:45 +00:00
|
|
|
{
|
2021-10-16 14:04:19 +00:00
|
|
|
setBitsInArray(new_bits, bit_count_);
|
2017-04-19 12:04:45 +00:00
|
|
|
}
|
2014-06-29 01:43:27 +00:00
|
|
|
|
2021-10-16 14:04:19 +00:00
|
|
|
return new_bits;
|
2011-03-28 16:31:05 +00:00
|
|
|
}
|
|
|
|
|
2021-10-16 14:04:19 +00:00
|
|
|
void Bitfield::ensureNthBitFits(size_t n)
|
2011-03-28 16:31:05 +00:00
|
|
|
{
|
2021-10-16 14:04:19 +00:00
|
|
|
TR_ASSERT_MSG(mode_ == OperationMode::Normal, "Can only reallocate storage in Normal mode");
|
2015-12-27 16:34:47 +00:00
|
|
|
|
2021-10-16 14:04:19 +00:00
|
|
|
size_t bytes_needed = getStorageSize(std::max(n, true_count_));
|
2011-03-28 16:31:05 +00:00
|
|
|
|
2021-10-16 14:04:19 +00:00
|
|
|
if (std::size(bits_) < bytes_needed)
|
2017-04-19 12:04:45 +00:00
|
|
|
{
|
2021-10-16 14:04:19 +00:00
|
|
|
bits_.resize(bytes_needed);
|
2017-04-19 12:04:45 +00:00
|
|
|
}
|
2015-12-27 16:34:47 +00:00
|
|
|
}
|
|
|
|
|
2011-03-28 16:31:05 +00:00
|
|
|
/****
|
|
|
|
*****
|
|
|
|
****/
|
|
|
|
|
2021-10-11 17:29:14 +00:00
|
|
|
Bitfield::Bitfield(size_t bit_count)
|
2011-02-23 03:54:04 +00:00
|
|
|
{
|
2021-10-16 14:04:19 +00:00
|
|
|
bit_count_ = bit_count;
|
|
|
|
true_count_ = 0;
|
|
|
|
setMode(OperationMode::Normal);
|
2021-10-11 17:29:14 +00:00
|
|
|
|
2021-10-16 14:04:19 +00:00
|
|
|
TR_ASSERT(isValid());
|
2009-06-15 00:11:06 +00:00
|
|
|
}
|
|
|
|
|
2021-10-16 14:04:19 +00:00
|
|
|
void Bitfield::setMode(Bitfield::OperationMode new_mode)
|
2011-03-28 16:31:05 +00:00
|
|
|
{
|
2021-10-16 14:04:19 +00:00
|
|
|
switch (new_mode)
|
2017-04-19 12:04:45 +00:00
|
|
|
{
|
2021-10-16 14:04:19 +00:00
|
|
|
case OperationMode::Normal:
|
|
|
|
switch (mode_)
|
|
|
|
{
|
|
|
|
case OperationMode::All:
|
|
|
|
{
|
|
|
|
// Switching from ALL mode to NORMAL, should set the bits
|
|
|
|
mode_ = OperationMode::Normal;
|
|
|
|
ensureNthBitFits(bit_count_);
|
|
|
|
setBitRangeImpl(0, bit_count_ - 1);
|
|
|
|
true_count_ = bit_count_; // switching from mode ALL, all bits are set
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case OperationMode::None:
|
|
|
|
{
|
|
|
|
// Switching from ALL mode to NORMAL, should set the bits
|
|
|
|
mode_ = OperationMode::Normal;
|
|
|
|
ensureNthBitFits(bit_count_);
|
|
|
|
clearBitRangeImpl(0, bit_count_ - 1);
|
|
|
|
true_count_ = 0; // switching from mode NONE, all bits are not set
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case OperationMode::Start:
|
|
|
|
mode_ = OperationMode::Normal;
|
|
|
|
// fall through
|
|
|
|
case OperationMode::Normal:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case OperationMode::All:
|
|
|
|
clearStorage();
|
|
|
|
true_count_ = bit_count_;
|
|
|
|
mode_ = OperationMode::All;
|
|
|
|
break;
|
|
|
|
case OperationMode::None:
|
|
|
|
clearStorage();
|
|
|
|
true_count_ = 0;
|
|
|
|
mode_ = OperationMode::None;
|
|
|
|
break;
|
|
|
|
case OperationMode::Start:
|
|
|
|
TR_UNREACHABLE();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
TR_ASSERT(isValid());
|
2011-03-28 16:31:05 +00:00
|
|
|
}
|
|
|
|
|
2021-10-16 14:04:19 +00:00
|
|
|
Bitfield::Bitfield(Span<uint8_t> new_bits, size_t bit_count, bool bounded)
|
|
|
|
: bit_count_(bit_count)
|
2011-03-28 16:31:05 +00:00
|
|
|
{
|
2021-10-16 14:04:19 +00:00
|
|
|
true_count_ = 0;
|
|
|
|
setMode(OperationMode::Normal);
|
2012-12-05 17:29:46 +00:00
|
|
|
|
2021-10-16 14:04:19 +00:00
|
|
|
// Having bounded=true, limits the amount of moved data to available storage size
|
|
|
|
size_t byte_count = bounded ? std::min(std::size(new_bits), getStorageSize(bit_count_)) : std::size(new_bits);
|
2012-12-05 17:29:46 +00:00
|
|
|
|
2021-10-16 14:04:19 +00:00
|
|
|
bits_.resize(byte_count);
|
|
|
|
std::copy_n(std::begin(new_bits), byte_count, std::begin(bits_));
|
2012-12-05 17:29:46 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
if (bounded)
|
2012-12-05 17:29:46 +00:00
|
|
|
{
|
2021-10-16 14:04:19 +00:00
|
|
|
/* ensure the excess new_bits are set to '0' */
|
|
|
|
int const excess_bit_count = bit_count_ & 7;
|
2017-04-19 12:04:45 +00:00
|
|
|
|
2019-07-14 12:40:41 +00:00
|
|
|
if (excess_bit_count != 0)
|
2017-04-19 12:04:45 +00:00
|
|
|
{
|
2021-10-16 14:04:19 +00:00
|
|
|
bits_[byte_count - 1] &= 0xFF << excess_bit_count;
|
2017-04-19 12:04:45 +00:00
|
|
|
}
|
2011-09-26 22:50:42 +00:00
|
|
|
}
|
|
|
|
|
2021-10-16 14:04:19 +00:00
|
|
|
setTrueCount(countArray());
|
2011-03-28 16:31:05 +00:00
|
|
|
}
|
|
|
|
|
2021-10-16 14:04:19 +00:00
|
|
|
Bitfield::Bitfield(bool const* flags, size_t n)
|
|
|
|
: mode_(OperationMode::Normal)
|
2011-09-20 23:39:40 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
size_t trueCount = 0;
|
2011-09-20 23:39:40 +00:00
|
|
|
|
2021-10-16 14:04:19 +00:00
|
|
|
clearStorage();
|
|
|
|
ensureNthBitFits(n);
|
|
|
|
|
|
|
|
TR_ASSERT(std::size(bits_) >= getStorageSize(n));
|
2011-09-20 23:39:40 +00:00
|
|
|
|
2021-10-16 14:04:19 +00:00
|
|
|
for (size_t index = 0; index < n; ++index)
|
2011-09-20 23:39:40 +00:00
|
|
|
{
|
2021-10-16 14:04:19 +00:00
|
|
|
if (flags[index])
|
2011-09-20 23:39:40 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
++trueCount;
|
2021-10-16 14:04:19 +00:00
|
|
|
bits_[index >> 3] |= (0x80 >> (index & 7));
|
2011-09-20 23:39:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-16 14:04:19 +00:00
|
|
|
setTrueCount(trueCount);
|
2011-09-20 23:39:40 +00:00
|
|
|
}
|
|
|
|
|
2021-10-16 14:04:19 +00:00
|
|
|
void Bitfield::setBit(size_t bit_index)
|
2011-03-28 16:31:05 +00:00
|
|
|
{
|
2021-10-16 14:04:19 +00:00
|
|
|
switch (mode_)
|
2011-03-28 16:31:05 +00:00
|
|
|
{
|
2021-10-16 14:04:19 +00:00
|
|
|
case OperationMode::Normal:
|
2020-09-10 23:50:46 +00:00
|
|
|
{
|
2021-10-16 14:04:19 +00:00
|
|
|
setBitImpl(bit_index);
|
|
|
|
break;
|
2020-09-10 23:50:46 +00:00
|
|
|
}
|
2021-10-16 14:04:19 +00:00
|
|
|
case OperationMode::All:
|
|
|
|
TR_ASSERT(bit_index <= bit_count_);
|
|
|
|
break;
|
|
|
|
case OperationMode::None:
|
|
|
|
setMode(OperationMode::Normal);
|
|
|
|
setBitImpl(bit_index);
|
|
|
|
break;
|
|
|
|
case OperationMode::Start:
|
|
|
|
TR_UNREACHABLE();
|
|
|
|
break;
|
2011-03-28 16:31:05 +00:00
|
|
|
}
|
2009-06-15 00:11:06 +00:00
|
|
|
}
|
|
|
|
|
2021-10-11 17:29:14 +00:00
|
|
|
void Bitfield::setBitRange(size_t begin, size_t end)
|
2009-06-15 00:11:06 +00:00
|
|
|
{
|
2021-10-16 14:04:19 +00:00
|
|
|
if (mode_ == OperationMode::All)
|
2017-04-19 12:04:45 +00:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2021-10-16 14:04:19 +00:00
|
|
|
else if (mode_ == OperationMode::None)
|
2017-04-19 12:04:45 +00:00
|
|
|
{
|
2021-10-16 14:04:19 +00:00
|
|
|
setMode(OperationMode::Normal);
|
2017-04-19 12:04:45 +00:00
|
|
|
}
|
2009-06-15 00:11:06 +00:00
|
|
|
|
2021-10-16 14:04:19 +00:00
|
|
|
size_t const true_bits_difference = (end - begin) - countRange(begin, end);
|
2014-06-29 01:43:27 +00:00
|
|
|
|
2021-10-16 14:04:19 +00:00
|
|
|
if (true_bits_difference == 0)
|
2009-06-15 00:11:06 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
return;
|
2009-06-15 00:11:06 +00:00
|
|
|
}
|
2017-04-19 12:04:45 +00:00
|
|
|
|
2021-10-16 14:04:19 +00:00
|
|
|
end--;
|
|
|
|
|
|
|
|
if (end >= bit_count_ || begin > end)
|
2017-04-19 12:04:45 +00:00
|
|
|
{
|
2021-10-16 14:04:19 +00:00
|
|
|
return;
|
2017-04-19 12:04:45 +00:00
|
|
|
}
|
|
|
|
|
2021-10-16 14:04:19 +00:00
|
|
|
setBitRangeImpl(begin, end);
|
2009-06-15 00:11:06 +00:00
|
|
|
|
2021-10-16 14:04:19 +00:00
|
|
|
TR_ASSERT(true_count_ + true_bits_difference <= bit_count_);
|
|
|
|
setTrueCount(true_count_ + true_bits_difference);
|
2009-06-15 00:11:06 +00:00
|
|
|
}
|
|
|
|
|
2021-10-11 17:29:14 +00:00
|
|
|
void Bitfield::clearBit(size_t bit)
|
2009-06-15 00:11:06 +00:00
|
|
|
{
|
2021-10-16 14:04:19 +00:00
|
|
|
TR_ASSERT(isValid());
|
|
|
|
|
|
|
|
switch (mode_)
|
|
|
|
{
|
|
|
|
case OperationMode::Normal:
|
|
|
|
clearBitImpl(bit);
|
|
|
|
break;
|
|
|
|
case OperationMode::All:
|
|
|
|
setMode(OperationMode::Normal);
|
|
|
|
clearBitImpl(bit);
|
|
|
|
break;
|
|
|
|
case OperationMode::None:
|
|
|
|
break;
|
|
|
|
case OperationMode::Start:
|
|
|
|
TR_UNREACHABLE();
|
|
|
|
break;
|
2011-03-28 16:31:05 +00:00
|
|
|
}
|
2009-06-15 00:11:06 +00:00
|
|
|
}
|
|
|
|
|
2021-10-11 17:29:14 +00:00
|
|
|
void Bitfield::clearBitRange(size_t begin, size_t end)
|
2009-06-15 00:11:06 +00:00
|
|
|
{
|
2021-10-16 14:04:19 +00:00
|
|
|
if (mode_ == OperationMode::None)
|
2017-04-19 12:04:45 +00:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2021-10-16 14:04:19 +00:00
|
|
|
else if (mode_ == OperationMode::All)
|
2017-04-19 12:04:45 +00:00
|
|
|
{
|
2021-10-16 14:04:19 +00:00
|
|
|
setMode(OperationMode::Normal);
|
2017-04-19 12:04:45 +00:00
|
|
|
}
|
2009-06-15 00:11:06 +00:00
|
|
|
|
2021-10-16 14:04:19 +00:00
|
|
|
size_t const true_bits_difference = countRange(begin, end); // all true bits in range will be gone
|
2009-06-15 00:11:06 +00:00
|
|
|
|
2021-10-16 14:04:19 +00:00
|
|
|
if (true_bits_difference == 0)
|
2017-04-19 12:04:45 +00:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2014-06-29 01:43:27 +00:00
|
|
|
|
2021-10-16 14:04:19 +00:00
|
|
|
end--;
|
|
|
|
|
|
|
|
if (end >= bit_count_ || begin > end)
|
2009-06-15 00:11:06 +00:00
|
|
|
{
|
2021-10-16 14:04:19 +00:00
|
|
|
return;
|
2009-06-15 00:11:06 +00:00
|
|
|
}
|
2017-04-19 12:04:45 +00:00
|
|
|
|
2021-10-16 14:04:19 +00:00
|
|
|
clearBitRangeImpl(begin, end);
|
2009-06-15 00:11:06 +00:00
|
|
|
|
2021-10-16 14:04:19 +00:00
|
|
|
TR_ASSERT(true_count_ >= true_bits_difference);
|
|
|
|
setTrueCount(true_count_ - true_bits_difference);
|
2011-02-23 03:54:04 +00:00
|
|
|
}
|