Matter SDK Coverage Report
Current view: top level - lib/support - BitMask.h (source / functions) Coverage Total Hit
Test: SHA:b879ecb8e99e175eea0a293a888bda853da2b19c Lines: 100.0 % 1 1
Test Date: 2025-01-17 19:00:11 Functions: 50.0 % 2 1

            Line data    Source code
       1              : /*
       2              :  *
       3              :  *    Copyright (c) 2022 Project CHIP Authors
       4              :  *
       5              :  *    Licensed under the Apache License, Version 2.0 (the "License");
       6              :  *    you may not use this file except in compliance with the License.
       7              :  *    You may obtain a copy of the License at
       8              :  *
       9              :  *        http://www.apache.org/licenses/LICENSE-2.0
      10              :  *
      11              :  *    Unless required by applicable law or agreed to in writing, software
      12              :  *    distributed under the License is distributed on an "AS IS" BASIS,
      13              :  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      14              :  *    See the License for the specific language governing permissions and
      15              :  *    limitations under the License.
      16              :  */
      17              : 
      18              : #pragma once
      19              : 
      20              : #include <lib/support/BitFlags.h>
      21              : 
      22              : namespace chip {
      23              : 
      24              : /**
      25              :  * Stores bit masks and flags in a more typesafe manner.
      26              :  *
      27              :  * Extends BitFlags for boolean flags and also adds support for bit-mask set options.
      28              :  *
      29              :  */
      30              : template <typename FlagsEnum, typename StorageType = typename std::underlying_type_t<FlagsEnum>>
      31              : class BitMask : public BitFlags<FlagsEnum, StorageType>
      32              : {
      33              : public:
      34              :     using IntegerType = typename BitFlags<FlagsEnum, StorageType>::IntegerType;
      35              : 
      36           60 :     constexpr BitMask() : BitFlags<FlagsEnum, StorageType>() {}
      37              :     constexpr BitMask(const BitFlags<FlagsEnum, StorageType> & other) : BitFlags<FlagsEnum, StorageType>(other) {}
      38              :     constexpr BitMask(BitFlags<FlagsEnum, StorageType> && other) : BitFlags<FlagsEnum, StorageType>(std::move(other)) {}
      39              :     BitMask(const BitMask &) = default;
      40              : 
      41              :     explicit BitMask(FlagsEnum value) : BitFlags<FlagsEnum, StorageType>(value) {}
      42              :     explicit BitMask(IntegerType value) : BitFlags<FlagsEnum, StorageType>(value) {}
      43              : 
      44              :     template <typename... Args>
      45              :     constexpr BitMask(FlagsEnum flag, Args &&... args) : BitFlags<FlagsEnum, StorageType>(flag, std::forward<Args>(args)...)
      46              :     {}
      47              : 
      48              :     template <typename... Args>
      49              :     constexpr BitMask(IntegerType value, Args &&... args) : BitFlags<FlagsEnum, StorageType>(value, std::forward<Args>(args)...)
      50              :     {}
      51              : 
      52              :     BitMask & operator=(const BitMask &) = default;
      53              : 
      54              :     BitMask & operator=(const BitFlags<FlagsEnum, StorageType> & other)
      55              :     {
      56              :         BitFlags<FlagsEnum, StorageType>::SetRaw(other.Raw());
      57              :         return *this;
      58              :     }
      59              : 
      60              :     BitMask & operator=(FlagsEnum value)
      61              :     {
      62              :         BitFlags<FlagsEnum, StorageType>::SetRaw(static_cast<StorageType>(value));
      63              :         return *this;
      64              :     }
      65              : 
      66              :     /**
      67              :      * Set a field within the bit mask integer.
      68              :      *
      69              :      * Fields are assumed to be contiguous bits within the underlying integer, for example:
      70              :      * A mask of 0x70 == 0b01110000 means that a 3 bit value is encoded at bits [4;6].
      71              :      *
      72              :      * Calling SetField(0x70, n) is equivalent to "(value & ~0x70) | (n << 4)"
      73              :      *
      74              :      * @param mask  The mask, code assumes a continous bit mask
      75              :      * @param value The value, NOT shifted, MUST fit within the number of bits of the mask
      76              :      */
      77              :     constexpr BitMask & SetField(FlagsEnum mask, IntegerType value)
      78              :     {
      79              :         IntegerType bitMask = static_cast<IntegerType>(mask);
      80              :         IntegerType shift   = GetShiftToFirstSetBit(bitMask);
      81              : 
      82              :         // NOTE: value should be fully contained within the shift mask.
      83              :         //
      84              :         // assert((value & (mask >> shift)) == value);
      85              : 
      86              :         // Clear bits overlayed by the mask
      87              :         IntegerType updated = static_cast<IntegerType>(BitFlags<FlagsEnum, StorageType>::Raw() & ~bitMask);
      88              : 
      89              :         // Set the right bits
      90              :         updated = static_cast<IntegerType>(updated | (bitMask & (value << shift)));
      91              : 
      92              :         BitFlags<FlagsEnum, StorageType>::SetRaw(updated);
      93              : 
      94              :         return *this;
      95              :     }
      96              : 
      97              :     /**
      98              :      * Gets an underlying field that is contained within a bit subset of the integer.
      99              :      * Examples:
     100              :      *    GetField(0x70) == GetField(0b01110000) == ((n & 0x70) >> 4) == ((n >> 4) 0x07)
     101              :      *    GetField(0xC0) == GetField(0b11000000) == ((n & 0xC0) >> 6) == ((n >> 6) 0x03)
     102              :      *
     103              :      * @param mask The bit mask to be used, assumed to be a contigous bit mask
     104              :      */
     105              :     IntegerType GetField(FlagsEnum mask) const
     106              :     {
     107              :         IntegerType bitMask = static_cast<IntegerType>(mask);
     108              :         IntegerType shift   = GetShiftToFirstSetBit(bitMask);
     109              : 
     110              :         // Forward the right bits
     111              :         return static_cast<IntegerType>(((BitFlags<FlagsEnum, StorageType>::Raw() & bitMask) >> shift));
     112              :     }
     113              : 
     114              : protected:
     115              :     /// Get the shift amount to reach the first non-zero bit in a bitmask
     116              :     ///
     117              :     /// Examples:
     118              :     ///    GetShiftToFirstSetBit(0b0000001) == 0
     119              :     ///    GetShiftToFirstSetBit(0b0011100) == 2
     120              :     ///    GetShiftToFirstSetBit(0b0110000) == 4
     121              :     ///
     122              :     /// Note: This does NOT validate if the given mask is a valid mask. So:
     123              :     ///    GetShiftToFirstSetBit(0b0100010) == 1
     124              :     ///    GetShiftToFirstSetBit(0b010110100) == 2
     125              :     static constexpr IntegerType GetShiftToFirstSetBit(IntegerType bitMask)
     126              :     {
     127              :         IntegerType count = 0;
     128              :         IntegerType mask  = 0x01;
     129              : 
     130              :         if (bitMask == 0)
     131              :         {
     132              :             return sizeof(bitMask); // generally invalid value
     133              :         }
     134              : 
     135              :         while ((mask & bitMask) == 0)
     136              :         {
     137              :             mask = static_cast<IntegerType>(mask << 1);
     138              :             count++;
     139              :         }
     140              :         return count;
     141              :     }
     142              : };
     143              : 
     144              : } // namespace chip
        

Generated by: LCOV version 2.0-1