mirror of
https://github.com/justinian/jsix.git
synced 2025-12-10 00:14:32 -08:00
[util] Remove enum_bitfields
The enum_bitfields system never worked quite right, and always had edge cases where name resolution for the SFINAE would fail. Move everything over to use util::bitset, which can be constexpr and boils down to inline integer bitops in release mode. Improved util::bitset itself, moving the array-backed base implementation into a new util::sized_bitset, and making the single-inttype backed implementation the base case. Also added a distinction between | or |= (which work with real bit values) and + or += (which work with bit indexes).
This commit is contained in:
@@ -3,15 +3,9 @@
|
||||
/// Data structures for reading jsix_boot.dat
|
||||
|
||||
#include <stdint.h>
|
||||
#include <util/enum_bitfields.h>
|
||||
|
||||
namespace bootproto {
|
||||
|
||||
enum class desc_flags : uint16_t {
|
||||
graphical = 0x0001,
|
||||
panic = 0x0002,
|
||||
symbols = 0x0004,
|
||||
};
|
||||
is_bitfield(desc_flags);
|
||||
enum class desc_flags { graphical, panic, symbols };
|
||||
|
||||
} // namespace bootproto
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <util/bitset.h>
|
||||
#include <util/counted.h>
|
||||
#include <util/enum_bitfields.h>
|
||||
|
||||
namespace bootproto {
|
||||
|
||||
@@ -18,19 +18,13 @@ constexpr uint64_t header_magic = 0x4c454e52454b366aull; // 'j6KERNEL'
|
||||
constexpr uint16_t header_version = 2;
|
||||
constexpr uint16_t min_header_version = 2;
|
||||
|
||||
enum class section_flags : uint32_t {
|
||||
none = 0,
|
||||
execute = 1,
|
||||
write = 2,
|
||||
read = 4,
|
||||
};
|
||||
is_bitfield(section_flags);
|
||||
enum class section_flags { none, execute, write, read };
|
||||
|
||||
struct program_section {
|
||||
uintptr_t phys_addr;
|
||||
uintptr_t virt_addr;
|
||||
uint32_t size;
|
||||
section_flags type;
|
||||
util::bitset32 type;
|
||||
};
|
||||
|
||||
struct program {
|
||||
@@ -112,18 +106,13 @@ struct frame_block
|
||||
uint64_t *bitmap;
|
||||
};
|
||||
|
||||
enum class boot_flags : uint16_t {
|
||||
none = 0x0000,
|
||||
debug = 0x0001,
|
||||
test = 0x0002,
|
||||
};
|
||||
is_bitfield(boot_flags);
|
||||
enum class boot_flags { none, debug, test };
|
||||
|
||||
struct args
|
||||
{
|
||||
uint32_t magic;
|
||||
uint16_t version;
|
||||
boot_flags flags;
|
||||
util::bitset16 flags;
|
||||
|
||||
void *pml4;
|
||||
util::counted<void> page_tables;
|
||||
|
||||
@@ -18,7 +18,7 @@ enum class feature {
|
||||
max
|
||||
};
|
||||
|
||||
using features = util::bitset<(unsigned)feature::max>;
|
||||
using features = util::sized_bitset<(unsigned)feature::max>;
|
||||
|
||||
class cpu_id
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include <util/enum_bitfields.h>
|
||||
#include <util/bitset.h>
|
||||
|
||||
namespace elf {
|
||||
|
||||
@@ -54,19 +54,12 @@ struct file_header
|
||||
|
||||
|
||||
enum class segment_type : uint32_t { null, load, dynamic, interpreter, note };
|
||||
enum class segment_flags : uint32_t
|
||||
{
|
||||
none = 0x00,
|
||||
exec = 0x01,
|
||||
write = 0x02,
|
||||
read = 0x04,
|
||||
};
|
||||
is_bitfield(segment_flags);
|
||||
enum class segment_flags { exec, write, read };
|
||||
|
||||
struct segment_header
|
||||
{
|
||||
segment_type type;
|
||||
segment_flags flags;
|
||||
util::bitset32 flags;
|
||||
uint64_t offset;
|
||||
|
||||
uint64_t vaddr;
|
||||
@@ -80,18 +73,13 @@ struct segment_header
|
||||
|
||||
|
||||
enum class section_type : uint32_t { null, progbits };
|
||||
enum class section_flags : uint64_t
|
||||
{
|
||||
write = 0x01,
|
||||
alloc = 0x02,
|
||||
exec = 0x04,
|
||||
};
|
||||
enum class section_flags { write, alloc, exec };
|
||||
|
||||
struct section_header
|
||||
{
|
||||
uint32_t name_offset;
|
||||
section_type type;
|
||||
section_flags flags;
|
||||
util::bitset64 flags;
|
||||
uint64_t addr;
|
||||
uint64_t offset;
|
||||
uint64_t size;
|
||||
@@ -102,5 +90,3 @@ struct section_header
|
||||
} __attribute__ ((packed));
|
||||
|
||||
} // namespace elf
|
||||
|
||||
is_bitfield(elf::section_flags);
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
/// Enums used as flags for syscalls
|
||||
|
||||
enum j6_vm_flags {
|
||||
#define VM_FLAG(name, v) j6_vm_flag_ ## name = v,
|
||||
j6_vm_flag_none = 0,
|
||||
#define VM_FLAG(name, v) j6_vm_flag_ ## name = (1ul << v),
|
||||
#include <j6/tables/vm_flags.inc>
|
||||
#undef VM_FLAG
|
||||
j6_vm_flag_MAX
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
VM_FLAG( none, 0x00000000 )
|
||||
VM_FLAG( write, 0 )
|
||||
VM_FLAG( exec, 1 )
|
||||
|
||||
VM_FLAG( write, 0x00000001 )
|
||||
VM_FLAG( exec, 0x00000002 )
|
||||
VM_FLAG( contiguous, 4 )
|
||||
VM_FLAG( large_pages, 5 )
|
||||
VM_FLAG( huge_pages, 6 )
|
||||
|
||||
VM_FLAG( contiguous, 0x00000010 )
|
||||
VM_FLAG( large_pages, 0x00000020 )
|
||||
VM_FLAG( huge_pages, 0x00000040 )
|
||||
VM_FLAG( write_combine, 8 )
|
||||
|
||||
VM_FLAG( write_combine, 0x00000100 )
|
||||
VM_FLAG( mmio, 12 )
|
||||
|
||||
VM_FLAG( mmio, 0x00001000 )
|
||||
|
||||
VM_FLAG( exact, 0x00010000 )
|
||||
VM_FLAG( ring, 0x00020000 )
|
||||
VM_FLAG( exact, 16 )
|
||||
VM_FLAG( ring, 17 )
|
||||
@@ -7,34 +7,148 @@
|
||||
namespace util {
|
||||
|
||||
/// A statically-sized templated bitset
|
||||
template <unsigned N>
|
||||
template <typename I>
|
||||
class bitset
|
||||
{
|
||||
public:
|
||||
using storage_type = I;
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
static constexpr storage_type bit_or(T b) { return 1ull << uint64_t(b); }
|
||||
|
||||
template <typename T, typename ...Args>
|
||||
static constexpr storage_type bit_or(T b, Args... bs) { return (1ull << storage_type(b)) | bit_or(bs...); }
|
||||
|
||||
public:
|
||||
constexpr bitset(storage_type v = 0) : m_bits {v} {}
|
||||
|
||||
constexpr bitset(const bitset<I> &o) : m_bits {o.m_bits} {}
|
||||
|
||||
template <typename ...Args>
|
||||
__attribute__ ((always_inline))
|
||||
static constexpr bitset of(Args... args) { return {bit_or(args...)}; }
|
||||
|
||||
template <typename T>
|
||||
__attribute__ ((always_inline))
|
||||
static constexpr bitset from(T i) { return {storage_type(i)}; }
|
||||
|
||||
__attribute__ ((always_inline))
|
||||
inline constexpr bitset & operator=(bitset b) { m_bits = b.m_bits; return *this; }
|
||||
|
||||
inline constexpr operator storage_type () const { return m_bits; }
|
||||
|
||||
template <typename T>
|
||||
__attribute__ ((always_inline))
|
||||
inline constexpr bool get(T i) const {
|
||||
return m_bits & bit(i);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
__attribute__ ((always_inline))
|
||||
inline bitset & set(T i) {
|
||||
m_bits |= bit(i);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
__attribute__ ((always_inline))
|
||||
inline bitset & clear(T i) {
|
||||
m_bits &= ~bit(i);
|
||||
return *this;
|
||||
}
|
||||
|
||||
__attribute__ ((always_inline))
|
||||
inline storage_type range(unsigned start, unsigned count) {
|
||||
return (m_bits >> start) & ~((1 << count) - 1);
|
||||
}
|
||||
|
||||
__attribute__ ((always_inline))
|
||||
inline bitset & set_range(unsigned start, unsigned count, storage_type val) {
|
||||
const storage_type mask = ~((1 << count) - 1) << start;
|
||||
m_bits = (m_bits & ~mask) | ((val << start) & mask);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
__attribute__ ((always_inline))
|
||||
inline constexpr bool operator[](T i) const { return get(i); }
|
||||
|
||||
__attribute__ ((always_inline))
|
||||
inline constexpr bitset operator|(bitset b) const { return {storage_type(m_bits | b.m_bits)}; }
|
||||
|
||||
template <typename T>
|
||||
__attribute__ ((always_inline))
|
||||
inline constexpr bitset operator+(T i) const { return {storage_type(m_bits | bit(i))}; }
|
||||
|
||||
__attribute__ ((always_inline))
|
||||
inline constexpr bitset operator|=(bitset b) { *this = *this|b; return *this; }
|
||||
|
||||
template <typename T>
|
||||
__attribute__ ((always_inline))
|
||||
inline constexpr bitset operator+=(T i) { set(i); return *this; }
|
||||
|
||||
__attribute__ ((always_inline))
|
||||
inline constexpr bitset operator&(const bitset &b) const { return {storage_type(m_bits & b.m_bits)}; }
|
||||
|
||||
template <typename T>
|
||||
__attribute__ ((always_inline))
|
||||
inline constexpr bitset operator&(T i) const { return {m_bits & bit(i)}; }
|
||||
|
||||
__attribute__ ((always_inline))
|
||||
inline constexpr bitset & operator&=(const bitset &b) { m_bits &= b.m_bits; return *this; }
|
||||
|
||||
__attribute__ ((always_inline))
|
||||
inline constexpr bool operator==(const bitset &b) const { return m_bits == b.m_bits; }
|
||||
|
||||
template <typename T>
|
||||
__attribute__ ((always_inline))
|
||||
inline constexpr bool operator==(T i) const { return m_bits == storage_type(i); }
|
||||
|
||||
inline constexpr bool empty() const { return m_bits == 0; }
|
||||
|
||||
inline constexpr uint64_t value() const { return m_bits; }
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
inline constexpr storage_type bit(T i) const { return (storage_type(1) << int(i)); }
|
||||
|
||||
storage_type m_bits;
|
||||
};
|
||||
|
||||
using bitset64 = bitset<uint64_t>;
|
||||
using bitset32 = bitset<uint32_t>;
|
||||
using bitset16 = bitset<uint16_t>;
|
||||
using bitset8 = bitset<uint8_t>;
|
||||
|
||||
template <unsigned N>
|
||||
class sized_bitset
|
||||
{
|
||||
static constexpr unsigned num_elems = (N + 63) / 64;
|
||||
|
||||
public:
|
||||
template <typename T>
|
||||
__attribute__ ((force_inline))
|
||||
__attribute__ ((always_inline))
|
||||
inline bool get(T i) const {
|
||||
return bits(i) & bit(i);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
__attribute__ ((force_inline))
|
||||
inline bitset & set(T i) {
|
||||
__attribute__ ((always_inline))
|
||||
inline sized_bitset & set(T i) {
|
||||
bits(i) |= bit(i);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
__attribute__ ((force_inline))
|
||||
inline bitset & clear(T i) {
|
||||
__attribute__ ((always_inline))
|
||||
inline sized_bitset & clear(T i) {
|
||||
bits(i) &= ~bit(i);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
__attribute__ ((force_inline))
|
||||
__attribute__ ((always_inline))
|
||||
inline bool operator[](T i) const { return get(i); }
|
||||
|
||||
inline bool empty() const {
|
||||
@@ -45,260 +159,18 @@ public:
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
__attribute__ ((force_inline))
|
||||
__attribute__ ((always_inline))
|
||||
inline uint64_t bit(T i) const { return (1ull << (static_cast<uint64_t>(i) & 63)); }
|
||||
|
||||
template <typename T>
|
||||
__attribute__ ((force_inline))
|
||||
__attribute__ ((always_inline))
|
||||
inline uint64_t &bits(T i) { return m_bits[static_cast<uint64_t>(i) >> 6]; }
|
||||
|
||||
template <typename T>
|
||||
__attribute__ ((force_inline))
|
||||
__attribute__ ((always_inline))
|
||||
inline uint64_t bits(T i) const { return m_bits[static_cast<uint64_t>(i) >> 6]; }
|
||||
|
||||
uint64_t m_bits[num_elems] = {0};
|
||||
};
|
||||
|
||||
namespace {
|
||||
}
|
||||
|
||||
/// A statically-sized templated bitset
|
||||
template <>
|
||||
class bitset<64>
|
||||
{
|
||||
template <typename T>
|
||||
static constexpr uint64_t bit_or(T b) { return 1ull << uint64_t(b); }
|
||||
|
||||
template <typename T, typename ...Args>
|
||||
static constexpr uint64_t bit_or(T b, Args... bs) { return (1ull << uint64_t(b)) | bit_or(bs...); }
|
||||
|
||||
public:
|
||||
bitset(uint64_t v = 0) : m_bits {v} {}
|
||||
|
||||
bitset(const bitset<64> &o) : m_bits {o.m_bits} {}
|
||||
|
||||
template <typename ...Args>
|
||||
constexpr explicit bitset(Args... args) : m_bits(bit_or(args...)) {}
|
||||
|
||||
template <typename T>
|
||||
__attribute__ ((force_inline))
|
||||
inline bitset & operator=(T v) { m_bits = static_cast<uint64_t>(v); return *this; }
|
||||
|
||||
inline constexpr operator const uint64_t () const { return m_bits; }
|
||||
|
||||
template <typename T>
|
||||
__attribute__ ((force_inline))
|
||||
inline constexpr bool get(T i) const {
|
||||
return m_bits & bit(i);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
__attribute__ ((force_inline))
|
||||
inline bitset & set(T i) {
|
||||
m_bits |= bit(i);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
__attribute__ ((force_inline))
|
||||
inline bitset & clear(T i) {
|
||||
m_bits &= ~bit(i);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
__attribute__ ((force_inline))
|
||||
inline constexpr bool operator[](T i) const { return get(i); }
|
||||
|
||||
inline constexpr bool empty() const { return m_bits == 0; }
|
||||
|
||||
inline constexpr uint64_t value() const { return m_bits; }
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
inline constexpr uint64_t bit(T i) const { return (1ull << static_cast<uint64_t>(i)); }
|
||||
|
||||
uint64_t m_bits;
|
||||
};
|
||||
|
||||
/// A statically-sized templated bitset
|
||||
template <>
|
||||
class bitset<32>
|
||||
{
|
||||
template <typename T>
|
||||
static constexpr uint32_t bit_or(T b) { return 1u << uint32_t(b); }
|
||||
|
||||
template <typename T, typename ...Args>
|
||||
static constexpr uint32_t bit_or(T b, Args... bs) { return (1u << uint32_t(b)) | bit_or(bs...); }
|
||||
|
||||
public:
|
||||
bitset(uint32_t v = 0) : m_bits {v} {}
|
||||
|
||||
bitset(const bitset<32> &o) : m_bits {o.m_bits} {}
|
||||
|
||||
template <typename ...Args>
|
||||
constexpr bitset(Args... args) : m_bits(bit_or(args...)) {}
|
||||
|
||||
template <typename T>
|
||||
inline bitset & operator=(T v) { m_bits = static_cast<uint32_t>(v); return *this; }
|
||||
|
||||
inline constexpr operator uint32_t () const { return m_bits; }
|
||||
|
||||
template <typename T>
|
||||
__attribute__ ((force_inline))
|
||||
inline constexpr bool get(T i) const {
|
||||
return m_bits & bit(i);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
__attribute__ ((force_inline))
|
||||
inline bitset & set(T i) {
|
||||
m_bits |= bit(i);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
__attribute__ ((force_inline))
|
||||
inline bitset & clear(T i) {
|
||||
m_bits &= ~bit(i);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
__attribute__ ((force_inline))
|
||||
inline bool operator[](T i) const { return get(i); }
|
||||
|
||||
inline bool empty() const { return m_bits == 0; }
|
||||
|
||||
inline constexpr uint32_t value() const { return m_bits; }
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
inline uint32_t bit(T i) const { return (1u << static_cast<uint32_t>(i)); }
|
||||
|
||||
uint32_t m_bits;
|
||||
};
|
||||
|
||||
/// A statically-sized templated bitset
|
||||
template <>
|
||||
class bitset<16>
|
||||
{
|
||||
template <typename T>
|
||||
static constexpr uint16_t bit_or(T b) { return 1u << uint16_t(b); }
|
||||
|
||||
template <typename T, typename ...Args>
|
||||
static constexpr uint16_t bit_or(T b, Args... bs) { return (1u << uint16_t(b)) | bit_or(bs...); }
|
||||
|
||||
public:
|
||||
bitset(uint16_t v = 0) : m_bits {v} {}
|
||||
|
||||
bitset(const bitset<16> &o) : m_bits {o.m_bits} {}
|
||||
|
||||
template <typename ...Args>
|
||||
constexpr bitset(Args... args) : m_bits(bit_or(args...)) {}
|
||||
|
||||
template <typename T>
|
||||
inline bitset & operator=(T v) { m_bits = static_cast<uint16_t>(v); return *this; }
|
||||
|
||||
inline constexpr operator uint16_t () const { return m_bits; }
|
||||
|
||||
template <typename T>
|
||||
__attribute__ ((force_inline))
|
||||
inline constexpr bool get(T i) const {
|
||||
return m_bits & bit(i);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
__attribute__ ((force_inline))
|
||||
inline bitset & set(T i) {
|
||||
m_bits |= bit(i);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
__attribute__ ((force_inline))
|
||||
inline bitset & clear(T i) {
|
||||
m_bits &= ~bit(i);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
__attribute__ ((force_inline))
|
||||
inline bool operator[](T i) const { return get(i); }
|
||||
|
||||
inline bool empty() const { return m_bits == 0; }
|
||||
|
||||
inline constexpr uint16_t value() const { return m_bits; }
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
inline uint16_t bit(T i) const { return (1u << static_cast<uint16_t>(i)); }
|
||||
|
||||
uint16_t m_bits;
|
||||
};
|
||||
|
||||
|
||||
/// A statically-sized templated bitset
|
||||
template <>
|
||||
class bitset<8>
|
||||
{
|
||||
template <typename T>
|
||||
static constexpr uint8_t bit_or(T b) { return 1u << uint8_t(b); }
|
||||
|
||||
template <typename T, typename ...Args>
|
||||
static constexpr uint8_t bit_or(T b, Args... bs) { return (1u << uint8_t(b)) | bit_or(bs...); }
|
||||
|
||||
public:
|
||||
bitset(uint8_t v = 0) : m_bits {v} {}
|
||||
|
||||
bitset(const bitset<8> &o) : m_bits {o.m_bits} {}
|
||||
|
||||
template <typename ...Args>
|
||||
constexpr bitset(Args... args) : m_bits(bit_or(args...)) {}
|
||||
|
||||
template <typename T>
|
||||
inline bitset & operator=(T v) { m_bits = static_cast<uint8_t>(v); return *this; }
|
||||
|
||||
inline constexpr operator uint8_t () const { return m_bits; }
|
||||
|
||||
template <typename T>
|
||||
__attribute__ ((force_inline))
|
||||
inline constexpr bool get(T i) const {
|
||||
return m_bits & bit(i);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
__attribute__ ((force_inline))
|
||||
inline bitset & set(T i) {
|
||||
m_bits |= bit(i);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
__attribute__ ((force_inline))
|
||||
inline bitset & clear(T i) {
|
||||
m_bits &= ~bit(i);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
__attribute__ ((force_inline))
|
||||
inline bool operator[](T i) const { return get(i); }
|
||||
|
||||
inline bool empty() const { return m_bits == 0; }
|
||||
|
||||
inline constexpr uint8_t value() const { return m_bits; }
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
inline uint8_t bit(T i) const { return (1u << static_cast<uint8_t>(i)); }
|
||||
|
||||
uint8_t m_bits;
|
||||
};
|
||||
|
||||
using bitset64 = bitset<64>;
|
||||
using bitset32 = bitset<32>;
|
||||
using bitset16 = bitset<16>;
|
||||
using bitset8 = bitset<8>;
|
||||
|
||||
} // namespace util
|
||||
|
||||
@@ -1,99 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <util/basic_types.h>
|
||||
|
||||
namespace util {
|
||||
namespace bits {
|
||||
|
||||
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(typename types::non_const<E>::type{})
|
||||
|| types::is_integral<E>::value;
|
||||
};
|
||||
|
||||
template <typename E, typename F>
|
||||
struct both_enum_or_int {
|
||||
static constexpr bool value =
|
||||
types::conjunction< enum_or_int<E>, enum_or_int<F> >::value;
|
||||
};
|
||||
|
||||
template <typename E, typename R>
|
||||
struct enable_if_bitfield {
|
||||
using enum_t = typename types::non_const<E>::type;
|
||||
using type = typename
|
||||
types::enable_if< is_enum_bitfield(enum_t{}), R >::type;
|
||||
};
|
||||
|
||||
template <typename E, typename F>
|
||||
constexpr typename types::enable_if<both_enum_or_int<E, F>::value,E>::type&
|
||||
operator |= (E &lhs, F rhs)
|
||||
{
|
||||
return lhs = static_cast<E>(
|
||||
static_cast<typename types::integral<E>::type>(lhs) |
|
||||
static_cast<typename types::integral<F>::type>(rhs));
|
||||
}
|
||||
|
||||
template <typename E, typename F>
|
||||
constexpr typename types::enable_if<both_enum_or_int<E, F>::value,E>::type&
|
||||
operator &= (E &lhs, F rhs)
|
||||
{
|
||||
return lhs = static_cast<E>(
|
||||
static_cast<typename types::integral<E>::type>(lhs) &
|
||||
static_cast<typename types::integral<F>::type>(rhs));
|
||||
}
|
||||
|
||||
template <typename E, typename F>
|
||||
constexpr typename types::enable_if<both_enum_or_int<E, F>::value,E>::type&
|
||||
operator ^= (E &lhs, F rhs)
|
||||
{
|
||||
return lhs = static_cast<E>(
|
||||
static_cast<typename types::integral<E>::type>(lhs) ^
|
||||
static_cast<typename types::integral<F>::type>(rhs));
|
||||
}
|
||||
|
||||
template <typename E, typename F>
|
||||
constexpr typename types::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 types::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 types::enable_if<both_enum_or_int<E, F>::value,E>::type
|
||||
operator ^ (E lhs, F rhs) { return lhs ^= rhs; }
|
||||
|
||||
template <typename E>
|
||||
constexpr typename enable_if_bitfield<E,E>::type
|
||||
operator ~ (E rhs) { return static_cast<E>(~static_cast<typename types::integral<E>::type>(rhs)); }
|
||||
|
||||
template <typename E>
|
||||
constexpr typename enable_if_bitfield<E,bool>::type
|
||||
operator ! (E rhs) { return static_cast<typename types::integral<E>::type>(rhs) == 0; }
|
||||
|
||||
/// Override logical-and to mean 'rhs contains all bits in lhs'
|
||||
template <typename E>
|
||||
constexpr typename enable_if_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 types::integral<E>::type>(set) &
|
||||
static_cast<typename types::integral<F>::type>(flags)) ==
|
||||
static_cast<typename types::integral<F>::type>(flags);
|
||||
}
|
||||
|
||||
} // namespace bits
|
||||
} // namespace util
|
||||
|
||||
#define is_bitfield(name) \
|
||||
constexpr bool is_enum_bitfield(name) { return true; } \
|
||||
using namespace ::util::bits;
|
||||
|
||||
@@ -20,7 +20,6 @@ module("util",
|
||||
"util/cdb.h",
|
||||
"util/counted.h",
|
||||
"util/deque.h",
|
||||
"util/enum_bitfields.h",
|
||||
"util/format.h",
|
||||
"util/hash.h",
|
||||
"util/linked_list.h",
|
||||
|
||||
Reference in New Issue
Block a user