LCOV - code coverage report
Current view: top level - mfbt - TypedEnumBits.h (source / functions) Hit Total Coverage
Test: output.info Lines: 12 14 85.7 %
Date: 2017-07-14 16:53:18 Functions: 76 155 49.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : /*
       8             :  * MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS allows using a typed enum as bit flags.
       9             :  */
      10             : 
      11             : #ifndef mozilla_TypedEnumBits_h
      12             : #define mozilla_TypedEnumBits_h
      13             : 
      14             : #include "mozilla/Attributes.h"
      15             : #include "mozilla/IntegerTypeTraits.h"
      16             : 
      17             : namespace mozilla {
      18             : 
      19             : /*
      20             :  * The problem that CastableTypedEnumResult aims to solve is that
      21             :  * typed enums are not convertible to bool, and there is no way to make them
      22             :  * be, yet user code wants to be able to write
      23             :  *
      24             :  *   if (myFlags & Flags::SOME_PARTICULAR_FLAG)              (1)
      25             :  *
      26             :  * There are different approaches to solving this. Most of them require
      27             :  * adapting user code. For example, we could implement operator! and have
      28             :  * the user write
      29             :  *
      30             :  *   if (!!(myFlags & Flags::SOME_PARTICULAR_FLAG))          (2)
      31             :  *
      32             :  * Or we could supply a IsNonZero() or Any() function returning whether
      33             :  * an enum value is nonzero, and have the user write
      34             :  *
      35             :  *   if (Any(Flags & Flags::SOME_PARTICULAR_FLAG))           (3)
      36             :  *
      37             :  * But instead, we choose to preserve the original user syntax (1) as it
      38             :  * is inherently more readable, and to ease porting existing code to typed
      39             :  * enums. We achieve this by having operator& and other binary bitwise
      40             :  * operators have as return type a class, CastableTypedEnumResult,
      41             :  * that wraps a typed enum but adds bool convertibility.
      42             :  */
      43             : template<typename E>
      44             : class CastableTypedEnumResult
      45             : {
      46             : private:
      47             :   const E mValue;
      48             : 
      49             : public:
      50     5827187 :   explicit constexpr CastableTypedEnumResult(E aValue)
      51     5827187 :     : mValue(aValue)
      52     5827187 :   {}
      53             : 
      54     1141773 :   constexpr operator E() const { return mValue; }
      55             : 
      56             :   template<typename DestinationType>
      57             :   explicit constexpr
      58     4512568 :   operator DestinationType() const { return DestinationType(mValue); }
      59             : 
      60      173046 :   constexpr bool operator !() const { return !bool(mValue); }
      61             : };
      62             : 
      63             : #define MOZ_CASTABLETYPEDENUMRESULT_BINOP(Op, OtherType, ReturnType) \
      64             : template<typename E> \
      65             : constexpr ReturnType \
      66             : operator Op(const OtherType& aE, const CastableTypedEnumResult<E>& aR) \
      67             : { \
      68             :   return ReturnType(aE Op OtherType(aR)); \
      69             : } \
      70             : template<typename E> \
      71             : constexpr ReturnType \
      72             : operator Op(const CastableTypedEnumResult<E>& aR, const OtherType& aE) \
      73             : { \
      74             :   return ReturnType(OtherType(aR) Op aE); \
      75             : } \
      76             : template<typename E> \
      77             : constexpr ReturnType \
      78             : operator Op(const CastableTypedEnumResult<E>& aR1, \
      79             :             const CastableTypedEnumResult<E>& aR2) \
      80             : { \
      81             :   return ReturnType(OtherType(aR1) Op OtherType(aR2)); \
      82             : }
      83             : 
      84         142 : MOZ_CASTABLETYPEDENUMRESULT_BINOP(|, E, CastableTypedEnumResult<E>)
      85      137603 : MOZ_CASTABLETYPEDENUMRESULT_BINOP(&, E, CastableTypedEnumResult<E>)
      86             : MOZ_CASTABLETYPEDENUMRESULT_BINOP(^, E, CastableTypedEnumResult<E>)
      87         605 : MOZ_CASTABLETYPEDENUMRESULT_BINOP(==, E, bool)
      88         146 : MOZ_CASTABLETYPEDENUMRESULT_BINOP(!=, E, bool)
      89             : 
      90             : template <typename E>
      91             : constexpr CastableTypedEnumResult<E>
      92           0 : operator ~(const CastableTypedEnumResult<E>& aR)
      93             : {
      94           0 :   return CastableTypedEnumResult<E>(~(E(aR)));
      95             : }
      96             : 
      97             : #define MOZ_CASTABLETYPEDENUMRESULT_COMPOUND_ASSIGN_OP(Op) \
      98             : template<typename E> \
      99             : E& \
     100             : operator Op(E& aR1, \
     101             :             const CastableTypedEnumResult<E>& aR2) \
     102             : { \
     103             :   return aR1 Op E(aR2); \
     104             : }
     105             : 
     106      167783 : MOZ_CASTABLETYPEDENUMRESULT_COMPOUND_ASSIGN_OP(&=)
     107       53069 : MOZ_CASTABLETYPEDENUMRESULT_COMPOUND_ASSIGN_OP(|=)
     108             : MOZ_CASTABLETYPEDENUMRESULT_COMPOUND_ASSIGN_OP(^=)
     109             : 
     110             : #undef MOZ_CASTABLETYPEDENUMRESULT_COMPOUND_ASSIGN_OP
     111             : 
     112             : #undef MOZ_CASTABLETYPEDENUMRESULT_BINOP
     113             : 
     114             : namespace detail {
     115             : template<typename E>
     116             : struct UnsignedIntegerTypeForEnum
     117             :   : UnsignedStdintTypeForSize<sizeof(E)>
     118             : {};
     119             : } // namespace detail
     120             : 
     121             : } // namespace mozilla
     122             : 
     123             : #define MOZ_MAKE_ENUM_CLASS_BINOP_IMPL(Name, Op) \
     124             :    inline constexpr mozilla::CastableTypedEnumResult<Name> \
     125             :    operator Op(Name a, Name b) \
     126             :    { \
     127             :      typedef mozilla::CastableTypedEnumResult<Name> Result; \
     128             :      typedef mozilla::detail::UnsignedIntegerTypeForEnum<Name>::Type U; \
     129             :      return Result(Name(U(a) Op U(b))); \
     130             :    } \
     131             :  \
     132             :    inline Name& \
     133             :    operator Op##=(Name& a, Name b) \
     134             :    { \
     135             :      return a = a Op b; \
     136             :    }
     137             : 
     138             : /**
     139             :  * MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS generates standard bitwise operators
     140             :  * for the given enum type. Use this to enable using an enum type as bit-field.
     141             :  */
     142             : #define MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(Name) \
     143             :    MOZ_MAKE_ENUM_CLASS_BINOP_IMPL(Name, |) \
     144             :    MOZ_MAKE_ENUM_CLASS_BINOP_IMPL(Name, &) \
     145             :    MOZ_MAKE_ENUM_CLASS_BINOP_IMPL(Name, ^) \
     146             :    inline constexpr mozilla::CastableTypedEnumResult<Name> \
     147             :    operator~(Name a) \
     148             :    { \
     149             :      typedef mozilla::CastableTypedEnumResult<Name> Result; \
     150             :      typedef mozilla::detail::UnsignedIntegerTypeForEnum<Name>::Type U; \
     151             :      return Result(Name(~(U(a)))); \
     152             :    }
     153             : 
     154             : #endif // mozilla_TypedEnumBits_h

Generated by: LCOV version 1.13