diff --git a/include/sta/enum_flags.hpp b/include/sta/enum_flags.hpp new file mode 100644 index 0000000..dcd999b --- /dev/null +++ b/include/sta/enum_flags.hpp @@ -0,0 +1,138 @@ +#ifndef STA_ENUM_FLAGS_HPP +#define STA_ENUM_FLAGS_HPP + +#include + + +namespace sta +{ + /** + * @brief 32-bit flag register with enum type representing single flag bits. + * + * @tparam F Enum type used for flag bits + */ + template + 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 operator |(enumType lhs, enumType rhs) \ + { \ + return sta::EnumFlags{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 + +/** + * @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 + + +#endif // STA_ENUM_FLAGS_HPP diff --git a/include/sta/enum_flags.tpp b/include/sta/enum_flags.tpp new file mode 100644 index 0000000..89107e4 --- /dev/null +++ b/include/sta/enum_flags.tpp @@ -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 instead" +#endif // !STA_ENUM_FLAGS_HPP + + +namespace sta +{ + template + EnumFlags::EnumFlags() + : flags_{0} + {} + + template + EnumFlags::EnumFlags(const EnumFlags & other) + : flags_{other.flags_} + {} + + template + EnumFlags::EnumFlags(flag_type flag) + : flags_{1U << static_cast(flag)} + {} + + template + EnumFlags::EnumFlags(uint32_t flags) + : flags_{flags} + {} + + + template + void EnumFlags::set(const EnumFlags & flags) + { + flags_ |= flags.flags_; + } + + template + void EnumFlags::clear(const EnumFlags & flags) + { + flags_ &= ~(flags.flags_); + } + + template + void EnumFlags::clear() + { + flags_ = 0; + } + + + template + bool EnumFlags::isSet(const EnumFlags & flags) const + { + return (flags_ & flags.flags_) == flags.flags_; + } + + template + bool EnumFlags::isAnySet(const EnumFlags & flags) const + { + return (flags_ & flags.flags_) != 0; + } + + + template + bool EnumFlags::operator ==(const EnumFlags & rhs) const + { + return (flags_ == rhs.flags_); + } + + template + bool EnumFlags::operator !=(const EnumFlags & rhs) const + { + return (flags_ != rhs.flags_); + } + + + template + EnumFlags EnumFlags::operator &(const EnumFlags & rhs) const + { + return EnumFlags(flags_ & rhs.flags_); + } + + template + EnumFlags EnumFlags::operator |(const EnumFlags & rhs) const + { + return EnumFlags(flags_ | rhs.flags_); + } + + + template + EnumFlags & EnumFlags::operator &=(const EnumFlags & rhs) + { + flags_ &= rhs.flags_; + return *this; + } + + template + EnumFlags & EnumFlags::operator |=(const EnumFlags & rhs) + { + flags_ |= rhs.flags_; + return *this; + } + + + template + EnumFlags::operator uint32_t() + { + return flags_; + } +} // namespace sta + + +#endif // STA_ENUM_FLAGS_TPP