diff options
author | Chris Robinson <[email protected]> | 2019-05-24 06:11:21 -0700 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2019-05-24 06:11:21 -0700 |
commit | 1945b50834e2be380e0ad206f9deefacb455191b (patch) | |
tree | c461695d4b58ae8469c9d92054f694ad984757e1 /common | |
parent | 857473b6b06314e18f52e97cb440e5daee1ad523 (diff) |
Add a unique byte type for dealing with raw bytes
Diffstat (limited to 'common')
-rw-r--r-- | common/albyte.h | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/common/albyte.h b/common/albyte.h new file mode 100644 index 00000000..6fc78dbd --- /dev/null +++ b/common/albyte.h @@ -0,0 +1,60 @@ +#ifndef AL_BYTE_H +#define AL_BYTE_H + +#include <type_traits> + +namespace al { + +/* The "canonical" way to store raw byte data. Like C++17's std::byte, it's not + * treated as a character type and does not work with arithmatic ops. Only + * bitwise ops are allowed. + */ +enum class byte : unsigned char { }; + +template<typename T, typename std::enable_if<std::is_integral<T>::value,int>::type = 0> +inline constexpr T to_integer(al::byte b) noexcept { return T(b); } + + +template<typename T, typename std::enable_if<std::is_integral<T>::value,int>::type = 0> +inline constexpr al::byte operator<<(al::byte lhs, T rhs) noexcept +{ return al::byte(to_integer<unsigned int>(lhs) << rhs); } + +template<typename T, typename std::enable_if<std::is_integral<T>::value,int>::type = 0> +inline constexpr al::byte operator>>(al::byte lhs, T rhs) noexcept +{ return al::byte(to_integer<unsigned int>(lhs) >> rhs); } + +#define AL_DECL_OP(op) \ +inline constexpr al::byte operator op (al::byte lhs, al::byte rhs) noexcept \ +{ return al::byte(to_integer<unsigned int>(lhs) op to_integer<unsigned int>(rhs)); } + +AL_DECL_OP(|) +AL_DECL_OP(&) +AL_DECL_OP(^) + +#undef AL_DECL_OP + +inline constexpr al::byte operator~(al::byte b) noexcept +{ return al::byte(~to_integer<unsigned int>(b)); } + + +template<typename T, typename std::enable_if<std::is_integral<T>::value,int>::type = 0> +inline al::byte& operator<<=(al::byte &lhs, T rhs) noexcept +{ lhs = lhs << rhs; return lhs; } + +template<typename T, typename std::enable_if<std::is_integral<T>::value,int>::type = 0> +inline al::byte& operator>>=(al::byte &lhs, T rhs) noexcept +{ lhs = lhs >> rhs; return lhs; } + +#define AL_DECL_OP(op) \ +inline al::byte& operator op##= (al::byte &lhs, al::byte rhs) noexcept \ +{ lhs = lhs op rhs; return lhs; } + +AL_DECL_OP(|) +AL_DECL_OP(&) +AL_DECL_OP(^) + +#undef AL_DECL_OP + +} // namespace al + +#endif /* AL_BYTE_H */ |