Matter SDK Coverage Report
Current view: top level - lib/core - TLVTags.h (source / functions) Coverage Total Hit
Test: SHA:b879ecb8e99e175eea0a293a888bda853da2b19c Lines: 100.0 % 35 35
Test Date: 2025-01-17 19:00:11 Functions: 100.0 % 47 47

            Line data    Source code
       1              : /*
       2              :  *
       3              :  *    Copyright (c) 2020 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              : #pragma once
      19              : 
      20              : #include <lib/support/StringBuilder.h>
      21              : #include <lib/support/TypeTraits.h>
      22              : 
      23              : #include <cstdint>
      24              : #include <type_traits>
      25              : 
      26              : namespace chip {
      27              : namespace TLV {
      28              : 
      29              : class Tag
      30              : {
      31              : public:
      32              :     enum SpecialTagNumber : uint32_t
      33              :     {
      34              :         kContextTagMaxNum = UINT8_MAX,
      35              :         kAnonymousTagNum,
      36              :         kUnknownImplicitTagNum
      37              :     };
      38              : 
      39              :     Tag() = default;
      40              : 
      41      5288519 :     constexpr bool operator==(const Tag & other) const { return mVal == other.mVal; }
      42      1300599 :     constexpr bool operator!=(const Tag & other) const { return mVal != other.mVal; }
      43              : 
      44              :     /// Appends the text representation of the tag to the given string builder base.
      45              :     StringBuilderBase & AppendTo(StringBuilderBase & out);
      46              : 
      47              : private:
      48     10378318 :     explicit constexpr Tag(uint64_t val) : mVal(val) {}
      49              : 
      50              :     friend constexpr Tag ProfileTag(uint32_t profileId, uint32_t tagNum);
      51              :     friend constexpr Tag ProfileTag(uint16_t vendorId, uint16_t profileNum, uint32_t tagNum);
      52              :     friend constexpr Tag ContextTag(uint8_t tagNum);
      53              :     friend constexpr Tag CommonTag(uint32_t tagNum);
      54              :     friend constexpr Tag AnonymousTag();
      55              :     friend constexpr Tag UnknownImplicitTag();
      56              : 
      57              :     // The following friend functions could be Tag class methods, but it turns out in some cases
      58              :     // they may not be inlined and then passing the tag by argument/value results in smaller code
      59              :     // than passing it by 'this' pointer. This can be worked around by applying 'always_inline'
      60              :     // function attribute, but friend functions are likely a more portable solution.
      61              : 
      62              :     friend constexpr uint32_t ProfileIdFromTag(Tag tag);
      63              :     friend constexpr uint16_t VendorIdFromTag(Tag tag);
      64              :     friend constexpr uint16_t ProfileNumFromTag(Tag tag);
      65              :     friend constexpr uint32_t TagNumFromTag(Tag tag);
      66              : 
      67              :     friend constexpr bool IsProfileTag(Tag tag);
      68              :     friend constexpr bool IsContextTag(Tag tag);
      69              :     friend constexpr bool IsSpecialTag(Tag tag);
      70              : 
      71              :     static constexpr uint32_t kProfileIdShift      = 32;
      72              :     static constexpr uint32_t kVendorIdShift       = 48;
      73              :     static constexpr uint32_t kProfileNumShift     = 32;
      74              :     static constexpr uint32_t kSpecialTagProfileId = 0xFFFFFFFF;
      75              : 
      76              :     // The storage of the tag value uses the following encoding:
      77              :     //
      78              :     //  63                              47                              31
      79              :     // +-------------------------------+-------------------------------+----------------------------------------------+
      80              :     // | Vendor id (bitwise-negated)   | Profile num (bitwise-negated) | Tag number                                   |
      81              :     // +-------------------------------+-------------------------------+----------------------------------------------+
      82              :     //
      83              :     // Vendor id and profile number are bitwise-negated in order to optimize the code size when
      84              :     // using context tags, the most commonly used tags in the SDK.
      85              :     uint64_t mVal;
      86              : };
      87              : 
      88              : enum TLVCommonProfiles
      89              : {
      90              :     /**
      91              :      * Used to indicate the absence of a profile id in a variable or member.
      92              :      * This is essentially the same as kCHIPProfile_NotSpecified defined in CHIPProfiles.h
      93              :      */
      94              :     kProfileIdNotSpecified = 0xFFFFFFFF,
      95              : 
      96              :     // TODO: Replace with chip::Profiles::kCHIPProfile_Common
      97              :     kCommonProfileId = 0
      98              : };
      99              : 
     100              : // TODO: Move to private namespace
     101              : enum class TLVTagControl : uint8_t
     102              : {
     103              :     // IMPORTANT: All values here must have no bits in common with specified
     104              :     // values of TLVElementType.
     105              :     Anonymous              = 0x00,
     106              :     ContextSpecific        = 0x20,
     107              :     CommonProfile_2Bytes   = 0x40,
     108              :     CommonProfile_4Bytes   = 0x60,
     109              :     ImplicitProfile_2Bytes = 0x80,
     110              :     ImplicitProfile_4Bytes = 0xA0,
     111              :     FullyQualified_6Bytes  = 0xC0,
     112              :     FullyQualified_8Bytes  = 0xE0
     113              : };
     114              : 
     115              : template <typename T>
     116      8815524 : inline uint8_t operator>>(TLVTagControl lhs, const T & rhs)
     117              : {
     118      8815524 :     return static_cast<uint8_t>(static_cast<uint8_t>(lhs) >> rhs);
     119              : }
     120              : 
     121              : // TODO: Move to private namespace
     122              : enum
     123              : {
     124              :     kTLVTagControlMask  = 0xE0,
     125              :     kTLVTagControlShift = 5
     126              : };
     127              : 
     128              : /**
     129              :  * Generates the API representation of a profile-specific TLV tag from a profile id and tag number
     130              :  *
     131              :  * @param[in]   profileId       The id of the profile within which the tag is defined.
     132              :  * @param[in]   tagNum          The profile-specific tag number assigned to the tag.
     133              :  * @return                      A 64-bit integer representing the tag.
     134              :  */
     135     10378318 : constexpr Tag ProfileTag(uint32_t profileId, uint32_t tagNum)
     136              : {
     137     10378318 :     return Tag((static_cast<uint64_t>(~profileId) << Tag::kProfileIdShift) | tagNum);
     138              : }
     139              : 
     140              : /**
     141              :  * Generates the API representation of a profile-specific TLV tag from a vendor id, profile number and tag number
     142              :  *
     143              :  * @param[in]   vendorId        The id of the vendor that defined the tag.
     144              :  * @param[in]   profileNum      The vendor assigned number for the profile within which the tag is defined.
     145              :  * @param[in]   tagNum          The profile-specific tag number assigned to the tag.
     146              :  * @return                      A 64-bit integer representing the tag.
     147              :  */
     148      1939944 : constexpr Tag ProfileTag(uint16_t vendorId, uint16_t profileNum, uint32_t tagNum)
     149              : {
     150      1939944 :     constexpr uint32_t kVendorIdShift = Tag::kVendorIdShift - Tag::kProfileIdShift;
     151              : 
     152      1939944 :     return ProfileTag((static_cast<uint32_t>(vendorId) << kVendorIdShift) | profileNum, tagNum);
     153              : }
     154              : 
     155              : /**
     156              :  * Generates the API representation of a context-specific TLV tag
     157              :  *
     158              :  * @param[in]   tagNum          The context-specific tag number assigned to the tag.
     159              :  * @return                      A 64-bit integer representing the tag.
     160              :  */
     161      2707725 : constexpr Tag ContextTag(uint8_t tagNum)
     162              : {
     163      2707725 :     return ProfileTag(Tag::kSpecialTagProfileId, tagNum);
     164              : }
     165              : 
     166              : /**
     167              :  * Also allow using enum class values as context tags.  There are four possible
     168              :  * cases when is_enum is true:
     169              :  *
     170              :  * 1) The enum is a scoped enum (enum class) and the underlying type is
     171              :  *    uint8_t.  Then the is_convertible test will test false, this overload will be
     172              :  *    used, to_underlying will return a uint8_t, and everything will work.
     173              :  * 2) The enum is a scoped enum (enum class) and the underlying type is
     174              :  *    not uint8_t.  Then the is_convertible test will test false, this overload will be
     175              :  *    used, to_underlying will return the other type, and -Wconversion will
     176              :  *    catch the type mismatch, if it's enabled.
     177              :  * 3) The enum is an old-style enum.  Then the is_convertible test will test
     178              :  *    true, this overload will be not be used, and the uint8_t overload will be
     179              :  *    used instead.  The compiler should then catch (at least with sufficient
     180              :  *    warnings turned on) if the constant being passed in is too big to fit into
     181              :  *    uint8_t.
     182              :  *
     183              :  * Leaving out the is_convertible test, so this overload gets used for old-style
     184              :  * enums, would cause old-style enums where the underlying type is wider than
     185              :  * uint8_t to fail compilation with -Wconversion even if the values are all
     186              :  * inside the uint8_t range, since to_underlying would explicitly return a type
     187              :  * that is wider than uint8_t.
     188              :  */
     189              : template <typename T, std::enable_if_t<std::is_enum<T>::value && !std::is_convertible<T, uint8_t>::value, int> = 0>
     190       169064 : constexpr Tag ContextTag(T tagNum)
     191              : {
     192       169064 :     return ContextTag(to_underlying(tagNum));
     193              : }
     194              : 
     195              : /**
     196              :  * Generates the API representation of a common profile TLV tag
     197              :  *
     198              :  * @param[in]   tagNum          The common profile tag number assigned to the tag.
     199              :  * @return                      A 64-bit integer representing the tag.
     200              :  */
     201          127 : constexpr Tag CommonTag(uint32_t tagNum)
     202              : {
     203          127 :     return ProfileTag(kCommonProfileId, tagNum);
     204              : }
     205              : 
     206              : /**
     207              :  * A value signifying a TLV element that has no tag (i.e. an anonymous element).
     208              :  */
     209      5051460 : constexpr Tag AnonymousTag()
     210              : {
     211      5051460 :     return ProfileTag(Tag::kSpecialTagProfileId, Tag::kAnonymousTagNum);
     212              : }
     213              : 
     214              : /**
     215              :  * An invalid tag that represents a TLV element decoding error due to unknown implicit profile id.
     216              :  */
     217      7820458 : constexpr Tag UnknownImplicitTag()
     218              : {
     219      7820458 :     return ProfileTag(Tag::kSpecialTagProfileId, Tag::kUnknownImplicitTagNum);
     220              : }
     221              : 
     222              : /**
     223              :  * Returns the profile id from a TLV tag
     224              :  *
     225              :  * @note The behavior of this function is undefined if the supplied tag is not a profile-specific tag.
     226              :  *
     227              :  * @param[in]   tag             The API representation of a profile-specific TLV tag.
     228              :  * @return                      The profile id.
     229              :  */
     230      1712645 : constexpr uint32_t ProfileIdFromTag(Tag tag)
     231              : {
     232      1712645 :     return ~static_cast<uint32_t>(tag.mVal >> Tag::kProfileIdShift);
     233              : }
     234              : 
     235              : /**
     236              :  * Returns the vendor id from a TLV tag
     237              :  *
     238              :  * @note The behavior of this function is undefined if the supplied tag is not a profile-specific tag.
     239              :  *
     240              :  * @param[in]   tag             The API representation of a profile-specific TLV tag.
     241              :  * @return                      The associated vendor id.
     242              :  */
     243           36 : constexpr uint16_t VendorIdFromTag(Tag tag)
     244              : {
     245           36 :     constexpr uint32_t kVendorIdShift = Tag::kVendorIdShift - Tag::kProfileIdShift;
     246              : 
     247           36 :     return static_cast<uint16_t>(ProfileIdFromTag(tag) >> kVendorIdShift);
     248              : }
     249              : 
     250              : /**
     251              :  * Returns the profile number from a TLV tag
     252              :  *
     253              :  * @note The behavior of this function is undefined if the supplied tag is not a profile-specific tag.
     254              :  *
     255              :  * @param[in]   tag             The API representation of a profile-specific TLV tag.
     256              :  * @return                      The associated profile number.
     257              :  */
     258           16 : constexpr uint16_t ProfileNumFromTag(Tag tag)
     259              : {
     260           16 :     return static_cast<uint16_t>(ProfileIdFromTag(tag));
     261              : }
     262              : 
     263              : /**
     264              :  * Returns the tag number from a TLV tag
     265              :  *
     266              :  * @note The behavior of this function is undefined if the supplied tag is not a profile-specific
     267              :  * or context-specific tag.
     268              :  *
     269              :  * @sa IsProfileTag() and IsContextTag()
     270              :  *
     271              :  * @param[in]   tag             The API representation of a profile-specific or context-specific TLV tag.
     272              :  * @return                      The associated tag number.
     273              :  */
     274      1023355 : constexpr uint32_t TagNumFromTag(Tag tag)
     275              : {
     276      1023355 :     return static_cast<uint32_t>(tag.mVal);
     277              : }
     278              : 
     279              : /**
     280              :  * Returns true of the supplied tag is a profile-specific tag.
     281              :  */
     282         8236 : constexpr bool IsProfileTag(Tag tag)
     283              : {
     284         8236 :     return ProfileIdFromTag(tag) != Tag::kSpecialTagProfileId;
     285              : }
     286              : 
     287              : /**
     288              :  * Returns true if the supplied tag is a context-specific tag.
     289              :  */
     290      1332982 : constexpr bool IsContextTag(Tag tag)
     291              : {
     292      1332982 :     return ProfileIdFromTag(tag) == Tag::kSpecialTagProfileId && TagNumFromTag(tag) <= Tag::kContextTagMaxNum;
     293              : }
     294              : 
     295              : // TODO: move to private namespace
     296       367527 : constexpr bool IsSpecialTag(Tag tag)
     297              : {
     298       367527 :     return ProfileIdFromTag(tag) == Tag::kSpecialTagProfileId;
     299              : }
     300              : 
     301              : } // namespace TLV
     302              : } // namespace chip
        

Generated by: LCOV version 2.0-1