/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ #ifndef INCLUDED_O3TL_TYPED_FLAGS_SET_HXX #define INCLUDED_O3TL_TYPED_FLAGS_SET_HXX #include #include #include namespace o3tl { template struct typed_flags {}; #if defined __GNUC__ && __GNUC__ == 4 && __GNUC_MINOR__ <= 7 && \ !defined __clang__ #define O3TL_STD_UNDERLYING_TYPE_E signed int #else #define O3TL_STD_UNDERLYING_TYPE_E typename std::underlying_type::type #endif /// Mark a (scoped) enumeration as a set of bit flags, with accompanying /// operations. /// /// template<> /// struct o3tl::typed_flags: o3tl::is_typed_flags {}; /// /// All relevant values must be non-negative. (Typically, the enumeration's /// underlying type will either be fixed and unsigned, or it will be unfixed--- /// and can thus default to a signed type---and all enumerators will have non- /// negative values.) /// /// \param E the enumeration type. /// \param M the all-bits-set value for the bit flags. template struct is_typed_flags { static_assert( M >= 0, "is_typed_flags expects only non-negative bit values"); typedef E Self; class Wrap { public: explicit Wrap(O3TL_STD_UNDERLYING_TYPE_E value): value_(value) { assert(value >= 0); } operator E() { return static_cast(value_); } #if !defined _MSC_VER || _MSC_VER > 1700 explicit #endif operator O3TL_STD_UNDERLYING_TYPE_E() { return value_; } #if !defined _MSC_VER || _MSC_VER > 1700 explicit #endif operator bool() { return value_ != 0; } private: O3TL_STD_UNDERLYING_TYPE_E value_; }; static O3TL_STD_UNDERLYING_TYPE_E const mask = M; }; } template inline typename o3tl::typed_flags::Wrap operator ~(E rhs) { assert(static_cast(rhs) >= 0); return static_cast::Wrap>( o3tl::typed_flags::mask & ~static_cast(rhs)); } template inline typename o3tl::typed_flags::Wrap operator ~( typename o3tl::typed_flags::Wrap rhs) { return static_cast::Wrap>( o3tl::typed_flags::mask & ~static_cast(rhs)); } template inline typename o3tl::typed_flags::Wrap operator &(E lhs, E rhs) { assert(static_cast(lhs) >= 0); assert(static_cast(rhs) >= 0); return static_cast::Wrap>( static_cast(lhs) & static_cast(rhs)); } template inline typename o3tl::typed_flags::Wrap operator &( E lhs, typename o3tl::typed_flags::Wrap rhs) { assert(static_cast(lhs) >= 0); return static_cast::Wrap>( static_cast(lhs) & static_cast(rhs)); } template inline typename o3tl::typed_flags::Wrap operator &( typename o3tl::typed_flags::Wrap lhs, E rhs) { assert(static_cast(rhs) >= 0); return static_cast::Wrap>( static_cast(lhs) & static_cast(rhs)); } template inline typename o3tl::typed_flags::Wrap operator &( typename o3tl::typed_flags::Wrap lhs, typename o3tl::typed_flags::Wrap rhs) { return static_cast::Wrap>( static_cast(lhs) & static_cast(rhs)); } template inline typename o3tl::typed_flags::Wrap operator |(E lhs, E rhs) { assert(static_cast(lhs) >= 0); assert(static_cast(rhs) >= 0); return static_cast::Wrap>( static_cast(lhs) | static_cast(rhs)); } template inline typename o3tl::typed_flags::Wrap operator |( E lhs, typename o3tl::typed_flags::Wrap rhs) { assert(static_cast(lhs) >= 0); return static_cast::Wrap>( static_cast(lhs) | static_cast(rhs)); } template inline typename o3tl::typed_flags::Wrap operator |( typename o3tl::typed_flags::Wrap lhs, E rhs) { assert(static_cast(rhs) >= 0); return static_cast::Wrap>( static_cast(lhs) | static_cast(rhs)); } template inline typename o3tl::typed_flags::Wrap operator |( typename o3tl::typed_flags::Wrap lhs, typename o3tl::typed_flags::Wrap rhs) { return static_cast::Wrap>( static_cast(lhs) | static_cast(rhs)); } template inline typename o3tl::typed_flags::Self operator &=(E & lhs, E rhs) { assert(static_cast(lhs) >= 0); assert(static_cast(rhs) >= 0); lhs = lhs & rhs; return lhs; } template inline typename o3tl::typed_flags::Self operator &=( E & lhs, typename o3tl::typed_flags::Wrap rhs) { assert(static_cast(lhs) >= 0); lhs = lhs & rhs; return lhs; } template inline typename o3tl::typed_flags::Self operator |=(E & lhs, E rhs) { assert(static_cast(lhs) >= 0); assert(static_cast(rhs) >= 0); lhs = lhs | rhs; return lhs; } template inline typename o3tl::typed_flags::Self operator |=( E & lhs, typename o3tl::typed_flags::Wrap rhs) { assert(static_cast(lhs) >= 0); lhs = lhs | rhs; return lhs; } #undef O3TL_STD_UNDERLYING_TYPE_E #endif /* INCLUDED_O3TL_TYPED_FLAGS_SET_HXX */ /* vim:set shiftwidth=4 softtabstop=4 expandtab: */