bitfield.cpp (3093B)
1 #include "libshit/bitfield.hpp" 2 3 #include "libshit/doctest.hpp" 4 5 #include <cstdint> 6 7 namespace Libshit 8 { 9 TEST_SUITE_BEGIN("Libshit::Bitfield"); 10 11 TEST_CASE("Empty BF") 12 { 13 Bitfield<> BF; 14 (void) BF; 15 } 16 17 namespace 18 { 19 enum class EnumA { A, B, C, D, ENUM_MAX = D }; 20 enum EnumB { X, Y, Z }; 21 22 using BF = Bitfield< 23 BitBool<struct Bool1>, 24 BitOptBool<struct OptBool>, 25 BitUInt<struct UInt, 2>, 26 BitEnum<struct Enum1, EnumA>, 27 BitEnum<struct Enum2, EnumB, EnumB::Z>, 28 BitOptEnum<struct Enum3, EnumA>, 29 BitBool<struct Bool2>>; 30 static_assert(sizeof(BF) == sizeof(std::uint16_t)); 31 } 32 33 TEST_CASE("Simple test") 34 { 35 BF bf; 36 auto check = [&](bool b1, std::optional<bool> ob, unsigned u, EnumA a, 37 EnumB b, std::optional<EnumA> o, bool b2, unsigned raw) 38 { 39 CAPTURE(bf); 40 CHECK(bf.Get<Bool1>() == b1); 41 CHECK(bf.Get<OptBool>() == ob); 42 CHECK(bf.Get<UInt>() == u); 43 CHECK(bf.Get<Enum1>() == a); 44 CHECK(bf.Get<Enum2>() == b); 45 CHECK(bf.Get<Enum3>() == o); 46 CHECK(bf.Get<Bool2>() == b2); 47 48 BF exp(b1, ob, u, a, b, o, b2); 49 CHECK(bf == exp); 50 CHECK(!(bf != exp)); 51 CHECK(bf.GetRaw() == raw); 52 53 }; 54 check(false, {}, 0, EnumA::A, EnumB::X, {}, false, 0); 55 56 bf.Set<Bool1>(true); 57 check(true, {}, 0, EnumA::A, EnumB::X, {}, false, 0b0'000'00'00'00'00'1); 58 59 bf.Set<OptBool>(false); 60 check(true, false, 0, EnumA::A, EnumB::X, {}, false, 0b0'000'00'00'00'10'1); 61 bf.Set<OptBool>(true); 62 check(true, true, 0, EnumA::A, EnumB::X, {}, false, 0b0'000'00'00'00'11'1); 63 bf.Set<OptBool>({}); 64 check(true, {}, 0, EnumA::A, EnumB::X, {}, false, 0b0'000'00'00'00'00'1); 65 66 bf.Set<UInt>(3); 67 check(true, {}, 3, EnumA::A, EnumB::X, {}, false, 0b0'000'00'00'11'00'1); 68 69 bf.Set<Enum3>(EnumA::B); 70 check(true, {}, 3, EnumA::A, EnumB::X, EnumA::B, false, 0b0'010'00'00'11'00'1); 71 72 bf.Set<Bool2>(false); 73 check(true, {}, 3, EnumA::A, EnumB::X, EnumA::B, false, 0b0'010'00'00'11'00'1); 74 bf.Set<Bool2>(true); 75 check(true, {}, 3, EnumA::A, EnumB::X, EnumA::B, true, 0b1'010'00'00'11'00'1); 76 77 bf.Set<Enum2>(EnumB::Z); 78 check(true, {}, 3, EnumA::A, EnumB::Z, EnumA::B, true, 0b1'010'10'00'11'00'1); 79 80 bf.Set<Enum3>({}); 81 check(true, {}, 3, EnumA::A, EnumB::Z, {}, true, 0b1'000'10'00'11'00'1); 82 83 bf.Set<UInt>(18); // should this be an error instead? 84 check(true, {}, 2, EnumA::A, EnumB::Z, {}, true, 0b1'000'10'00'10'00'1); 85 86 bf.Set<Bool1>(false); 87 check(false, {}, 2, EnumA::A, EnumB::Z, {}, true, 0b1'000'10'00'10'00'0); 88 89 bf = BF{true, {}, 3, EnumA::C, EnumB::X, EnumA::A, false}; 90 check(true, {}, 3, EnumA::C, EnumB::X, EnumA::A, false, 0b0'001'00'10'11'00'1); 91 } 92 93 // just because I can 94 static constexpr BF Test0() 95 { 96 BF bf; 97 bf.Set<Bool1>(true); 98 return bf; 99 } 100 static_assert(Test0().Get<Bool1>()); 101 static_assert(!Test0().Get<Bool2>()); 102 103 TEST_CASE("BitNop") 104 { 105 Bitfield<BitBool<Bool1>, BitNop> bf(true); 106 CHECK(bf.Get<Bool1>() == true); 107 } 108 109 TEST_SUITE_END(); 110 }