Add enum flag implementation

This commit is contained in:
Henrik Stickann 2022-04-14 15:18:42 +02:00
parent c1d468bb32
commit 9056cfc264
2 changed files with 251 additions and 0 deletions

138
include/sta/enum_flags.hpp Normal file
View File

@ -0,0 +1,138 @@
#ifndef STA_ENUM_FLAGS_HPP
#define STA_ENUM_FLAGS_HPP
#include <cstdint>
namespace sta
{
/**
* @brief 32-bit flag register with enum type representing single flag bits.
*
* @tparam F Enum type used for flag bits
*/
template <typename F>
class EnumFlags
{
public:
using flag_type = F; /**< Enum type used for flag bits */
public:
EnumFlags();
EnumFlags(const EnumFlags & other);
/**
* @brief Construct from single flag.
*
* @param flag Single flag bit to set
*/
EnumFlags(flag_type flag);
// Modification
//
/**
* @brief Set bits from flags register.
*
* @param flags Flag bits to set
*/
void set(const EnumFlags & flags);
/**
* @brief Clear flag bits.
*
* @param flags Flag bits to clear
*/
void clear(const EnumFlags & flags);
/**
* @brief Clear all flag bits.
*/
void clear();
// Inspection
//
/**
* @brief Test if all flags are set.
*
* @param flags Flag bits to check
* @return True if all checked flag bits are set
*/
bool isSet(const EnumFlags & flags) const;
/**
* @brief Test if any flag is set.
*
* @param flags Flag bits to check
* @return True if any checked flag bit is set
*/
bool isAnySet(const EnumFlags & flags) const;
// Operator overloads
//
// Comparison
bool operator ==(const EnumFlags & rhs) const;
bool operator !=(const EnumFlags & rhs) const;
// Bitwise operators
EnumFlags operator &(const EnumFlags & rhs) const;
EnumFlags operator |(const EnumFlags & rhs) const;
// Assignment
EnumFlags & operator &=(const EnumFlags & rhs);
EnumFlags & operator |=(const EnumFlags & rhs);
// Conversion
explicit operator uint32_t();
private:
EnumFlags(uint32_t flags);
private:
uint32_t flags_; /**< Flags register */
};
} // namespace sta
/**
* @brief Provide overload for operator | to combine enum values.
*
* @param enumType Enum type to overload
*/
#define STA_ENUM_FLAGS_OVERLOAD(enumType) \
sta::EnumFlags<enumType> operator |(enumType lhs, enumType rhs) \
{ \
return sta::EnumFlags<enumType>{lhs} | rhs; \
}
/**
* @brief Declare alias for sta::EnumFlags specialization.
*
* @param enumType Enum type for specialization
*/
#define STA_ENUM_FLAGS_ALIAS(enumType) \
using enumType ## Flags = sta::EnumFlags<enumType>
/**
* @brief Declare enum and create sta::EnumFlags alias and overloads.
*
* @param enumType Name of new enum class
* @param value1 First enum value
* @param ... Enum values 2 - 32
*/
#define STA_ENUM_FLAGS_DECL(enumType, value1, ...) \
enum class enumType \
{ \
value1, ##__VA_ARGS__ \
}; \
STA_ENUM_FLAGS_ALIAS(enumType); \
STA_ENUM_FLAGS_OVERLOAD(enumType)
// Include template implementation
#include <sta/enum_flags.tpp>
#endif // STA_ENUM_FLAGS_HPP

113
include/sta/enum_flags.tpp Normal file
View File

@ -0,0 +1,113 @@
#ifndef STA_ENUM_FLAGS_TPP
#define STA_ENUM_FLAGS_TPP
#ifndef STA_ENUM_FLAGS_HPP
# error "Direct use of internal header. Use <sta/enum_flags.hpp> instead"
#endif // !STA_ENUM_FLAGS_HPP
namespace sta
{
template <typename F>
EnumFlags<F>::EnumFlags()
: flags_{0}
{}
template <typename F>
EnumFlags<F>::EnumFlags(const EnumFlags & other)
: flags_{other.flags_}
{}
template <typename F>
EnumFlags<F>::EnumFlags(flag_type flag)
: flags_{1U << static_cast<uint8_t>(flag)}
{}
template <typename F>
EnumFlags<F>::EnumFlags(uint32_t flags)
: flags_{flags}
{}
template <typename F>
void EnumFlags<F>::set(const EnumFlags & flags)
{
flags_ |= flags.flags_;
}
template <typename F>
void EnumFlags<F>::clear(const EnumFlags & flags)
{
flags_ &= ~(flags.flags_);
}
template <typename F>
void EnumFlags<F>::clear()
{
flags_ = 0;
}
template <typename F>
bool EnumFlags<F>::isSet(const EnumFlags & flags) const
{
return (flags_ & flags.flags_) == flags.flags_;
}
template <typename F>
bool EnumFlags<F>::isAnySet(const EnumFlags & flags) const
{
return (flags_ & flags.flags_) != 0;
}
template <typename F>
bool EnumFlags<F>::operator ==(const EnumFlags<F> & rhs) const
{
return (flags_ == rhs.flags_);
}
template <typename F>
bool EnumFlags<F>::operator !=(const EnumFlags<F> & rhs) const
{
return (flags_ != rhs.flags_);
}
template <typename F>
EnumFlags<F> EnumFlags<F>::operator &(const EnumFlags<F> & rhs) const
{
return EnumFlags(flags_ & rhs.flags_);
}
template <typename F>
EnumFlags<F> EnumFlags<F>::operator |(const EnumFlags<F> & rhs) const
{
return EnumFlags(flags_ | rhs.flags_);
}
template <typename F>
EnumFlags<F> & EnumFlags<F>::operator &=(const EnumFlags<F> & rhs)
{
flags_ &= rhs.flags_;
return *this;
}
template <typename F>
EnumFlags<F> & EnumFlags<F>::operator |=(const EnumFlags<F> & rhs)
{
flags_ |= rhs.flags_;
return *this;
}
template <typename F>
EnumFlags<F>::operator uint32_t()
{
return flags_;
}
} // namespace sta
#endif // STA_ENUM_FLAGS_TPP