LCOV - code coverage report
Current view: top level - lib/support - BitFlags.h (source / functions) Hit Total Coverage
Test: lcov_final.info Lines: 38 38 100.0 %
Date: 2024-02-15 08:20:41 Functions: 155 207 74.9 %

          Line data    Source code
       1             : /*
       2             :  *
       3             :  *    Copyright (c) 2020-2021 Project CHIP Authors
       4             :  *    Copyright (c) 2013-2017 Nest Labs, Inc.
       5             :  *
       6             :  *    Licensed under the Apache License, Version 2.0 (the "License");
       7             :  *    you may not use this file except in compliance with the License.
       8             :  *    You may obtain a copy of the License at
       9             :  *
      10             :  *        http://www.apache.org/licenses/LICENSE-2.0
      11             :  *
      12             :  *    Unless required by applicable law or agreed to in writing, software
      13             :  *    distributed under the License is distributed on an "AS IS" BASIS,
      14             :  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      15             :  *    See the License for the specific language governing permissions and
      16             :  *    limitations under the License.
      17             :  */
      18             : 
      19             : /**
      20             :  *    @file
      21             :  *      This file defines functions for manipulating Boolean flags in
      22             :  *      a bitfield.
      23             :  *
      24             :  */
      25             : 
      26             : #pragma once
      27             : 
      28             : #include <stdint.h>
      29             : 
      30             : #include <type_traits>
      31             : #include <utility>
      32             : 
      33             : namespace chip {
      34             : 
      35             : /**
      36             :  * Stores bit flags in a type safe manner.
      37             :  *
      38             :  * @tparam FlagsEnum is an `enum` or (preferably) `enum class` type.
      39             :  * @tparam StorageType is the underlying storage type (like uint16_t, uint32_t etc.)
      40             :  *         and defaults to the underlying storage type of `FlagsEnum`.
      41             :  */
      42             : template <typename FlagsEnum, typename StorageType = typename std::underlying_type_t<FlagsEnum>>
      43             : class BitFlags
      44             : {
      45             : public:
      46             :     static_assert(sizeof(StorageType) >= sizeof(FlagsEnum), "All flags should fit in the storage type");
      47             :     using IntegerType = StorageType;
      48             : 
      49      106563 :     constexpr BitFlags() : mValue(0) {}
      50             :     BitFlags(const BitFlags & other)       = default;
      51             :     BitFlags & operator=(const BitFlags &) = default;
      52             : 
      53        4337 :     explicit constexpr BitFlags(FlagsEnum value) : mValue(static_cast<IntegerType>(value)) {}
      54        2652 :     explicit constexpr BitFlags(IntegerType value) : mValue(value) {}
      55             : 
      56             :     template <typename... Args>
      57       17994 :     constexpr BitFlags(FlagsEnum flag, Args &&... args) : mValue(Or(flag, std::forward<Args>(args)...))
      58       17994 :     {}
      59             : 
      60             :     template <typename... Args>
      61             :     constexpr BitFlags(const BitFlags<FlagsEnum> & flags, Args &&... args) : mValue(Or(flags, std::forward<Args>(args)...))
      62             :     {}
      63             : 
      64             :     template <typename... Args>
      65          22 :     constexpr BitFlags(IntegerType value, Args &&... args) : mValue(value | Or(std::forward<Args>(args)...))
      66          22 :     {}
      67             : 
      68             :     /**
      69             :      * Set flag(s).
      70             :      *
      71             :      * @param other     Flag(s) to set. Any flags not set in @a other are unaffected.
      72             :      */
      73             :     BitFlags & Set(const BitFlags & other)
      74             :     {
      75             :         mValue |= other.mValue;
      76             :         return *this;
      77             :     }
      78             : 
      79             :     /**
      80             :      * Set flag(s).
      81             :      *
      82             :      * @param flag      Typed flag(s) to set. Any flags not in @a v are unaffected.
      83             :      */
      84     4207451 :     constexpr BitFlags & Set(FlagsEnum flag)
      85             :     {
      86     4207451 :         mValue |= static_cast<IntegerType>(flag);
      87     4207451 :         return *this;
      88             :     }
      89             : 
      90             :     /**
      91             :      * Set or clear flag(s).
      92             :      *
      93             :      * @param flag      Typed flag(s) to set or clear. Any flags not in @a flag are unaffected.
      94             :      * @param isSet     If true, set the flag; if false, clear it.
      95             :      */
      96      221279 :     constexpr BitFlags & Set(FlagsEnum flag, bool isSet) { return isSet ? Set(flag) : Clear(flag); }
      97             : 
      98             :     /**
      99             :      * Clear flag(s).
     100             :      *
     101             :      * @param other     Typed flag(s) to clear. Any flags not in @a other are unaffected.
     102             :      */
     103             :     BitFlags & Clear(const BitFlags & other)
     104             :     {
     105             :         mValue &= static_cast<IntegerType>(~static_cast<IntegerType>(other.mValue));
     106             :         return *this;
     107             :     }
     108             : 
     109             :     /**
     110             :      * Clear flag(s).
     111             :      *
     112             :      * @param flag  Typed flag(s) to clear. Any flags not in @a flag are unaffected.
     113             :      */
     114      155395 :     constexpr BitFlags & Clear(FlagsEnum flag)
     115             :     {
     116      155395 :         mValue &= static_cast<IntegerType>(~static_cast<IntegerType>(flag));
     117      155395 :         return *this;
     118             :     }
     119             : 
     120             :     /**
     121             :      * Clear all flags.
     122             :      */
     123       31467 :     BitFlags & ClearAll()
     124             :     {
     125       31467 :         mValue = 0;
     126       31467 :         return *this;
     127             :     }
     128             : 
     129             :     /**
     130             :      * Check whether flag(s) are set.
     131             :      *
     132             :      * @param flag      Flag(s) to test.
     133             :      * @returns         True if any flag in @a flag is set, otherwise false.
     134             :      */
     135     8823867 :     constexpr bool Has(FlagsEnum flag) const { return (mValue & static_cast<IntegerType>(flag)) != 0; }
     136             : 
     137             :     /**
     138             :      * Check that no flags outside the arguments are set.
     139             :      *
     140             :      * @param args      Flags to test. Arguments can be BitFlags<FlagsEnum>, BitFlags<FlagsEnum>, or FlagsEnum.
     141             :      * @returns         True if no flag is set other than those passed.
     142             :      *                  False if any flag is set other than those passed.
     143             :      *
     144             :      * @note            Flags passed need not be set; this test only requires that no *other* flags be set.
     145             :      */
     146             :     template <typename... Args>
     147        2697 :     bool HasOnly(Args &&... args) const
     148             :     {
     149        2697 :         return (mValue & Or(std::forward<Args>(args)...)) == mValue;
     150             :     }
     151             : 
     152             :     /**
     153             :      * Check that all given flags are set.
     154             :      *
     155             :      * @param args      Flags to test. Arguments can be BitFlags<FlagsEnum>, BitFlags<FlagsEnum>, or FlagsEnum.
     156             :      * @returns         True if all given flags are set.
     157             :      *                  False if any given flag is not set.
     158             :      */
     159             :     template <typename... Args>
     160       21224 :     bool HasAll(Args &&... args) const
     161             :     {
     162       21224 :         const IntegerType all = Or(std::forward<Args>(args)...);
     163       21224 :         return (mValue & all) == all;
     164             :     }
     165             : 
     166             :     /**
     167             :      * Check that at least one of the given flags is set.
     168             :      *
     169             :      * @param args      Flags to test. Arguments can be BitFlags<FlagsEnum>, BitFlags<FlagsEnum>, or FlagsEnum.
     170             :      * @returns         True if all given flags are set.
     171             :      *                  False if any given flag is not set.
     172             :      */
     173             :     template <typename... Args>
     174        2612 :     bool HasAny(Args &&... args) const
     175             :     {
     176        2612 :         return (mValue & Or(std::forward<Args>(args)...)) != 0;
     177             :     }
     178             : 
     179             :     /**
     180             :      * Check that at least one flag is set.
     181             :      *
     182             :      * @returns         True if any flag is set, false otherwise.
     183             :      */
     184     4094355 :     bool HasAny() const { return mValue != 0; }
     185             : 
     186             :     /**
     187             :      * Find the logical intersection of flags.
     188             :      *
     189             :      * @param lhs       Some flags.
     190             :      * @param rhs       Some flags.
     191             :      * @returns         Flags set in both @a lhs and @a rhs.
     192             :      *
     193             :      * @note: A multi-argument `BitFlags` constructor serves the function of `operator|`.
     194             :      */
     195           4 :     friend BitFlags<FlagsEnum> operator&(BitFlags<FlagsEnum> lhs, const BitFlags<FlagsEnum> & rhs)
     196             :     {
     197           4 :         return BitFlags<FlagsEnum>(lhs.mValue & rhs.mValue);
     198             :     }
     199             : 
     200             :     /**
     201             :      * Get the flags as the type FlagsEnum.
     202             :      *
     203             :      * @note            This allows easily storing flags as a base FlagsEnum in a POD type,
     204             :      *                  and enables equality comparisons.
     205             :      */
     206          74 :     operator FlagsEnum() const { return static_cast<FlagsEnum>(mValue); }
     207             : 
     208             :     /**
     209             :      * Set and/or clear all flags with a value of the underlying storage type.
     210             :      *
     211             :      * @param value     New storage value.
     212             :      */
     213       72822 :     BitFlags & SetRaw(IntegerType value)
     214             :     {
     215       72822 :         mValue = value;
     216       72822 :         return *this;
     217             :     }
     218             : 
     219             :     /**
     220             :      * Get the flags as the underlying integer type.
     221             :      *
     222             :      * @note            This is intended to be used only to store flags into a raw binary record.
     223             :      */
     224       96858 :     constexpr IntegerType Raw() const { return mValue; }
     225             : 
     226             :     /**
     227             :      * Get the address of the flags as a pointer to the underlying integer type.
     228             :      *
     229             :      * @note            This is intended to be used only to read flags from a raw binary record.
     230             :      */
     231           8 :     StorageType * RawStorage() { return &mValue; }
     232             : 
     233             : private:
     234             :     // Find the union of BitFlags and/or FlagsEnum values.
     235             :     template <typename... Args>
     236       44766 :     static constexpr IntegerType Or(FlagsEnum flag, Args &&... args)
     237             :     {
     238       44766 :         return static_cast<IntegerType>(flag) | Or(std::forward<Args>(args)...);
     239             :     }
     240             :     template <typename... Args>
     241             :     static constexpr IntegerType Or(const BitFlags<FlagsEnum> & flags, Args &&... args)
     242             :     {
     243             :         return flags.mValue | Or(std::forward<Args>(args)...);
     244             :     }
     245       42867 :     static constexpr IntegerType Or(FlagsEnum value) { return static_cast<IntegerType>(value); }
     246        1636 :     static constexpr IntegerType Or(const BitFlags<FlagsEnum> & flags) { return flags.Raw(); }
     247             : 
     248             :     StorageType mValue = 0;
     249             : };
     250             : 
     251             : } // namespace chip

Generated by: LCOV version 1.14