Branch libreoffice-5-0-4
[LibreOffice.git] / include / o3tl / typed_flags_set.hxx
blob01a4009abcc5ac04bafd1bc702b01ddc8d1691e6
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #ifndef INCLUDED_O3TL_TYPED_FLAGS_SET_HXX
21 #define INCLUDED_O3TL_TYPED_FLAGS_SET_HXX
23 #include <sal/config.h>
25 #include <cassert>
26 #include <type_traits>
28 namespace o3tl {
30 namespace detail {
32 template<typename T> inline
33 typename std::enable_if<std::is_signed<T>::value, bool>::type isNonNegative(
34 T value)
36 return value >= 0;
39 template<typename T> inline
40 typename std::enable_if<std::is_unsigned<T>::value, bool>::type isNonNegative(T)
42 return true;
47 template<typename T> struct typed_flags {};
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
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");
75 typedef E Self;
77 class Wrap {
78 public:
79 explicit Wrap(O3TL_STD_UNDERLYING_TYPE_E value):
80 value_(value)
81 { assert(detail::isNonNegative(value)); }
83 operator E() { return static_cast<E>(value_); }
85 explicit operator O3TL_STD_UNDERLYING_TYPE_E() { return value_; }
87 explicit operator bool() { return value_ != 0; }
89 private:
90 O3TL_STD_UNDERLYING_TYPE_E value_;
93 static O3TL_STD_UNDERLYING_TYPE_E const mask = M;
98 template<typename E>
99 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 & ~static_cast<O3TL_STD_UNDERLYING_TYPE_E>(rhs));
108 template<typename E>
109 inline typename o3tl::typed_flags<E>::Wrap operator ~(
110 typename o3tl::typed_flags<E>::Wrap rhs)
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));
117 template<typename E>
118 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 ^ static_cast<O3TL_STD_UNDERLYING_TYPE_E>(rhs));
130 template<typename E>
131 inline typename o3tl::typed_flags<E>::Wrap operator ^(
132 E lhs, typename o3tl::typed_flags<E>::Wrap rhs)
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 ^ static_cast<O3TL_STD_UNDERLYING_TYPE_E>(rhs));
142 template<typename E>
143 inline typename o3tl::typed_flags<E>::Wrap operator ^(
144 typename o3tl::typed_flags<E>::Wrap lhs, E rhs)
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));
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)
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));
164 template<typename E>
165 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 & static_cast<O3TL_STD_UNDERLYING_TYPE_E>(rhs));
177 template<typename E>
178 inline typename o3tl::typed_flags<E>::Wrap operator &(
179 E lhs, typename o3tl::typed_flags<E>::Wrap rhs)
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 & static_cast<O3TL_STD_UNDERLYING_TYPE_E>(rhs));
189 template<typename E>
190 inline typename o3tl::typed_flags<E>::Wrap operator &(
191 typename o3tl::typed_flags<E>::Wrap lhs, E rhs)
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 & static_cast<O3TL_STD_UNDERLYING_TYPE_E>(rhs));
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)
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));
211 template<typename E>
212 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 | static_cast<O3TL_STD_UNDERLYING_TYPE_E>(rhs));
224 template<typename E>
225 inline typename o3tl::typed_flags<E>::Wrap operator |(
226 E lhs, typename o3tl::typed_flags<E>::Wrap rhs)
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 | static_cast<O3TL_STD_UNDERLYING_TYPE_E>(rhs));
236 template<typename E>
237 inline typename o3tl::typed_flags<E>::Wrap operator |(
238 typename o3tl::typed_flags<E>::Wrap lhs, E rhs)
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 | static_cast<O3TL_STD_UNDERLYING_TYPE_E>(rhs));
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)
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));
258 template<typename E>
259 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 lhs = lhs & rhs;
267 return lhs;
270 template<typename E>
271 inline typename o3tl::typed_flags<E>::Self operator &=(
272 E & lhs, typename o3tl::typed_flags<E>::Wrap rhs)
274 assert(
275 o3tl::detail::isNonNegative(
276 static_cast<O3TL_STD_UNDERLYING_TYPE_E>(lhs)));
277 lhs = lhs & rhs;
278 return lhs;
281 template<typename E>
282 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 lhs = lhs | rhs;
290 return lhs;
293 template<typename E>
294 inline typename o3tl::typed_flags<E>::Self operator |=(
295 E & lhs, typename o3tl::typed_flags<E>::Wrap rhs)
297 assert(
298 o3tl::detail::isNonNegative(
299 static_cast<O3TL_STD_UNDERLYING_TYPE_E>(lhs)));
300 lhs = lhs | rhs;
301 return lhs;
304 template<typename E>
305 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 lhs = lhs ^ rhs;
313 return lhs;
316 template<typename E>
317 inline typename o3tl::typed_flags<E>::Self operator ^=(
318 E & lhs, typename o3tl::typed_flags<E>::Wrap rhs)
320 assert(
321 o3tl::detail::isNonNegative(
322 static_cast<O3TL_STD_UNDERLYING_TYPE_E>(lhs)));
323 lhs = lhs ^ rhs;
324 return lhs;
327 #endif /* INCLUDED_O3TL_TYPED_FLAGS_SET_HXX */
329 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */