|
- #pragma once
- #include <cstddef>
- #include <cstdint>
- #include <climits>
- #include <type_traits>
-
- // https://stackoverflow.com/a/263738
- /* a=target variable, b=bit number to act upon 0-n */
- #define BIT_SET(a,b) ((a) |= (1ULL<<(b)))
- #define BIT_CLEAR(a,b) ((a) &= ~(1ULL<<(b)))
- #define BIT_FLIP(a,b) ((a) ^= (1ULL<<(b)))
- #define BIT_CHECK(a,b) (!!((a) & (1ULL<<(b)))) // '!!' to make sure this returns 0 or 1
-
- /* x=target variable, y=mask */
- #define BITMASK_SET(x,y) ((x) |= (y))
- #define BITMASK_CLEAR(x,y) ((x) &= (~(y)))
- #define BITMASK_FLIP(x,y) ((x) ^= (y))
- #define BITMASK_CHECK_ALL(x,y) (!(~(x) & (y)))
- #define BITMASK_CHECK_ANY(x,y) ((x) & (y))
-
- namespace itsy_bitsy {
-
- template <std::size_t sz, typename C = void>
- struct bit_type {
- typedef uint64_t type;
- };
-
- template <std::size_t sz>
- struct bit_type<sz, std::enable_if_t<(sz <= 1)>> {
- typedef bool type;
- };
-
- template <std::size_t sz>
- struct bit_type<sz, std::enable_if_t<(sz > 2 && sz <= 16)>> {
- typedef uint16_t type;
- };
-
- template <std::size_t sz>
- struct bit_type<sz, std::enable_if_t<(sz > 16 && sz <= 32)>> {
- typedef uint32_t type;
- };
-
- template <std::size_t sz>
- struct bit_type<sz, std::enable_if_t<(sz > 32 && sz <= 64)>> {
- typedef uint64_t type;
- };
-
- template <std::size_t sz>
- using bit_type_t = typename bit_type<sz>::type;
-
- template <typename T, typename V>
- bool vcxx_warning_crap(std::true_type, V val) {
- return val != 0;
- }
-
- template <typename T, typename V>
- T vcxx_warning_crap(std::false_type, V val) {
- return static_cast<T>(val);
- }
-
- template <typename T, typename V>
- auto vcxx_warning_crap(V val) {
- return vcxx_warning_crap<T>(std::is_same<bool, T>(), val);
- }
-
- template <typename Base, std::size_t baseOffset = 0x0, std::size_t bit_target = 0x0, std::size_t size = 0x1>
- void write(Base& b, bit_type_t<size> bits) {
- uintptr_t baseAddr = reinterpret_cast<uintptr_t>(&b);
- uintptr_t offs = baseOffset;
- unsigned char* byt = reinterpret_cast<unsigned char*>(baseAddr + offs);
- char testb = *byt & (1 << bit_target);
- if (bits)
- BIT_SET(*byt, bit_target);
- else
- BIT_CLEAR(*byt, bit_target);
- }
-
- template <typename Base, std::size_t baseOffset = 0x0, std::size_t bit_target = 0x0, std::size_t size = 0x1>
- bit_type_t<size> read(Base& b) {
- uintptr_t baseAddr = reinterpret_cast<uintptr_t>(&b);
- uintptr_t offs = baseOffset;
- unsigned char* byt = reinterpret_cast<unsigned char*>(baseAddr + offs);
- char test = *byt & (1 << bit_target);
- if (test)
- return true;
- return false;
- }
- }
|