Check for librt earlier
[openal-soft.git] / common / albyte.h
blob23864636060a2d930b7c9d65c1561c05ac80b0d1
1 #ifndef AL_BYTE_H
2 #define AL_BYTE_H
4 #include <cstddef>
5 #include <limits>
6 #include <type_traits>
8 namespace al {
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; }
50 AL_DECL_OP(|)
51 AL_DECL_OP(&)
52 AL_DECL_OP(^)
54 #undef AL_DECL_OP
56 inline constexpr al::byte operator~(al::byte b) noexcept
57 { return al::byte(~to_integer<unsigned int>(b)); }
60 template<size_t N>
61 class bitfield {
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]{};
67 public:
68 template<size_t b>
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);
74 template<size_t b>
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));
80 template<size_t b>
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)>
88 void set() noexcept
90 set<b>();
91 set<args...>();
95 #undef REQUIRES
97 } // namespace al
99 #endif /* AL_BYTE_H */