Limit convolution processing to the output ambisonic order
[openal-soft.git] / common / albyte.h
blobf21b45ec7e558b6d86acb39c3e21f97841f5807c
1 #ifndef AL_BYTE_H
2 #define AL_BYTE_H
4 #include <cstddef>
5 #include <cstdint>
6 #include <limits>
7 #include <type_traits>
9 namespace al {
11 /* The "canonical" way to store raw byte data. Like C++17's std::byte, it's not
12 * treated as a character type and does not work with arithmatic ops. Only
13 * bitwise ops are allowed.
15 enum class byte : unsigned char { };
17 #define REQUIRES(...) std::enable_if_t<(__VA_ARGS__),bool> = true
19 template<typename T, REQUIRES(std::is_integral<T>::value)>
20 inline constexpr T to_integer(al::byte b) noexcept { return T(b); }
23 template<typename T, REQUIRES(std::is_integral<T>::value)>
24 inline constexpr al::byte operator<<(al::byte lhs, T rhs) noexcept
25 { return al::byte(to_integer<unsigned int>(lhs) << rhs); }
27 template<typename T, REQUIRES(std::is_integral<T>::value)>
28 inline constexpr al::byte operator>>(al::byte lhs, T rhs) noexcept
29 { return al::byte(to_integer<unsigned int>(lhs) >> rhs); }
31 template<typename T, REQUIRES(std::is_integral<T>::value)>
32 inline al::byte& operator<<=(al::byte &lhs, T rhs) noexcept
33 { lhs = lhs << rhs; return lhs; }
35 template<typename T, REQUIRES(std::is_integral<T>::value)>
36 inline al::byte& operator>>=(al::byte &lhs, T rhs) noexcept
37 { lhs = lhs >> rhs; return lhs; }
39 #define AL_DECL_OP(op, opeq) \
40 template<typename T, REQUIRES(std::is_integral<T>::value)> \
41 inline constexpr al::byte operator op (al::byte lhs, T rhs) noexcept \
42 { return al::byte(to_integer<unsigned int>(lhs) op static_cast<unsigned int>(rhs)); } \
43 template<typename T, REQUIRES(std::is_integral<T>::value)> \
44 inline al::byte& operator opeq (al::byte &lhs, T rhs) noexcept \
45 { lhs = lhs op rhs; return lhs; } \
46 inline constexpr al::byte operator op (al::byte lhs, al::byte rhs) noexcept \
47 { return al::byte(lhs op to_integer<unsigned int>(rhs)); } \
48 inline al::byte& operator opeq (al::byte &lhs, al::byte rhs) noexcept \
49 { lhs = lhs op rhs; return lhs; }
51 AL_DECL_OP(|, |=)
52 AL_DECL_OP(&, &=)
53 AL_DECL_OP(^, ^=)
55 #undef AL_DECL_OP
57 inline constexpr al::byte operator~(al::byte b) noexcept
58 { return al::byte(~to_integer<unsigned int>(b)); }
61 namespace detail_ {
62 template<size_t> struct Elem { };
63 template<> struct Elem<1> { using type = uint8_t; };
64 template<> struct Elem<2> { using type = uint16_t; };
65 template<> struct Elem<3> { using type = uint32_t; };
66 template<> struct Elem<4> { using type = uint32_t; };
68 template<size_t N> using ElemT = typename Elem<N>::type;
69 } // namespace detail_
71 template<size_t N>
72 class bitfield {
73 static constexpr size_t bits_per_byte{std::numeric_limits<unsigned char>::digits};
74 static constexpr size_t NumElems{(N+bits_per_byte-1) / bits_per_byte};
76 using storage_type = detail_::ElemT<NumElems>;
77 storage_type vals{};
79 public:
80 template<size_t b>
81 inline void set() noexcept
83 static_assert(b < N, "Bit index out of range");
84 vals |= 1 << b;
86 template<size_t b>
87 inline void unset() noexcept
89 static_assert(b < N, "Bit index out of range");
90 vals &= static_cast<storage_type>(~(1 << b));
92 template<size_t b>
93 inline bool get() const noexcept
95 static_assert(b < N, "Bit index out of range");
96 return (vals & (1 << b)) != 0;
99 template<size_t b, size_t ...args, REQUIRES(sizeof...(args) > 0)>
100 void set() noexcept
102 set<b>();
103 set<args...>();
107 #undef REQUIRES
109 } // namespace al
111 #endif /* AL_BYTE_H */