[kutil] Make enum bitfields usable in other scopes
Changing the SFINAE/enable_if strategy from a type to a constexpr function means that it can be defined in other scopes than the functions themselves, because of function overloading. This lets us put everything into the kutil::bitfields namespace, and make bitfields out of enums in other namespaces. Also took the chance to clean up the implementation a bit.
This commit is contained in:
@@ -84,7 +84,7 @@ enum class acpi_fadt_flags : uint32_t
|
|||||||
hw_reduced_acpi = 0x00100000,
|
hw_reduced_acpi = 0x00100000,
|
||||||
low_pwr_s0_idle = 0x00200000
|
low_pwr_s0_idle = 0x00200000
|
||||||
};
|
};
|
||||||
IS_BITFIELD(acpi_fadt_flags);
|
is_bitfield(acpi_fadt_flags);
|
||||||
|
|
||||||
struct acpi_fadt
|
struct acpi_fadt
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -19,6 +19,18 @@ protected:
|
|||||||
uint32_t *m_base;
|
uint32_t *m_base;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Controller for processor-local APICs
|
||||||
|
class lapic :
|
||||||
|
public apic
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// Constructor
|
||||||
|
/// \arg base Physicl base address of the APIC's MMIO registers
|
||||||
|
lapic(uintptr_t base);
|
||||||
|
|
||||||
|
/// Get the local APIC's ID
|
||||||
|
uint8_t get_id();
|
||||||
|
|
||||||
enum class ipi : uint32_t
|
enum class ipi : uint32_t
|
||||||
{
|
{
|
||||||
// Delivery modes
|
// Delivery modes
|
||||||
@@ -34,19 +46,6 @@ enum class ipi : uint32_t
|
|||||||
edge = 0x0000, ///< edge-triggered
|
edge = 0x0000, ///< edge-triggered
|
||||||
level = 0x8000, ///< level-triggered
|
level = 0x8000, ///< level-triggered
|
||||||
};
|
};
|
||||||
IS_BITFIELD(ipi);
|
|
||||||
|
|
||||||
/// Controller for processor-local APICs
|
|
||||||
class lapic :
|
|
||||||
public apic
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/// Constructor
|
|
||||||
/// \arg base Physicl base address of the APIC's MMIO registers
|
|
||||||
lapic(uintptr_t base);
|
|
||||||
|
|
||||||
/// Get the local APIC's ID
|
|
||||||
uint8_t get_id();
|
|
||||||
|
|
||||||
/// Send an inter-processor interrupt.
|
/// Send an inter-processor interrupt.
|
||||||
/// \arg mode The sending mode
|
/// \arg mode The sending mode
|
||||||
@@ -144,3 +143,6 @@ private:
|
|||||||
uint8_t m_id;
|
uint8_t m_id;
|
||||||
uint8_t m_version;
|
uint8_t m_version;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
is_bitfield(lapic::ipi);
|
||||||
|
|
||||||
|
|||||||
@@ -34,13 +34,13 @@ GDT::GDT(TSS *tss) :
|
|||||||
m_ptr.base = &m_entries[0];
|
m_ptr.base = &m_entries[0];
|
||||||
|
|
||||||
// Kernel CS/SS - always 64bit
|
// Kernel CS/SS - always 64bit
|
||||||
set(kern_cs_index, 0, 0xfffff, true, gdt_type::read_write | gdt_type::execute);
|
set(kern_cs_index, 0, 0xfffff, true, type::read_write | type::execute);
|
||||||
set(kern_ss_index, 0, 0xfffff, true, gdt_type::read_write);
|
set(kern_ss_index, 0, 0xfffff, true, type::read_write);
|
||||||
|
|
||||||
// User CS32/SS/CS64 - layout expected by SYSRET
|
// User CS32/SS/CS64 - layout expected by SYSRET
|
||||||
set(user_cs32_index, 0, 0xfffff, false, gdt_type::ring3 | gdt_type::read_write | gdt_type::execute);
|
set(user_cs32_index, 0, 0xfffff, false, type::ring3 | type::read_write | type::execute);
|
||||||
set(user_ss_index, 0, 0xfffff, true, gdt_type::ring3 | gdt_type::read_write);
|
set(user_ss_index, 0, 0xfffff, true, type::ring3 | type::read_write);
|
||||||
set(user_cs64_index, 0, 0xfffff, true, gdt_type::ring3 | gdt_type::read_write | gdt_type::execute);
|
set(user_cs64_index, 0, 0xfffff, true, type::ring3 | type::read_write | type::execute);
|
||||||
|
|
||||||
set_tss(tss);
|
set_tss(tss);
|
||||||
}
|
}
|
||||||
@@ -63,7 +63,7 @@ GDT::install() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
GDT::set(uint8_t i, uint32_t base, uint64_t limit, bool is64, gdt_type type)
|
GDT::set(uint8_t i, uint32_t base, uint64_t limit, bool is64, type t)
|
||||||
{
|
{
|
||||||
m_entries[i].limit_low = limit & 0xffff;
|
m_entries[i].limit_low = limit & 0xffff;
|
||||||
m_entries[i].size = (limit >> 16) & 0xf;
|
m_entries[i].size = (limit >> 16) & 0xf;
|
||||||
@@ -73,7 +73,7 @@ GDT::set(uint8_t i, uint32_t base, uint64_t limit, bool is64, gdt_type type)
|
|||||||
m_entries[i].base_mid = (base >> 16) & 0xff;
|
m_entries[i].base_mid = (base >> 16) & 0xff;
|
||||||
m_entries[i].base_high = (base >> 24) & 0xff;
|
m_entries[i].base_high = (base >> 24) & 0xff;
|
||||||
|
|
||||||
m_entries[i].type = type | gdt_type::system | gdt_type::present;
|
m_entries[i].type = t | type::system | type::present;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct tss_descriptor
|
struct tss_descriptor
|
||||||
@@ -81,7 +81,7 @@ struct tss_descriptor
|
|||||||
uint16_t limit_low;
|
uint16_t limit_low;
|
||||||
uint16_t base_00;
|
uint16_t base_00;
|
||||||
uint8_t base_16;
|
uint8_t base_16;
|
||||||
gdt_type type;
|
GDT::type type;
|
||||||
uint8_t size;
|
uint8_t size;
|
||||||
uint8_t base_24;
|
uint8_t base_24;
|
||||||
uint32_t base_32;
|
uint32_t base_32;
|
||||||
@@ -105,10 +105,10 @@ GDT::set_tss(TSS *tss)
|
|||||||
tssd.reserved = 0;
|
tssd.reserved = 0;
|
||||||
|
|
||||||
tssd.type =
|
tssd.type =
|
||||||
gdt_type::accessed |
|
type::accessed |
|
||||||
gdt_type::execute |
|
type::execute |
|
||||||
gdt_type::ring3 |
|
type::ring3 |
|
||||||
gdt_type::present;
|
type::present;
|
||||||
|
|
||||||
kutil::memcpy(&m_entries[tss_index], &tssd, sizeof(tss_descriptor));
|
kutil::memcpy(&m_entries[tss_index], &tssd, sizeof(tss_descriptor));
|
||||||
}
|
}
|
||||||
@@ -141,26 +141,26 @@ GDT::dump(unsigned index) const
|
|||||||
gdt[i].limit_low;
|
gdt[i].limit_low;
|
||||||
|
|
||||||
cons->printf(" %02d:", i);
|
cons->printf(" %02d:", i);
|
||||||
if (! bitfield_has(gdt[i].type, gdt_type::present)) {
|
if (! (gdt[i].type && type::present)) {
|
||||||
cons->puts(" Not Present\n");
|
cons->puts(" Not Present\n");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
cons->printf(" Base %08x limit %05x ", base, limit);
|
cons->printf(" Base %08x limit %05x ", base, limit);
|
||||||
|
|
||||||
switch (gdt[i].type & gdt_type::ring3) {
|
switch (gdt[i].type & type::ring3) {
|
||||||
case gdt_type::ring3: cons->puts("ring3"); break;
|
case type::ring3: cons->puts("ring3"); break;
|
||||||
case gdt_type::ring2: cons->puts("ring2"); break;
|
case type::ring2: cons->puts("ring2"); break;
|
||||||
case gdt_type::ring1: cons->puts("ring1"); break;
|
case type::ring1: cons->puts("ring1"); break;
|
||||||
default: cons->puts("ring0"); break;
|
default: cons->puts("ring0"); break;
|
||||||
}
|
}
|
||||||
|
|
||||||
cons->printf(" %s %s %s %s %s %s %s\n",
|
cons->printf(" %s %s %s %s %s %s %s\n",
|
||||||
bitfield_has(gdt[i].type, gdt_type::accessed) ? "A" : " ",
|
(gdt[i].type && type::accessed) ? "A" : " ",
|
||||||
bitfield_has(gdt[i].type, gdt_type::read_write) ? "RW" : " ",
|
(gdt[i].type && type::read_write) ? "RW" : " ",
|
||||||
bitfield_has(gdt[i].type, gdt_type::conforming) ? "C" : " ",
|
(gdt[i].type && type::conforming) ? "C" : " ",
|
||||||
bitfield_has(gdt[i].type, gdt_type::execute) ? "EX" : " ",
|
(gdt[i].type && type::execute) ? "EX" : " ",
|
||||||
bitfield_has(gdt[i].type, gdt_type::system) ? "S" : " ",
|
(gdt[i].type && type::system) ? "S" : " ",
|
||||||
(gdt[i].size & 0x80) ? "KB" : " B",
|
(gdt[i].size & 0x80) ? "KB" : " B",
|
||||||
(gdt[i].size & 0x60) == 0x20 ? "64" :
|
(gdt[i].size & 0x60) == 0x20 ? "64" :
|
||||||
(gdt[i].size & 0x60) == 0x40 ? "32" : "16");
|
(gdt[i].size & 0x60) == 0x40 ? "32" : "16");
|
||||||
|
|||||||
@@ -7,20 +7,6 @@
|
|||||||
|
|
||||||
class TSS;
|
class TSS;
|
||||||
|
|
||||||
enum class gdt_type : uint8_t
|
|
||||||
{
|
|
||||||
accessed = 0x01,
|
|
||||||
read_write = 0x02,
|
|
||||||
conforming = 0x04,
|
|
||||||
execute = 0x08,
|
|
||||||
system = 0x10,
|
|
||||||
ring1 = 0x20,
|
|
||||||
ring2 = 0x40,
|
|
||||||
ring3 = 0x60,
|
|
||||||
present = 0x80
|
|
||||||
};
|
|
||||||
IS_BITFIELD(gdt_type);
|
|
||||||
|
|
||||||
class GDT
|
class GDT
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -39,8 +25,21 @@ public:
|
|||||||
/// \arg index Which entry to print, or -1 for all entries
|
/// \arg index Which entry to print, or -1 for all entries
|
||||||
void dump(unsigned index = -1) const;
|
void dump(unsigned index = -1) const;
|
||||||
|
|
||||||
|
enum class type : uint8_t
|
||||||
|
{
|
||||||
|
accessed = 0x01,
|
||||||
|
read_write = 0x02,
|
||||||
|
conforming = 0x04,
|
||||||
|
execute = 0x08,
|
||||||
|
system = 0x10,
|
||||||
|
ring1 = 0x20,
|
||||||
|
ring2 = 0x40,
|
||||||
|
ring3 = 0x60,
|
||||||
|
present = 0x80
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void set(uint8_t i, uint32_t base, uint64_t limit, bool is64, gdt_type type);
|
void set(uint8_t i, uint32_t base, uint64_t limit, bool is64, type t);
|
||||||
void set_tss(TSS *tss);
|
void set_tss(TSS *tss);
|
||||||
|
|
||||||
struct descriptor
|
struct descriptor
|
||||||
@@ -48,7 +47,7 @@ private:
|
|||||||
uint16_t limit_low;
|
uint16_t limit_low;
|
||||||
uint16_t base_low;
|
uint16_t base_low;
|
||||||
uint8_t base_mid;
|
uint8_t base_mid;
|
||||||
gdt_type type;
|
type type;
|
||||||
uint8_t size;
|
uint8_t size;
|
||||||
uint8_t base_high;
|
uint8_t base_high;
|
||||||
} __attribute__ ((packed, align(8)));
|
} __attribute__ ((packed, align(8)));
|
||||||
@@ -64,3 +63,5 @@ private:
|
|||||||
|
|
||||||
ptr m_ptr;
|
ptr m_ptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
is_bitfield(GDT::type);
|
||||||
|
|||||||
@@ -263,7 +263,7 @@ start_aps(lapic &apic, const kutil::vector<uint8_t> &ids, void *kpml4)
|
|||||||
size_t free_stack_count = 0;
|
size_t free_stack_count = 0;
|
||||||
uintptr_t stack_area_start = 0;
|
uintptr_t stack_area_start = 0;
|
||||||
|
|
||||||
ipi mode = ipi::init | ipi::level | ipi::assert;
|
lapic::ipi mode = lapic::ipi::init | lapic::ipi::level | lapic::ipi::assert;
|
||||||
apic.send_ipi_broadcast(mode, false, 0);
|
apic.send_ipi_broadcast(mode, false, 0);
|
||||||
|
|
||||||
for (uint8_t id : ids) {
|
for (uint8_t id : ids) {
|
||||||
@@ -301,7 +301,7 @@ start_aps(lapic &apic, const kutil::vector<uint8_t> &ids, void *kpml4)
|
|||||||
size_t current_count = ap_startup_count;
|
size_t current_count = ap_startup_count;
|
||||||
log::debug(logs::boot, "Starting AP %d: stack %llx", cpu->index, stack_end);
|
log::debug(logs::boot, "Starting AP %d: stack %llx", cpu->index, stack_end);
|
||||||
|
|
||||||
ipi startup = ipi::startup | ipi::assert;
|
lapic::ipi startup = lapic::ipi::startup | lapic::ipi::assert;
|
||||||
|
|
||||||
apic.send_ipi(startup, vector, id);
|
apic.send_ipi(startup, vector, id);
|
||||||
for (unsigned i = 0; i < 20; ++i) {
|
for (unsigned i = 0; i < 20; ++i) {
|
||||||
|
|||||||
@@ -24,6 +24,11 @@ using memory::kernel_max_heap;
|
|||||||
|
|
||||||
using namespace kernel;
|
using namespace kernel;
|
||||||
|
|
||||||
|
namespace kernel {
|
||||||
|
namespace args {
|
||||||
|
is_bitfield(section_flags);
|
||||||
|
}}
|
||||||
|
|
||||||
extern "C" void initialize_main_thread();
|
extern "C" void initialize_main_thread();
|
||||||
extern "C" uintptr_t initialize_main_user_stack();
|
extern "C" uintptr_t initialize_main_user_stack();
|
||||||
|
|
||||||
@@ -203,8 +208,8 @@ load_simple_process(args::program &program)
|
|||||||
|
|
||||||
for (const auto § : program.sections) {
|
for (const auto § : program.sections) {
|
||||||
vm_flags flags =
|
vm_flags flags =
|
||||||
(bitfield_has(sect.type, section_flags::execute) ? vm_flags::exec : vm_flags::none) |
|
((sect.type && section_flags::execute) ? vm_flags::exec : vm_flags::none) |
|
||||||
(bitfield_has(sect.type, section_flags::write) ? vm_flags::write : vm_flags::none);
|
((sect.type && section_flags::write) ? vm_flags::write : vm_flags::none);
|
||||||
|
|
||||||
vm_area *vma = new vm_area_fixed(sect.phys_addr, sect.size, flags);
|
vm_area *vma = new vm_area_fixed(sect.phys_addr, sect.size, flags);
|
||||||
space.add(sect.virt_addr, vma);
|
space.add(sect.virt_addr, vma);
|
||||||
|
|||||||
@@ -174,4 +174,4 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
IS_BITFIELD(vm_flags);
|
is_bitfield(vm_flags);
|
||||||
|
|||||||
@@ -194,4 +194,4 @@ inline bool operator<(page_table::level a, page_table::level b) {
|
|||||||
inline page_table::level& operator++(page_table::level& l) { l = l + 1; return l; }
|
inline page_table::level& operator++(page_table::level& l) { l = l + 1; return l; }
|
||||||
inline page_table::level& operator--(page_table::level& l) { l = l - 1; return l; }
|
inline page_table::level& operator--(page_table::level& l) { l = l - 1; return l; }
|
||||||
|
|
||||||
IS_BITFIELD(page_table::flag);
|
is_bitfield(page_table::flag);
|
||||||
|
|||||||
@@ -132,4 +132,4 @@ private:
|
|||||||
kutil::spinlock m_lock;
|
kutil::spinlock m_lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
IS_BITFIELD(vm_space::fault_type);
|
is_bitfield(vm_space::fault_type);
|
||||||
|
|||||||
@@ -2,16 +2,16 @@
|
|||||||
|
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
template<typename E>
|
namespace kutil {
|
||||||
struct is_enum_bitfield { static constexpr bool value = false; };
|
namespace bitfields {
|
||||||
|
|
||||||
#define IS_BITFIELD(name) \
|
template <typename E>
|
||||||
template<> struct ::is_enum_bitfield<name> {static constexpr bool value=true;}
|
constexpr bool is_enum_bitfield(E) { return false; }
|
||||||
|
|
||||||
template <typename E>
|
template <typename E>
|
||||||
struct enum_or_int {
|
struct enum_or_int {
|
||||||
static constexpr bool value =
|
static constexpr bool value =
|
||||||
std::disjunction< is_enum_bitfield<E>, std::is_integral<E> >::value;
|
is_enum_bitfield(E{}) || std::is_integral<E>::value;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename E, typename F>
|
template <typename E, typename F>
|
||||||
@@ -34,116 +34,62 @@ template <> struct integral<unsigned long> { using type = unsigned long; };
|
|||||||
template <> struct integral<long long> { using type = long long; };
|
template <> struct integral<long long> { using type = long long; };
|
||||||
template <> struct integral<unsigned long long> { using type = unsigned 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 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 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 static_cast<E> (
|
|
||||||
static_cast<typename integral<E>::type>(lhs) ^
|
|
||||||
static_cast<typename integral<F>::type>(rhs));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename E>
|
|
||||||
constexpr typename std::enable_if<is_enum_bitfield<E>::value,E>::type
|
|
||||||
operator ~ (E rhs)
|
|
||||||
{
|
|
||||||
return static_cast<E>(~static_cast<typename std::underlying_type<E>::type>(rhs));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename E, typename F>
|
template <typename E, typename F>
|
||||||
constexpr typename std::enable_if<both_enum_or_int<E, F>::value,E>::type&
|
constexpr typename std::enable_if<both_enum_or_int<E, F>::value,E>::type&
|
||||||
operator |= (E &lhs, F rhs)
|
operator |= (E &lhs, F rhs)
|
||||||
{
|
{
|
||||||
lhs = static_cast<E>(
|
return lhs = static_cast<E>(
|
||||||
static_cast<typename integral<E>::type>(lhs) |
|
static_cast<typename integral<E>::type>(lhs) |
|
||||||
static_cast<typename integral<F>::type>(rhs));
|
static_cast<typename integral<F>::type>(rhs));
|
||||||
|
|
||||||
return lhs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename E, typename F>
|
template <typename E, typename F>
|
||||||
constexpr typename std::enable_if<both_enum_or_int<E, F>::value,E>::type&
|
constexpr typename std::enable_if<both_enum_or_int<E, F>::value,E>::type&
|
||||||
operator &= (E &lhs, F rhs)
|
operator &= (E &lhs, F rhs)
|
||||||
{
|
{
|
||||||
lhs = static_cast<E>(
|
return lhs = static_cast<E>(
|
||||||
static_cast<typename integral<E>::type>(lhs) &
|
static_cast<typename integral<E>::type>(lhs) &
|
||||||
static_cast<typename integral<F>::type>(rhs));
|
static_cast<typename integral<F>::type>(rhs));
|
||||||
|
|
||||||
return lhs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename E, typename F>
|
template <typename E, typename F>
|
||||||
constexpr typename std::enable_if<both_enum_or_int<E, F>::value,E>::type&
|
constexpr typename std::enable_if<both_enum_or_int<E, F>::value,E>::type&
|
||||||
operator ^= (E &lhs, F rhs)
|
operator ^= (E &lhs, F rhs)
|
||||||
{
|
{
|
||||||
lhs = static_cast<E>(
|
return lhs = static_cast<E>(
|
||||||
static_cast<typename integral<E>::type>(lhs) ^
|
static_cast<typename integral<E>::type>(lhs) ^
|
||||||
static_cast<typename integral<F>::type>(rhs));
|
static_cast<typename integral<F>::type>(rhs));
|
||||||
|
|
||||||
return lhs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename E, typename F>
|
template <typename E, typename F>
|
||||||
constexpr typename std::enable_if<both_enum_or_int<E, F>::value,E>::type&
|
constexpr typename std::enable_if<both_enum_or_int<E, F>::value,E>::type
|
||||||
operator -= (E &lhs, F rhs)
|
operator & (E lhs, F rhs) { return lhs &= rhs; }
|
||||||
{
|
|
||||||
lhs = static_cast<E>(
|
|
||||||
static_cast<typename integral<E>::type>(lhs) &
|
|
||||||
~static_cast<typename integral<F>::type>(rhs));
|
|
||||||
|
|
||||||
return lhs;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename E, typename F>
|
template <typename E, typename F>
|
||||||
constexpr typename std::enable_if<both_enum_or_int<E, F>::value,E>::type&
|
constexpr typename std::enable_if<both_enum_or_int<E, F>::value,E>::type
|
||||||
operator += (E &lhs, F rhs)
|
operator | (E lhs, F rhs) { return lhs |= rhs; }
|
||||||
{
|
|
||||||
lhs = static_cast<E>(
|
|
||||||
static_cast<typename integral<E>::type>(lhs) |
|
|
||||||
static_cast<typename integral<F>::type>(rhs));
|
|
||||||
|
|
||||||
return lhs;
|
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>
|
template <typename E>
|
||||||
constexpr typename std::enable_if<is_enum_bitfield<E>::value,bool>::type
|
constexpr typename std::enable_if<is_enum_bitfield(E{}),E>::type
|
||||||
operator ! (E rhs)
|
operator ~ (E rhs) { return static_cast<E>(~static_cast<typename std::underlying_type<E>::type>(rhs)); }
|
||||||
{
|
|
||||||
return static_cast<typename std::underlying_type<E>::type>(rhs) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename E>
|
template <typename E>
|
||||||
constexpr bool
|
constexpr typename std::enable_if<is_enum_bitfield(E{}),bool>::type
|
||||||
bitfield_has(E set, E flag)
|
operator ! (E rhs) { return static_cast<typename std::underlying_type<E>::type>(rhs) == 0; }
|
||||||
{
|
|
||||||
return
|
|
||||||
(static_cast<typename std::underlying_type<E>::type>(set) &
|
|
||||||
static_cast<typename std::underlying_type<E>::type>(flag)) ==
|
|
||||||
static_cast<typename std::underlying_type<E>::type>(flag);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Overload the logical-and operator to be 'bitwise-and, bool-cast'
|
/// Override logical-and to mean 'rhs contains all bits in lhs'
|
||||||
template <typename E>
|
template <typename E>
|
||||||
constexpr typename std::enable_if<is_enum_bitfield<E>::value,bool>::type
|
constexpr typename std::enable_if<is_enum_bitfield(E{}),bool>::type
|
||||||
operator && (E set, E flag)
|
operator && (E rhs, E lhs) { return (rhs & lhs) == lhs; }
|
||||||
{
|
|
||||||
return (set & flag) == flag;
|
} // namespace bitfields
|
||||||
}
|
} // namespace kutil
|
||||||
|
|
||||||
|
#define is_bitfield(name) \
|
||||||
|
constexpr bool is_enum_bitfield(name) { return true; } \
|
||||||
|
using namespace kutil::bitfields;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user