mirror of
https://github.com/transmission/transmission
synced 2025-01-03 13:35:36 +00:00
39376f2105
* Modernize bitfield.cc: Grouped member functions into the struct; C++ construction * Modernize bitfield.cc: Naming style similar to qt/ C++ source * Modernize bitfield.cc: Bitfield test updated to new API * Modernize bitfield.cc: Renames for private functions * Modernize bitfield.cc: Formatting * Modernize bitfield.cc: Remove struct in 'struct Bitfield' and update commented code too Co-authored-by: Charles Kerr <charles@charleskerr.com>
146 lines
3.3 KiB
C++
146 lines
3.3 KiB
C++
/*
|
|
* This file Copyright (C) 2008-2014 Mnemosyne LLC
|
|
*
|
|
* It may be used under the GNU GPL versions 2 or 3
|
|
* or any future license endorsed by Mnemosyne LLC.
|
|
*
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#ifndef __TRANSMISSION__
|
|
#error only libtransmission should #include this header.
|
|
#endif
|
|
|
|
#include "transmission.h"
|
|
#include "tr-macros.h"
|
|
#include "tr-assert.h"
|
|
|
|
/// @brief Implementation of the BitTorrent spec's Bitfield array of bits
|
|
struct Bitfield
|
|
{
|
|
public:
|
|
/***
|
|
**** life cycle
|
|
***/
|
|
explicit Bitfield(size_t bit_count);
|
|
|
|
Bitfield()
|
|
: Bitfield(0)
|
|
{
|
|
}
|
|
|
|
~Bitfield()
|
|
{
|
|
this->setHasNone();
|
|
}
|
|
|
|
/***
|
|
****
|
|
***/
|
|
|
|
void setHasAll();
|
|
|
|
void setHasNone();
|
|
|
|
/// @brief Sets one bit
|
|
void setBit(size_t bit);
|
|
|
|
/// @brief Sets bit range [begin, end) to 1
|
|
void setBitRange(size_t begin, size_t end);
|
|
|
|
/// @brief Clears one bit
|
|
void clearBit(size_t bit);
|
|
|
|
/// @brief Clears bit range [begin, end) to 0
|
|
void clearBitRange(size_t begin, size_t end);
|
|
|
|
/***
|
|
****
|
|
***/
|
|
|
|
[[nodiscard]] size_t countRange(size_t begin, size_t end) const
|
|
{
|
|
if (this->hasAll())
|
|
{
|
|
return end - begin;
|
|
}
|
|
|
|
if (this->hasNone())
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
return this->countRangeImpl(begin, end);
|
|
}
|
|
|
|
[[nodiscard]] size_t countBits() const;
|
|
|
|
[[nodiscard]] constexpr bool hasAll() const
|
|
{
|
|
return this->bit_count_ != 0 ? (this->true_count_ == this->bit_count_) : this->hint_ == HAS_ALL;
|
|
}
|
|
|
|
[[nodiscard]] constexpr bool hasNone() const
|
|
{
|
|
return this->bit_count_ != 0 ? (this->true_count_ == 0) : this->hint_ == HAS_NONE;
|
|
}
|
|
|
|
[[nodiscard]] bool readBit(size_t n) const;
|
|
|
|
/***
|
|
****
|
|
***/
|
|
|
|
void setFromFlags(bool const* bytes, size_t n);
|
|
|
|
void setFromBitfield(Bitfield const& src);
|
|
|
|
void setRaw(void const* newBits, size_t byte_count, bool bounded);
|
|
|
|
void* getRaw(size_t* byte_count) const;
|
|
|
|
[[nodiscard]] size_t getBitCount() const
|
|
{
|
|
return bit_count_;
|
|
}
|
|
|
|
private:
|
|
[[nodiscard]] constexpr size_t countArray() const;
|
|
[[nodiscard]] size_t countRangeImpl(size_t begin, size_t end) const;
|
|
static void setBitsInArray(uint8_t* array, size_t bit_count);
|
|
static constexpr size_t getStorageSize(size_t bit_count)
|
|
{
|
|
return (bit_count >> 3) + ((bit_count & 7) != 0 ? 1 : 0);
|
|
}
|
|
void ensureBitsAlloced(size_t n);
|
|
bool ensureNthBitAlloced(size_t nth);
|
|
void freeArray();
|
|
void setTrueCount(size_t n);
|
|
void rebuildTrueCount();
|
|
void incTrueCount(size_t i);
|
|
void decTrueCount(size_t i);
|
|
|
|
#ifdef TR_ENABLE_ASSERTS
|
|
[[nodiscard]] bool isValid() const;
|
|
#endif
|
|
|
|
uint8_t* bits_ = nullptr;
|
|
size_t alloc_count_ = 0;
|
|
size_t bit_count_ = 0;
|
|
size_t true_count_ = 0;
|
|
|
|
enum OperationMode
|
|
{
|
|
/// @brief Normal operation: storage of bytes contains bits to set or clear
|
|
NORMAL,
|
|
/// @brief If bit_count_==0, storage is inactive, consider all bits to be 1
|
|
HAS_ALL,
|
|
/// @brief If bit_count_==0, storage is inactive, consider all bits to be 0
|
|
HAS_NONE,
|
|
};
|
|
|
|
// Special cases for when full or empty but we don't know the bitCount.
|
|
// This occurs when a magnet link's peers send have all / have none
|
|
OperationMode hint_ = NORMAL;
|
|
};
|