Cosmetics.
[LibreOffice.git] / include / o3tl / typed_flags_set.hxx
blobbf795908bad50d4eef5dbed654fb28a49930ac5b
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 #include <o3tl/underlyingenumvalue.hxx>
29 #include <sal/types.h>
31 namespace o3tl {
33 namespace detail {
35 template<typename T> constexpr
36 typename std::enable_if<std::is_signed<T>::value, bool>::type isNonNegative(
37 T value)
39 return value >= 0;
42 template<typename T> constexpr
43 typename std::enable_if<std::is_unsigned<T>::value, bool>::type isNonNegative(T)
45 return true;
50 template<typename T> struct typed_flags {};
52 /// Mark a (scoped) enumeration as a set of bit flags, with accompanying
53 /// operations.
54 ///
55 /// template<>
56 /// struct o3tl::typed_flags<TheE>: o3tl::is_typed_flags<TheE, TheM> {};
57 ///
58 /// All relevant values must be non-negative. (Typically, the enumeration's
59 /// underlying type will either be fixed and unsigned, or it will be unfixed---
60 /// and can thus default to a signed type---and all enumerators will have non-
61 /// negative values.)
62 ///
63 /// \param E the enumeration type.
64 /// \param M the all-bits-set value for the bit flags.
65 template<typename E, typename std::underlying_type<E>::type M>
66 struct is_typed_flags {
67 static_assert(
68 M >= 0, "is_typed_flags expects only non-negative bit values");
70 typedef E Self;
72 class Wrap {
73 public:
74 typedef is_typed_flags Unwrapped;
76 explicit constexpr Wrap(typename std::underlying_type<E>::type value):
77 value_(value)
79 assert(detail::isNonNegative(value));
80 assert(
81 static_cast<typename std::underlying_type<E>::type>(~0) == M
82 // avoid "operands don't affect result" warnings when M
83 // covers all bits of the underlying type
84 || (value & ~M) == 0);
87 constexpr operator E() const { return static_cast<E>(value_); }
89 explicit constexpr operator typename std::underlying_type<E>::type()
90 const
91 { return value_; }
93 explicit constexpr operator bool() const { return value_ != 0; }
95 private:
96 typename std::underlying_type<E>::type value_;
99 static typename std::underlying_type<E>::type const mask = M;
104 template<typename E>
105 constexpr typename o3tl::typed_flags<E>::Wrap operator ~(E rhs) {
106 assert(
107 o3tl::detail::isNonNegative(
108 o3tl::underlyingEnumValue(rhs)));
109 return static_cast<typename o3tl::typed_flags<E>::Wrap>(
110 o3tl::typed_flags<E>::mask
111 & ~o3tl::underlyingEnumValue(rhs));
114 template<typename E> constexpr typename o3tl::typed_flags<E>::Wrap operator ~(
115 typename o3tl::typed_flags<E>::Wrap rhs)
117 return static_cast<typename o3tl::typed_flags<E>::Wrap>(
118 o3tl::typed_flags<E>::mask
119 & ~o3tl::underlyingEnumValue<E>(rhs));
122 template<typename E> constexpr typename o3tl::typed_flags<E>::Wrap operator ^(
123 E lhs, E rhs)
125 assert(
126 o3tl::detail::isNonNegative(
127 o3tl::underlyingEnumValue(lhs)));
128 assert(
129 o3tl::detail::isNonNegative(
130 o3tl::underlyingEnumValue(rhs)));
131 return static_cast<typename o3tl::typed_flags<E>::Wrap>(
132 o3tl::underlyingEnumValue(lhs)
133 ^ o3tl::underlyingEnumValue(rhs));
136 template<typename E> constexpr typename o3tl::typed_flags<E>::Wrap operator ^(
137 E lhs, typename o3tl::typed_flags<E>::Wrap rhs)
139 assert(
140 o3tl::detail::isNonNegative(
141 o3tl::underlyingEnumValue(lhs)));
142 return static_cast<typename o3tl::typed_flags<E>::Wrap>(
143 o3tl::underlyingEnumValue(lhs)
144 ^ o3tl::underlyingEnumValue<E>(rhs));
147 template<typename E> constexpr typename o3tl::typed_flags<E>::Wrap operator ^(
148 typename o3tl::typed_flags<E>::Wrap lhs, E rhs)
150 assert(
151 o3tl::detail::isNonNegative(
152 o3tl::underlyingEnumValue(rhs)));
153 return static_cast<typename o3tl::typed_flags<E>::Wrap>(
154 o3tl::underlyingEnumValue<E>(lhs)
155 ^ o3tl::underlyingEnumValue(rhs));
158 template<typename W> constexpr
159 typename o3tl::typed_flags<typename W::Unwrapped::Self>::Wrap operator ^(
160 W lhs, W rhs)
162 return static_cast<W>(
163 o3tl::underlyingEnumValue<typename W::Unwrapped::Self>(lhs)
164 ^ o3tl::underlyingEnumValue<typename W::Unwrapped::Self>(rhs));
167 template<typename E>
168 constexpr typename o3tl::typed_flags<E>::Wrap operator &(E lhs, E rhs) {
169 assert(
170 o3tl::detail::isNonNegative(
171 o3tl::underlyingEnumValue(lhs)));
172 assert(
173 o3tl::detail::isNonNegative(
174 o3tl::underlyingEnumValue(rhs)));
175 return static_cast<typename o3tl::typed_flags<E>::Wrap>(
176 o3tl::underlyingEnumValue(lhs)
177 & o3tl::underlyingEnumValue(rhs));
180 template<typename E> constexpr typename o3tl::typed_flags<E>::Wrap operator &(
181 E lhs, typename o3tl::typed_flags<E>::Wrap rhs)
183 assert(
184 o3tl::detail::isNonNegative(
185 o3tl::underlyingEnumValue(lhs)));
186 return static_cast<typename o3tl::typed_flags<E>::Wrap>(
187 o3tl::underlyingEnumValue(lhs)
188 & o3tl::underlyingEnumValue<E>(rhs));
191 template<typename E> constexpr typename o3tl::typed_flags<E>::Wrap operator &(
192 typename o3tl::typed_flags<E>::Wrap lhs, E rhs)
194 assert(
195 o3tl::detail::isNonNegative(
196 o3tl::underlyingEnumValue(rhs)));
197 return static_cast<typename o3tl::typed_flags<E>::Wrap>(
198 o3tl::underlyingEnumValue<E>(lhs)
199 & o3tl::underlyingEnumValue(rhs));
202 template<typename W> constexpr
203 typename o3tl::typed_flags<typename W::Unwrapped::Self>::Wrap operator &(
204 W lhs, W rhs)
206 return static_cast<W>(
207 o3tl::underlyingEnumValue<typename W::Unwrapped::Self>(lhs)
208 & o3tl::underlyingEnumValue<typename W::Unwrapped::Self>(rhs));
211 template<typename E>
212 constexpr typename o3tl::typed_flags<E>::Wrap operator |(E lhs, E rhs) {
213 assert(
214 o3tl::detail::isNonNegative(
215 o3tl::underlyingEnumValue(lhs)));
216 assert(
217 o3tl::detail::isNonNegative(
218 o3tl::underlyingEnumValue(rhs)));
219 return static_cast<typename o3tl::typed_flags<E>::Wrap>(
220 o3tl::underlyingEnumValue(lhs)
221 | o3tl::underlyingEnumValue(rhs));
224 template<typename E> constexpr typename o3tl::typed_flags<E>::Wrap operator |(
225 E lhs, typename o3tl::typed_flags<E>::Wrap rhs)
227 assert(
228 o3tl::detail::isNonNegative(
229 o3tl::underlyingEnumValue(lhs)));
230 return static_cast<typename o3tl::typed_flags<E>::Wrap>(
231 o3tl::underlyingEnumValue(lhs)
232 | o3tl::underlyingEnumValue<E>(rhs));
235 template<typename E> constexpr typename o3tl::typed_flags<E>::Wrap operator |(
236 typename o3tl::typed_flags<E>::Wrap lhs, E rhs)
238 assert(
239 o3tl::detail::isNonNegative(
240 o3tl::underlyingEnumValue(rhs)));
241 return static_cast<typename o3tl::typed_flags<E>::Wrap>(
242 o3tl::underlyingEnumValue<E>(lhs)
243 | o3tl::underlyingEnumValue(rhs));
246 template<typename W> constexpr
247 typename o3tl::typed_flags<typename W::Unwrapped::Self>::Wrap operator |(
248 W lhs, W rhs)
250 return static_cast<W>(
251 o3tl::underlyingEnumValue<typename W::Unwrapped::Self>(lhs)
252 | o3tl::underlyingEnumValue<typename W::Unwrapped::Self>(rhs));
255 template<typename E>
256 inline typename o3tl::typed_flags<E>::Self operator &=(E & lhs, E rhs) {
257 assert(
258 o3tl::detail::isNonNegative(
259 o3tl::underlyingEnumValue(lhs)));
260 assert(
261 o3tl::detail::isNonNegative(
262 o3tl::underlyingEnumValue(rhs)));
263 lhs = lhs & rhs;
264 return lhs;
267 template<typename E>
268 inline typename o3tl::typed_flags<E>::Self operator &=(
269 E & lhs, typename o3tl::typed_flags<E>::Wrap rhs)
271 assert(
272 o3tl::detail::isNonNegative(
273 o3tl::underlyingEnumValue(lhs)));
274 lhs = lhs & rhs;
275 return lhs;
278 template<typename E>
279 inline typename o3tl::typed_flags<E>::Self operator |=(E & lhs, E rhs) {
280 assert(
281 o3tl::detail::isNonNegative(
282 o3tl::underlyingEnumValue(lhs)));
283 assert(
284 o3tl::detail::isNonNegative(
285 o3tl::underlyingEnumValue(rhs)));
286 lhs = lhs | rhs;
287 return lhs;
290 template<typename E>
291 inline typename o3tl::typed_flags<E>::Self operator |=(
292 E & lhs, typename o3tl::typed_flags<E>::Wrap rhs)
294 assert(
295 o3tl::detail::isNonNegative(
296 o3tl::underlyingEnumValue(lhs)));
297 lhs = lhs | rhs;
298 return lhs;
301 template<typename E>
302 inline typename o3tl::typed_flags<E>::Self operator ^=(E & lhs, E rhs) {
303 assert(
304 o3tl::detail::isNonNegative(
305 o3tl::underlyingEnumValue(lhs)));
306 assert(
307 o3tl::detail::isNonNegative(
308 o3tl::underlyingEnumValue(rhs)));
309 lhs = lhs ^ rhs;
310 return lhs;
313 template<typename E>
314 inline typename o3tl::typed_flags<E>::Self operator ^=(
315 E & lhs, typename o3tl::typed_flags<E>::Wrap rhs)
317 assert(
318 o3tl::detail::isNonNegative(
319 o3tl::underlyingEnumValue(lhs)));
320 lhs = lhs ^ rhs;
321 return lhs;
324 #endif /* INCLUDED_O3TL_TYPED_FLAGS_SET_HXX */
326 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */