1 // Copyright 2017 The Dawn Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #ifndef DAWN_ENUM_CLASS_BITMASKS_H_ 16 #define DAWN_ENUM_CLASS_BITMASKS_H_ 17 18 #include <type_traits> 19 20 // The operators in dawn:: namespace need be introduced into other namespaces with 21 // using-declarations for C++ Argument Dependent Lookup to work. 22 #define DAWN_IMPORT_BITMASK_OPERATORS \ 23 using dawn::operator|; \ 24 using dawn::operator&; \ 25 using dawn::operator^; \ 26 using dawn::operator~; \ 27 using dawn::operator&=; \ 28 using dawn::operator|=; \ 29 using dawn::operator^=; \ 30 using dawn::HasZeroOrOneBits; 31 32 namespace dawn { 33 34 template <typename T> 35 struct IsDawnBitmask { 36 static constexpr bool enable = false; 37 }; 38 39 template <typename T, typename Enable = void> 40 struct LowerBitmask { 41 static constexpr bool enable = false; 42 }; 43 44 template <typename T> 45 struct LowerBitmask<T, typename std::enable_if<IsDawnBitmask<T>::enable>::type> { 46 static constexpr bool enable = true; 47 using type = T; 48 constexpr static T Lower(T t) { 49 return t; 50 } 51 }; 52 53 template <typename T> 54 struct BoolConvertible { 55 using Integral = typename std::underlying_type<T>::type; 56 57 constexpr BoolConvertible(Integral value) : value(value) { 58 } 59 constexpr operator bool() const { 60 return value != 0; 61 } 62 constexpr operator T() const { 63 return static_cast<T>(value); 64 } 65 66 Integral value; 67 }; 68 69 template <typename T> 70 struct LowerBitmask<BoolConvertible<T>> { 71 static constexpr bool enable = true; 72 using type = T; 73 static constexpr type Lower(BoolConvertible<T> t) { 74 return t; 75 } 76 }; 77 78 template <typename T1, 79 typename T2, 80 typename = typename std::enable_if<LowerBitmask<T1>::enable && 81 LowerBitmask<T2>::enable>::type> 82 constexpr BoolConvertible<typename LowerBitmask<T1>::type> operator|(T1 left, T2 right) { 83 using T = typename LowerBitmask<T1>::type; 84 using Integral = typename std::underlying_type<T>::type; 85 return static_cast<Integral>(LowerBitmask<T1>::Lower(left)) | 86 static_cast<Integral>(LowerBitmask<T2>::Lower(right)); 87 } 88 89 template <typename T1, 90 typename T2, 91 typename = typename std::enable_if<LowerBitmask<T1>::enable && 92 LowerBitmask<T2>::enable>::type> 93 constexpr BoolConvertible<typename LowerBitmask<T1>::type> operator&(T1 left, T2 right) { 94 using T = typename LowerBitmask<T1>::type; 95 using Integral = typename std::underlying_type<T>::type; 96 return static_cast<Integral>(LowerBitmask<T1>::Lower(left)) & 97 static_cast<Integral>(LowerBitmask<T2>::Lower(right)); 98 } 99 100 template <typename T1, 101 typename T2, 102 typename = typename std::enable_if<LowerBitmask<T1>::enable && 103 LowerBitmask<T2>::enable>::type> 104 constexpr BoolConvertible<typename LowerBitmask<T1>::type> operator^(T1 left, T2 right) { 105 using T = typename LowerBitmask<T1>::type; 106 using Integral = typename std::underlying_type<T>::type; 107 return static_cast<Integral>(LowerBitmask<T1>::Lower(left)) ^ 108 static_cast<Integral>(LowerBitmask<T2>::Lower(right)); 109 } 110 111 template <typename T1> 112 constexpr BoolConvertible<typename LowerBitmask<T1>::type> operator~(T1 t) { 113 using T = typename LowerBitmask<T1>::type; 114 using Integral = typename std::underlying_type<T>::type; 115 return ~static_cast<Integral>(LowerBitmask<T1>::Lower(t)); 116 } 117 118 template <typename T, 119 typename T2, 120 typename = typename std::enable_if<IsDawnBitmask<T>::enable && 121 LowerBitmask<T2>::enable>::type> 122 constexpr T& operator&=(T& l, T2 right) { 123 T r = LowerBitmask<T2>::Lower(right); 124 l = l & r; 125 return l; 126 } 127 128 template <typename T, 129 typename T2, 130 typename = typename std::enable_if<IsDawnBitmask<T>::enable && 131 LowerBitmask<T2>::enable>::type> 132 constexpr T& operator|=(T& l, T2 right) { 133 T r = LowerBitmask<T2>::Lower(right); 134 l = l | r; 135 return l; 136 } 137 138 template <typename T, 139 typename T2, 140 typename = typename std::enable_if<IsDawnBitmask<T>::enable && 141 LowerBitmask<T2>::enable>::type> 142 constexpr T& operator^=(T& l, T2 right) { 143 T r = LowerBitmask<T2>::Lower(right); 144 l = l ^ r; 145 return l; 146 } 147 148 template <typename T> 149 constexpr bool HasZeroOrOneBits(T value) { 150 using Integral = typename std::underlying_type<T>::type; 151 return (static_cast<Integral>(value) & (static_cast<Integral>(value) - 1)) == 0; 152 } 153 154 } // namespace dawn 155 156 #endif // DAWN_ENUM_CLASS_BITMASKS_H_ 157