EnumFlags.h (2535B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * vim: set ts=8 sts=2 et sw=2 tw=80: 3 * This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef util_EnumFlags_h 8 #define util_EnumFlags_h 9 10 #include "mozilla/Attributes.h" 11 12 #include <initializer_list> 13 #include <type_traits> 14 15 namespace js { 16 17 // Wrapper type for flags fields based on an enum type. 18 // 19 // EnumFlags does not (implicitly) convert to/from the underlying integer type. 20 // That can be supported for specific flags fields by deriving from this class 21 // and implementing an extra constructor and/or |operator FieldType|. 22 // 23 // Note: this type is similar to mfbt/EnumSet.h, but has the same size in debug 24 // and release builds so is more appropriate for core data structures where we 25 // don't want this size difference. 26 template <typename EnumType> 27 class EnumFlags { 28 protected: 29 // Use the enum's underlying type for the flags field. This makes JIT accesses 30 // more predictable and simplifies the implementation of this class. 31 static_assert(std::is_enum_v<EnumType>); 32 using FieldType = std::underlying_type_t<EnumType>; 33 static_assert(std::is_unsigned_v<FieldType>); 34 35 FieldType flags_ = 0; 36 37 explicit constexpr EnumFlags(FieldType rawFlags) : flags_(rawFlags) {} 38 39 public: 40 constexpr EnumFlags() = default; 41 42 constexpr MOZ_IMPLICIT EnumFlags(std::initializer_list<EnumType> list) { 43 for (EnumType flag : list) { 44 setFlag(flag); 45 } 46 } 47 48 constexpr bool hasFlag(EnumType flag) const { 49 return flags_ & static_cast<FieldType>(flag); 50 } 51 constexpr void setFlag(EnumType flag) { 52 flags_ |= static_cast<FieldType>(flag); 53 } 54 constexpr void clearFlag(EnumType flag) { 55 flags_ &= ~static_cast<FieldType>(flag); 56 } 57 constexpr void setFlag(EnumType flag, bool b) { 58 if (b) { 59 setFlag(flag); 60 } else { 61 clearFlag(flag); 62 } 63 } 64 65 constexpr bool hasAnyFlag(const EnumFlags& other) const { 66 return (flags_ & other.flags_) != 0; 67 } 68 69 constexpr bool isEmpty() const { return flags_ == 0; } 70 71 constexpr FieldType toRaw() const { return flags_; } 72 void setRaw(FieldType flag) { flags_ = flag; } 73 74 constexpr bool operator==(const EnumFlags& other) const { 75 return flags_ == other.flags_; 76 } 77 constexpr bool operator!=(const EnumFlags& other) const { 78 return flags_ != other.flags_; 79 } 80 }; 81 82 } // namespace js 83 84 #endif // util_EnumFlags_h