Skip to content

Commit

Permalink
add helper enum macros, that easily enable bitwise operations
Browse files Browse the repository at this point in the history
Usage is demonstrated in logger.
  • Loading branch information
wbenny committed Aug 1, 2019
1 parent d3d9752 commit 3a41720
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 23 deletions.
1 change: 1 addition & 0 deletions src/hvpp/hvpp.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@
<ClInclude Include="hvpp\interrupt.h" />
<ClInclude Include="hvpp\lib\debugger.h" />
<ClInclude Include="hvpp\lib\device.h" />
<ClInclude Include="hvpp\lib\enum.h" />
<ClInclude Include="hvpp\lib\ioctl.h" />
<ClInclude Include="hvpp\config.h" />
<ClInclude Include="hvpp\ept.h" />
Expand Down
3 changes: 3 additions & 0 deletions src/hvpp/hvpp.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,9 @@
<ClInclude Include="hvpp\lib\mm\physical_memory_descriptor.h">
<Filter>Header Files\hvpp\lib\mm</Filter>
</ClInclude>
<ClInclude Include="hvpp\lib\enum.h">
<Filter>Header Files\hvpp\lib</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<MASM Include="hvpp\ia32\context.asm">
Expand Down
62 changes: 62 additions & 0 deletions src/hvpp/hvpp/lib/enum.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#pragma once
#include <type_traits>

//
// (ref: http://blog.bitwigglers.org/using-enum-classes-as-type-safe-bitmasks/)
//

template<
typename Enum1,
typename Enum2 = Enum1
>
struct enum_operators
{
static constexpr bool enable_neg = false;
static constexpr bool enable_not = false;
static constexpr bool enable_and = false;
static constexpr bool enable_or = false;
static constexpr bool enable_xor = false;
};

#define hvpp_enum_operators(Enum1) \
template<> \
struct enum_operators<Enum1> \
{ \
static constexpr bool enable_neg = true; \
static constexpr bool enable_not = true; \
static constexpr bool enable_and = true; \
static constexpr bool enable_or = true; \
static constexpr bool enable_xor = true; \
}

template<typename Enum1>
constexpr typename std::enable_if_t<enum_operators<Enum1>::enable_neg, bool> operator!(Enum1 rhs) noexcept
{ return static_cast<bool>(!static_cast<std::underlying_type_t<Enum1>>(rhs)); }

template<typename Enum1>
constexpr typename std::enable_if_t<enum_operators<Enum1>::enable_not, Enum1> operator~(Enum1 rhs) noexcept
{ return static_cast<Enum1>(~static_cast<std::underlying_type_t<Enum1>>(rhs)); }

template<typename Enum1, typename Enum2>
constexpr typename std::enable_if_t<enum_operators<Enum1, Enum2>::enable_and, Enum1> operator&(Enum1 lhs, Enum2 rhs) noexcept
{ return static_cast<Enum1>( static_cast<std::underlying_type_t<Enum1>>(lhs) & static_cast<std::underlying_type_t<Enum2>>(rhs)); }

template<typename Enum1, typename Enum2>
constexpr typename std::enable_if_t<enum_operators<Enum1, Enum2>::enable_or, Enum1> operator|(Enum1 lhs, Enum2 rhs) noexcept
{ return static_cast<Enum1>(static_cast<std::underlying_type_t<Enum1>>(lhs) | static_cast<std::underlying_type_t<Enum2>>(rhs)); }

template<typename Enum1, typename Enum2>
constexpr typename std::enable_if_t<enum_operators<Enum1, Enum2>::enable_xor, Enum1> operator^(Enum1 lhs, Enum2 rhs) noexcept
{ return static_cast<Enum1>(static_cast<std::underlying_type_t<Enum1>>(lhs) ^ static_cast<std::underlying_type_t<Enum2>>(rhs)); }

template<typename Enum1, typename Enum2>
constexpr typename std::enable_if_t<enum_operators<Enum1, Enum2>::enable_and, Enum1>& operator&=(Enum1& lhs, Enum2 rhs) noexcept
{ return reinterpret_cast<Enum1&>(reinterpret_cast<std::underlying_type_t<Enum1>&>(lhs) &= static_cast<std::underlying_type_t<Enum2>>(rhs)); }

template<typename Enum1, typename Enum2>
constexpr typename std::enable_if_t<enum_operators<Enum1, Enum2>::enable_or, Enum1>& operator|=(Enum1& lhs, Enum2 rhs) noexcept
{ return reinterpret_cast<Enum1&>(reinterpret_cast<std::underlying_type_t<Enum1>&>(lhs) |= static_cast<std::underlying_type_t<Enum2>>(rhs)); }

template<typename Enum1, typename Enum2>
constexpr typename std::enable_if_t<enum_operators<Enum1, Enum2>::enable_xor, Enum1>& operator^=(Enum1& lhs, Enum2 rhs) noexcept
{ return reinterpret_cast<Enum1&>(reinterpret_cast<std::underlying_type_t<Enum1>&>(lhs) ^= static_cast<std::underlying_type_t<Enum2>>(rhs)); }
26 changes: 3 additions & 23 deletions src/hvpp/hvpp/lib/log.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#pragma once
#include "enum.h"
#include "error.h"

#include <cstdint>
Expand Down Expand Up @@ -35,29 +36,8 @@ namespace logger
default_flags = print_time | print_processor_number /*| print_function_name*/,
};

constexpr inline level_t operator&(level_t value1, level_t value2) noexcept
{ return static_cast<level_t>(static_cast<uint32_t>(value1) & static_cast<uint32_t>(value2)); }

constexpr inline level_t operator|(level_t value1, level_t value2) noexcept
{ return static_cast<level_t>(static_cast<uint32_t>(value1) | static_cast<uint32_t>(value2)); }

constexpr inline level_t& operator&=(level_t& value1, level_t value2) noexcept
{ value1 = value1 & value2; return value1; }

constexpr inline level_t& operator|=(level_t& value1, level_t value2) noexcept
{ value1 = value1 | value2; return value1; }

constexpr inline options_t operator&(options_t value1, options_t value2) noexcept
{ return static_cast<options_t>(static_cast<uint32_t>(value1) & static_cast<uint32_t>(value2)); }

constexpr inline options_t operator|(options_t value1, options_t value2) noexcept
{ return static_cast<options_t>(static_cast<uint32_t>(value1) | static_cast<uint32_t>(value2)); }

constexpr inline options_t& operator&=(options_t& value1, options_t value2) noexcept
{ value1 = value1 & value2; return value1; }

constexpr inline options_t& operator|=(options_t& value1, options_t value2) noexcept
{ value1 = value1 | value2; return value1; }
hvpp_enum_operators(level_t);
hvpp_enum_operators(options_t);

namespace detail
{
Expand Down

0 comments on commit 3a41720

Please sign in to comment.