transmission/libtransmission/bitfield.h

147 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;
};