[includes] Move enum_bitfields.h to base includes

Pull this widely-useful header out of kutil, so more things can use it.
Also replace its dependency on <type_traits> by defining our own custom
basic_types.h which contains a subset of the standard's types.
This commit is contained in:
Justin C. Miller
2021-07-31 14:40:23 -07:00
parent 5524ca5b25
commit 5e2cfab7ba
11 changed files with 154 additions and 114 deletions

View File

@@ -1,6 +1,6 @@
#pragma once
#include <stdint.h>
#include "kutil/enum_bitfields.h"
#include "enum_bitfields.h"
namespace elf {
@@ -95,4 +95,4 @@ struct section_header
} // namespace elf
IS_BITFIELD(elf::section_flags);
is_bitfield(elf::section_flags);

View File

@@ -1,105 +0,0 @@
#pragma once
#include <type_traits>
namespace kutil {
namespace bitfields {
template <typename E>
constexpr bool is_enum_bitfield(E) { return false; }
template <typename E>
struct enum_or_int {
static constexpr bool value =
is_enum_bitfield(E{}) || std::is_integral<E>::value;
};
template <typename E, typename F>
struct both_enum_or_int {
static constexpr bool value =
std::conjunction< enum_or_int<E>, enum_or_int<F> >::value;
};
template <typename E>
struct integral { using type = typename std::underlying_type<E>::type; };
template <> struct integral<char> { using type = char; };
template <> struct integral<unsigned char> { using type = unsigned char; };
template <> struct integral<short> { using type = short; };
template <> struct integral<unsigned short> { using type = unsigned short; };
template <> struct integral<int> { using type = int; };
template <> struct integral<unsigned int> { using type = unsigned int; };
template <> struct integral<long> { using type = long; };
template <> struct integral<unsigned long> { using type = unsigned long; };
template <> struct integral<long long> { using type = long long; };
template <> struct integral<unsigned long long> { using type = unsigned long long; };
template <typename E, typename F>
constexpr typename std::enable_if<both_enum_or_int<E, F>::value,E>::type&
operator |= (E &lhs, F rhs)
{
return lhs = static_cast<E>(
static_cast<typename integral<E>::type>(lhs) |
static_cast<typename integral<F>::type>(rhs));
}
template <typename E, typename F>
constexpr typename std::enable_if<both_enum_or_int<E, F>::value,E>::type&
operator &= (E &lhs, F rhs)
{
return lhs = static_cast<E>(
static_cast<typename integral<E>::type>(lhs) &
static_cast<typename integral<F>::type>(rhs));
}
template <typename E, typename F>
constexpr typename std::enable_if<both_enum_or_int<E, F>::value,E>::type&
operator ^= (E &lhs, F rhs)
{
return lhs = static_cast<E>(
static_cast<typename integral<E>::type>(lhs) ^
static_cast<typename integral<F>::type>(rhs));
}
template <typename E, typename F>
constexpr typename std::enable_if<both_enum_or_int<E, F>::value,E>::type
operator & (E lhs, F rhs) { return lhs &= rhs; }
template <typename E, typename F>
constexpr typename std::enable_if<both_enum_or_int<E, F>::value,E>::type
operator | (E lhs, F rhs) { return lhs |= rhs; }
template <typename E, typename F>
constexpr typename std::enable_if<both_enum_or_int<E, F>::value,E>::type
operator ^ (E lhs, F rhs) { return lhs ^= rhs; }
template <typename E>
constexpr typename std::enable_if<is_enum_bitfield(E{}),E>::type
operator ~ (E rhs) { return static_cast<E>(~static_cast<typename std::underlying_type<E>::type>(rhs)); }
template <typename E>
constexpr typename std::enable_if<is_enum_bitfield(E{}),bool>::type
operator ! (E rhs) { return static_cast<typename std::underlying_type<E>::type>(rhs) == 0; }
/// Override logical-and to mean 'rhs contains all bits in lhs'
template <typename E>
constexpr typename std::enable_if<is_enum_bitfield(E{}),bool>::type
operator && (E rhs, E lhs) { return (rhs & lhs) == lhs; }
/// Generic 'has' for non-marked bitfields
template <typename E, typename F>
constexpr bool has(E set, F flags)
{
return
(static_cast<typename integral<E>::type>(set) &
static_cast<typename integral<F>::type>(flags)) ==
static_cast<typename integral<F>::type>(flags);
}
} // namespace bitfields
} // namespace kutil
#define is_bitfield(name) \
constexpr bool is_enum_bitfield(name) { return true; } \
using namespace kutil::bitfields;