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>
|
|
|
|
#include <cstring> /* memset */
|
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"
|
2017-04-21 07:40:57 +00:00
|
|
|
#include "utils.h" /* tr_new0() */
|
2011-02-23 03:54:04 +00:00
|
|
|
|
2011-03-28 16:31:05 +00:00
|
|
|
/****
|
|
|
|
*****
|
|
|
|
****/
|
|
|
|
|
2021-10-06 22:24:04 +00:00
|
|
|
static constexpr int8_t const trueBitCount[256] = {
|
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-11 17:29:14 +00:00
|
|
|
constexpr size_t Bitfield::countArray() const
|
2011-03-30 04:14:57 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
size_t ret = 0;
|
2021-10-11 17:29:14 +00:00
|
|
|
size_t i = this->alloc_count_;
|
2011-03-30 04:14:57 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
while (i > 0)
|
|
|
|
{
|
2021-10-11 17:29:14 +00:00
|
|
|
ret += trueBitCount[this->bits_[--i]];
|
2017-04-19 12:04:45 +00:00
|
|
|
}
|
2011-03-30 04:14:57 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
return ret;
|
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-11 17:29:14 +00:00
|
|
|
if (this->bit_count_ == 0)
|
2017-04-19 12:04:45 +00:00
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
2011-03-28 16:31:05 +00:00
|
|
|
|
2021-10-11 17:29:14 +00:00
|
|
|
if (first_byte >= this->alloc_count_)
|
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);
|
2021-10-11 17:29:14 +00:00
|
|
|
TR_ASSERT(this->bits_ != nullptr);
|
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-11 17:29:14 +00:00
|
|
|
uint8_t val = this->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
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
ret += trueBitCount[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-11 17:29:14 +00:00
|
|
|
size_t const walk_end = std::min(this->alloc_count_, 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-11 17:29:14 +00:00
|
|
|
uint8_t val = this->bits_[first_byte];
|
2017-05-13 22:38:31 +00:00
|
|
|
val <<= first_shift;
|
|
|
|
val >>= first_shift;
|
2017-04-19 12:04:45 +00:00
|
|
|
ret += trueBitCount[val];
|
|
|
|
|
|
|
|
/* 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-11 17:29:14 +00:00
|
|
|
ret += trueBitCount[this->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-11 17:29:14 +00:00
|
|
|
if (last_byte < this->alloc_count_)
|
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-11 17:29:14 +00:00
|
|
|
val = this->bits_[last_byte];
|
2017-05-13 22:38:31 +00:00
|
|
|
val >>= last_shift;
|
|
|
|
val <<= last_shift;
|
2017-04-19 12:04:45 +00:00
|
|
|
ret += trueBitCount[val];
|
2011-03-30 04:14:57 +00:00
|
|
|
}
|
2011-03-28 16:31:05 +00:00
|
|
|
}
|
|
|
|
|
2017-06-08 07:24:12 +00:00
|
|
|
TR_ASSERT(ret <= (begin - end));
|
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-11 17:29:14 +00:00
|
|
|
if (this->hasAll())
|
2017-04-19 12:04:45 +00:00
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
2012-12-13 02:00:45 +00:00
|
|
|
|
2021-10-11 17:29:14 +00:00
|
|
|
if (this->hasNone())
|
2017-04-19 12:04:45 +00:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2012-12-13 02:00:45 +00:00
|
|
|
|
2021-10-11 17:29:14 +00:00
|
|
|
if (n >> 3U >= this->alloc_count_)
|
2017-04-19 12:04:45 +00:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2012-12-13 02:00:45 +00:00
|
|
|
|
2021-10-11 17:29:14 +00:00
|
|
|
return (this->bits_[n >> 3U] << (n & 7U) & 0x80) != 0;
|
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-11 17:29:14 +00:00
|
|
|
TR_ASSERT((this->alloc_count_ == 0) == (this->bits_ == nullptr));
|
|
|
|
TR_ASSERT(this->bits_ == nullptr || this->true_count_ == this->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-11 17:29:14 +00:00
|
|
|
TR_ASSERT(this->isValid());
|
2012-12-05 17:29:46 +00:00
|
|
|
|
2021-10-11 17:29:14 +00:00
|
|
|
return this->true_count_;
|
2011-04-05 00:29:42 +00:00
|
|
|
}
|
|
|
|
|
2021-10-11 17:29:14 +00:00
|
|
|
void Bitfield::setBitsInArray(uint8_t* array, size_t bit_count)
|
2011-03-30 04:14:57 +00:00
|
|
|
{
|
2017-04-20 16:02:19 +00:00
|
|
|
uint8_t const val = 0xFF;
|
2021-10-11 17:29:14 +00:00
|
|
|
size_t const n = getStorageSize(bit_count);
|
2012-12-05 17:29:46 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
if (n > 0)
|
2013-07-29 04:19:15 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
memset(array, val, n - 1);
|
2012-12-05 17:29:46 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
array[n - 1] = val << (n * 8 - bit_count);
|
2013-07-29 04:19:15 +00:00
|
|
|
}
|
2011-03-28 16:31:05 +00:00
|
|
|
}
|
|
|
|
|
2021-10-11 17:29:14 +00:00
|
|
|
void* Bitfield::getRaw(size_t* byte_count) const
|
2011-03-28 16:31:05 +00:00
|
|
|
{
|
2021-10-11 17:29:14 +00:00
|
|
|
TR_ASSERT(this->bit_count_ > 0);
|
2017-06-13 02:24:09 +00:00
|
|
|
|
2021-10-11 17:29:14 +00:00
|
|
|
size_t const n = getStorageSize(this->bit_count_);
|
|
|
|
uint8_t* newBits = tr_new0(uint8_t, n);
|
2011-03-28 16:31:05 +00:00
|
|
|
|
2021-10-11 17:29:14 +00:00
|
|
|
if (this->alloc_count_ != 0)
|
2012-12-05 17:29:46 +00:00
|
|
|
{
|
2021-10-11 17:29:14 +00:00
|
|
|
TR_ASSERT(this->alloc_count_ <= n);
|
|
|
|
std::memcpy(newBits, this->bits_, this->alloc_count_);
|
2012-12-05 17:29:46 +00:00
|
|
|
}
|
2021-10-11 17:29:14 +00:00
|
|
|
else if (this->hasAll())
|
2012-12-05 17:29:46 +00:00
|
|
|
{
|
2021-10-11 17:29:14 +00:00
|
|
|
setBitsInArray(newBits, this->bit_count_);
|
2011-09-28 16:07:35 +00:00
|
|
|
}
|
2011-03-28 16:31:05 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
*byte_count = n;
|
2021-10-11 17:29:14 +00:00
|
|
|
return newBits;
|
2011-03-28 16:31:05 +00:00
|
|
|
}
|
|
|
|
|
2021-10-11 17:29:14 +00:00
|
|
|
void Bitfield::ensureBitsAlloced(size_t n)
|
2009-06-15 00:11:06 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
size_t bytes_needed;
|
2021-10-11 17:29:14 +00:00
|
|
|
bool const has_all = this->hasAll();
|
2011-03-28 16:31:05 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
if (has_all)
|
|
|
|
{
|
2021-10-11 17:29:14 +00:00
|
|
|
bytes_needed = getStorageSize(std::max(n, this->true_count_));
|
2017-04-19 12:04:45 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-10-11 17:29:14 +00:00
|
|
|
bytes_needed = getStorageSize(n);
|
2017-04-19 12:04:45 +00:00
|
|
|
}
|
2011-03-30 04:14:57 +00:00
|
|
|
|
2021-10-11 17:29:14 +00:00
|
|
|
if (this->alloc_count_ < bytes_needed)
|
2011-03-30 04:14:57 +00:00
|
|
|
{
|
2021-10-11 17:29:14 +00:00
|
|
|
this->bits_ = tr_renew(uint8_t, this->bits_, bytes_needed);
|
|
|
|
std::memset(this->bits_ + this->alloc_count_, 0, bytes_needed - this->alloc_count_);
|
|
|
|
this->alloc_count_ = bytes_needed;
|
2011-03-30 04:14:57 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
if (has_all)
|
|
|
|
{
|
2021-10-11 17:29:14 +00:00
|
|
|
setBitsInArray(this->bits_, this->true_count_);
|
2017-04-19 12:04:45 +00:00
|
|
|
}
|
2011-03-30 04:14:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-11 17:29:14 +00:00
|
|
|
bool Bitfield::ensureNthBitAlloced(size_t nth)
|
2011-09-28 16:07:35 +00:00
|
|
|
{
|
2021-10-11 17:29:14 +00:00
|
|
|
// count is zero-based, so we need to allocate nth+1 bits before setting the nth
|
2017-04-19 12:04:45 +00:00
|
|
|
if (nth == SIZE_MAX)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2014-06-29 01:43:27 +00:00
|
|
|
|
2021-10-11 17:29:14 +00:00
|
|
|
this->ensureBitsAlloced(nth + 1);
|
2017-04-19 12:04:45 +00:00
|
|
|
return true;
|
2011-09-28 16:07:35 +00:00
|
|
|
}
|
|
|
|
|
2021-10-11 17:29:14 +00:00
|
|
|
void Bitfield::freeArray()
|
2011-03-30 04:14:57 +00:00
|
|
|
{
|
2021-10-11 17:29:14 +00:00
|
|
|
tr_free(this->bits_);
|
|
|
|
this->bits_ = nullptr;
|
|
|
|
this->alloc_count_ = 0;
|
2011-03-28 16:31:05 +00:00
|
|
|
}
|
|
|
|
|
2021-10-11 17:29:14 +00:00
|
|
|
void Bitfield::setTrueCount(size_t n)
|
2011-03-28 16:31:05 +00:00
|
|
|
{
|
2021-10-11 17:29:14 +00:00
|
|
|
TR_ASSERT(this->bit_count_ == 0 || n <= this->bit_count_);
|
2015-12-27 16:34:47 +00:00
|
|
|
|
2021-10-11 17:29:14 +00:00
|
|
|
this->true_count_ = n;
|
2011-03-28 16:31:05 +00:00
|
|
|
|
2021-10-11 17:29:14 +00:00
|
|
|
if (this->hasAll() || this->hasNone())
|
2017-04-19 12:04:45 +00:00
|
|
|
{
|
2021-10-11 17:29:14 +00:00
|
|
|
this->freeArray();
|
2017-04-19 12:04:45 +00:00
|
|
|
}
|
2011-03-28 16:31:05 +00:00
|
|
|
|
2021-10-11 17:29:14 +00:00
|
|
|
TR_ASSERT(this->isValid());
|
2011-03-28 16:31:05 +00:00
|
|
|
}
|
|
|
|
|
2021-10-11 17:29:14 +00:00
|
|
|
void Bitfield::rebuildTrueCount()
|
2011-03-28 16:31:05 +00:00
|
|
|
{
|
2021-10-11 17:29:14 +00:00
|
|
|
this->setTrueCount(this->countArray());
|
2009-06-15 00:11:06 +00:00
|
|
|
}
|
|
|
|
|
2021-10-11 17:29:14 +00:00
|
|
|
void Bitfield::incTrueCount(size_t i)
|
2009-06-15 00:11:06 +00:00
|
|
|
{
|
2021-10-11 17:29:14 +00:00
|
|
|
TR_ASSERT(this->bit_count_ == 0 || i <= this->bit_count_);
|
|
|
|
TR_ASSERT(this->bit_count_ == 0 || this->true_count_ <= this->bit_count_ - i);
|
2015-12-27 16:34:47 +00:00
|
|
|
|
2021-10-11 17:29:14 +00:00
|
|
|
this->setTrueCount(this->true_count_ + i);
|
2011-02-23 03:54:04 +00:00
|
|
|
}
|
2009-06-15 00:11:06 +00:00
|
|
|
|
2021-10-11 17:29:14 +00:00
|
|
|
void Bitfield::decTrueCount(size_t i)
|
2015-12-27 16:34:47 +00:00
|
|
|
{
|
2021-10-11 17:29:14 +00:00
|
|
|
TR_ASSERT(this->bit_count_ == 0 || i <= this->bit_count_);
|
|
|
|
TR_ASSERT(this->bit_count_ == 0 || this->true_count_ >= i);
|
2015-12-27 16:34:47 +00:00
|
|
|
|
2021-10-11 17:29:14 +00:00
|
|
|
this->setTrueCount(this->true_count_ - i);
|
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-11 17:29:14 +00:00
|
|
|
this->bit_count_ = bit_count;
|
|
|
|
this->true_count_ = 0;
|
|
|
|
this->bits_ = nullptr;
|
|
|
|
this->alloc_count_ = 0;
|
|
|
|
this->hint_ = NORMAL;
|
|
|
|
|
|
|
|
TR_ASSERT(this->isValid());
|
2009-06-15 00:11:06 +00:00
|
|
|
}
|
|
|
|
|
2021-10-11 17:29:14 +00:00
|
|
|
void Bitfield::setHasNone()
|
2011-03-28 16:31:05 +00:00
|
|
|
{
|
2021-10-11 17:29:14 +00:00
|
|
|
this->freeArray();
|
|
|
|
this->true_count_ = 0;
|
|
|
|
this->hint_ = HAS_NONE;
|
2011-03-30 04:14:57 +00:00
|
|
|
|
2021-10-11 17:29:14 +00:00
|
|
|
TR_ASSERT(this->isValid());
|
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::setHasAll()
|
2011-03-28 16:31:05 +00:00
|
|
|
{
|
2021-10-11 17:29:14 +00:00
|
|
|
this->freeArray();
|
|
|
|
this->true_count_ = this->bit_count_;
|
|
|
|
this->hint_ = HAS_ALL;
|
2011-03-30 04:14:57 +00:00
|
|
|
|
2021-10-11 17:29:14 +00:00
|
|
|
TR_ASSERT(this->isValid());
|
2011-03-28 16:31:05 +00:00
|
|
|
}
|
|
|
|
|
2021-10-11 17:29:14 +00:00
|
|
|
void Bitfield::setFromBitfield(Bitfield const& src)
|
2011-03-28 16:31:05 +00:00
|
|
|
{
|
2021-10-11 17:29:14 +00:00
|
|
|
if (src.hasAll())
|
2017-04-19 12:04:45 +00:00
|
|
|
{
|
2021-10-11 17:29:14 +00:00
|
|
|
this->setHasAll();
|
2017-04-19 12:04:45 +00:00
|
|
|
}
|
2021-10-11 17:29:14 +00:00
|
|
|
else if (src.hasNone())
|
2017-04-19 12:04:45 +00:00
|
|
|
{
|
2021-10-11 17:29:14 +00:00
|
|
|
this->setHasNone();
|
2017-04-19 12:04:45 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-10-11 17:29:14 +00:00
|
|
|
this->setRaw(src.bits_, src.alloc_count_, true);
|
2017-04-19 12:04:45 +00:00
|
|
|
}
|
2011-03-28 16:31:05 +00:00
|
|
|
}
|
|
|
|
|
2021-10-11 17:29:14 +00:00
|
|
|
void Bitfield::setRaw(void const* newBits, size_t byte_count, bool bounded)
|
2011-03-28 16:31:05 +00:00
|
|
|
{
|
2021-10-11 17:29:14 +00:00
|
|
|
this->freeArray();
|
|
|
|
this->true_count_ = 0;
|
2012-12-05 17:29:46 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
if (bounded)
|
|
|
|
{
|
2021-10-11 17:29:14 +00:00
|
|
|
byte_count = std::min(byte_count, getStorageSize(this->bit_count_));
|
2017-04-19 12:04:45 +00:00
|
|
|
}
|
2012-12-05 17:29:46 +00:00
|
|
|
|
2021-10-11 17:29:14 +00:00
|
|
|
this->bits_ = static_cast<uint8_t*>(tr_memdup(newBits, byte_count));
|
|
|
|
this->alloc_count_ = byte_count;
|
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-11 17:29:14 +00:00
|
|
|
/* ensure the excess newBits are set to '0' */
|
|
|
|
int const excess_bit_count = byte_count * 8 - this->bit_count_;
|
2017-06-13 02:24:09 +00:00
|
|
|
|
2017-06-08 07:24:12 +00:00
|
|
|
TR_ASSERT(excess_bit_count >= 0);
|
|
|
|
TR_ASSERT(excess_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-11 17:29:14 +00:00
|
|
|
this->bits_[this->alloc_count_ - 1] &= 0xff << excess_bit_count;
|
2017-04-19 12:04:45 +00:00
|
|
|
}
|
2011-09-26 22:50:42 +00:00
|
|
|
}
|
|
|
|
|
2021-10-11 17:29:14 +00:00
|
|
|
this->rebuildTrueCount();
|
2011-03-28 16:31:05 +00:00
|
|
|
}
|
|
|
|
|
2021-10-11 17:29:14 +00:00
|
|
|
void Bitfield::setFromFlags(bool const* flags, size_t n)
|
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-11 17:29:14 +00:00
|
|
|
this->freeArray();
|
|
|
|
this->ensureBitsAlloced(n);
|
2011-09-20 23:39:40 +00:00
|
|
|
|
2017-05-13 22:38:31 +00:00
|
|
|
for (size_t i = 0; i < n; ++i)
|
2011-09-20 23:39:40 +00:00
|
|
|
{
|
2021-10-11 17:29:14 +00:00
|
|
|
if (flags[i] && this->bits_ != nullptr)
|
2011-09-20 23:39:40 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
++trueCount;
|
2021-10-11 17:29:14 +00:00
|
|
|
this->bits_[i >> 3U] |= (0x80 >> (i & 7U));
|
2011-09-20 23:39:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-11 17:29:14 +00:00
|
|
|
this->setTrueCount(trueCount);
|
2011-09-20 23:39:40 +00:00
|
|
|
}
|
|
|
|
|
2021-10-11 17:29:14 +00:00
|
|
|
void Bitfield::setBit(size_t bit)
|
2011-03-28 16:31:05 +00:00
|
|
|
{
|
2021-10-11 17:29:14 +00:00
|
|
|
if (!this->readBit(bit) && this->ensureNthBitAlloced(bit))
|
2011-03-28 16:31:05 +00:00
|
|
|
{
|
2021-10-11 17:29:14 +00:00
|
|
|
size_t const offset = bit >> 3U;
|
2020-09-10 23:50:46 +00:00
|
|
|
|
2021-10-11 17:29:14 +00:00
|
|
|
if ((this->bits_ != nullptr) && (offset < this->alloc_count_))
|
2020-09-10 23:50:46 +00:00
|
|
|
{
|
2021-10-11 17:29:14 +00:00
|
|
|
this->bits_[offset] |= 0x80 >> (bit & 7U);
|
|
|
|
this->incTrueCount(1);
|
2020-09-10 23:50:46 +00:00
|
|
|
}
|
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
|
|
|
{
|
2017-05-01 15:46:41 +00:00
|
|
|
size_t sb;
|
|
|
|
size_t eb;
|
|
|
|
unsigned char sm;
|
|
|
|
unsigned char em;
|
2021-10-11 17:29:14 +00:00
|
|
|
size_t const diff = (end - begin) - this->countRange(begin, end);
|
2009-06-15 00:11:06 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
if (diff == 0)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2009-06-15 00:11:06 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
end--;
|
2009-06-15 00:11:06 +00:00
|
|
|
|
2021-10-11 17:29:14 +00:00
|
|
|
if (end >= this->bit_count_ || begin > end)
|
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
|
|
|
sb = begin >> 3;
|
|
|
|
sm = ~(0xff << (8 - (begin & 7)));
|
|
|
|
eb = end >> 3;
|
|
|
|
em = 0xff << (7 - (end & 7));
|
2014-06-29 01:43:27 +00:00
|
|
|
|
2021-10-11 17:29:14 +00:00
|
|
|
if (!this->ensureNthBitAlloced(end))
|
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
|
|
|
|
|
|
|
if (sb == eb)
|
|
|
|
{
|
2021-10-11 17:29:14 +00:00
|
|
|
this->bits_[sb] |= sm & em;
|
2017-04-19 12:04:45 +00:00
|
|
|
}
|
|
|
|
else
|
2009-06-15 00:11:06 +00:00
|
|
|
{
|
2021-10-11 17:29:14 +00:00
|
|
|
this->bits_[sb] |= sm;
|
|
|
|
this->bits_[eb] |= em;
|
2017-04-19 12:04:45 +00:00
|
|
|
|
|
|
|
if (++sb < eb)
|
|
|
|
{
|
2021-10-11 17:29:14 +00:00
|
|
|
std::memset(this->bits_ + sb, 0xff, eb - sb);
|
2017-04-19 12:04:45 +00:00
|
|
|
}
|
2009-06-15 00:11:06 +00:00
|
|
|
}
|
|
|
|
|
2021-10-11 17:29:14 +00:00
|
|
|
this->incTrueCount(diff);
|
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-11 17:29:14 +00:00
|
|
|
TR_ASSERT(this->isValid());
|
2009-06-15 00:11:06 +00:00
|
|
|
|
2021-10-11 17:29:14 +00:00
|
|
|
if (this->readBit(bit) && this->ensureNthBitAlloced(bit))
|
2011-03-28 16:31:05 +00:00
|
|
|
{
|
2021-10-11 17:29:14 +00:00
|
|
|
this->bits_[bit >> 3U] &= 0xff7f >> (bit & 7U);
|
|
|
|
this->decTrueCount(1);
|
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
|
|
|
{
|
2017-05-01 15:46:41 +00:00
|
|
|
size_t sb;
|
|
|
|
size_t eb;
|
|
|
|
unsigned char sm;
|
|
|
|
unsigned char em;
|
2021-10-11 17:29:14 +00:00
|
|
|
size_t const diff = this->countRange(begin, end);
|
2011-03-28 16:31:05 +00:00
|
|
|
|
2017-04-30 16:25:26 +00:00
|
|
|
if (diff == 0)
|
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
|
|
|
end--;
|
2009-06-15 00:11:06 +00:00
|
|
|
|
2021-10-11 17:29:14 +00:00
|
|
|
if (end >= this->bit_count_ || begin > end)
|
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
|
|
|
sb = begin >> 3;
|
|
|
|
sm = 0xff << (8 - (begin & 7));
|
|
|
|
eb = end >> 3;
|
|
|
|
em = ~(0xff << (7 - (end & 7)));
|
2009-06-15 00:11:06 +00:00
|
|
|
|
2021-10-11 17:29:14 +00:00
|
|
|
if (!this->ensureNthBitAlloced(end))
|
2017-04-19 12:04:45 +00:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2014-06-29 01:43:27 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
if (sb == eb)
|
2009-06-15 00:11:06 +00:00
|
|
|
{
|
2021-10-11 17:29:14 +00:00
|
|
|
this->bits_[sb] &= sm | em;
|
2009-06-15 00:11:06 +00:00
|
|
|
}
|
2017-04-19 12:04:45 +00:00
|
|
|
else
|
2009-06-15 00:11:06 +00:00
|
|
|
{
|
2021-10-11 17:29:14 +00:00
|
|
|
this->bits_[sb] &= sm;
|
|
|
|
this->bits_[eb] &= em;
|
2017-04-19 12:04:45 +00:00
|
|
|
|
|
|
|
if (++sb < eb)
|
|
|
|
{
|
2021-10-11 17:29:14 +00:00
|
|
|
std::memset(this->bits_ + sb, 0, eb - sb);
|
2017-04-19 12:04:45 +00:00
|
|
|
}
|
2009-06-15 00:11:06 +00:00
|
|
|
}
|
|
|
|
|
2021-10-11 17:29:14 +00:00
|
|
|
this->decTrueCount(diff);
|
2011-02-23 03:54:04 +00:00
|
|
|
}
|