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

            Line data    Source code
       1              : /*
       2              :  *
       3              :  *    Copyright (c) 2020-2021 Project CHIP Authors
       4              :  *    Copyright (c) 2015-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/TLVUpdater.h>
      19              : 
      20              : #include <stdint.h>
      21              : #include <string.h>
      22              : 
      23              : #include <lib/core/CHIPConfig.h>
      24              : #include <lib/core/CHIPError.h>
      25              : #include <lib/core/TLVCommon.h>
      26              : #include <lib/core/TLVReader.h>
      27              : #include <lib/core/TLVTags.h>
      28              : #include <lib/core/TLVTypes.h>
      29              : #include <lib/core/TLVWriter.h>
      30              : #include <lib/support/BufferWriter.h>
      31              : #include <lib/support/CodeUtils.h>
      32              : #include <lib/support/logging/Constants.h>
      33              : #include <lib/support/logging/TextOnlyLogging.h>
      34              : 
      35              : namespace chip {
      36              : namespace TLV {
      37              : 
      38              : using namespace chip::Encoding;
      39              : 
      40            4 : CHIP_ERROR TLVUpdater::Init(uint8_t * buf, uint32_t dataLen, uint32_t maxLen)
      41              : {
      42              :     uint32_t freeLen;
      43              : 
      44            4 :     VerifyOrReturnError(buf != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
      45              : 
      46            4 :     VerifyOrReturnError(maxLen >= dataLen, CHIP_ERROR_BUFFER_TOO_SMALL);
      47              : 
      48              :     // memmove the buffer data to end of the buffer
      49            4 :     freeLen = maxLen - dataLen;
      50            4 :     memmove(buf + freeLen, buf, dataLen);
      51              : 
      52              :     // Init reader
      53            4 :     mUpdaterReader.Init(buf + freeLen, dataLen);
      54              : 
      55              :     // Init writer
      56            4 :     mUpdaterWriter.Init(buf, freeLen);
      57            4 :     mUpdaterWriter.SetCloseContainerReserved(false);
      58            4 :     mElementStartAddr = buf + freeLen;
      59              : 
      60            4 :     return CHIP_NO_ERROR;
      61              : }
      62              : 
      63            2 : CHIP_ERROR TLVUpdater::Init(TLVReader & aReader, uint32_t freeLen)
      64              : {
      65            2 :     uint8_t * buf             = const_cast<uint8_t *>(aReader.GetReadPoint());
      66            2 :     uint32_t remainingDataLen = aReader.GetRemainingLength();
      67            2 :     uint32_t readDataLen      = aReader.GetLengthRead();
      68              : 
      69              :     // TLVUpdater does not support backing stores yet
      70            2 :     VerifyOrReturnError(aReader.mBackingStore == nullptr, CHIP_ERROR_NOT_IMPLEMENTED);
      71              : 
      72              :     // TLVReader should point to a non-NULL buffer
      73            2 :     VerifyOrReturnError(buf != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
      74              : 
      75              :     // If reader is already on an element, reset it to start of element
      76            2 :     if (aReader.ElementType() != TLVElementType::NotSpecified)
      77              :     {
      78              :         uint8_t elemHeadLen;
      79              : 
      80            2 :         ReturnErrorOnFailure(aReader.GetElementHeadLength(elemHeadLen));
      81              : 
      82            2 :         buf -= elemHeadLen;
      83            2 :         remainingDataLen += elemHeadLen;
      84            2 :         readDataLen -= elemHeadLen;
      85              :     }
      86              : 
      87              :     // memmove the buffer data to end of the buffer
      88            2 :     memmove(buf + freeLen, buf, remainingDataLen);
      89              : 
      90              :     // Initialize the internal reader object
      91            2 :     mUpdaterReader.mBackingStore  = nullptr;
      92            2 :     mUpdaterReader.mReadPoint     = buf + freeLen;
      93            2 :     mUpdaterReader.mBufEnd        = buf + freeLen + remainingDataLen;
      94            2 :     mUpdaterReader.mLenRead       = readDataLen;
      95            2 :     mUpdaterReader.mMaxLen        = aReader.mMaxLen;
      96            2 :     mUpdaterReader.mControlByte   = kTLVControlByte_NotSpecified;
      97            2 :     mUpdaterReader.mElemTag       = AnonymousTag();
      98            2 :     mUpdaterReader.mElemLenOrVal  = 0;
      99            2 :     mUpdaterReader.mContainerType = aReader.mContainerType;
     100            2 :     mUpdaterReader.SetContainerOpen(false);
     101              : 
     102            2 :     mUpdaterReader.ImplicitProfileId = aReader.ImplicitProfileId;
     103            2 :     mUpdaterReader.AppData           = aReader.AppData;
     104              : 
     105              :     // TODO(#30825): Need to ensure we use TLVWriter public API rather than touch the innards.
     106              : 
     107              :     // Initialize the internal writer object
     108            2 :     mUpdaterWriter.mBackingStore  = nullptr;
     109            2 :     mUpdaterWriter.mBufStart      = buf - readDataLen;
     110            2 :     mUpdaterWriter.mWritePoint    = buf;
     111            2 :     mUpdaterWriter.mRemainingLen  = freeLen;
     112            2 :     mUpdaterWriter.mLenWritten    = readDataLen;
     113            2 :     mUpdaterWriter.mMaxLen        = readDataLen + freeLen;
     114            2 :     mUpdaterWriter.mContainerType = aReader.mContainerType;
     115            2 :     mUpdaterWriter.SetContainerOpen(false);
     116            2 :     mUpdaterWriter.SetCloseContainerReserved(false);
     117              : 
     118            2 :     mUpdaterWriter.ImplicitProfileId     = aReader.ImplicitProfileId;
     119            2 :     mUpdaterWriter.mInitializationCookie = TLVWriter::kExpectedInitializationCookie;
     120              : 
     121              :     // Cache element start address for internal use
     122            2 :     mElementStartAddr = buf + freeLen;
     123              : 
     124              :     // Clear the input reader object before returning. The user can no longer
     125              :     // use the original TLVReader object anymore.
     126            2 :     aReader.Init(static_cast<const uint8_t *>(nullptr), 0);
     127              : 
     128            2 :     return CHIP_NO_ERROR;
     129              : }
     130              : 
     131            4 : void TLVUpdater::SetImplicitProfileId(uint32_t profileId)
     132              : {
     133            4 :     mUpdaterReader.ImplicitProfileId = profileId;
     134            4 :     mUpdaterWriter.ImplicitProfileId = profileId;
     135            4 : }
     136              : 
     137           23 : CHIP_ERROR TLVUpdater::Next()
     138              : {
     139              :     // Skip current element if the reader is already positioned on an element
     140           23 :     ReturnErrorOnFailure(mUpdaterReader.Skip());
     141              : 
     142           22 :     AdjustInternalWriterFreeSpace();
     143              : 
     144              :     // Move the reader to next element
     145           22 :     ReturnErrorOnFailure(mUpdaterReader.Next());
     146              : 
     147           14 :     return CHIP_NO_ERROR;
     148              : }
     149              : 
     150            6 : CHIP_ERROR TLVUpdater::Move()
     151              : {
     152            6 :     VerifyOrReturnError(mUpdaterWriter.IsInitialized(), CHIP_ERROR_INCORRECT_STATE);
     153              : 
     154              :     const uint8_t * elementEnd;
     155              :     uint32_t copyLen;
     156              : 
     157            6 :     VerifyOrReturnError(static_cast<TLVElementType>((mUpdaterReader.mControlByte & kTLVTypeMask)) != TLVElementType::EndOfContainer,
     158              :                         CHIP_END_OF_TLV);
     159              : 
     160            6 :     VerifyOrReturnError(mUpdaterReader.GetType() != kTLVType_NotSpecified, CHIP_ERROR_INVALID_TLV_ELEMENT);
     161              : 
     162              :     // Skip to the end of the element
     163            6 :     ReturnErrorOnFailure(mUpdaterReader.Skip());
     164              : 
     165            6 :     elementEnd = mUpdaterReader.mReadPoint;
     166              : 
     167            6 :     copyLen = static_cast<uint32_t>(elementEnd - mElementStartAddr);
     168              : 
     169              :     // Move the element to output TLV
     170            6 :     memmove(mUpdaterWriter.mWritePoint, mElementStartAddr, copyLen);
     171              : 
     172              :     // Adjust the updater state
     173            6 :     mElementStartAddr += copyLen;
     174            6 :     mUpdaterWriter.mWritePoint += copyLen;
     175            6 :     mUpdaterWriter.mLenWritten += copyLen;
     176            6 :     mUpdaterWriter.mMaxLen += copyLen;
     177              : 
     178            6 :     return CHIP_NO_ERROR;
     179              : }
     180              : 
     181            3 : void TLVUpdater::MoveUntilEnd()
     182              : {
     183            3 :     VerifyOrDie(mUpdaterWriter.IsInitialized());
     184              : 
     185            3 :     const uint8_t * buffEnd = mUpdaterReader.GetReadPoint() + mUpdaterReader.GetRemainingLength();
     186              : 
     187            3 :     uint32_t copyLen = static_cast<uint32_t>(buffEnd - mElementStartAddr);
     188              : 
     189              :     // Move all elements till end to output TLV
     190            3 :     memmove(mUpdaterWriter.mWritePoint, mElementStartAddr, copyLen);
     191              : 
     192              :     // TODO(#30825): Need to ensure public API is used rather than touching the innards.
     193              :     // Adjust the updater state
     194            3 :     mElementStartAddr += copyLen;
     195            3 :     mUpdaterWriter.mWritePoint += copyLen;
     196            3 :     mUpdaterWriter.mLenWritten += copyLen;
     197            3 :     mUpdaterWriter.mMaxLen += copyLen;
     198            3 :     mUpdaterWriter.mContainerType = kTLVType_NotSpecified;
     199            3 :     mUpdaterWriter.SetContainerOpen(false);
     200            3 :     mUpdaterWriter.SetCloseContainerReserved(false);
     201            3 :     mUpdaterReader.mReadPoint += copyLen;
     202            3 :     mUpdaterReader.mLenRead += copyLen;
     203            3 :     mUpdaterReader.mControlByte   = kTLVControlByte_NotSpecified;
     204            3 :     mUpdaterReader.mElemTag       = AnonymousTag();
     205            3 :     mUpdaterReader.mElemLenOrVal  = 0;
     206            3 :     mUpdaterReader.mContainerType = kTLVType_NotSpecified;
     207            3 :     mUpdaterReader.SetContainerOpen(false);
     208            3 : }
     209              : 
     210            3 : CHIP_ERROR TLVUpdater::EnterContainer(TLVType & outerContainerType)
     211              : {
     212            3 :     VerifyOrReturnError(mUpdaterWriter.IsInitialized(), CHIP_ERROR_INCORRECT_STATE);
     213              : 
     214              :     TLVType containerType;
     215              : 
     216            3 :     VerifyOrReturnError(TLVTypeIsContainer(static_cast<TLVType>(mUpdaterReader.mControlByte & kTLVTypeMask)),
     217              :                         CHIP_ERROR_INCORRECT_STATE);
     218              : 
     219              :     // Change the updater state
     220            3 :     AdjustInternalWriterFreeSpace();
     221              : 
     222            3 :     ReturnErrorOnFailure(mUpdaterWriter.StartContainer(mUpdaterReader.GetTag(), mUpdaterReader.GetType(), containerType));
     223              : 
     224            3 :     ReturnErrorOnFailure(mUpdaterReader.EnterContainer(containerType));
     225              : 
     226            3 :     outerContainerType = containerType;
     227              : 
     228            3 :     return CHIP_NO_ERROR;
     229              : }
     230              : 
     231            3 : CHIP_ERROR TLVUpdater::ExitContainer(TLVType outerContainerType)
     232              : {
     233            3 :     ReturnErrorOnFailure(mUpdaterReader.ExitContainer(outerContainerType));
     234              : 
     235              :     // Change the updater's state
     236            3 :     AdjustInternalWriterFreeSpace();
     237              : 
     238            3 :     ReturnErrorOnFailure(mUpdaterWriter.EndContainer(outerContainerType));
     239              : 
     240            3 :     return CHIP_NO_ERROR;
     241              : }
     242              : 
     243              : /**
     244              :  * This is a private method that adjusts the TLVUpdater's free space count by
     245              :  * accounting for the freespace from mElementStartAddr to current read point.
     246              :  */
     247           28 : void TLVUpdater::AdjustInternalWriterFreeSpace()
     248              : {
     249           28 :     VerifyOrDie(mUpdaterWriter.IsInitialized());
     250              : 
     251           28 :     const uint8_t * nextElementStart = mUpdaterReader.mReadPoint;
     252              : 
     253           28 :     if (nextElementStart != mElementStartAddr)
     254              :     {
     255              :         // Increase the internal writer's free space state variables
     256           11 :         uint32_t spaceIncrease = static_cast<uint32_t>(nextElementStart - mElementStartAddr);
     257           11 :         mUpdaterWriter.mRemainingLen += spaceIncrease;
     258           11 :         mUpdaterWriter.mMaxLen += spaceIncrease;
     259              : 
     260              :         // Cache the start address of the next element
     261           11 :         mElementStartAddr = nextElementStart;
     262              :     }
     263           28 : }
     264              : 
     265              : } // namespace TLV
     266              : } // namespace chip
        

Generated by: LCOV version 2.0-1