10 /* The "canonical" way to store raw byte data. Like C++17's std::byte, it's not
11 * treated as a character type and does not work with arithmatic ops. Only
12 * bitwise ops are allowed.
14 enum class byte
: unsigned char { };
16 #define REQUIRES(...) typename std::enable_if<(__VA_ARGS__),bool>::type = true
18 template<typename T
, REQUIRES(std::is_integral
<T
>::value
)>
19 inline constexpr T
to_integer(al::byte b
) noexcept
{ return T(b
); }
22 template<typename T
, REQUIRES(std::is_integral
<T
>::value
)>
23 inline constexpr al::byte
operator<<(al::byte lhs
, T rhs
) noexcept
24 { return al::byte(to_integer
<unsigned int>(lhs
) << rhs
); }
26 template<typename T
, REQUIRES(std::is_integral
<T
>::value
)>
27 inline constexpr al::byte
operator>>(al::byte lhs
, T rhs
) noexcept
28 { return al::byte(to_integer
<unsigned int>(lhs
) >> rhs
); }
30 template<typename T
, REQUIRES(std::is_integral
<T
>::value
)>
31 inline al::byte
& operator<<=(al::byte
&lhs
, T rhs
) noexcept
32 { lhs
= lhs
<< rhs
; return lhs
; }
34 template<typename T
, REQUIRES(std::is_integral
<T
>::value
)>
35 inline al::byte
& operator>>=(al::byte
&lhs
, T rhs
) noexcept
36 { lhs
= lhs
>> rhs
; return lhs
; }
38 #define AL_DECL_OP(op) \
39 template<typename T, REQUIRES(std::is_integral<T>::value)> \
40 inline constexpr al::byte operator op (al::byte lhs, T rhs) noexcept \
41 { return al::byte(to_integer<unsigned int>(lhs) op static_cast<unsigned int>(rhs)); } \
42 template<typename T, REQUIRES(std::is_integral<T>::value)> \
43 inline al::byte& operator op##= (al::byte &lhs, T rhs) noexcept \
44 { lhs = lhs op rhs; return lhs; } \
45 inline constexpr al::byte operator op (al::byte lhs, al::byte rhs) noexcept \
46 { return al::byte(lhs op to_integer<unsigned int>(rhs)); } \
47 inline al::byte& operator op##= (al::byte &lhs, al::byte rhs) noexcept \
48 { lhs = lhs op rhs; return lhs; }
56 inline constexpr al::byte
operator~(al::byte b
) noexcept
57 { return al::byte(~to_integer
<unsigned int>(b
)); }
62 static constexpr size_t bits_per_byte
{std::numeric_limits
<unsigned char>::digits
};
63 static constexpr size_t NumElems
{(N
+bits_per_byte
-1) / bits_per_byte
};
65 byte vals
[NumElems
]{};
69 inline void set() noexcept
71 static_assert(b
< N
, "Bit index out of range");
72 vals
[b
/bits_per_byte
] |= 1 << (b
%bits_per_byte
);
75 inline void unset() noexcept
77 static_assert(b
< N
, "Bit index out of range");
78 vals
[b
/bits_per_byte
] &= ~(1 << (b
%bits_per_byte
));
81 inline bool get() const noexcept
83 static_assert(b
< N
, "Bit index out of range");
84 return (vals
[b
/bits_per_byte
] & (1 << (b
%bits_per_byte
))) != byte
{};
87 template<size_t b
, size_t ...args
, REQUIRES(sizeof...(args
) > 0)>
99 #endif /* AL_BYTE_H */