LCOV - code coverage report
Current view: top level - app/MessageDef - MessageDefHelper.cpp (source / functions) Hit Total Coverage
Test: lcov_final.info Lines: 91 98 92.9 %
Date: 2024-02-15 08:20:41 Functions: 5 5 100.0 %

          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             : #include <algorithm>
      26             : #include <app/AppConfig.h>
      27             : #include <app/InteractionModelRevision.h>
      28             : #include <app/util/basic-types.h>
      29             : #include <inttypes.h>
      30             : #include <lib/support/logging/CHIPLogging.h>
      31             : #include <stdarg.h>
      32             : #include <stdio.h>
      33             : 
      34             : namespace chip {
      35             : namespace app {
      36             : #if CHIP_CONFIG_IM_PRETTY_PRINT && CHIP_DETAIL_LOGGING
      37             : // this is used to run in signle thread for IM message debug purpose
      38             : namespace {
      39             : uint32_t gPrettyPrintingDepthLevel = 0;
      40             : char gLineBuffer[CHIP_CONFIG_LOG_MESSAGE_MAX_SIZE];
      41             : size_t gCurLineBufferSize = 0;
      42             : } // namespace
      43             : 
      44      313207 : void PrettyPrintIMBlankLine()
      45             : {
      46      313207 :     if (gCurLineBufferSize)
      47             :     {
      48             :         // Don't need to explicitly NULL-terminate the string because
      49             :         // snprintf takes care of that.
      50      305456 :         ChipLogDetail(DataManagement, "%s", gLineBuffer);
      51      305456 :         gCurLineBufferSize = 0;
      52             :     }
      53             : 
      54     1137867 :     for (uint32_t i = 0; i < gPrettyPrintingDepthLevel; i++)
      55             :     {
      56      824660 :         if (sizeof(gLineBuffer) > gCurLineBufferSize)
      57             :         {
      58      824660 :             size_t sizeLeft = sizeof(gLineBuffer) - gCurLineBufferSize;
      59      824660 :             size_t ret      = (size_t) (snprintf(gLineBuffer + gCurLineBufferSize, sizeLeft, "\t"));
      60      824660 :             if (ret > 0)
      61             :             {
      62      824660 :                 gCurLineBufferSize += std::min(ret, sizeLeft);
      63             :             }
      64             :         }
      65             :     }
      66      313207 : }
      67             : 
      68     1832426 : void PrettyPrintIM(bool aIsNewLine, const char * aFmt, ...)
      69             : {
      70             :     va_list args;
      71     1832426 :     va_start(args, aFmt);
      72             : 
      73     1832426 :     if (aIsNewLine)
      74             :     {
      75      278376 :         PrettyPrintIMBlankLine();
      76             :     }
      77             : 
      78     1832426 :     if (sizeof(gLineBuffer) > gCurLineBufferSize)
      79             :     {
      80      793636 :         size_t sizeLeft = sizeof(gLineBuffer) - gCurLineBufferSize;
      81      793636 :         size_t ret      = (size_t) (vsnprintf(gLineBuffer + gCurLineBufferSize, sizeLeft, aFmt, args));
      82      793636 :         if (ret > 0)
      83             :         {
      84      793636 :             gCurLineBufferSize += std::min(ret, sizeLeft);
      85             :         }
      86             :     }
      87             : 
      88     1832426 :     va_end(args);
      89     1832426 : }
      90       73380 : void IncreaseDepth()
      91             : {
      92       73380 :     gPrettyPrintingDepthLevel++;
      93       73380 : }
      94             : 
      95       73379 : void DecreaseDepth()
      96             : {
      97       73379 :     gPrettyPrintingDepthLevel--;
      98       73379 : }
      99             : #endif
     100             : 
     101             : #if CHIP_CONFIG_IM_PRETTY_PRINT
     102       34851 : CHIP_ERROR CheckIMPayload(TLV::TLVReader & aReader, int aDepth, const char * aLabel)
     103             : {
     104       34851 :     if (aDepth == 0)
     105             :     {
     106        7565 :         PRETTY_PRINT("%s = ", aLabel);
     107             :     }
     108             :     else
     109             :     {
     110       27286 :         if (TLV::IsContextTag(aReader.GetTag()))
     111             :         {
     112       23073 :             PRETTY_PRINT("0x%" PRIx32 " = ", TLV::TagNumFromTag(aReader.GetTag()));
     113             :         }
     114        4213 :         else if (TLV::IsProfileTag(aReader.GetTag()))
     115             :         {
     116           0 :             PRETTY_PRINT("0x%" PRIx32 "::0x%" PRIx32 " = ", TLV::ProfileIdFromTag(aReader.GetTag()),
     117             :                          TLV::TagNumFromTag(aReader.GetTag()));
     118             :         }
     119             :         else
     120             :         {
     121             :             // Anonymous tag, don't print anything
     122             :         }
     123             :     }
     124             : 
     125       34851 :     switch (aReader.GetType())
     126             :     {
     127        3803 :     case TLV::kTLVType_Structure:
     128        3803 :         PRETTY_PRINT("{");
     129        3803 :         break;
     130             : 
     131        4851 :     case TLV::kTLVType_Array:
     132        4851 :         PRETTY_PRINT_SAMELINE("[");
     133        4851 :         PRETTY_PRINT("\t\t");
     134        4851 :         break;
     135             : 
     136          90 :     case TLV::kTLVType_SignedInteger: {
     137             :         int64_t value_s64;
     138             : 
     139          90 :         ReturnErrorOnFailure(aReader.Get(value_s64));
     140             : 
     141             :         // TODO: Figure out how to not use PRId64 here, since it's not supported
     142             :         // on all libcs.
     143          90 :         PRETTY_PRINT_SAMELINE("%" PRId64 ", ", value_s64);
     144          90 :         break;
     145             :     }
     146             : 
     147       13412 :     case TLV::kTLVType_UnsignedInteger: {
     148             :         uint64_t value_u64;
     149             : 
     150       13412 :         ReturnErrorOnFailure(aReader.Get(value_u64));
     151             : 
     152             :         // TODO: Figure out how to not use PRIu64 here, since it's not supported
     153             :         // on all libcs.
     154       13412 :         PRETTY_PRINT_SAMELINE("%" PRIu64 ", ", value_u64);
     155       13412 :         break;
     156             :     }
     157             : 
     158        3112 :     case TLV::kTLVType_FloatingPointNumber: {
     159             :         double value_fp;
     160             : 
     161        3112 :         ReturnErrorOnFailure(aReader.Get(value_fp));
     162             : 
     163        3112 :         PRETTY_PRINT_SAMELINE("%f, ", value_fp);
     164        3112 :         break;
     165             :     }
     166        3268 :     case TLV::kTLVType_Boolean: {
     167             :         bool value_b;
     168             : 
     169        3268 :         ReturnErrorOnFailure(aReader.Get(value_b));
     170             : 
     171        3268 :         PRETTY_PRINT_SAMELINE("%s, ", value_b ? "true" : "false");
     172        3268 :         break;
     173             :     }
     174             : 
     175        1562 :     case TLV::kTLVType_UTF8String: {
     176             :         char value_s[CHIP_CONFIG_LOG_MESSAGE_MAX_SIZE];
     177             : 
     178             : #if CHIP_DETAIL_LOGGING
     179        1562 :         uint32_t readerLen = aReader.GetLength();
     180             : #endif // CHIP_DETAIL_LOGGING
     181        1562 :         CHIP_ERROR err = aReader.GetString(value_s, sizeof(value_s));
     182        1562 :         VerifyOrReturnError(err == CHIP_NO_ERROR || err == CHIP_ERROR_BUFFER_TOO_SMALL, err);
     183             : 
     184        1562 :         if (err == CHIP_ERROR_BUFFER_TOO_SMALL)
     185             :         {
     186           0 :             PRETTY_PRINT_SAMELINE("... (char string too long: %" PRIu32 " chars) ...", readerLen);
     187             :         }
     188             :         else
     189             :         {
     190        1562 :             PRETTY_PRINT_SAMELINE("\"%s\" (%" PRIu32 " chars), ", value_s, readerLen);
     191             :         }
     192        1562 :         break;
     193             :     }
     194             : 
     195        4742 :     case TLV::kTLVType_ByteString: {
     196             :         uint8_t value_b[CHIP_CONFIG_LOG_MESSAGE_MAX_SIZE];
     197             :         uint32_t len, readerLen;
     198             : 
     199        4742 :         readerLen = aReader.GetLength();
     200             : 
     201        4742 :         CHIP_ERROR err = aReader.GetBytes(value_b, sizeof(value_b));
     202        4742 :         VerifyOrReturnError(err == CHIP_NO_ERROR || err == CHIP_ERROR_BUFFER_TOO_SMALL, err);
     203             : 
     204        4742 :         PRETTY_PRINT_SAMELINE("[");
     205        4742 :         PRETTY_PRINT("\t\t");
     206             : 
     207        4742 :         if (readerLen < sizeof(value_b))
     208             :         {
     209        4742 :             len = readerLen;
     210             :         }
     211             :         else
     212             :         {
     213           0 :             len = sizeof(value_b);
     214             :         }
     215             : 
     216        4742 :         if (err == CHIP_ERROR_BUFFER_TOO_SMALL)
     217             :         {
     218           0 :             PRETTY_PRINT_SAMELINE("... (byte string too long) ...");
     219             :         }
     220             :         else
     221             :         {
     222     1527744 :             for (size_t i = 0; i < len; i++)
     223             :             {
     224     1523002 :                 PRETTY_PRINT_SAMELINE("0x%02x, ", value_b[i]);
     225             :             }
     226             :         }
     227             : 
     228        4742 :         PRETTY_PRINT("] (%" PRIu32 " bytes)", readerLen);
     229        4742 :         break;
     230             :     }
     231             : 
     232          11 :     case TLV::kTLVType_Null:
     233          11 :         PRETTY_PRINT_SAMELINE("NULL");
     234          11 :         break;
     235             : 
     236           0 :     default:
     237           0 :         PRETTY_PRINT_SAMELINE("--");
     238           0 :         break;
     239             :     }
     240             : 
     241       34851 :     if (aReader.GetType() == TLV::kTLVType_Structure || aReader.GetType() == TLV::kTLVType_Array)
     242             :     {
     243        8654 :         const char terminating_char = (aReader.GetType() == TLV::kTLVType_Structure) ? '}' : ']';
     244             :         TLV::TLVType type;
     245             : 
     246             :         IgnoreUnusedVariable(terminating_char);
     247             : 
     248        8654 :         ReturnErrorOnFailure(aReader.EnterContainer(type));
     249             : 
     250             :         CHIP_ERROR err;
     251       35940 :         while ((err = aReader.Next()) == CHIP_NO_ERROR)
     252             :         {
     253       27286 :             PRETTY_PRINT_INCDEPTH();
     254             : 
     255       27286 :             ReturnErrorOnFailure(CheckIMPayload(aReader, aDepth + 1, aLabel));
     256             : 
     257       27286 :             PRETTY_PRINT_DECDEPTH();
     258             :         }
     259             : 
     260        8654 :         PRETTY_PRINT("%c,", terminating_char);
     261             : 
     262        8654 :         ReturnErrorOnFailure(aReader.ExitContainer(type));
     263             :     }
     264             : 
     265       34851 :     return CHIP_NO_ERROR;
     266             : }
     267             : #endif // CHIP_CONFIG_IM_PRETTY_PRINT
     268             : 
     269             : }; // namespace app
     270             : }; // namespace chip

Generated by: LCOV version 1.14