tdf#130857 qt weld: Support mail merge "Server Auth" dialog
[LibreOffice.git] / include / o3tl / typed_flags_set.hxx
blob413ee9579d4d69a192086279ecf846626dd1d7d7
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>
30 namespace o3tl {
32 namespace detail {
34 template<typename T> constexpr
35 typename std::enable_if<std::is_signed<T>::value, bool>::type isNonNegative(
36 T value)
38 return value >= 0;
41 template<typename T> constexpr
42 typename std::enable_if<std::is_unsigned<T>::value, bool>::type isNonNegative(T)
44 return true;
49 template<typename T> struct typed_flags {};
51 /// Mark a (scoped) enumeration as a set of bit flags, with accompanying
52 /// operations.
53 ///
54 /// template<>
55 /// struct o3tl::typed_flags<TheE>: o3tl::is_typed_flags<TheE, TheM> {};
56 ///
57 /// All relevant values must be non-negative. (Typically, the enumeration's
58 /// underlying type will either be fixed and unsigned, or it will be unfixed---
59 /// and can thus default to a signed type---and all enumerators will have non-
60 /// negative values.)
61 ///
62 /// \param E the enumeration type.
63 /// \param M the all-bits-set value for the bit flags.
64 template<typename E, typename std::underlying_type<E>::type M>
65 struct is_typed_flags {
66 static_assert(
67 M >= 0, "is_typed_flags expects only non-negative bit values");
69 typedef E Self;
71 class Wrap {
72 public:
73 typedef is_typed_flags Unwrapped;
75 explicit constexpr Wrap(typename std::underlying_type<E>::type value):
76 value_(value)
78 assert(detail::isNonNegative(value));
79 assert(
80 static_cast<typename std::underlying_type<E>::type>(~0) == M
81 // avoid "operands don't affect result" warnings when M
82 // covers all bits of the underlying type
83 || (value & ~M) == 0);
86 constexpr operator E() const { return static_cast<E>(value_); }
88 explicit constexpr operator typename std::underlying_type<E>::type()
89 const
90 { return value_; }
92 explicit constexpr operator bool() const { return value_ != 0; }
94 private:
95 typename std::underlying_type<E>::type value_;
98 static typename std::underlying_type<E>::type const mask = M;
103 template<typename E>
104 constexpr typename o3tl::typed_flags<E>::Wrap operator ~(E rhs) {
105 assert(
106 o3tl::detail::isNonNegative(
107 o3tl::to_underlying(rhs)));
108 return static_cast<typename o3tl::typed_flags<E>::Wrap>(
109 o3tl::typed_flags<E>::mask
110 & ~o3tl::to_underlying(rhs));
113 template<typename E> constexpr typename o3tl::typed_flags<E>::Wrap operator ~(
114 typename o3tl::typed_flags<E>::Wrap rhs)
116 return static_cast<typename o3tl::typed_flags<E>::Wrap>(
117 o3tl::typed_flags<E>::mask
118 & ~o3tl::to_underlying<E>(rhs));
121 template<typename E> constexpr typename o3tl::typed_flags<E>::Wrap operator ^(
122 E lhs, E rhs)
124 assert(
125 o3tl::detail::isNonNegative(
126 o3tl::to_underlying(lhs)));
127 assert(
128 o3tl::detail::isNonNegative(
129 o3tl::to_underlying(rhs)));
130 return static_cast<typename o3tl::typed_flags<E>::Wrap>(
131 o3tl::to_underlying(lhs)
132 ^ o3tl::to_underlying(rhs));
135 template<typename E> constexpr typename o3tl::typed_flags<E>::Wrap operator ^(
136 E lhs, typename o3tl::typed_flags<E>::Wrap rhs)
138 assert(
139 o3tl::detail::isNonNegative(
140 o3tl::to_underlying(lhs)));
141 return static_cast<typename o3tl::typed_flags<E>::Wrap>(
142 o3tl::to_underlying(lhs)
143 ^ o3tl::to_underlying<E>(rhs));
146 template<typename E> constexpr typename o3tl::typed_flags<E>::Wrap operator ^(
147 typename o3tl::typed_flags<E>::Wrap lhs, E rhs)
149 assert(
150 o3tl::detail::isNonNegative(
151 o3tl::to_underlying(rhs)));
152 return static_cast<typename o3tl::typed_flags<E>::Wrap>(
153 o3tl::to_underlying<E>(lhs)
154 ^ o3tl::to_underlying(rhs));
157 template<typename W> constexpr
158 typename o3tl::typed_flags<typename W::Unwrapped::Self>::Wrap operator ^(
159 W lhs, W rhs)
161 return static_cast<W>(
162 o3tl::to_underlying<typename W::Unwrapped::Self>(lhs)
163 ^ o3tl::to_underlying<typename W::Unwrapped::Self>(rhs));
166 template<typename E>
167 constexpr typename o3tl::typed_flags<E>::Wrap operator &(E lhs, E rhs) {
168 assert(
169 o3tl::detail::isNonNegative(
170 o3tl::to_underlying(lhs)));
171 assert(
172 o3tl::detail::isNonNegative(
173 o3tl::to_underlying(rhs)));
174 return static_cast<typename o3tl::typed_flags<E>::Wrap>(
175 o3tl::to_underlying(lhs)
176 & o3tl::to_underlying(rhs));
179 template<typename E> constexpr typename o3tl::typed_flags<E>::Wrap operator &(
180 E lhs, typename o3tl::typed_flags<E>::Wrap rhs)
182 assert(
183 o3tl::detail::isNonNegative(
184 o3tl::to_underlying(lhs)));
185 return static_cast<typename o3tl::typed_flags<E>::Wrap>(
186 o3tl::to_underlying(lhs)
187 & o3tl::to_underlying<E>(rhs));
190 template<typename E> constexpr typename o3tl::typed_flags<E>::Wrap operator &(
191 typename o3tl::typed_flags<E>::Wrap lhs, E rhs)
193 assert(
194 o3tl::detail::isNonNegative(
195 o3tl::to_underlying(rhs)));
196 return static_cast<typename o3tl::typed_flags<E>::Wrap>(
197 o3tl::to_underlying<E>(lhs)
198 & o3tl::to_underlying(rhs));
201 template<typename W> constexpr
202 typename o3tl::typed_flags<typename W::Unwrapped::Self>::Wrap operator &(
203 W lhs, W rhs)
205 return static_cast<W>(
206 o3tl::to_underlying<typename W::Unwrapped::Self>(lhs)
207 & o3tl::to_underlying<typename W::Unwrapped::Self>(rhs));
210 template<typename E>
211 constexpr typename o3tl::typed_flags<E>::Wrap operator |(E lhs, E rhs) {
212 assert(
213 o3tl::detail::isNonNegative(
214 o3tl::to_underlying(lhs)));
215 assert(
216 o3tl::detail::isNonNegative(
217 o3tl::to_underlying(rhs)));
218 return static_cast<typename o3tl::typed_flags<E>::Wrap>(
219 o3tl::to_underlying(lhs)
220 | o3tl::to_underlying(rhs));
223 template<typename E> constexpr typename o3tl::typed_flags<E>::Wrap operator |(
224 E lhs, typename o3tl::typed_flags<E>::Wrap rhs)
226 assert(
227 o3tl::detail::isNonNegative(
228 o3tl::to_underlying(lhs)));
229 return static_cast<typename o3tl::typed_flags<E>::Wrap>(
230 o3tl::to_underlying(lhs)
231 | o3tl::to_underlying<E>(rhs));
234 template<typename E> constexpr typename o3tl::typed_flags<E>::Wrap operator |(
235 typename o3tl::typed_flags<E>::Wrap lhs, E rhs)
237 assert(
238 o3tl::detail::isNonNegative(
239 o3tl::to_underlying(rhs)));
240 return static_cast<typename o3tl::typed_flags<E>::Wrap>(
241 o3tl::to_underlying<E>(lhs)
242 | o3tl::to_underlying(rhs));
245 template<typename W> constexpr
246 typename o3tl::typed_flags<typename W::Unwrapped::Self>::Wrap operator |(
247 W lhs, W rhs)
249 return static_cast<W>(
250 o3tl::to_underlying<typename W::Unwrapped::Self>(lhs)
251 | o3tl::to_underlying<typename W::Unwrapped::Self>(rhs));
254 template<typename E>
255 inline typename o3tl::typed_flags<E>::Self operator &=(E & lhs, E rhs) {
256 assert(
257 o3tl::detail::isNonNegative(
258 o3tl::to_underlying(lhs)));
259 assert(
260 o3tl::detail::isNonNegative(
261 o3tl::to_underlying(rhs)));
262 lhs = lhs & rhs;
263 return lhs;
266 template<typename E>
267 inline typename o3tl::typed_flags<E>::Self operator &=(
268 E & lhs, typename o3tl::typed_flags<E>::Wrap rhs)
270 assert(
271 o3tl::detail::isNonNegative(
272 o3tl::to_underlying(lhs)));
273 lhs = lhs & rhs;
274 return lhs;
277 template<typename E>
278 inline typename o3tl::typed_flags<E>::Self operator |=(E & lhs, E rhs) {
279 assert(
280 o3tl::detail::isNonNegative(
281 o3tl::to_underlying(lhs)));
282 assert(
283 o3tl::detail::isNonNegative(
284 o3tl::to_underlying(rhs)));
285 lhs = lhs | rhs;
286 return lhs;
289 template<typename E>
290 inline typename o3tl::typed_flags<E>::Self operator |=(
291 E & lhs, typename o3tl::typed_flags<E>::Wrap rhs)
293 assert(
294 o3tl::detail::isNonNegative(
295 o3tl::to_underlying(lhs)));
296 lhs = lhs | rhs;
297 return lhs;
300 template<typename E>
301 inline typename o3tl::typed_flags<E>::Self operator ^=(E & lhs, E rhs) {
302 assert(
303 o3tl::detail::isNonNegative(
304 o3tl::to_underlying(lhs)));
305 assert(
306 o3tl::detail::isNonNegative(
307 o3tl::to_underlying(rhs)));
308 lhs = lhs ^ rhs;
309 return lhs;
312 template<typename E>
313 inline typename o3tl::typed_flags<E>::Self operator ^=(
314 E & lhs, typename o3tl::typed_flags<E>::Wrap rhs)
316 assert(
317 o3tl::detail::isNonNegative(
318 o3tl::to_underlying(lhs)));
319 lhs = lhs ^ rhs;
320 return lhs;
323 #endif /* INCLUDED_O3TL_TYPED_FLAGS_SET_HXX */
325 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */