LCOV - code coverage report
Current view: top level - lib/core - TLVReader.cpp (source / functions) Hit Total Coverage
Test: lcov_final.info Lines: 518 552 93.8 %
Date: 2024-02-15 08:20:41 Functions: 51 51 100.0 %

          Line data    Source code
       1             : /*
       2             :  *
       3             :  *    Copyright (c) 2020-2023 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             : #include <lib/core/TLVReader.h>
      19             : 
      20             : #include <stdint.h>
      21             : #include <string.h>
      22             : 
      23             : #include <lib/core/CHIPConfig.h>
      24             : #include <lib/core/CHIPEncoding.h>
      25             : #include <lib/core/CHIPError.h>
      26             : #include <lib/core/CHIPSafeCasts.h>
      27             : #include <lib/core/DataModelTypes.h>
      28             : #include <lib/core/Optional.h>
      29             : #include <lib/core/TLVBackingStore.h>
      30             : #include <lib/core/TLVCommon.h>
      31             : #include <lib/core/TLVTags.h>
      32             : #include <lib/core/TLVTypes.h>
      33             : #include <lib/support/BufferWriter.h>
      34             : #include <lib/support/BytesToHex.h>
      35             : #include <lib/support/CHIPMem.h>
      36             : #include <lib/support/CodeUtils.h>
      37             : #include <lib/support/SafeInt.h>
      38             : #include <lib/support/Span.h>
      39             : #include <lib/support/logging/TextOnlyLogging.h>
      40             : 
      41             : #if CHIP_CONFIG_TLV_VALIDATE_CHAR_STRING_ON_READ
      42             : #include <lib/support/utf8.h>
      43             : #endif
      44             : 
      45             : namespace chip {
      46             : namespace TLV {
      47             : 
      48             : using namespace chip::Encoding;
      49             : 
      50             : static const uint8_t sTagSizes[] = { 0, 1, 2, 4, 2, 4, 6, 8 };
      51             : 
      52     1461629 : void TLVReader::Init(const uint8_t * data, size_t dataLen)
      53             : {
      54             :     // TODO: Maybe we can just make mMaxLen and mLenRead size_t instead?
      55     1461629 :     uint32_t actualDataLen = dataLen > UINT32_MAX ? UINT32_MAX : static_cast<uint32_t>(dataLen);
      56     1461629 :     mBackingStore          = nullptr;
      57     1461629 :     mReadPoint             = data;
      58     1461629 :     mBufEnd                = data + actualDataLen;
      59     1461629 :     mLenRead               = 0;
      60     1461629 :     mMaxLen                = actualDataLen;
      61     1461629 :     ClearElementState();
      62     1461629 :     mContainerType = kTLVType_NotSpecified;
      63     1461629 :     SetContainerOpen(false);
      64             : 
      65     1461629 :     ImplicitProfileId = kProfileIdNotSpecified;
      66     1461629 : }
      67             : 
      68        4137 : CHIP_ERROR TLVReader::Init(TLVBackingStore & backingStore, uint32_t maxLen)
      69             : {
      70        4137 :     mBackingStore   = &backingStore;
      71        4137 :     mReadPoint      = nullptr;
      72        4137 :     uint32_t bufLen = 0;
      73        4137 :     CHIP_ERROR err  = mBackingStore->OnInit(*this, mReadPoint, bufLen);
      74        4137 :     if (err != CHIP_NO_ERROR)
      75           0 :         return err;
      76             : 
      77        4137 :     mBufEnd  = mReadPoint + bufLen;
      78        4137 :     mLenRead = 0;
      79        4137 :     mMaxLen  = maxLen;
      80        4137 :     ClearElementState();
      81        4137 :     mContainerType = kTLVType_NotSpecified;
      82        4137 :     SetContainerOpen(false);
      83             : 
      84        4137 :     ImplicitProfileId = kProfileIdNotSpecified;
      85        4137 :     AppData           = nullptr;
      86        4137 :     return CHIP_NO_ERROR;
      87             : }
      88             : 
      89      499742 : void TLVReader::Init(const TLVReader & aReader)
      90             : {
      91             :     // Initialize private data members
      92             : 
      93      499742 :     mElemTag       = aReader.mElemTag;
      94      499742 :     mElemLenOrVal  = aReader.mElemLenOrVal;
      95      499742 :     mBackingStore  = aReader.mBackingStore;
      96      499742 :     mReadPoint     = aReader.mReadPoint;
      97      499742 :     mBufEnd        = aReader.mBufEnd;
      98      499742 :     mLenRead       = aReader.mLenRead;
      99      499742 :     mMaxLen        = aReader.mMaxLen;
     100      499742 :     mControlByte   = aReader.mControlByte;
     101      499742 :     mContainerType = aReader.mContainerType;
     102      499742 :     SetContainerOpen(aReader.IsContainerOpen());
     103             : 
     104             :     // Initialize public data members
     105             : 
     106      499742 :     ImplicitProfileId = aReader.ImplicitProfileId;
     107      499742 :     AppData           = aReader.AppData;
     108      499742 : }
     109             : 
     110     7805406 : TLVType TLVReader::GetType() const
     111             : {
     112     7805406 :     TLVElementType elemType = ElementType();
     113     7805406 :     if (elemType == TLVElementType::EndOfContainer)
     114           4 :         return kTLVType_NotSpecified;
     115     7805402 :     if (elemType == TLVElementType::FloatingPointNumber32 || elemType == TLVElementType::FloatingPointNumber64)
     116       11442 :         return kTLVType_FloatingPointNumber;
     117     7793960 :     if (elemType == TLVElementType::NotSpecified || elemType >= TLVElementType::Null)
     118     3122694 :         return static_cast<TLVType>(elemType);
     119     4671266 :     return static_cast<TLVType>(static_cast<uint8_t>(elemType) & ~kTLVTypeSizeMask);
     120             : }
     121             : 
     122      100527 : uint32_t TLVReader::GetLength() const
     123             : {
     124      100527 :     if (TLVTypeHasLength(ElementType()))
     125       87389 :         return static_cast<uint32_t>(mElemLenOrVal);
     126       13138 :     return 0;
     127             : }
     128             : 
     129     2770769 : CHIP_ERROR TLVReader::Get(bool & v) const
     130             : {
     131     2770769 :     TLVElementType elemType = ElementType();
     132     2770769 :     if (elemType == TLVElementType::BooleanFalse)
     133     1381442 :         v = false;
     134     1389327 :     else if (elemType == TLVElementType::BooleanTrue)
     135     1389326 :         v = true;
     136             :     else
     137           1 :         return CHIP_ERROR_WRONG_TLV_TYPE;
     138     2770768 :     return CHIP_NO_ERROR;
     139             : }
     140             : 
     141     1357639 : CHIP_ERROR TLVReader::Get(int8_t & v) const
     142             : {
     143     1357639 :     int64_t v64    = 0;
     144     1357639 :     CHIP_ERROR err = Get(v64);
     145     1357639 :     if (!CanCastTo<int8_t>(v64))
     146             :     {
     147          45 :         return CHIP_ERROR_INVALID_INTEGER_VALUE;
     148             :     }
     149     1357594 :     v = static_cast<int8_t>(v64);
     150     1357594 :     return err;
     151             : }
     152             : 
     153     1353864 : CHIP_ERROR TLVReader::Get(int16_t & v) const
     154             : {
     155     1353864 :     int64_t v64    = 0;
     156     1353864 :     CHIP_ERROR err = Get(v64);
     157     1353864 :     if (!CanCastTo<int16_t>(v64))
     158             :     {
     159           4 :         return CHIP_ERROR_INVALID_INTEGER_VALUE;
     160             :     }
     161     1353860 :     v = static_cast<int16_t>(v64);
     162     1353860 :     return err;
     163             : }
     164             : 
     165     1354237 : CHIP_ERROR TLVReader::Get(int32_t & v) const
     166             : {
     167     1354237 :     int64_t v64    = 0;
     168     1354237 :     CHIP_ERROR err = Get(v64);
     169     1354237 :     if (!CanCastTo<int32_t>(v64))
     170             :     {
     171           2 :         return CHIP_ERROR_INVALID_INTEGER_VALUE;
     172             :     }
     173     1354235 :     v = static_cast<int32_t>(v64);
     174     1354235 :     return err;
     175             : }
     176             : 
     177     5420580 : CHIP_ERROR TLVReader::Get(int64_t & v) const
     178             : {
     179             :     // Internal callers of this method depend on it not modifying "v" on failure.
     180     5420580 :     switch (ElementType())
     181             :     {
     182     5419252 :     case TLVElementType::Int8:
     183     5419252 :         v = CastToSigned(static_cast<uint8_t>(mElemLenOrVal));
     184     5419252 :         break;
     185          88 :     case TLVElementType::Int16:
     186          88 :         v = CastToSigned(static_cast<uint16_t>(mElemLenOrVal));
     187          88 :         break;
     188         800 :     case TLVElementType::Int32:
     189         800 :         v = CastToSigned(static_cast<uint32_t>(mElemLenOrVal));
     190         800 :         break;
     191          39 :     case TLVElementType::Int64:
     192          39 :         v = CastToSigned(mElemLenOrVal);
     193          39 :         break;
     194         401 :     default:
     195         401 :         return CHIP_ERROR_WRONG_TLV_TYPE;
     196             :     }
     197             : 
     198     5420179 :     return CHIP_NO_ERROR;
     199             : }
     200             : 
     201     1393664 : CHIP_ERROR TLVReader::Get(uint8_t & v) const
     202             : {
     203     1393664 :     uint64_t v64   = 0;
     204     1393664 :     CHIP_ERROR err = Get(v64);
     205     1393664 :     if (!CanCastTo<uint8_t>(v64))
     206             :     {
     207           3 :         return CHIP_ERROR_INVALID_INTEGER_VALUE;
     208             :     }
     209     1393661 :     v = static_cast<uint8_t>(v64);
     210     1393661 :     return err;
     211             : }
     212             : 
     213       69611 : CHIP_ERROR TLVReader::Get(uint16_t & v) const
     214             : {
     215       69611 :     uint64_t v64   = 0;
     216       69611 :     CHIP_ERROR err = Get(v64);
     217       69611 :     if (!CanCastTo<uint16_t>(v64))
     218             :     {
     219           4 :         return CHIP_ERROR_INVALID_INTEGER_VALUE;
     220             :     }
     221       69607 :     v = static_cast<uint16_t>(v64);
     222       69607 :     return err;
     223             : }
     224             : 
     225       73053 : CHIP_ERROR TLVReader::Get(uint32_t & v) const
     226             : {
     227       73053 :     uint64_t v64   = 0;
     228       73053 :     CHIP_ERROR err = Get(v64);
     229       73053 :     if (!CanCastTo<uint32_t>(v64))
     230             :     {
     231           1 :         return CHIP_ERROR_INVALID_INTEGER_VALUE;
     232             :     }
     233       73052 :     v = static_cast<uint32_t>(v64);
     234       73052 :     return err;
     235             : }
     236             : 
     237     1587136 : CHIP_ERROR TLVReader::Get(uint64_t & v) const
     238             : {
     239             :     // Internal callers of this method depend on it not modifying "v" on failure.
     240     1587136 :     switch (ElementType())
     241             :     {
     242      232120 :     case TLVElementType::UInt8:
     243             :     case TLVElementType::UInt16:
     244             :     case TLVElementType::UInt32:
     245             :     case TLVElementType::UInt64:
     246      232120 :         v = mElemLenOrVal;
     247      232120 :         break;
     248     1355016 :     default:
     249     1355016 :         return CHIP_ERROR_WRONG_TLV_TYPE;
     250             :     }
     251      232120 :     return CHIP_NO_ERROR;
     252             : }
     253             : 
     254             : namespace {
     255        2446 : float BitCastToFloat(const uint64_t elemLenOrVal)
     256             : {
     257             :     float f;
     258        2446 :     auto unsigned32 = static_cast<uint32_t>(elemLenOrVal);
     259        2446 :     memcpy(&f, &unsigned32, sizeof(f));
     260        2446 :     return f;
     261             : }
     262             : } // namespace
     263             : 
     264             : // Note: Unlike the integer Get functions, this code avoids doing conversions
     265             : // between float and double wherever possible, because these conversions are
     266             : // relatively expensive on platforms that use soft-float instruction sets.
     267             : 
     268         485 : CHIP_ERROR TLVReader::Get(float & v) const
     269             : {
     270         485 :     switch (ElementType())
     271             :     {
     272         483 :     case TLVElementType::FloatingPointNumber32: {
     273         483 :         v = BitCastToFloat(mElemLenOrVal);
     274         483 :         break;
     275             :     }
     276           2 :     default:
     277           2 :         return CHIP_ERROR_WRONG_TLV_TYPE;
     278             :     }
     279         483 :     return CHIP_NO_ERROR;
     280             : }
     281             : 
     282        4031 : CHIP_ERROR TLVReader::Get(double & v) const
     283             : {
     284        4031 :     switch (ElementType())
     285             :     {
     286        1963 :     case TLVElementType::FloatingPointNumber32: {
     287        1963 :         v = BitCastToFloat(mElemLenOrVal);
     288        1963 :         break;
     289             :     }
     290        2067 :     case TLVElementType::FloatingPointNumber64: {
     291             :         double d;
     292        2067 :         memcpy(&d, &mElemLenOrVal, sizeof(d));
     293        2067 :         v = d;
     294        2067 :         break;
     295             :     }
     296           1 :     default:
     297           1 :         return CHIP_ERROR_WRONG_TLV_TYPE;
     298             :     }
     299        4030 :     return CHIP_NO_ERROR;
     300             : }
     301             : 
     302       10268 : CHIP_ERROR TLVReader::Get(ByteSpan & v) const
     303             : {
     304             :     const uint8_t * val;
     305       10268 :     ReturnErrorOnFailure(GetDataPtr(val));
     306       10264 :     v = ByteSpan(val, GetLength());
     307             : 
     308       10264 :     return CHIP_NO_ERROR;
     309             : }
     310             : 
     311             : namespace {
     312             : constexpr int kUnicodeInformationSeparator1       = 0x1F;
     313             : constexpr size_t kMaxLocalizedStringIdentifierLen = 2 * sizeof(LocalizedStringIdentifier);
     314             : } // namespace
     315             : 
     316         429 : CHIP_ERROR TLVReader::Get(CharSpan & v) const
     317             : {
     318         429 :     if (!TLVTypeIsUTF8String(ElementType()))
     319             :     {
     320           2 :         return CHIP_ERROR_WRONG_TLV_TYPE;
     321             :     }
     322             : 
     323             :     const uint8_t * bytes;
     324         427 :     ReturnErrorOnFailure(GetDataPtr(bytes)); // Does length sanity checks
     325         425 :     if (bytes == nullptr)
     326             :     {
     327             :         // Calling memchr further down with bytes == nullptr would have undefined behaviour, exiting early.
     328          98 :         return CHIP_NO_ERROR;
     329             :     }
     330             : 
     331         327 :     uint32_t len = GetLength();
     332             : 
     333             :     // If Unicode Information Separator 1 (0x1f) is present in the string then method returns
     334             :     // string ending at first appearance of the Information Separator 1.
     335         327 :     const uint8_t * infoSeparator = reinterpret_cast<const uint8_t *>(memchr(bytes, kUnicodeInformationSeparator1, len));
     336         327 :     if (infoSeparator != nullptr)
     337             :     {
     338           5 :         len = static_cast<uint32_t>(infoSeparator - bytes);
     339             :     }
     340             : 
     341         327 :     v = CharSpan(Uint8::to_const_char(bytes), len);
     342             : #if CHIP_CONFIG_TLV_VALIDATE_CHAR_STRING_ON_READ
     343             :     // Spec requirement: A.11.2. UTF-8 and Octet Strings
     344             :     //
     345             :     // For UTF-8 strings, the value octets SHALL encode a valid
     346             :     // UTF-8 character (code points) sequence.
     347             :     //
     348             :     // Senders SHALL NOT include a terminating null character to
     349             :     // mark the end of a string.
     350             : 
     351             :     if (!Utf8::IsValid(v))
     352             :     {
     353             :         return CHIP_ERROR_INVALID_UTF8;
     354             :     }
     355             : 
     356             :     if (!v.empty() && (v.back() == 0))
     357             :     {
     358             :         return CHIP_ERROR_INVALID_TLV_CHAR_STRING;
     359             :     }
     360             : #endif // CHIP_CONFIG_TLV_VALIDATE_CHAR_STRING_ON_READ
     361         327 :     return CHIP_NO_ERROR;
     362             : }
     363             : 
     364          15 : CHIP_ERROR TLVReader::Get(Optional<LocalizedStringIdentifier> & lsid)
     365             : {
     366          15 :     lsid.ClearValue();
     367          15 :     VerifyOrReturnError(TLVTypeIsUTF8String(ElementType()), CHIP_ERROR_WRONG_TLV_TYPE);
     368             : 
     369             :     const uint8_t * bytes;
     370          14 :     ReturnErrorOnFailure(GetDataPtr(bytes)); // Does length sanity checks
     371          14 :     if (bytes == nullptr)
     372             :     {
     373             :         // Calling memchr further down with bytes == nullptr would have undefined behaviour, exiting early.
     374           0 :         return CHIP_NO_ERROR;
     375             :     }
     376             : 
     377          14 :     uint32_t len = GetLength();
     378             : 
     379          14 :     const uint8_t * infoSeparator1 = static_cast<const uint8_t *>(memchr(bytes, kUnicodeInformationSeparator1, len));
     380          14 :     if (infoSeparator1 == nullptr)
     381             :     {
     382           1 :         return CHIP_NO_ERROR;
     383             :     }
     384             : 
     385          13 :     const uint8_t * lsidPtr = infoSeparator1 + 1;
     386          13 :     len -= static_cast<uint32_t>(lsidPtr - bytes);
     387             : 
     388          13 :     const uint8_t * infoSeparator2 = static_cast<const uint8_t *>(memchr(lsidPtr, kUnicodeInformationSeparator1, len));
     389          13 :     if (infoSeparator2 != nullptr)
     390             :     {
     391           3 :         len = static_cast<uint32_t>(infoSeparator2 - lsidPtr);
     392             :     }
     393          13 :     if (len == 0)
     394             :     {
     395           1 :         return CHIP_NO_ERROR;
     396             :     }
     397          12 :     VerifyOrReturnError(len <= kMaxLocalizedStringIdentifierLen, CHIP_ERROR_INVALID_TLV_ELEMENT);
     398             :     // Leading zeroes are not allowed.
     399          11 :     VerifyOrReturnError(static_cast<char>(lsidPtr[0]) != '0', CHIP_ERROR_INVALID_TLV_ELEMENT);
     400             : 
     401           9 :     char idStr[kMaxLocalizedStringIdentifierLen] = { '0', '0', '0', '0' };
     402           9 :     memcpy(&idStr[kMaxLocalizedStringIdentifierLen - len], lsidPtr, len);
     403             : 
     404             :     LocalizedStringIdentifier id;
     405           9 :     VerifyOrReturnError(Encoding::UppercaseHexToUint16(idStr, sizeof(idStr), id) == sizeof(LocalizedStringIdentifier),
     406             :                         CHIP_ERROR_INVALID_TLV_ELEMENT);
     407             : 
     408           8 :     lsid.SetValue(id);
     409           8 :     return CHIP_NO_ERROR;
     410             : }
     411             : 
     412        7861 : CHIP_ERROR TLVReader::GetBytes(uint8_t * buf, size_t bufSize)
     413             : {
     414        7861 :     if (!TLVTypeIsString(ElementType()))
     415           2 :         return CHIP_ERROR_WRONG_TLV_TYPE;
     416             : 
     417        7859 :     if (mElemLenOrVal > bufSize)
     418           0 :         return CHIP_ERROR_BUFFER_TOO_SMALL;
     419             : 
     420        7859 :     CHIP_ERROR err = ReadData(buf, static_cast<uint32_t>(mElemLenOrVal));
     421        7859 :     if (err != CHIP_NO_ERROR)
     422           0 :         return err;
     423             : 
     424        7859 :     mElemLenOrVal = 0;
     425             : 
     426        7859 :     return CHIP_NO_ERROR;
     427             : }
     428             : 
     429        3039 : CHIP_ERROR TLVReader::GetString(char * buf, size_t bufSize)
     430             : {
     431        3039 :     if (!TLVTypeIsString(ElementType()))
     432           1 :         return CHIP_ERROR_WRONG_TLV_TYPE;
     433             : 
     434        3038 :     if ((mElemLenOrVal + 1) > bufSize)
     435           1 :         return CHIP_ERROR_BUFFER_TOO_SMALL;
     436             : 
     437        3037 :     buf[mElemLenOrVal] = 0;
     438             : 
     439        3037 :     return GetBytes(reinterpret_cast<uint8_t *>(buf), bufSize - 1);
     440             : }
     441             : 
     442           1 : CHIP_ERROR TLVReader::DupBytes(uint8_t *& buf, uint32_t & dataLen)
     443             : {
     444           1 :     if (!TLVTypeIsString(ElementType()))
     445           0 :         return CHIP_ERROR_WRONG_TLV_TYPE;
     446             : 
     447           1 :     buf = static_cast<uint8_t *>(chip::Platform::MemoryAlloc(static_cast<uint32_t>(mElemLenOrVal)));
     448           1 :     if (buf == nullptr)
     449           0 :         return CHIP_ERROR_NO_MEMORY;
     450             : 
     451           1 :     CHIP_ERROR err = ReadData(buf, static_cast<uint32_t>(mElemLenOrVal));
     452           1 :     if (err != CHIP_NO_ERROR)
     453             :     {
     454           0 :         chip::Platform::MemoryFree(buf);
     455           0 :         buf = nullptr;
     456           0 :         return err;
     457             :     }
     458             : 
     459           1 :     dataLen       = static_cast<uint32_t>(mElemLenOrVal);
     460           1 :     mElemLenOrVal = 0;
     461             : 
     462           1 :     return CHIP_NO_ERROR;
     463             : }
     464             : 
     465           2 : CHIP_ERROR TLVReader::DupString(char *& buf)
     466             : {
     467           2 :     if (!TLVTypeIsString(ElementType()))
     468           1 :         return CHIP_ERROR_WRONG_TLV_TYPE;
     469             : 
     470           1 :     if (mElemLenOrVal > UINT32_MAX - 1)
     471           0 :         return CHIP_ERROR_NO_MEMORY;
     472             : 
     473           1 :     buf = static_cast<char *>(chip::Platform::MemoryAlloc(static_cast<uint32_t>(mElemLenOrVal + 1)));
     474           1 :     if (buf == nullptr)
     475           0 :         return CHIP_ERROR_NO_MEMORY;
     476             : 
     477           1 :     CHIP_ERROR err = ReadData(reinterpret_cast<uint8_t *>(buf), static_cast<uint32_t>(mElemLenOrVal));
     478           1 :     if (err != CHIP_NO_ERROR)
     479             :     {
     480           0 :         chip::Platform::MemoryFree(buf);
     481           0 :         buf = nullptr;
     482           0 :         return err;
     483             :     }
     484             : 
     485           1 :     buf[mElemLenOrVal] = 0;
     486           1 :     mElemLenOrVal      = 0;
     487             : 
     488           1 :     return err;
     489             : }
     490             : 
     491       20918 : CHIP_ERROR TLVReader::GetDataPtr(const uint8_t *& data) const
     492             : {
     493       20918 :     VerifyOrReturnError(TLVTypeIsString(ElementType()), CHIP_ERROR_WRONG_TLV_TYPE);
     494             : 
     495       20915 :     if (GetLength() == 0)
     496             :     {
     497        3794 :         data = nullptr;
     498        3794 :         return CHIP_NO_ERROR;
     499             :     }
     500             : 
     501       17121 :     uint32_t remainingLen = static_cast<decltype(mMaxLen)>(mBufEnd - mReadPoint);
     502             : 
     503             :     // Verify that the entirety of the data is available in the buffer.
     504             :     // Note that this may not be possible if the reader is reading from a chain of buffers.
     505       17121 :     VerifyOrReturnError(remainingLen >= static_cast<uint32_t>(mElemLenOrVal), CHIP_ERROR_TLV_UNDERRUN);
     506       17117 :     data = mReadPoint;
     507       17117 :     return CHIP_NO_ERROR;
     508             : }
     509             : 
     510        1639 : CHIP_ERROR TLVReader::OpenContainer(TLVReader & containerReader)
     511             : {
     512        1639 :     TLVElementType elemType = ElementType();
     513        1639 :     if (!TLVTypeIsContainer(elemType))
     514           1 :         return CHIP_ERROR_INCORRECT_STATE;
     515             : 
     516        1638 :     containerReader.mBackingStore = mBackingStore;
     517        1638 :     containerReader.mReadPoint    = mReadPoint;
     518        1638 :     containerReader.mBufEnd       = mBufEnd;
     519        1638 :     containerReader.mLenRead      = mLenRead;
     520        1638 :     containerReader.mMaxLen       = mMaxLen;
     521        1638 :     containerReader.ClearElementState();
     522        1638 :     containerReader.mContainerType = static_cast<TLVType>(elemType);
     523        1638 :     containerReader.SetContainerOpen(false);
     524        1638 :     containerReader.ImplicitProfileId = ImplicitProfileId;
     525        1638 :     containerReader.AppData           = AppData;
     526             : 
     527        1638 :     SetContainerOpen(true);
     528             : 
     529        1638 :     return CHIP_NO_ERROR;
     530             : }
     531             : 
     532        1566 : CHIP_ERROR TLVReader::CloseContainer(TLVReader & containerReader)
     533             : {
     534             :     CHIP_ERROR err;
     535             : 
     536        1566 :     if (!IsContainerOpen())
     537           1 :         return CHIP_ERROR_INCORRECT_STATE;
     538             : 
     539        1565 :     if (static_cast<TLVElementType>(containerReader.mContainerType) != ElementType())
     540           0 :         return CHIP_ERROR_INCORRECT_STATE;
     541             : 
     542        1565 :     err = containerReader.SkipToEndOfContainer();
     543        1565 :     if (err != CHIP_NO_ERROR)
     544           0 :         return err;
     545             : 
     546        1565 :     mBackingStore = containerReader.mBackingStore;
     547        1565 :     mReadPoint    = containerReader.mReadPoint;
     548        1565 :     mBufEnd       = containerReader.mBufEnd;
     549        1565 :     mLenRead      = containerReader.mLenRead;
     550        1565 :     mMaxLen       = containerReader.mMaxLen;
     551        1565 :     ClearElementState();
     552             : 
     553        1565 :     return CHIP_NO_ERROR;
     554             : }
     555             : 
     556     3098058 : CHIP_ERROR TLVReader::EnterContainer(TLVType & outerContainerType)
     557             : {
     558     3098058 :     TLVElementType elemType = ElementType();
     559     3098058 :     if (!TLVTypeIsContainer(elemType))
     560           1 :         return CHIP_ERROR_INCORRECT_STATE;
     561             : 
     562     3098057 :     outerContainerType = mContainerType;
     563     3098057 :     mContainerType     = static_cast<TLVType>(elemType);
     564             : 
     565     3098057 :     ClearElementState();
     566     3098057 :     SetContainerOpen(false);
     567             : 
     568     3098057 :     return CHIP_NO_ERROR;
     569             : }
     570             : 
     571      327958 : CHIP_ERROR TLVReader::ExitContainer(TLVType outerContainerType)
     572             : {
     573             :     CHIP_ERROR err;
     574             : 
     575      327958 :     err = SkipToEndOfContainer();
     576      327958 :     if (err != CHIP_NO_ERROR)
     577          26 :         return err;
     578             : 
     579      327932 :     mContainerType = outerContainerType;
     580      327932 :     ClearElementState();
     581             : 
     582      327932 :     return CHIP_NO_ERROR;
     583             : }
     584             : 
     585        5879 : CHIP_ERROR TLVReader::VerifyEndOfContainer()
     586             : {
     587        5879 :     CHIP_ERROR err = Next();
     588        5879 :     if (err == CHIP_END_OF_TLV)
     589        5878 :         return CHIP_NO_ERROR;
     590           1 :     if (err == CHIP_NO_ERROR)
     591           0 :         return CHIP_ERROR_UNEXPECTED_TLV_ELEMENT;
     592           1 :     return err;
     593             : }
     594             : 
     595     7912499 : CHIP_ERROR TLVReader::Next()
     596             : {
     597     7912499 :     ReturnErrorOnFailure(Skip());
     598     7909945 :     ReturnErrorOnFailure(ReadElement());
     599             : 
     600     7889489 :     TLVElementType elemType = ElementType();
     601             : 
     602     7889489 :     VerifyOrReturnError(elemType != TLVElementType::EndOfContainer, CHIP_END_OF_TLV);
     603             : 
     604             :     // Ensure that GetDataPtr calls can be called immediately after Next, so
     605             :     // that `Get(ByteSpan&)` does not need to advance buffers and just works
     606     7721066 :     if (TLVTypeIsString(elemType) && (GetLength() != 0))
     607             :     {
     608       28066 :         ReturnErrorOnFailure(EnsureData(CHIP_ERROR_TLV_UNDERRUN));
     609             :     }
     610             : 
     611     7721066 :     return CHIP_NO_ERROR;
     612             : }
     613             : 
     614       79340 : CHIP_ERROR TLVReader::Expect(Tag expectedTag)
     615             : {
     616       79340 :     VerifyOrReturnError(GetType() != kTLVType_NotSpecified, CHIP_ERROR_WRONG_TLV_TYPE);
     617       79336 :     VerifyOrReturnError(GetTag() == expectedTag, CHIP_ERROR_UNEXPECTED_TLV_ELEMENT);
     618       79298 :     return CHIP_NO_ERROR;
     619             : }
     620             : 
     621       78750 : CHIP_ERROR TLVReader::Next(Tag expectedTag)
     622             : {
     623       78750 :     ReturnErrorOnFailure(Next());
     624       76776 :     ReturnErrorOnFailure(Expect(expectedTag));
     625       76741 :     return CHIP_NO_ERROR;
     626             : }
     627             : 
     628     6982215 : CHIP_ERROR TLVReader::Expect(TLVType expectedType, Tag expectedTag)
     629             : {
     630     6982215 :     VerifyOrReturnError(GetType() == expectedType, CHIP_ERROR_WRONG_TLV_TYPE);
     631     6974000 :     VerifyOrReturnError(GetTag() == expectedTag, CHIP_ERROR_UNEXPECTED_TLV_ELEMENT);
     632     6917074 :     return CHIP_NO_ERROR;
     633             : }
     634             : 
     635     6978214 : CHIP_ERROR TLVReader::Next(TLVType expectedType, Tag expectedTag)
     636             : {
     637     6978214 :     ReturnErrorOnFailure(Next());
     638     6966899 :     ReturnErrorOnFailure(Expect(expectedType, expectedTag));
     639     6902729 :     return CHIP_NO_ERROR;
     640             : }
     641             : 
     642     7939175 : CHIP_ERROR TLVReader::Skip()
     643             : {
     644             :     CHIP_ERROR err;
     645     7939175 :     TLVElementType elemType = ElementType();
     646             : 
     647     7939175 :     if (elemType == TLVElementType::EndOfContainer)
     648        2552 :         return CHIP_END_OF_TLV;
     649             : 
     650     7936623 :     if (TLVTypeIsContainer(elemType))
     651             :     {
     652             :         TLVType outerContainerType;
     653      180148 :         err = EnterContainer(outerContainerType);
     654      180148 :         if (err != CHIP_NO_ERROR)
     655           4 :             return err;
     656      180148 :         err = ExitContainer(outerContainerType);
     657      180148 :         if (err != CHIP_NO_ERROR)
     658           4 :             return err;
     659             :     }
     660             : 
     661             :     else
     662             :     {
     663     7756475 :         err = SkipData();
     664     7756475 :         if (err != CHIP_NO_ERROR)
     665           0 :             return err;
     666             : 
     667     7756475 :         ClearElementState();
     668             :     }
     669             : 
     670     7936619 :     return CHIP_NO_ERROR;
     671             : }
     672             : 
     673             : /**
     674             :  * Clear the state of the TLVReader.
     675             :  * This method is used to position the reader before the first TLV,
     676             :  * between TLVs or after the last TLV.
     677             :  */
     678    12651433 : void TLVReader::ClearElementState()
     679             : {
     680    12651433 :     mElemTag      = AnonymousTag();
     681    12651433 :     mControlByte  = kTLVControlByte_NotSpecified;
     682    12651433 :     mElemLenOrVal = 0;
     683    12651433 : }
     684             : 
     685             : /**
     686             :  * Skip any data contained in the current TLV by reading over it without
     687             :  * a destination buffer.
     688             :  *
     689             :  * @retval #CHIP_NO_ERROR              If the reader was successfully positioned at the end of the
     690             :  *                                      data.
     691             :  * @retval other                        Other CHIP or platform error codes returned by the configured
     692             :  *                                      TLVBackingStore.
     693             :  */
     694    10343952 : CHIP_ERROR TLVReader::SkipData()
     695             : {
     696    10343952 :     CHIP_ERROR err          = CHIP_NO_ERROR;
     697    10343952 :     TLVElementType elemType = ElementType();
     698             : 
     699    10343952 :     if (TLVTypeHasLength(elemType))
     700             :     {
     701      212035 :         err = ReadData(nullptr, static_cast<uint32_t>(mElemLenOrVal));
     702      212035 :         if (err != CHIP_NO_ERROR)
     703           0 :             return err;
     704             :     }
     705             : 
     706    10343952 :     return err;
     707             : }
     708             : 
     709      329523 : CHIP_ERROR TLVReader::SkipToEndOfContainer()
     710             : {
     711             :     CHIP_ERROR err;
     712      329523 :     TLVType outerContainerType = mContainerType;
     713      329523 :     uint32_t nestLevel         = 0;
     714             : 
     715             :     // If the user calls Next() after having called OpenContainer() but before calling
     716             :     // CloseContainer() they're effectively doing a close container by skipping over
     717             :     // the container element.  So reset the 'container open' flag here to prevent them
     718             :     // from calling CloseContainer() with the now orphaned container reader.
     719      329523 :     SetContainerOpen(false);
     720             : 
     721             :     while (true)
     722             :     {
     723     2916974 :         TLVElementType elemType = ElementType();
     724             : 
     725     2916974 :         if (elemType == TLVElementType::EndOfContainer)
     726             :         {
     727      807715 :             if (nestLevel == 0)
     728      329497 :                 return CHIP_NO_ERROR;
     729             : 
     730      478218 :             nestLevel--;
     731      478218 :             mContainerType = (nestLevel == 0) ? outerContainerType : kTLVType_UnknownContainer;
     732             :         }
     733             : 
     734     2109259 :         else if (TLVTypeIsContainer(elemType))
     735             :         {
     736      478219 :             nestLevel++;
     737      478219 :             mContainerType = static_cast<TLVType>(elemType);
     738             :         }
     739             : 
     740     2587477 :         err = SkipData();
     741     2587477 :         if (err != CHIP_NO_ERROR)
     742           0 :             return err;
     743             : 
     744     2587477 :         err = ReadElement();
     745     2587477 :         if (err != CHIP_NO_ERROR)
     746          26 :             return err;
     747     2587451 :     }
     748             : }
     749             : 
     750    10497422 : CHIP_ERROR TLVReader::ReadElement()
     751             : {
     752             :     CHIP_ERROR err;
     753             :     uint8_t stagingBuf[17]; // 17 = 1 control byte + 8 tag bytes + 8 length/value bytes
     754             :     const uint8_t * p;
     755             :     TLVElementType elemType;
     756             : 
     757             :     // Make sure we have input data. Return CHIP_END_OF_TLV if no more data is available.
     758    10497422 :     err = EnsureData(CHIP_END_OF_TLV);
     759    10497422 :     if (err != CHIP_NO_ERROR)
     760        9592 :         return err;
     761             : 
     762    10487830 :     if (mReadPoint == nullptr)
     763             :     {
     764           0 :         return CHIP_ERROR_INVALID_TLV_ELEMENT;
     765             :     }
     766             :     // Get the element's control byte.
     767    10487830 :     mControlByte = *mReadPoint;
     768             : 
     769             :     // Extract the element type from the control byte. Fail if it's invalid.
     770    10487830 :     elemType = ElementType();
     771    10487830 :     if (!IsValidTLVType(elemType))
     772        4101 :         return CHIP_ERROR_INVALID_TLV_ELEMENT;
     773             : 
     774             :     // Extract the tag control from the control byte.
     775    10483729 :     TLVTagControl tagControl = static_cast<TLVTagControl>(mControlByte & kTLVTagControlMask);
     776             : 
     777             :     // Determine the number of bytes in the element's tag, if any.
     778    10483729 :     uint8_t tagBytes = sTagSizes[tagControl >> kTLVTagControlShift];
     779             : 
     780             :     // Extract the size of length/value field from the control byte.
     781    10483729 :     TLVFieldSize lenOrValFieldSize = GetTLVFieldSize(elemType);
     782             : 
     783             :     // Determine the number of bytes in the length/value field.
     784    10483729 :     uint8_t valOrLenBytes = TLVFieldSizeToBytes(lenOrValFieldSize);
     785             : 
     786             :     // Determine the number of bytes in the element's 'head'. This includes: the control byte, the tag bytes (if present), the
     787             :     // length bytes (if present), and for elements that don't have a length (e.g. integers), the value bytes.
     788    10483729 :     uint8_t elemHeadBytes = static_cast<uint8_t>(1 + tagBytes + valOrLenBytes);
     789             : 
     790             :     // If the head of the element overlaps the end of the input buffer, read the bytes into the staging buffer
     791             :     // and arrange to parse them from there. Otherwise read them directly from the input buffer.
     792    10483729 :     if (elemHeadBytes > (mBufEnd - mReadPoint))
     793             :     {
     794         137 :         err = ReadData(stagingBuf, elemHeadBytes);
     795         137 :         if (err != CHIP_NO_ERROR)
     796           0 :             return err;
     797         137 :         p = stagingBuf;
     798             :     }
     799             :     else
     800             :     {
     801    10483592 :         p = mReadPoint;
     802    10483592 :         mReadPoint += elemHeadBytes;
     803    10483592 :         mLenRead += elemHeadBytes;
     804             :     }
     805             : 
     806             :     // Skip over the control byte.
     807    10483729 :     p++;
     808             : 
     809             :     // Read the tag field, if present.
     810    10483729 :     mElemTag = ReadTag(tagControl, p);
     811             : 
     812             :     // Read the length/value field, if present.
     813    10483729 :     switch (lenOrValFieldSize)
     814             :     {
     815     7362303 :     case kTLVFieldSize_0Byte:
     816     7362303 :         mElemLenOrVal = 0;
     817     7362303 :         break;
     818     2579685 :     case kTLVFieldSize_1Byte:
     819     2579685 :         mElemLenOrVal = Read8(p);
     820     2579685 :         break;
     821      114717 :     case kTLVFieldSize_2Byte:
     822      114717 :         mElemLenOrVal = LittleEndian::Read16(p);
     823      114717 :         break;
     824      335675 :     case kTLVFieldSize_4Byte:
     825      335675 :         mElemLenOrVal = LittleEndian::Read32(p);
     826      335675 :         break;
     827       91349 :     case kTLVFieldSize_8Byte:
     828       91349 :         mElemLenOrVal = LittleEndian::Read64(p);
     829       91349 :         VerifyOrReturnError(!TLVTypeHasLength(elemType) || (mElemLenOrVal <= UINT32_MAX), CHIP_ERROR_NOT_IMPLEMENTED);
     830       90203 :         break;
     831             :     }
     832             : 
     833    10482583 :     return VerifyElement();
     834             : }
     835             : 
     836    10482583 : CHIP_ERROR TLVReader::VerifyElement()
     837             : {
     838    10482583 :     if (ElementType() == TLVElementType::EndOfContainer)
     839             :     {
     840      853167 :         if (mContainerType == kTLVType_NotSpecified)
     841         138 :             return CHIP_ERROR_INVALID_TLV_ELEMENT;
     842      853029 :         if (mElemTag != AnonymousTag())
     843         418 :             return CHIP_ERROR_INVALID_TLV_TAG;
     844             :     }
     845             :     else
     846             :     {
     847     9629416 :         if (mElemTag == UnknownImplicitTag())
     848           0 :             return CHIP_ERROR_UNKNOWN_IMPLICIT_TLV_TAG;
     849     9629416 :         switch (mContainerType)
     850             :         {
     851     1465531 :         case kTLVType_NotSpecified:
     852     1465531 :             if (IsContextTag(mElemTag))
     853         324 :                 return CHIP_ERROR_INVALID_TLV_TAG;
     854     1465207 :             break;
     855     5556735 :         case kTLVType_Structure:
     856     5556735 :             if (mElemTag == AnonymousTag())
     857        1016 :                 return CHIP_ERROR_INVALID_TLV_TAG;
     858     5555719 :             break;
     859     1632853 :         case kTLVType_Array:
     860     1632853 :             if (mElemTag != AnonymousTag())
     861        2249 :                 return CHIP_ERROR_INVALID_TLV_TAG;
     862     1630604 :             break;
     863      974297 :         case kTLVType_UnknownContainer:
     864             :         case kTLVType_List:
     865      974297 :             break;
     866           0 :         default:
     867           0 :             return CHIP_ERROR_INCORRECT_STATE;
     868             :         }
     869             :     }
     870             : 
     871             :     // If the current element encodes a specific length (e.g. a UTF8 string or a byte string), verify
     872             :     // that the purported length fits within the remaining bytes of the encoding (as delineated by mMaxLen).
     873             :     //
     874             :     // Note that this check is not strictly necessary to prevent runtime errors, as any attempt to access
     875             :     // the data of an element with an invalid length will result in an error.  However checking the length
     876             :     // here catches the error earlier, and ensures that the application will never see the erroneous length
     877             :     // value.
     878             :     //
     879    10478438 :     if (TLVTypeHasLength(ElementType()))
     880             :     {
     881      216870 :         uint32_t overallLenRemaining = mMaxLen - mLenRead;
     882      216870 :         if (overallLenRemaining < static_cast<uint32_t>(mElemLenOrVal))
     883        1498 :             return CHIP_ERROR_TLV_UNDERRUN;
     884             :     }
     885             : 
     886    10476940 :     return CHIP_NO_ERROR;
     887             : }
     888             : 
     889    10483729 : Tag TLVReader::ReadTag(TLVTagControl tagControl, const uint8_t *& p) const
     890             : {
     891             :     uint16_t vendorId;
     892             :     uint16_t profileNum;
     893             : 
     894    10483729 :     switch (tagControl)
     895             :     {
     896     3732195 :     case TLVTagControl::ContextSpecific:
     897     3732195 :         return ContextTag(Read8(p));
     898        1853 :     case TLVTagControl::CommonProfile_2Bytes:
     899        1853 :         return CommonTag(LittleEndian::Read16(p));
     900        2246 :     case TLVTagControl::CommonProfile_4Bytes:
     901        2246 :         return CommonTag(LittleEndian::Read32(p));
     902     1378278 :     case TLVTagControl::ImplicitProfile_2Bytes:
     903     1378278 :         if (ImplicitProfileId == kProfileIdNotSpecified)
     904           0 :             return UnknownImplicitTag();
     905     1378278 :         return ProfileTag(ImplicitProfileId, LittleEndian::Read16(p));
     906        3050 :     case TLVTagControl::ImplicitProfile_4Bytes:
     907        3050 :         if (ImplicitProfileId == kProfileIdNotSpecified)
     908           0 :             return UnknownImplicitTag();
     909        3050 :         return ProfileTag(ImplicitProfileId, LittleEndian::Read32(p));
     910     2833812 :     case TLVTagControl::FullyQualified_6Bytes:
     911     2833812 :         vendorId   = LittleEndian::Read16(p);
     912     2833812 :         profileNum = LittleEndian::Read16(p);
     913     2833812 :         return ProfileTag(vendorId, profileNum, LittleEndian::Read16(p));
     914        1898 :     case TLVTagControl::FullyQualified_8Bytes:
     915        1898 :         vendorId   = LittleEndian::Read16(p);
     916        1898 :         profileNum = LittleEndian::Read16(p);
     917        1898 :         return ProfileTag(vendorId, profileNum, LittleEndian::Read32(p));
     918     2530397 :     case TLVTagControl::Anonymous:
     919             :     default:
     920     2530397 :         return AnonymousTag();
     921             :     }
     922             : }
     923             : 
     924      241188 : CHIP_ERROR TLVReader::ReadData(uint8_t * buf, uint32_t len)
     925             : {
     926             :     CHIP_ERROR err;
     927             : 
     928      305833 :     while (len > 0)
     929             :     {
     930       64645 :         err = EnsureData(CHIP_ERROR_TLV_UNDERRUN);
     931       64645 :         if (err != CHIP_NO_ERROR)
     932           0 :             return err;
     933             : 
     934       64645 :         uint32_t remainingLen = static_cast<decltype(mMaxLen)>(mBufEnd - mReadPoint);
     935             : 
     936       64645 :         uint32_t readLen = len;
     937       64645 :         if (readLen > remainingLen)
     938         156 :             readLen = remainingLen;
     939             : 
     940       64645 :         if (buf != nullptr)
     941             :         {
     942       24956 :             memcpy(buf, mReadPoint, readLen);
     943       24956 :             buf += readLen;
     944             :         }
     945       64645 :         mReadPoint += readLen;
     946       64645 :         mLenRead += readLen;
     947       64645 :         len -= readLen;
     948             :     }
     949             : 
     950      241188 :     return CHIP_NO_ERROR;
     951             : }
     952             : 
     953    10590133 : CHIP_ERROR TLVReader::EnsureData(CHIP_ERROR noDataErr)
     954             : {
     955             :     CHIP_ERROR err;
     956             : 
     957    10590133 :     if (mReadPoint == mBufEnd)
     958             :     {
     959        9878 :         if (mLenRead == mMaxLen)
     960        9592 :             return noDataErr;
     961             : 
     962         286 :         if (mBackingStore == nullptr)
     963           0 :             return noDataErr;
     964             : 
     965             :         uint32_t bufLen;
     966         286 :         err = mBackingStore->GetNextBuffer(*this, mReadPoint, bufLen);
     967         286 :         if (err != CHIP_NO_ERROR)
     968           0 :             return err;
     969         286 :         if (bufLen == 0)
     970           0 :             return noDataErr;
     971             : 
     972             :         // Cap mBufEnd so that we don't read beyond the user's specified maximum length, even
     973             :         // if the underlying buffer is larger.
     974         286 :         uint32_t overallLenRemaining = mMaxLen - mLenRead;
     975         286 :         if (overallLenRemaining < bufLen)
     976           0 :             bufLen = overallLenRemaining;
     977             : 
     978         286 :         mBufEnd = mReadPoint + bufLen;
     979             :     }
     980             : 
     981    10580541 :     return CHIP_NO_ERROR;
     982             : }
     983             : 
     984             : /**
     985             :  * This is a private method used to compute the length of a TLV element head.
     986             :  */
     987           2 : CHIP_ERROR TLVReader::GetElementHeadLength(uint8_t & elemHeadBytes) const
     988             : {
     989             :     uint8_t tagBytes;
     990             :     uint8_t valOrLenBytes;
     991             :     TLVTagControl tagControl;
     992             :     TLVFieldSize lenOrValFieldSize;
     993           2 :     TLVElementType elemType = ElementType();
     994             : 
     995             :     // Verify element is of valid TLVType.
     996           2 :     VerifyOrReturnError(IsValidTLVType(elemType), CHIP_ERROR_INVALID_TLV_ELEMENT);
     997             : 
     998             :     // Extract the tag control from the control byte.
     999           2 :     tagControl = static_cast<TLVTagControl>(mControlByte & kTLVTagControlMask);
    1000             : 
    1001             :     // Determine the number of bytes in the element's tag, if any.
    1002           2 :     tagBytes = sTagSizes[tagControl >> kTLVTagControlShift];
    1003             : 
    1004             :     // Extract the size of length/value field from the control byte.
    1005           2 :     lenOrValFieldSize = GetTLVFieldSize(elemType);
    1006             : 
    1007             :     // Determine the number of bytes in the length/value field.
    1008           2 :     valOrLenBytes = TLVFieldSizeToBytes(lenOrValFieldSize);
    1009             : 
    1010             :     // Determine the number of bytes in the element's 'head'. This includes: the
    1011             :     // control byte, the tag bytes (if present), the length bytes (if present),
    1012             :     // and for elements that don't have a length (e.g. integers), the value
    1013             :     // bytes.
    1014           2 :     VerifyOrReturnError(CanCastTo<uint8_t>(1 + tagBytes + valOrLenBytes), CHIP_ERROR_INTERNAL);
    1015           2 :     elemHeadBytes = static_cast<uint8_t>(1 + tagBytes + valOrLenBytes);
    1016             : 
    1017           2 :     return CHIP_NO_ERROR;
    1018             : }
    1019             : 
    1020             : /**
    1021             :  * This is a private method that returns the TLVElementType from mControlByte
    1022             :  */
    1023    81385675 : TLVElementType TLVReader::ElementType() const
    1024             : {
    1025    81385675 :     if (mControlByte == static_cast<uint16_t>(kTLVControlByte_NotSpecified))
    1026     9556020 :         return TLVElementType::NotSpecified;
    1027    71829655 :     return static_cast<TLVElementType>(mControlByte & kTLVTypeMask);
    1028             : }
    1029             : 
    1030      133345 : CHIP_ERROR TLVReader::FindElementWithTag(Tag tag, TLVReader & destReader) const
    1031             : {
    1032      133345 :     CHIP_ERROR err = CHIP_NO_ERROR;
    1033             : 
    1034             :     chip::TLV::TLVReader reader;
    1035      133345 :     reader.Init(*this);
    1036             : 
    1037      323720 :     while (CHIP_NO_ERROR == (err = reader.Next()))
    1038             :     {
    1039      298398 :         VerifyOrExit(chip::TLV::kTLVType_NotSpecified != reader.GetType(), err = CHIP_ERROR_INVALID_TLV_ELEMENT);
    1040             : 
    1041      298398 :         if (tag == reader.GetTag())
    1042             :         {
    1043      108023 :             destReader.Init(reader);
    1044      108023 :             break;
    1045             :         }
    1046             :     }
    1047             : 
    1048       25322 : exit:
    1049      133345 :     ChipLogIfFalse((CHIP_NO_ERROR == err) || (CHIP_END_OF_TLV == err));
    1050             : 
    1051      133345 :     return err;
    1052             : }
    1053             : 
    1054        1352 : CHIP_ERROR TLVReader::CountRemainingInContainer(size_t * size) const
    1055             : {
    1056        1352 :     if (mContainerType == kTLVType_NotSpecified)
    1057             :     {
    1058           0 :         return CHIP_ERROR_INCORRECT_STATE;
    1059             :     }
    1060             : 
    1061        1352 :     TLVReader tempReader(*this);
    1062        1352 :     size_t count = 0;
    1063             :     CHIP_ERROR err;
    1064        4102 :     while ((err = tempReader.Next()) == CHIP_NO_ERROR)
    1065             :     {
    1066        2750 :         ++count;
    1067             :     };
    1068        1352 :     if (err == CHIP_END_OF_TLV)
    1069             :     {
    1070        1352 :         *size = count;
    1071        1352 :         return CHIP_NO_ERROR;
    1072             :     }
    1073           0 :     return err;
    1074             : }
    1075             : 
    1076          10 : CHIP_ERROR ContiguousBufferTLVReader::OpenContainer(ContiguousBufferTLVReader & containerReader)
    1077             : {
    1078             :     // We are going to initialize containerReader by calling our superclass
    1079             :     // OpenContainer method.  The superclass only knows how to initialize
    1080             :     // members the superclass knows about, so we assert that we don't have any
    1081             :     // extra members that need initializing.  If such members ever get added,
    1082             :     // they would need to be initialized in this method.
    1083             :     static_assert(sizeof(ContiguousBufferTLVReader) == sizeof(TLVReader), "We have state the superclass is not initializing?");
    1084          10 :     return TLVReader::OpenContainer(containerReader);
    1085             : }
    1086             : 
    1087          11 : CHIP_ERROR ContiguousBufferTLVReader::GetStringView(Span<const char> & data)
    1088             : {
    1089          11 :     return Get(data);
    1090             : }
    1091             : 
    1092         301 : CHIP_ERROR ContiguousBufferTLVReader::GetByteView(ByteSpan & data)
    1093             : {
    1094         301 :     if (!TLVTypeIsByteString(ElementType()))
    1095             :     {
    1096           2 :         return CHIP_ERROR_WRONG_TLV_TYPE;
    1097             :     }
    1098             : 
    1099         299 :     return Get(data);
    1100             : }
    1101             : 
    1102             : } // namespace TLV
    1103             : } // namespace chip

Generated by: LCOV version 1.14