1 | // Copyright 2014 the V8 project authors. All rights reserved. |
2 | // Use of this source code is governed by a BSD-style license that can be |
3 | // found in the LICENSE file. |
4 | |
5 | #ifndef V8_BASE_FLAGS_H_ |
6 | #define V8_BASE_FLAGS_H_ |
7 | |
8 | #include <cstddef> |
9 | |
10 | #include "src/base/compiler-specific.h" |
11 | |
12 | namespace v8 { |
13 | namespace base { |
14 | |
15 | // The Flags class provides a type-safe way of storing OR-combinations of enum |
16 | // values. The Flags<T, S> class is a template class, where T is an enum type, |
17 | // and S is the underlying storage type (usually int). |
18 | // |
19 | // The traditional C++ approach for storing OR-combinations of enum values is to |
20 | // use an int or unsigned int variable. The inconvenience with this approach is |
21 | // that there's no type checking at all; any enum value can be OR'd with any |
22 | // other enum value and passed on to a function that takes an int or unsigned |
23 | // int. |
24 | template <typename T, typename S = int> |
25 | class Flags final { |
26 | public: |
27 | using flag_type = T; |
28 | using mask_type = S; |
29 | |
30 | constexpr Flags() : mask_(0) {} |
31 | constexpr Flags(flag_type flag) // NOLINT(runtime/explicit) |
32 | : mask_(static_cast<S>(flag)) {} |
33 | constexpr explicit Flags(mask_type mask) : mask_(static_cast<S>(mask)) {} |
34 | |
35 | constexpr bool operator==(flag_type flag) const { |
36 | return mask_ == static_cast<S>(flag); |
37 | } |
38 | constexpr bool operator!=(flag_type flag) const { |
39 | return mask_ != static_cast<S>(flag); |
40 | } |
41 | |
42 | Flags& operator&=(const Flags& flags) { |
43 | mask_ &= flags.mask_; |
44 | return *this; |
45 | } |
46 | Flags& operator|=(const Flags& flags) { |
47 | mask_ |= flags.mask_; |
48 | return *this; |
49 | } |
50 | Flags& operator^=(const Flags& flags) { |
51 | mask_ ^= flags.mask_; |
52 | return *this; |
53 | } |
54 | |
55 | constexpr Flags operator&(const Flags& flags) const { |
56 | return Flags(*this) &= flags; |
57 | } |
58 | constexpr Flags operator|(const Flags& flags) const { |
59 | return Flags(*this) |= flags; |
60 | } |
61 | constexpr Flags operator^(const Flags& flags) const { |
62 | return Flags(*this) ^= flags; |
63 | } |
64 | |
65 | Flags& operator&=(flag_type flag) { return operator&=(Flags(flag)); } |
66 | Flags& operator|=(flag_type flag) { return operator|=(Flags(flag)); } |
67 | Flags& operator^=(flag_type flag) { return operator^=(Flags(flag)); } |
68 | |
69 | constexpr Flags operator&(flag_type flag) const { |
70 | return operator&(Flags(flag)); |
71 | } |
72 | constexpr Flags operator|(flag_type flag) const { |
73 | return operator|(Flags(flag)); |
74 | } |
75 | constexpr Flags operator^(flag_type flag) const { |
76 | return operator^(Flags(flag)); |
77 | } |
78 | |
79 | constexpr Flags operator~() const { return Flags(~mask_); } |
80 | |
81 | constexpr operator mask_type() const { return mask_; } |
82 | constexpr bool operator!() const { return !mask_; } |
83 | |
84 | friend size_t hash_value(const Flags& flags) { return flags.mask_; } |
85 | |
86 | private: |
87 | mask_type mask_; |
88 | }; |
89 | |
90 | #define DEFINE_OPERATORS_FOR_FLAGS(Type) \ |
91 | inline Type operator&( \ |
92 | Type::flag_type lhs, \ |
93 | Type::flag_type rhs)ALLOW_UNUSED_TYPE V8_WARN_UNUSED_RESULT; \ |
94 | inline Type operator&(Type::flag_type lhs, Type::flag_type rhs) { \ |
95 | return Type(lhs) & rhs; \ |
96 | } \ |
97 | inline Type operator&( \ |
98 | Type::flag_type lhs, \ |
99 | const Type& rhs)ALLOW_UNUSED_TYPE V8_WARN_UNUSED_RESULT; \ |
100 | inline Type operator&(Type::flag_type lhs, const Type& rhs) { \ |
101 | return rhs & lhs; \ |
102 | } \ |
103 | inline void operator&(Type::flag_type lhs, \ |
104 | Type::mask_type rhs)ALLOW_UNUSED_TYPE; \ |
105 | inline void operator&(Type::flag_type lhs, Type::mask_type rhs) {} \ |
106 | inline Type operator|(Type::flag_type lhs, Type::flag_type rhs) \ |
107 | ALLOW_UNUSED_TYPE V8_WARN_UNUSED_RESULT; \ |
108 | inline Type operator|(Type::flag_type lhs, Type::flag_type rhs) { \ |
109 | return Type(lhs) | rhs; \ |
110 | } \ |
111 | inline Type operator|(Type::flag_type lhs, const Type& rhs) \ |
112 | ALLOW_UNUSED_TYPE V8_WARN_UNUSED_RESULT; \ |
113 | inline Type operator|(Type::flag_type lhs, const Type& rhs) { \ |
114 | return rhs | lhs; \ |
115 | } \ |
116 | inline void operator|(Type::flag_type lhs, Type::mask_type rhs) \ |
117 | ALLOW_UNUSED_TYPE; \ |
118 | inline void operator|(Type::flag_type lhs, Type::mask_type rhs) {} \ |
119 | inline Type operator^(Type::flag_type lhs, Type::flag_type rhs) \ |
120 | ALLOW_UNUSED_TYPE V8_WARN_UNUSED_RESULT; \ |
121 | inline Type operator^(Type::flag_type lhs, Type::flag_type rhs) { \ |
122 | return Type(lhs) ^ rhs; \ |
123 | } \ |
124 | inline Type operator^(Type::flag_type lhs, const Type& rhs) \ |
125 | ALLOW_UNUSED_TYPE V8_WARN_UNUSED_RESULT; \ |
126 | inline Type operator^(Type::flag_type lhs, const Type& rhs) { \ |
127 | return rhs ^ lhs; \ |
128 | } \ |
129 | inline void operator^(Type::flag_type lhs, Type::mask_type rhs) \ |
130 | ALLOW_UNUSED_TYPE; \ |
131 | inline void operator^(Type::flag_type lhs, Type::mask_type rhs) {} \ |
132 | inline Type operator~(Type::flag_type val)ALLOW_UNUSED_TYPE; \ |
133 | inline Type operator~(Type::flag_type val) { return ~Type(val); } |
134 | |
135 | } // namespace base |
136 | } // namespace v8 |
137 | |
138 | #endif // V8_BASE_FLAGS_H_ |
139 | |