mirror of
https://github.com/CraftyBoss/SuperMarioOdysseyOnline.git
synced 2024-11-25 04:35:17 +00:00
127 lines
3.7 KiB
C
127 lines
3.7 KiB
C
|
#pragma once
|
||
|
|
||
|
#include <basis/seadRawPrint.h>
|
||
|
#include <basis/seadTypes.h>
|
||
|
|
||
|
namespace sead
|
||
|
{
|
||
|
class BitFlagUtil
|
||
|
{
|
||
|
public:
|
||
|
/// Popcount.
|
||
|
static int countOnBit(u32 x);
|
||
|
/// Count trailing zeroes (ctz).
|
||
|
static int countContinuousOffBitFromRight(u32 x) { return countOnBit((x & -x) - 1); }
|
||
|
static int countRightOnBit(u32 x, int bit);
|
||
|
static int findOnBitFromRight(u32 x, int num);
|
||
|
|
||
|
/// Popcount.
|
||
|
static int countOnBit64(u64 x)
|
||
|
{
|
||
|
return countOnBit(static_cast<u32>(x)) + countOnBit(static_cast<u32>(x >> 32));
|
||
|
}
|
||
|
/// Count trailing zeroes (ctz).
|
||
|
static int countContinuousOffBitFromRight64(u64 x) { return countOnBit64((x & -x) - 1); }
|
||
|
static int countRightOnBit64(u64 x, int bit);
|
||
|
static int findOnBitFromRight64(u64 x, int num);
|
||
|
};
|
||
|
|
||
|
template <typename T>
|
||
|
class BitFlag
|
||
|
{
|
||
|
public:
|
||
|
BitFlag() : mBits(0) {}
|
||
|
BitFlag(T bits) : mBits(bits) {}
|
||
|
|
||
|
operator T() const { return mBits; }
|
||
|
|
||
|
void makeAllZero() { mBits = 0; }
|
||
|
void makeAllOne() { mBits = ~T(0); }
|
||
|
|
||
|
void setDirect(T bits) { mBits = bits; }
|
||
|
T getDirect() const { return mBits; }
|
||
|
T* getPtr() { return &mBits; }
|
||
|
const T* getPtr() const { return &mBits; }
|
||
|
size_t getByteSize() const { return sizeof(T); }
|
||
|
|
||
|
void set(T val) { mBits |= val; }
|
||
|
void reset(T val) { mBits &= ~val; }
|
||
|
void toggle(T val) { mBits ^= val; }
|
||
|
void change(T val, bool on)
|
||
|
{
|
||
|
if (on)
|
||
|
set(val);
|
||
|
else
|
||
|
reset(val);
|
||
|
}
|
||
|
bool isZero() const { return mBits == 0; }
|
||
|
/// Checks if (at least) one of the bits are set.
|
||
|
bool isOn(T val) const { return (mBits & val) != 0; }
|
||
|
/// Checks if all of the bits are set.
|
||
|
bool isOnAll(T val) const { return (mBits & val) == val; }
|
||
|
bool isOff(T val) const { return !isOn(val); }
|
||
|
|
||
|
bool testAndClear(T val)
|
||
|
{
|
||
|
if (!isOn(val))
|
||
|
return false;
|
||
|
reset(val);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// TODO: what is this even supposed to do? (This function is known to exist
|
||
|
// because it is present in debug info for pead in Super Mario Run.)
|
||
|
T getMask(T v) const;
|
||
|
|
||
|
static T makeMask(int bit) { return T(1) << bit; }
|
||
|
|
||
|
void setBit(int bit) { set(makeMask(bit)); }
|
||
|
void resetBit(int bit) { reset(makeMask(bit)); }
|
||
|
void changeBit(int bit, bool on) { change(makeMask(bit), on); }
|
||
|
void toggleBit(int bit) { toggle(makeMask(bit)); }
|
||
|
bool isOnBit(int bit) const { return isOn(makeMask(bit)); }
|
||
|
bool isOffBit(int bit) const { return isOff(makeMask(bit)); }
|
||
|
bool testAndClearBit(int bit) { return testAndClear(makeMask(bit)); }
|
||
|
|
||
|
/// Popcount.
|
||
|
int countOnBit() const
|
||
|
{
|
||
|
if constexpr (sizeof(T) <= 4)
|
||
|
return BitFlagUtil::countOnBit(mBits);
|
||
|
else
|
||
|
return BitFlagUtil::countOnBit64(mBits);
|
||
|
}
|
||
|
/// Count trailing zeroes.
|
||
|
int countContinuousOffBitFromRight() const
|
||
|
{
|
||
|
if constexpr (sizeof(T) <= 4)
|
||
|
return BitFlagUtil::countContinuousOffBitFromRight(mBits);
|
||
|
else
|
||
|
return BitFlagUtil::countContinuousOffBitFromRight64(mBits);
|
||
|
}
|
||
|
int countRightOnBit(int bit) const
|
||
|
{
|
||
|
if constexpr (sizeof(T) <= 4)
|
||
|
return BitFlagUtil::countRightOnBit(mBits, bit);
|
||
|
else
|
||
|
return BitFlagUtil::countRightOnBit64(mBits, bit);
|
||
|
}
|
||
|
int findOnBitFromRight(int num) const
|
||
|
{
|
||
|
if constexpr (sizeof(T) <= 4)
|
||
|
return BitFlagUtil::findOnBitFromRight(mBits, num);
|
||
|
else
|
||
|
return BitFlagUtil::findOnBitFromRight64(mBits, num);
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
T mBits;
|
||
|
};
|
||
|
|
||
|
using BitFlag8 = BitFlag<u8>;
|
||
|
using BitFlag16 = BitFlag<u16>;
|
||
|
using BitFlag32 = BitFlag<u32>;
|
||
|
using BitFlag64 = BitFlag<u64>;
|
||
|
|
||
|
} // namespace sead
|