//********************************** Banshee Engine (www.banshee3d.com) **************************************************// //**************** Copyright (c) 2016 Marko Pintera (marko.pintera@gmail.com). All rights reserved. **********************// #pragma once namespace bs { /** @addtogroup General * @{ */ /** Wrapper around an enum that allows simple use of bitwise logic operations. */ template class Flags { public: typedef Storage InternalType; Flags() :mBits(0) { } Flags(Enum value) { mBits = static_cast(value); } Flags(const Flags& value) { mBits = value.mBits; } explicit Flags(Storage bits) { mBits = bits; } /** Checks whether all of the provided bits are set */ bool isSet(Enum value) const { return (mBits & static_cast(value)) == static_cast(value); } /** Activates all of the provided bits. */ Flags& set(Enum value) { mBits |= static_cast(value); return *this; } /** Deactivates all of the provided bits. */ void unset(Enum value) { mBits &= ~static_cast(value); } bool operator==(Enum rhs) const { return mBits == static_cast(rhs); } bool operator==(const Flags& rhs) const { return mBits == rhs.mBits; } bool operator==(bool rhs) const { return ((bool)*this) == rhs; } bool operator!=(Enum rhs) const { return mBits != static_cast(rhs); } bool operator!=(const Flags& rhs) const { return mBits != rhs.mBits; } Flags& operator= (Enum rhs) { mBits = static_cast(rhs); return *this; } Flags& operator= (const Flags& rhs) { mBits = rhs.mBits; return *this; } Flags& operator|= (Enum rhs) { mBits |= static_cast(rhs); return *this; } Flags& operator|= (const Flags& rhs) { mBits |= rhs.mBits; return *this; } Flags operator| (Enum rhs) const { Flags out(*this); out |= rhs; return out; } Flags operator| (const Flags& rhs) const { Flags out(*this); out |= rhs; return out; } Flags& operator&= (Enum rhs) { mBits &= static_cast(rhs); return *this; } Flags& operator&= (const Flags& rhs) { mBits &= rhs.mBits; return *this; } Flags operator& (Enum rhs) const { Flags out = *this; out.mBits &= static_cast(rhs); return out; } Flags operator& (const Flags& rhs) const { Flags out = *this; out.mBits &= rhs.mBits; return out; } Flags& operator^= (Enum rhs) { mBits ^= static_cast(rhs); return *this; } Flags& operator^= (const Flags& rhs) { mBits ^= rhs.mBits; return *this; } Flags operator^ (Enum rhs) const { Flags out = *this; out.mBits ^= static_cast(rhs); return out; } Flags operator^ (const Flags& rhs) const { Flags out = *this; out.mBits ^= rhs.mBits; return out; } Flags operator~ () const { Flags out; out.mBits = (Storage)~mBits; return out; } operator bool() const { return mBits ? true : false; } operator UINT8() const { return static_cast(mBits); } operator UINT16() const { return static_cast(mBits); } operator UINT32() const { return static_cast(mBits); } friend Flags operator&(Enum a, Flags &b) { Flags out; out.mBits = a & b.mBits; return out; } private: Storage mBits; }; /** Defines global operators for a Flags implementation. */ #define BS_FLAGS_OPERATORS(Enum) BS_FLAGS_OPERATORS_EXT(Enum, UINT32) /** Defines global operators for a Flags implementation. */ #define BS_FLAGS_OPERATORS_EXT(Enum, Storage) \ inline Flags operator|(Enum a, Enum b) { Flags r(a); r |= b; return r; } \ inline Flags operator&(Enum a, Enum b) { Flags r(a); r &= b; return r; } \ inline Flags operator~(Enum a) { return ~Flags(a); } /** @cond SPECIALIZATIONS */ /** * RTTIPlainType for Flags. * * @see RTTIPlainType */ template struct RTTIPlainType> { enum { id = TID_Flags }; enum { hasDynamicSize = 0 }; /** @copydoc RTTIPlainType::toMemory */ static void toMemory(const Flags& data, char* memory) { Storage storageData = (Storage)data; RTTIPlainType::toMemory(storageData, memory); } /** @copydoc RTTIPlainType::fromMemory */ static UINT32 fromMemory(Flags& data, char* memory) { Storage storageData; RTTIPlainType::fromMemory(storageData, memory); data = Flags(storageData); return sizeof(Flags); } /** @copydoc RTTIPlainType::getDynamicSize */ static UINT32 getDynamicSize(const Flags& data) { assert(false); return sizeof(Flags); } }; /** @endcond */ /** @} */ } /** @cond STDLIB */ namespace std { /** Hash value generator for Flags. */ template struct hash> { size_t operator()(const bs::Flags& key) const { return (Storage)key; } }; } /** @endcond */