• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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