Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #ifndef INCLUDED_O3TL_TYPED_FLAGS_SET_HXX
21 : #define INCLUDED_O3TL_TYPED_FLAGS_SET_HXX
22 :
23 : #include <sal/config.h>
24 :
25 : #include <cassert>
26 : #include <type_traits>
27 :
28 : namespace o3tl {
29 :
30 : namespace detail {
31 :
32 : template<typename T> inline
33 : typename std::enable_if<std::is_signed<T>::value, bool>::type isNonNegative(
34 : T value)
35 : {
36 : return value >= 0;
37 : }
38 :
39 : template<typename T> inline
40 : typename std::enable_if<std::is_unsigned<T>::value, bool>::type isNonNegative(T)
41 : {
42 : return true;
43 : }
44 :
45 : }
46 :
47 : template<typename T> struct typed_flags {};
48 :
49 : #if defined __GNUC__ && __GNUC__ == 4 && __GNUC_MINOR__ <= 6 && \
50 : !defined __clang__
51 : // use largest sensible unsigned type as fallback
52 : #define O3TL_STD_UNDERLYING_TYPE_E unsigned long long
53 : #else
54 : #define O3TL_STD_UNDERLYING_TYPE_E typename std::underlying_type<E>::type
55 : #endif
56 :
57 : /// Mark a (scoped) enumeration as a set of bit flags, with accompanying
58 : /// operations.
59 : ///
60 : /// template<>
61 : /// struct o3tl::typed_flags<TheE>: o3tl::is_typed_flags<TheE, TheM> {};
62 : ///
63 : /// All relevant values must be non-negative. (Typically, the enumeration's
64 : /// underlying type will either be fixed and unsigned, or it will be unfixed---
65 : /// and can thus default to a signed type---and all enumerators will have non-
66 : /// negative values.)
67 : ///
68 : /// \param E the enumeration type.
69 : /// \param M the all-bits-set value for the bit flags.
70 : template<typename E, O3TL_STD_UNDERLYING_TYPE_E M>
71 : struct is_typed_flags {
72 : static_assert(
73 : M >= 0, "is_typed_flags expects only non-negative bit values");
74 :
75 : typedef E Self;
76 :
77 : class Wrap {
78 : public:
79 647916541 : explicit Wrap(O3TL_STD_UNDERLYING_TYPE_E value):
80 647916541 : value_(value)
81 647916541 : { assert(detail::isNonNegative(value)); }
82 :
83 105927040 : operator E() { return static_cast<E>(value_); }
84 :
85 298159057 : explicit operator O3TL_STD_UNDERLYING_TYPE_E() { return value_; }
86 :
87 243830444 : explicit operator bool() { return value_ != 0; }
88 :
89 : private:
90 : O3TL_STD_UNDERLYING_TYPE_E value_;
91 : };
92 :
93 : static O3TL_STD_UNDERLYING_TYPE_E const mask = M;
94 : };
95 :
96 : }
97 :
98 : template<typename E>
99 3253126 : inline typename o3tl::typed_flags<E>::Wrap operator ~(E rhs) {
100 : assert(
101 : o3tl::detail::isNonNegative(
102 : static_cast<O3TL_STD_UNDERLYING_TYPE_E>(rhs)));
103 : return static_cast<typename o3tl::typed_flags<E>::Wrap>(
104 : o3tl::typed_flags<E>::mask
105 3253126 : & ~static_cast<O3TL_STD_UNDERLYING_TYPE_E>(rhs));
106 : }
107 :
108 : template<typename E>
109 : inline typename o3tl::typed_flags<E>::Wrap operator ~(
110 : typename o3tl::typed_flags<E>::Wrap rhs)
111 : {
112 : return static_cast<typename o3tl::typed_flags<E>::Wrap>(
113 : o3tl::typed_flags<E>::mask
114 : & ~static_cast<O3TL_STD_UNDERLYING_TYPE_E>(rhs));
115 : }
116 :
117 : template<typename E>
118 75099 : inline typename o3tl::typed_flags<E>::Wrap operator ^(E lhs, E rhs) {
119 : assert(
120 : o3tl::detail::isNonNegative(
121 : static_cast<O3TL_STD_UNDERLYING_TYPE_E>(lhs)));
122 : assert(
123 : o3tl::detail::isNonNegative(
124 : static_cast<O3TL_STD_UNDERLYING_TYPE_E>(rhs)));
125 : return static_cast<typename o3tl::typed_flags<E>::Wrap>(
126 : static_cast<O3TL_STD_UNDERLYING_TYPE_E>(lhs)
127 75099 : ^ static_cast<O3TL_STD_UNDERLYING_TYPE_E>(rhs));
128 : }
129 :
130 : template<typename E>
131 0 : inline typename o3tl::typed_flags<E>::Wrap operator ^(
132 : E lhs, typename o3tl::typed_flags<E>::Wrap rhs)
133 : {
134 : assert(
135 : o3tl::detail::isNonNegative(
136 : static_cast<O3TL_STD_UNDERLYING_TYPE_E>(lhs)));
137 : return static_cast<typename o3tl::typed_flags<E>::Wrap>(
138 : static_cast<O3TL_STD_UNDERLYING_TYPE_E>(lhs)
139 0 : ^ static_cast<O3TL_STD_UNDERLYING_TYPE_E>(rhs));
140 : }
141 :
142 : template<typename E>
143 : inline typename o3tl::typed_flags<E>::Wrap operator ^(
144 : typename o3tl::typed_flags<E>::Wrap lhs, E rhs)
145 : {
146 : assert(
147 : o3tl::detail::isNonNegative(
148 : static_cast<O3TL_STD_UNDERLYING_TYPE_E>(rhs)));
149 : return static_cast<typename o3tl::typed_flags<E>::Wrap>(
150 : static_cast<O3TL_STD_UNDERLYING_TYPE_E>(lhs)
151 : ^ static_cast<O3TL_STD_UNDERLYING_TYPE_E>(rhs));
152 : }
153 :
154 : template<typename E>
155 : inline typename o3tl::typed_flags<E>::Wrap operator ^(
156 : typename o3tl::typed_flags<E>::Wrap lhs,
157 : typename o3tl::typed_flags<E>::Wrap rhs)
158 : {
159 : return static_cast<typename o3tl::typed_flags<E>::Wrap>(
160 : static_cast<O3TL_STD_UNDERLYING_TYPE_E>(lhs)
161 : ^ static_cast<O3TL_STD_UNDERLYING_TYPE_E>(rhs));
162 : }
163 :
164 : template<typename E>
165 236621388 : inline typename o3tl::typed_flags<E>::Wrap operator &(E lhs, E rhs) {
166 : assert(
167 : o3tl::detail::isNonNegative(
168 : static_cast<O3TL_STD_UNDERLYING_TYPE_E>(lhs)));
169 : assert(
170 : o3tl::detail::isNonNegative(
171 : static_cast<O3TL_STD_UNDERLYING_TYPE_E>(rhs)));
172 : return static_cast<typename o3tl::typed_flags<E>::Wrap>(
173 : static_cast<O3TL_STD_UNDERLYING_TYPE_E>(lhs)
174 236621388 : & static_cast<O3TL_STD_UNDERLYING_TYPE_E>(rhs));
175 : }
176 :
177 : template<typename E>
178 13788197 : inline typename o3tl::typed_flags<E>::Wrap operator &(
179 : E lhs, typename o3tl::typed_flags<E>::Wrap rhs)
180 : {
181 : assert(
182 : o3tl::detail::isNonNegative(
183 : static_cast<O3TL_STD_UNDERLYING_TYPE_E>(lhs)));
184 : return static_cast<typename o3tl::typed_flags<E>::Wrap>(
185 : static_cast<O3TL_STD_UNDERLYING_TYPE_E>(lhs)
186 13788197 : & static_cast<O3TL_STD_UNDERLYING_TYPE_E>(rhs));
187 : }
188 :
189 : template<typename E>
190 71 : inline typename o3tl::typed_flags<E>::Wrap operator &(
191 : typename o3tl::typed_flags<E>::Wrap lhs, E rhs)
192 : {
193 : assert(
194 : o3tl::detail::isNonNegative(
195 : static_cast<O3TL_STD_UNDERLYING_TYPE_E>(rhs)));
196 : return static_cast<typename o3tl::typed_flags<E>::Wrap>(
197 : static_cast<O3TL_STD_UNDERLYING_TYPE_E>(lhs)
198 71 : & static_cast<O3TL_STD_UNDERLYING_TYPE_E>(rhs));
199 : }
200 :
201 : template<typename E>
202 : inline typename o3tl::typed_flags<E>::Wrap operator &(
203 : typename o3tl::typed_flags<E>::Wrap lhs,
204 : typename o3tl::typed_flags<E>::Wrap rhs)
205 : {
206 : return static_cast<typename o3tl::typed_flags<E>::Wrap>(
207 : static_cast<O3TL_STD_UNDERLYING_TYPE_E>(lhs)
208 : & static_cast<O3TL_STD_UNDERLYING_TYPE_E>(rhs));
209 : }
210 :
211 : template<typename E>
212 109807871 : inline typename o3tl::typed_flags<E>::Wrap operator |(E lhs, E rhs) {
213 : assert(
214 : o3tl::detail::isNonNegative(
215 : static_cast<O3TL_STD_UNDERLYING_TYPE_E>(lhs)));
216 : assert(
217 : o3tl::detail::isNonNegative(
218 : static_cast<O3TL_STD_UNDERLYING_TYPE_E>(rhs)));
219 : return static_cast<typename o3tl::typed_flags<E>::Wrap>(
220 : static_cast<O3TL_STD_UNDERLYING_TYPE_E>(lhs)
221 109807871 : | static_cast<O3TL_STD_UNDERLYING_TYPE_E>(rhs));
222 : }
223 :
224 : template<typename E>
225 4801 : inline typename o3tl::typed_flags<E>::Wrap operator |(
226 : E lhs, typename o3tl::typed_flags<E>::Wrap rhs)
227 : {
228 : assert(
229 : o3tl::detail::isNonNegative(
230 : static_cast<O3TL_STD_UNDERLYING_TYPE_E>(lhs)));
231 : return static_cast<typename o3tl::typed_flags<E>::Wrap>(
232 : static_cast<O3TL_STD_UNDERLYING_TYPE_E>(lhs)
233 4801 : | static_cast<O3TL_STD_UNDERLYING_TYPE_E>(rhs));
234 : }
235 :
236 : template<typename E>
237 284365988 : inline typename o3tl::typed_flags<E>::Wrap operator |(
238 : typename o3tl::typed_flags<E>::Wrap lhs, E rhs)
239 : {
240 : assert(
241 : o3tl::detail::isNonNegative(
242 : static_cast<O3TL_STD_UNDERLYING_TYPE_E>(rhs)));
243 : return static_cast<typename o3tl::typed_flags<E>::Wrap>(
244 : static_cast<O3TL_STD_UNDERLYING_TYPE_E>(lhs)
245 284365988 : | static_cast<O3TL_STD_UNDERLYING_TYPE_E>(rhs));
246 : }
247 :
248 : template<typename E>
249 : inline typename o3tl::typed_flags<E>::Wrap operator |(
250 : typename o3tl::typed_flags<E>::Wrap lhs,
251 : typename o3tl::typed_flags<E>::Wrap rhs)
252 : {
253 : return static_cast<typename o3tl::typed_flags<E>::Wrap>(
254 : static_cast<O3TL_STD_UNDERLYING_TYPE_E>(lhs)
255 : | static_cast<O3TL_STD_UNDERLYING_TYPE_E>(rhs));
256 : }
257 :
258 : template<typename E>
259 4 : inline typename o3tl::typed_flags<E>::Self operator &=(E & lhs, E rhs) {
260 : assert(
261 : o3tl::detail::isNonNegative(
262 : static_cast<O3TL_STD_UNDERLYING_TYPE_E>(lhs)));
263 : assert(
264 : o3tl::detail::isNonNegative(
265 : static_cast<O3TL_STD_UNDERLYING_TYPE_E>(rhs)));
266 4 : lhs = lhs & rhs;
267 4 : return lhs;
268 : }
269 :
270 : template<typename E>
271 3467025 : inline typename o3tl::typed_flags<E>::Self operator &=(
272 : E & lhs, typename o3tl::typed_flags<E>::Wrap rhs)
273 : {
274 : assert(
275 : o3tl::detail::isNonNegative(
276 : static_cast<O3TL_STD_UNDERLYING_TYPE_E>(lhs)));
277 3467025 : lhs = lhs & rhs;
278 3467025 : return lhs;
279 : }
280 :
281 : template<typename E>
282 9541484 : inline typename o3tl::typed_flags<E>::Self operator |=(E & lhs, E rhs) {
283 : assert(
284 : o3tl::detail::isNonNegative(
285 : static_cast<O3TL_STD_UNDERLYING_TYPE_E>(lhs)));
286 : assert(
287 : o3tl::detail::isNonNegative(
288 : static_cast<O3TL_STD_UNDERLYING_TYPE_E>(rhs)));
289 9541484 : lhs = lhs | rhs;
290 9541484 : return lhs;
291 : }
292 :
293 : template<typename E>
294 1352 : inline typename o3tl::typed_flags<E>::Self operator |=(
295 : E & lhs, typename o3tl::typed_flags<E>::Wrap rhs)
296 : {
297 : assert(
298 : o3tl::detail::isNonNegative(
299 : static_cast<O3TL_STD_UNDERLYING_TYPE_E>(lhs)));
300 1352 : lhs = lhs | rhs;
301 1352 : return lhs;
302 : }
303 :
304 : template<typename E>
305 0 : inline typename o3tl::typed_flags<E>::Self operator ^=(E & lhs, E rhs) {
306 : assert(
307 : o3tl::detail::isNonNegative(
308 : static_cast<O3TL_STD_UNDERLYING_TYPE_E>(lhs)));
309 : assert(
310 : o3tl::detail::isNonNegative(
311 : static_cast<O3TL_STD_UNDERLYING_TYPE_E>(rhs)));
312 0 : lhs = lhs ^ rhs;
313 0 : return lhs;
314 : }
315 :
316 : template<typename E>
317 : inline typename o3tl::typed_flags<E>::Self operator ^=(
318 : E & lhs, typename o3tl::typed_flags<E>::Wrap rhs)
319 : {
320 : assert(
321 : o3tl::detail::isNonNegative(
322 : static_cast<O3TL_STD_UNDERLYING_TYPE_E>(lhs)));
323 : lhs = lhs ^ rhs;
324 : return lhs;
325 : }
326 :
327 : #endif /* INCLUDED_O3TL_TYPED_FLAGS_SET_HXX */
328 :
329 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|