Matter SDK Coverage Report
Current view: top level - app/MessageDef - MessageDefHelper.cpp (source / functions) Coverage Total Hit
Test: SHA:704d97f9c619242ad76fcf75aeabc67802fa72d4 Lines: 92.5 % 106 98
Test Date: 2026-05-18 07:37:39 Functions: 100.0 % 5 5

            Line data    Source code
       1              : /**
       2              :  *
       3              :  *    Copyright (c) 2020-2021 Project CHIP Authors
       4              :  *    Copyright (c) 2018 Google LLC.
       5              :  *    Copyright (c) 2016-2017 Nest Labs, Inc.
       6              :  *    Licensed under the Apache License, Version 2.0 (the "License");
       7              :  *    you may not use this file except in compliance with the License.
       8              :  *    You may obtain a copy of the License at
       9              :  *
      10              :  *        http://www.apache.org/licenses/LICENSE-2.0
      11              :  *
      12              :  *    Unless required by applicable law or agreed to in writing, software
      13              :  *    distributed under the License is distributed on an "AS IS" BASIS,
      14              :  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      15              :  *    See the License for the specific language governing permissions and
      16              :  *    limitations under the License.
      17              :  */
      18              : /**
      19              :  *    @file
      20              :  *      This file defines message helper functions in CHIP interaction model
      21              :  *
      22              :  */
      23              : 
      24              : #include "MessageDefHelper.h"
      25              : 
      26              : #include <algorithm>
      27              : #include <app/AppConfig.h>
      28              : #include <app/SpecificationDefinedRevisions.h>
      29              : #include <app/util/basic-types.h>
      30              : #include <lib/core/CHIPConfig.h>
      31              : #include <lib/support/ScopedMemoryBuffer.h>
      32              : #include <lib/support/logging/CHIPLogging.h>
      33              : 
      34              : #include <cinttypes>
      35              : #include <cstdarg>
      36              : #include <cstdio>
      37              : 
      38              : namespace chip {
      39              : namespace app {
      40              : #if CHIP_CONFIG_IM_PRETTY_PRINT && CHIP_DETAIL_LOGGING
      41              : // this is used to run in signle thread for IM message debug purpose
      42              : namespace {
      43              : uint32_t gPrettyPrintingDepthLevel = 0;
      44              : char gLineBuffer[CHIP_CONFIG_LOG_MESSAGE_MAX_SIZE];
      45              : size_t gCurLineBufferSize = 0;
      46              : } // namespace
      47              : 
      48       526713 : void PrettyPrintIMBlankLine()
      49              : {
      50       526713 :     if (gCurLineBufferSize)
      51              :     {
      52              :         // Don't need to explicitly NULL-terminate the string because
      53              :         // snprintf takes care of that.
      54       514214 :         ChipLogDetail(DataManagement, "%s", gLineBuffer);
      55       514214 :         gCurLineBufferSize = 0;
      56              :     }
      57              : 
      58      1886711 :     for (uint32_t i = 0; i < gPrettyPrintingDepthLevel; i++)
      59              :     {
      60      1359998 :         if (sizeof(gLineBuffer) > gCurLineBufferSize)
      61              :         {
      62      1359998 :             size_t sizeLeft = sizeof(gLineBuffer) - gCurLineBufferSize;
      63      1359998 :             size_t ret      = (size_t) (snprintf(gLineBuffer + gCurLineBufferSize, sizeLeft, "\t"));
      64      1359998 :             if (ret > 0)
      65              :             {
      66      1359998 :                 gCurLineBufferSize += std::min(ret, sizeLeft);
      67              :             }
      68              :         }
      69              :     }
      70       526713 : }
      71              : 
      72      3511601 : void PrettyPrintIM(bool aIsNewLine, const char * aFmt, ...)
      73              : {
      74              :     va_list args;
      75      3511601 :     va_start(args, aFmt);
      76              : 
      77      3511601 :     if (aIsNewLine)
      78              :     {
      79       469054 :         PrettyPrintIMBlankLine();
      80              :     }
      81              : 
      82      3511601 :     if (sizeof(gLineBuffer) > gCurLineBufferSize)
      83              :     {
      84      1419416 :         size_t sizeLeft = sizeof(gLineBuffer) - gCurLineBufferSize;
      85      1419416 :         size_t ret      = (size_t) (vsnprintf(gLineBuffer + gCurLineBufferSize, sizeLeft, aFmt, args));
      86      1419416 :         if (ret > 0)
      87              :         {
      88      1419416 :             gCurLineBufferSize += std::min(ret, sizeLeft);
      89              :         }
      90              :     }
      91              : 
      92      3511601 :     va_end(args);
      93      3511601 : }
      94       118594 : void IncreaseDepth()
      95              : {
      96       118594 :     gPrettyPrintingDepthLevel++;
      97       118594 : }
      98              : 
      99       118593 : void DecreaseDepth()
     100              : {
     101       118593 :     gPrettyPrintingDepthLevel--;
     102       118593 : }
     103              : #endif
     104              : 
     105              : #if CHIP_CONFIG_IM_PRETTY_PRINT
     106              : 
     107        52352 : CHIP_ERROR CheckIMPayload(TLV::TLVReader & aReader, int aDepth, const char * aLabel)
     108              : {
     109              :     // do not allow fully unbounded recursion.
     110        52352 :     constexpr int kMaxRecursionDepth = 100;
     111              : 
     112        52352 :     if (aDepth > kMaxRecursionDepth)
     113              :     {
     114            0 :         PRETTY_PRINT("!!! RECURSION LIMIT REACHED !!!");
     115            0 :         return CHIP_ERROR_RECURSION_DEPTH_LIMIT;
     116              :     }
     117              : 
     118        52352 :     if (aDepth == 0)
     119              :     {
     120        12112 :         PRETTY_PRINT("%s = ", aLabel);
     121              :     }
     122              :     else
     123              :     {
     124        40240 :         if (TLV::IsContextTag(aReader.GetTag()))
     125              :         {
     126        29405 :             PRETTY_PRINT("0x%" PRIx32 " = ", TLV::TagNumFromTag(aReader.GetTag()));
     127              :         }
     128        10835 :         else if (TLV::IsProfileTag(aReader.GetTag()))
     129              :         {
     130            0 :             PRETTY_PRINT("0x%" PRIx32 "::0x%" PRIx32 " = ", TLV::ProfileIdFromTag(aReader.GetTag()),
     131              :                          TLV::TagNumFromTag(aReader.GetTag()));
     132              :         }
     133              :         else
     134              :         {
     135              :             // Anonymous tag, don't print anything
     136              :         }
     137              :     }
     138              : 
     139        52352 :     switch (aReader.GetType())
     140              :     {
     141         6602 :     case TLV::kTLVType_Structure:
     142         6602 :         PRETTY_PRINT("{");
     143         6602 :         break;
     144              : 
     145         7143 :     case TLV::kTLVType_Array:
     146         7143 :         PRETTY_PRINT_SAMELINE("[");
     147         7143 :         PRETTY_PRINT("\t\t");
     148         7143 :         break;
     149              : 
     150           94 :     case TLV::kTLVType_SignedInteger: {
     151              :         int64_t value_s64;
     152              : 
     153           94 :         ReturnErrorOnFailure(aReader.Get(value_s64));
     154              : 
     155              :         // TODO: Figure out how to not use PRId64 here, since it's not supported
     156              :         // on all libcs.
     157           94 :         PRETTY_PRINT_SAMELINE("%" PRId64 " (signed), ", value_s64);
     158           94 :         break;
     159              :     }
     160              : 
     161        18492 :     case TLV::kTLVType_UnsignedInteger: {
     162              :         uint64_t value_u64;
     163              : 
     164        18492 :         ReturnErrorOnFailure(aReader.Get(value_u64));
     165              : 
     166              :         // TODO: Figure out how to not use PRIu64 here, since it's not supported
     167              :         // on all libcs.
     168        18492 :         PRETTY_PRINT_SAMELINE("%" PRIu64 " (unsigned), ", value_u64);
     169        18492 :         break;
     170              :     }
     171              : 
     172         3266 :     case TLV::kTLVType_FloatingPointNumber: {
     173              :         double value_fp;
     174              : 
     175         3266 :         ReturnErrorOnFailure(aReader.Get(value_fp));
     176              : 
     177         3266 :         PRETTY_PRINT_SAMELINE("%f, ", value_fp);
     178         3266 :         break;
     179              :     }
     180         3361 :     case TLV::kTLVType_Boolean: {
     181              :         bool value_b;
     182              : 
     183         3361 :         ReturnErrorOnFailure(aReader.Get(value_b));
     184              : 
     185         3361 :         PRETTY_PRINT_SAMELINE("%s, ", value_b ? "true" : "false");
     186         3361 :         break;
     187              :     }
     188              : 
     189         1711 :     case TLV::kTLVType_UTF8String: {
     190         1711 :         chip::Platform::ScopedMemoryBuffer<char> value_s;
     191         1711 :         VerifyOrReturnError(!value_s.Alloc(CHIP_CONFIG_LOG_MESSAGE_MAX_SIZE).IsNull(), CHIP_ERROR_NO_MEMORY);
     192              : 
     193              : #if CHIP_DETAIL_LOGGING
     194         1711 :         uint32_t readerLen = aReader.GetLength();
     195              : #endif // CHIP_DETAIL_LOGGING
     196         1711 :         CHIP_ERROR err = aReader.GetString(value_s.Get(), CHIP_CONFIG_LOG_MESSAGE_MAX_SIZE);
     197         3422 :         VerifyOrReturnError(err == CHIP_NO_ERROR || err == CHIP_ERROR_BUFFER_TOO_SMALL, err);
     198              : 
     199         3422 :         if (err == CHIP_ERROR_BUFFER_TOO_SMALL)
     200              :         {
     201            0 :             PRETTY_PRINT_SAMELINE("... (char string too long: %" PRIu32 " chars) ...", readerLen);
     202              :         }
     203              :         else
     204              :         {
     205         1711 :             PRETTY_PRINT_SAMELINE("\"%s\" (%" PRIu32 " chars), ", value_s.Get(), readerLen);
     206              :         }
     207         1711 :         break;
     208         1711 :     }
     209              : 
     210        11479 :     case TLV::kTLVType_ByteString: {
     211        11479 :         chip::Platform::ScopedMemoryBuffer<uint8_t> value_b;
     212        11479 :         VerifyOrReturnError(!value_b.Alloc(CHIP_CONFIG_LOG_MESSAGE_MAX_SIZE).IsNull(), CHIP_ERROR_NO_MEMORY);
     213              : 
     214        11479 :         uint32_t readerLen = aReader.GetLength();
     215              : 
     216        11479 :         CHIP_ERROR err = aReader.GetBytes(value_b.Get(), CHIP_CONFIG_LOG_MESSAGE_MAX_SIZE);
     217        22958 :         VerifyOrReturnError(err == CHIP_NO_ERROR || err == CHIP_ERROR_BUFFER_TOO_SMALL, err);
     218              : 
     219        11479 :         PRETTY_PRINT_SAMELINE("[");
     220        11479 :         PRETTY_PRINT("\t\t");
     221              : 
     222        22958 :         if (err == CHIP_ERROR_BUFFER_TOO_SMALL)
     223              :         {
     224            0 :             PRETTY_PRINT_SAMELINE("... (byte string too long) ...");
     225              :         }
     226              :         else
     227              :         {
     228        11479 :             const uint32_t len = std::min(readerLen, static_cast<uint32_t>(CHIP_CONFIG_LOG_MESSAGE_MAX_SIZE));
     229      3008276 :             for (size_t i = 0; i < len; i++)
     230              :             {
     231      2996797 :                 PRETTY_PRINT_SAMELINE("0x%02x, ", value_b[i]);
     232              :             }
     233              :         }
     234              : 
     235        11479 :         PRETTY_PRINT("] (%" PRIu32 " bytes)", readerLen);
     236        11479 :         break;
     237        11479 :     }
     238              : 
     239          204 :     case TLV::kTLVType_Null:
     240          204 :         PRETTY_PRINT_SAMELINE("NULL");
     241          204 :         break;
     242              : 
     243            0 :     default:
     244            0 :         PRETTY_PRINT_SAMELINE("--");
     245            0 :         break;
     246              :     }
     247              : 
     248        52352 :     if (aReader.GetType() == TLV::kTLVType_Structure || aReader.GetType() == TLV::kTLVType_Array)
     249              :     {
     250        13745 :         const char terminating_char = (aReader.GetType() == TLV::kTLVType_Structure) ? '}' : ']';
     251              :         TLV::TLVType type;
     252              : 
     253              :         IgnoreUnusedVariable(terminating_char);
     254              : 
     255        13745 :         ReturnErrorOnFailure(aReader.EnterContainer(type));
     256              : 
     257              :         CHIP_ERROR err;
     258       107970 :         while ((err = aReader.Next()) == CHIP_NO_ERROR)
     259              :         {
     260        40240 :             PRETTY_PRINT_INCDEPTH();
     261              : 
     262        40240 :             ReturnErrorOnFailure(CheckIMPayload(aReader, aDepth + 1, aLabel));
     263              : 
     264        40240 :             PRETTY_PRINT_DECDEPTH();
     265              :         }
     266              : 
     267        13745 :         PRETTY_PRINT("%c,", terminating_char);
     268              : 
     269        13745 :         ReturnErrorOnFailure(aReader.ExitContainer(type));
     270              :     }
     271              : 
     272        52352 :     return CHIP_NO_ERROR;
     273              : }
     274              : #endif // CHIP_CONFIG_IM_PRETTY_PRINT
     275              : 
     276              : }; // namespace app
     277              : }; // namespace chip
        

Generated by: LCOV version 2.0-1