Matter SDK Coverage Report
Current view: top level - lib/format - protocol_decoder.cpp (source / functions) Coverage Total Hit
Test: SHA:b879ecb8e99e175eea0a293a888bda853da2b19c Lines: 84.8 % 329 279
Test Date: 2025-01-17 19:00:11 Functions: 100.0 % 14 14

            Line data    Source code
       1              : /*
       2              :  *
       3              :  *    Copyright (c) 2023 Project CHIP Authors
       4              :  *    All rights reserved.
       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/format/protocol_decoder.h>
      19              : 
      20              : #include <lib/format/FlatTree.h>
      21              : #include <lib/format/FlatTreePosition.h>
      22              : 
      23              : namespace chip {
      24              : namespace Decoders {
      25              : 
      26              : namespace {
      27              : 
      28              : using namespace chip::TLV;
      29              : 
      30              : using chip::StringBuilderBase;
      31              : using chip::TLVMeta::AttributeTag;
      32              : using chip::TLVMeta::ClusterTag;
      33              : using chip::TLVMeta::CommandTag;
      34              : using chip::TLVMeta::ConstantValueTag;
      35              : using chip::TLVMeta::EventTag;
      36              : using chip::TLVMeta::ItemType;
      37              : 
      38              : class ByTag
      39              : {
      40              : public:
      41          602 :     constexpr ByTag(Tag tag) : mTag(tag) {}
      42         2764 :     bool operator()(const chip::TLVMeta::ItemInfo & item) { return item.tag == mTag; }
      43              : 
      44              : private:
      45              :     const Tag mTag;
      46              : };
      47              : 
      48          228 : CHIP_ERROR FormatCurrentValue(const TLVReader & reader, chip::StringBuilderBase & out)
      49              : {
      50          228 :     switch (reader.GetType())
      51              :     {
      52            0 :     case kTLVType_SignedInteger: {
      53              :         int64_t sVal;
      54            0 :         ReturnErrorOnFailure(reader.Get(sVal));
      55            0 :         out.AddFormat("%" PRIi64, sVal);
      56            0 :         break;
      57              :     }
      58          195 :     case kTLVType_UnsignedInteger: {
      59              :         uint64_t uVal;
      60          195 :         ReturnErrorOnFailure(reader.Get(uVal));
      61          195 :         out.AddFormat("%" PRIu64, uVal);
      62          195 :         break;
      63              :     }
      64           18 :     case kTLVType_Boolean: {
      65              :         bool bVal;
      66           18 :         ReturnErrorOnFailure(reader.Get(bVal));
      67           18 :         out.Add(bVal ? "true" : "false");
      68           18 :         break;
      69              :     }
      70            0 :     case kTLVType_FloatingPointNumber: {
      71              :         double fpVal;
      72            0 :         ReturnErrorOnFailure(reader.Get(fpVal));
      73            0 :         out.AddFormat("%lf", fpVal);
      74            0 :         break;
      75              :     }
      76            2 :     case kTLVType_UTF8String: {
      77            2 :         const uint8_t * strbuf = nullptr;
      78            2 :         ReturnErrorOnFailure(reader.GetDataPtr(strbuf));
      79            2 :         out.AddFormat("\"%-.*s\"", static_cast<int>(reader.GetLength()), strbuf);
      80            2 :         break;
      81              :     }
      82           10 :     case kTLVType_ByteString: {
      83           10 :         const uint8_t * strbuf = nullptr;
      84           10 :         ReturnErrorOnFailure(reader.GetDataPtr(strbuf));
      85           10 :         out.Add("hex:");
      86          388 :         for (uint32_t i = 0; i < reader.GetLength(); i++)
      87              :         {
      88          378 :             out.AddFormat("%02X", strbuf[i]);
      89              :         }
      90           10 :         break;
      91              :     }
      92            3 :     case kTLVType_Null:
      93            3 :         out.Add("NULL");
      94            3 :         break;
      95              : 
      96            0 :     case kTLVType_NotSpecified:
      97            0 :         out.Add("Not Specified");
      98            0 :         break;
      99            0 :     default:
     100            0 :         out.Add("???");
     101            0 :         break;
     102              :     }
     103              : 
     104          228 :     return CHIP_NO_ERROR;
     105              : }
     106              : 
     107              : // Returns a null terminated string containing the current reader value
     108          228 : void PrettyPrintCurrentValue(const TLVReader & reader, chip::StringBuilderBase & out, PayloadDecoderBase::DecodePosition & position)
     109              : {
     110          228 :     CHIP_ERROR err = FormatCurrentValue(reader, out);
     111              : 
     112          228 :     if (err != CHIP_NO_ERROR)
     113              :     {
     114            0 :         out.AddFormat("ERR: %" CHIP_ERROR_FORMAT, err.Format());
     115           16 :         return;
     116              :     }
     117              : 
     118          228 :     auto data = position.Get();
     119          228 :     if (data == nullptr)
     120              :     {
     121           16 :         return;
     122              :     }
     123              : 
     124              :     // Report enum values in human readable form
     125          212 :     if (data->type == ItemType::kEnum && (reader.GetType() == kTLVType_UnsignedInteger))
     126              :     {
     127            5 :         uint64_t value = 0;
     128            5 :         VerifyOrReturn(reader.Get(value) == CHIP_NO_ERROR);
     129              : 
     130            5 :         position.Enter(ByTag(ConstantValueTag(value)));
     131            5 :         auto enum_data = position.Get();
     132            5 :         if (enum_data != nullptr)
     133              :         {
     134            5 :             out.Add(" == ").Add(enum_data->name);
     135              :         }
     136            5 :         position.Exit();
     137              :     }
     138              : 
     139          212 :     if (data->type == ItemType::kBitmap && (reader.GetType() == kTLVType_UnsignedInteger))
     140              :     {
     141            2 :         uint64_t value = 0;
     142            2 :         VerifyOrReturn(reader.Get(value) == CHIP_NO_ERROR);
     143              : 
     144            2 :         uint64_t bit = 0x01;
     145            2 :         bool first   = true;
     146          130 :         for (unsigned i = 0; i < 64; i++, bit <<= 1)
     147              :         {
     148          128 :             if ((value & bit) == 0)
     149              :             {
     150          123 :                 continue;
     151              :             }
     152              : 
     153              :             // NOTE: this only can select individual bits;
     154            5 :             position.Enter(ByTag(ConstantValueTag(bit)));
     155            5 :             auto bitmap_data = position.Get();
     156            5 :             if (bitmap_data == nullptr)
     157              :             {
     158            0 :                 position.Exit();
     159            0 :                 continue;
     160              :             }
     161              : 
     162              :             // Try to pretty print the value
     163            5 :             if (first)
     164              :             {
     165            2 :                 out.Add(" == ");
     166            2 :                 first = false;
     167              :             }
     168              :             else
     169              :             {
     170            3 :                 out.Add(" | ");
     171              :             }
     172              : 
     173            5 :             out.Add(bitmap_data->name);
     174            5 :             value = value & (~bit);
     175              : 
     176            5 :             position.Exit();
     177              :         }
     178              : 
     179            2 :         if (!first && value)
     180              :         {
     181              :             // Only append if some constants were found.
     182            0 :             out.AddFormat(" | 0x%08" PRIX64, value);
     183              :         }
     184              :     }
     185              : 
     186          212 :     out.AddMarkerIfOverflow();
     187              : }
     188              : 
     189              : } // namespace
     190              : 
     191           28 : PayloadDecoderBase::PayloadDecoderBase(const PayloadDecoderInitParams & params, StringBuilderBase & nameBuilder,
     192           28 :                                        StringBuilderBase & valueBuilder) :
     193           28 :     mProtocol(params.GetProtocol()),
     194           28 :     mMessageType(params.GetMessageType()), mNameBuilder(nameBuilder), mValueBuilder(valueBuilder),
     195              : 
     196           28 :     mPayloadPosition(params.GetProtocolDecodeTree(), params.GetProtocolDecodeTreeSize()),
     197           56 :     mIMContentPosition(params.GetClusterDecodeTree(), params.GetClusterDecodeTreeSize())
     198           28 : {}
     199              : 
     200           28 : void PayloadDecoderBase::StartDecoding(const TLVReader & reader)
     201              : {
     202           28 :     mReader = reader;
     203           28 :     mPayloadPosition.ResetToTop();
     204           28 :     mIMContentPosition.ResetToTop();
     205           28 :     mCurrentNesting = 0;
     206           28 :     mClusterId      = 0;
     207           28 :     mAttributeId    = 0;
     208           28 :     mEventId        = 0;
     209           28 :     mCommandId      = 0;
     210           28 :     mState          = State::kStarting;
     211           28 : }
     212              : 
     213          605 : bool PayloadDecoderBase::Next(PayloadEntry & entry)
     214              : {
     215          605 :     switch (mState)
     216              :     {
     217           28 :     case State::kStarting:
     218           28 :         NextFromStarting(entry);
     219           28 :         return true;
     220          516 :     case State::kValueRead:
     221          516 :         NextFromValueRead(entry);
     222          516 :         return true;
     223           33 :     case State::kContentRead:
     224           33 :         NextFromContentRead(entry);
     225           33 :         return true;
     226           28 :     case State::kDone:
     227           28 :         return false;
     228              :     }
     229              :     // should never happen
     230            0 :     return false;
     231              : }
     232              : 
     233           28 : void PayloadDecoderBase::NextFromStarting(PayloadEntry & entry)
     234              : {
     235              :     // Find the right protocol (fake cluster id)
     236           28 :     mPayloadPosition.Enter(ByTag(ClusterTag(0xFFFF0000 | mProtocol.ToFullyQualifiedSpecForm())));
     237           28 :     mPayloadPosition.Enter(ByTag(AttributeTag(mMessageType)));
     238              : 
     239           28 :     auto data = mPayloadPosition.Get();
     240           28 :     if (data == nullptr)
     241              :     {
     242              :         // do not try to decode unknown data. assume binary
     243            2 :         mNameBuilder.Reset().AddFormat("PROTO(0x%" PRIX32 ", 0x%X)", mProtocol.ToFullyQualifiedSpecForm(), mMessageType);
     244            2 :         mValueBuilder.Reset().Add("UNKNOWN");
     245            2 :         entry  = PayloadEntry::SimpleValue(mNameBuilder.c_str(), mValueBuilder.c_str());
     246            2 :         mState = State::kDone;
     247            7 :         return;
     248              :     }
     249              : 
     250              :     // name is known (so valid protocol)
     251           26 :     if (mReader.GetTotalLength() == 0)
     252              :     {
     253            4 :         mState = State::kDone;
     254            4 :         entry  = PayloadEntry::SimpleValue(data->name, "");
     255            4 :         return;
     256              :     }
     257              : 
     258           22 :     if (data->type == ItemType::kProtocolBinaryData)
     259              :     {
     260            1 :         mState = State::kDone;
     261            1 :         entry  = PayloadEntry::SimpleValue(data->name, "BINARY DATA");
     262            1 :         return;
     263              :     }
     264              : 
     265           21 :     CHIP_ERROR err = mReader.Next(kTLVType_Structure, AnonymousTag());
     266           21 :     if (err != CHIP_NO_ERROR)
     267              :     {
     268            0 :         mValueBuilder.Reset().AddFormat("ERROR getting Anonymous Structure TLV: %" CHIP_ERROR_FORMAT, err.Format());
     269            0 :         mState = State::kDone;
     270            0 :         entry  = PayloadEntry::SimpleValue(data->name, mValueBuilder.c_str());
     271            0 :         return;
     272              :     }
     273              : 
     274           21 :     EnterContainer(entry);
     275              : }
     276              : 
     277          166 : void PayloadDecoderBase::ExitContainer(PayloadEntry & entry)
     278              : {
     279          166 :     entry = PayloadEntry::NestingExit();
     280              : 
     281          166 :     if (mCurrentNesting > 0)
     282              :     {
     283          166 :         if (mState == State::kContentRead)
     284              :         {
     285           11 :             mIMContentPosition.Exit();
     286           11 :             if (mIMContentPosition.DescendDepth() <= 1)
     287              :             {
     288              :                 // Lever for actual content is 2: cluster::attr/cmd/ev
     289            7 :                 mState = State::kValueRead;
     290            7 :                 mPayloadPosition.Exit();
     291              :             }
     292              :         }
     293              :         else
     294              :         {
     295          155 :             mPayloadPosition.Exit();
     296              :         }
     297          166 :         CHIP_ERROR err = mReader.ExitContainer(mNestingEnters[--mCurrentNesting]);
     298          166 :         if (err != CHIP_NO_ERROR)
     299              :         {
     300            0 :             mValueBuilder.Reset().AddFormat("ERROR: %" CHIP_ERROR_FORMAT, err.Format());
     301            0 :             mNameBuilder.Reset().AddFormat("END CONTAINER");
     302            0 :             entry  = PayloadEntry::SimpleValue(mNameBuilder.c_str(), mValueBuilder.c_str());
     303            0 :             mState = State::kDone;
     304            0 :             return;
     305              :         }
     306              :     }
     307              : 
     308          166 :     if (mCurrentNesting == 0)
     309              :     {
     310           21 :         mState = State::kDone;
     311              :     }
     312              : }
     313              : 
     314          167 : bool PayloadDecoderBase::ReaderEnterContainer(PayloadEntry & entry)
     315              : {
     316          167 :     if (mCurrentNesting >= kMaxDecodeDepth)
     317              :     {
     318            1 :         mValueBuilder.AddFormat("NESTING DEPTH REACHED");
     319            1 :         mReader.GetTag().AppendTo(mNameBuilder.Reset());
     320            1 :         entry = PayloadEntry::SimpleValue(mNameBuilder.c_str(), mValueBuilder.c_str());
     321            1 :         return false;
     322              :     }
     323              : 
     324              :     TLVType containerType;
     325          166 :     CHIP_ERROR err = mReader.EnterContainer(containerType);
     326          166 :     if (err != CHIP_NO_ERROR)
     327              :     {
     328            0 :         mValueBuilder.AddFormat("ERROR entering container: %" CHIP_ERROR_FORMAT, err.Format());
     329            0 :         mReader.GetTag().AppendTo(mNameBuilder.Reset()); // assume enter is not done, so tag is correct
     330            0 :         entry  = PayloadEntry::SimpleValue(mNameBuilder.c_str(), mValueBuilder.c_str());
     331            0 :         mState = State::kDone;
     332            0 :         return false;
     333              :     }
     334              : 
     335          166 :     mNestingEnters[mCurrentNesting++] = containerType;
     336              : 
     337          166 :     return true;
     338              : }
     339              : 
     340          160 : void PayloadDecoderBase::EnterContainer(PayloadEntry & entry)
     341              : {
     342              :     // Tag fetch must be done BEFORE entering container
     343          160 :     chip::TLV::Tag tag = mReader.GetTag();
     344              : 
     345          160 :     VerifyOrReturn(ReaderEnterContainer(entry));
     346              : 
     347          159 :     const chip::TLVMeta::ItemInfo * data = nullptr;
     348              : 
     349          159 :     if (mState == State::kContentRead)
     350              :     {
     351            4 :         data = mIMContentPosition.Get();
     352              :     }
     353              :     else
     354              :     {
     355          155 :         mState = State::kValueRead;
     356          155 :         data   = mPayloadPosition.Get();
     357              :     }
     358              : 
     359          159 :     if (data == nullptr)
     360              :     {
     361           32 :         tag.AppendTo(mNameBuilder.Reset());
     362           32 :         entry = PayloadEntry::NestingEnter(mNameBuilder.c_str());
     363              :     }
     364              :     else
     365              :     {
     366          127 :         entry = PayloadEntry::NestingEnter(data->name);
     367              :     }
     368              : }
     369              : 
     370           33 : void PayloadDecoderBase::NextFromContentRead(PayloadEntry & entry)
     371              : {
     372           33 :     CHIP_ERROR err = mReader.Next();
     373           33 :     if (err == CHIP_END_OF_TLV)
     374              :     {
     375           11 :         ExitContainer(entry);
     376           20 :         return;
     377              :     }
     378              : 
     379           22 :     if (err != CHIP_NO_ERROR)
     380              :     {
     381            0 :         mValueBuilder.Reset().AddFormat("ERROR on TLV Next: %" CHIP_ERROR_FORMAT, err.Format());
     382            0 :         entry  = PayloadEntry::SimpleValue("TLV_ERR", mValueBuilder.c_str());
     383            0 :         mState = State::kDone;
     384            0 :         return;
     385              :     }
     386              : 
     387           22 :     if (mCurrentNesting > 0 && mNestingEnters[mCurrentNesting - 1] == kTLVType_List)
     388              :     {
     389              :         // Spec A5.3: `The members of a list may be encoded with any form of tag, including an anonymous tag.`
     390              :         // TLVMeta always uses Anonymous
     391            0 :         mIMContentPosition.Enter(ByTag(AnonymousTag()));
     392              :     }
     393              :     else
     394              :     {
     395           22 :         mIMContentPosition.Enter(ByTag(mReader.GetTag()));
     396              :     }
     397           22 :     auto data = mIMContentPosition.Get();
     398              : 
     399           22 :     if (data != nullptr)
     400              :     {
     401           15 :         if (data->type == ItemType::kProtocolBinaryData)
     402              :         {
     403            0 :             mIMContentPosition.Exit();
     404            0 :             entry = PayloadEntry::SimpleValue(data->name, "BINARY DATA");
     405            0 :             return;
     406              :         }
     407              :     }
     408              : 
     409           22 :     if (TLVTypeIsContainer(mReader.GetType()))
     410              :     {
     411            4 :         EnterContainer(entry);
     412            4 :         return;
     413              :     }
     414              : 
     415           18 :     PrettyPrintCurrentValue(mReader, mValueBuilder.Reset(), mIMContentPosition);
     416           18 :     mIMContentPosition.Exit();
     417              : 
     418           18 :     if (data == nullptr)
     419              :     {
     420            5 :         mReader.GetTag().AppendTo(mNameBuilder.Reset());
     421            5 :         entry = PayloadEntry::SimpleValue(mNameBuilder.c_str(), mValueBuilder.c_str());
     422            5 :         return;
     423              :     }
     424              : 
     425           13 :     entry = PayloadEntry::SimpleValue(data->name, mValueBuilder.c_str());
     426              : }
     427              : 
     428           24 : void PayloadDecoderBase::MoveToContent(PayloadEntry & entry)
     429              : {
     430           24 :     if (!mIMContentPosition.HasValidTree())
     431              :     {
     432            9 :         mPayloadPosition.Exit();
     433            9 :         return;
     434              :     }
     435              : 
     436           15 :     VerifyOrDie((entry.GetType() == PayloadEntry::IMPayloadType::kAttribute) ||
     437              :                 (entry.GetType() == PayloadEntry::IMPayloadType::kCommand) ||
     438              :                 (entry.GetType() == PayloadEntry::IMPayloadType::kEvent));
     439              : 
     440           15 :     mNameBuilder.Reset();
     441              : 
     442           15 :     mIMContentPosition.ResetToTop();
     443           15 :     mIMContentPosition.Enter(ByTag(ClusterTag(entry.GetClusterId())));
     444           15 :     auto data = mIMContentPosition.Get();
     445           15 :     if (data != nullptr)
     446              :     {
     447           14 :         mNameBuilder.AddFormat("%s::", data->name);
     448              :     }
     449              :     else
     450              :     {
     451            1 :         mNameBuilder.AddFormat("0x%" PRIx32 "::", entry.GetClusterId());
     452              :     }
     453              : 
     454           15 :     uint32_t id          = 0;
     455           15 :     const char * id_type = "UNKNOWN";
     456              : 
     457           15 :     switch (entry.GetType())
     458              :     {
     459           11 :     case PayloadEntry::IMPayloadType::kAttribute:
     460           11 :         mIMContentPosition.Enter(ByTag(AttributeTag(entry.GetAttributeId())));
     461           11 :         id      = entry.GetAttributeId();
     462           11 :         id_type = "ATTR";
     463           11 :         break;
     464            2 :     case PayloadEntry::IMPayloadType::kCommand:
     465            2 :         mIMContentPosition.Enter(ByTag(CommandTag(entry.GetCommandId())));
     466            2 :         id      = entry.GetCommandId();
     467            2 :         id_type = "CMD";
     468            2 :         break;
     469            2 :     case PayloadEntry::IMPayloadType::kEvent:
     470            2 :         mIMContentPosition.Enter(ByTag(EventTag(entry.GetEventId())));
     471            2 :         id      = entry.GetEventId();
     472            2 :         id_type = "EV";
     473            2 :         break;
     474            0 :     default:
     475              :         // never happens: verified all case above covered.
     476            0 :         break;
     477              :     }
     478              : 
     479           15 :     data = mIMContentPosition.Get();
     480           15 :     if (data != nullptr)
     481              :     {
     482           14 :         mNameBuilder.AddFormat("%s", data->name);
     483              :     }
     484              :     else
     485              :     {
     486            1 :         mNameBuilder.AddFormat("%s(0x%" PRIx32 ")", id_type, id);
     487              :     }
     488              : 
     489           15 :     if (TLVTypeIsContainer(mReader.GetType()))
     490              :     {
     491            7 :         mState = State::kContentRead;
     492            7 :         entry  = PayloadEntry::NestingEnter(mNameBuilder.c_str());
     493            7 :         ReaderEnterContainer(entry);
     494              :     }
     495              :     else
     496              :     {
     497            8 :         PrettyPrintCurrentValue(mReader, mValueBuilder.Reset(), mIMContentPosition);
     498            8 :         entry = PayloadEntry::SimpleValue(mNameBuilder.c_str(), mValueBuilder.c_str());
     499              : 
     500              :         // Can simply exit, only one value to return
     501            8 :         mPayloadPosition.Exit();
     502              :     }
     503              : }
     504              : 
     505          516 : void PayloadDecoderBase::NextFromValueRead(PayloadEntry & entry)
     506              : {
     507          516 :     CHIP_ERROR err = mReader.Next();
     508          516 :     if (err == CHIP_END_OF_TLV)
     509              :     {
     510          155 :         ExitContainer(entry);
     511          325 :         return;
     512              :     }
     513              : 
     514          361 :     if (err != CHIP_NO_ERROR)
     515              :     {
     516            0 :         mValueBuilder.Reset().AddFormat("ERROR on TLV Next: %" CHIP_ERROR_FORMAT, err.Format());
     517            0 :         entry  = PayloadEntry::SimpleValue("TLV_ERR", mValueBuilder.c_str());
     518            0 :         mState = State::kDone;
     519            0 :         return;
     520              :     }
     521              : 
     522              :     // Attempt to find information about the current tag
     523          361 :     mPayloadPosition.Enter(ByTag(mReader.GetTag()));
     524          361 :     auto data = mPayloadPosition.Get();
     525              : 
     526              :     // handle special types
     527          361 :     if (data != nullptr)
     528              :     {
     529          319 :         if (data->type == ItemType::kProtocolBinaryData)
     530              :         {
     531            0 :             mPayloadPosition.Exit();
     532            0 :             entry = PayloadEntry::SimpleValue(data->name, "BINARY DATA");
     533            0 :             return;
     534              :         }
     535              : 
     536          319 :         if (data->type == ItemType::kProtocolPayloadAttribute)
     537              :         {
     538           20 :             entry = PayloadEntry::AttributePayload(mClusterId, mAttributeId);
     539           20 :             MoveToContent(entry);
     540           20 :             return;
     541              :         }
     542              : 
     543          299 :         if (data->type == ItemType::kProtocolPayloadCommand)
     544              :         {
     545            2 :             entry = PayloadEntry::CommandPayload(mClusterId, mCommandId);
     546            2 :             MoveToContent(entry);
     547            2 :             return;
     548              :         }
     549              : 
     550          297 :         if (data->type == ItemType::kProtocolPayloadEvent)
     551              :         {
     552            2 :             entry = PayloadEntry::EventPayload(mClusterId, mEventId);
     553            2 :             MoveToContent(entry);
     554            2 :             return;
     555              :         }
     556              :     }
     557              : 
     558          337 :     if (TLVTypeIsContainer(mReader.GetType()))
     559              :     {
     560          135 :         EnterContainer(entry);
     561          135 :         return;
     562              :     }
     563              : 
     564          202 :     if (data == nullptr)
     565              :     {
     566           11 :         mReader.GetTag().AppendTo(mNameBuilder.Reset());
     567           11 :         PrettyPrintCurrentValue(mReader, mValueBuilder.Reset(), mPayloadPosition);
     568           11 :         entry = PayloadEntry::SimpleValue(mNameBuilder.c_str(), mValueBuilder.c_str());
     569           11 :         mPayloadPosition.Exit();
     570           11 :         return;
     571              :     }
     572              : 
     573              :     // at this point, data is "simple data" or "simple data with meaning"
     574              : 
     575          191 :     const chip::TLVMeta::ItemInfo * info = nullptr;
     576          191 :     switch (data->type)
     577              :     {
     578           41 :     case ItemType::kProtocolClusterId:
     579           41 :         mReader.Get(mClusterId);
     580           41 :         mIMContentPosition.ResetToTop();
     581           41 :         mIMContentPosition.Enter(ByTag(ClusterTag(mClusterId)));
     582           41 :         info = mIMContentPosition.Get();
     583           41 :         break;
     584           36 :     case ItemType::kProtocolAttributeId:
     585           36 :         mReader.Get(mAttributeId);
     586           36 :         mIMContentPosition.ResetToTop();
     587           36 :         mIMContentPosition.Enter(ByTag(ClusterTag(mClusterId)));
     588           36 :         mIMContentPosition.Enter(ByTag(AttributeTag(mAttributeId)));
     589           36 :         info = mIMContentPosition.Get();
     590           36 :         break;
     591            3 :     case ItemType::kProtocolCommandId:
     592            3 :         mReader.Get(mCommandId);
     593            3 :         mIMContentPosition.ResetToTop();
     594            3 :         mIMContentPosition.Enter(ByTag(ClusterTag(mClusterId)));
     595            3 :         mIMContentPosition.Enter(ByTag(CommandTag(mCommandId)));
     596            3 :         info = mIMContentPosition.Get();
     597            3 :         break;
     598            2 :     case ItemType::kProtocolEventId:
     599            2 :         mReader.Get(mEventId);
     600            2 :         mIMContentPosition.ResetToTop();
     601            2 :         mIMContentPosition.Enter(ByTag(ClusterTag(mClusterId)));
     602            2 :         mIMContentPosition.Enter(ByTag(EventTag(mEventId)));
     603            2 :         info = mIMContentPosition.Get();
     604            2 :         break;
     605          109 :     default:
     606          109 :         break;
     607              :     }
     608              : 
     609          191 :     PrettyPrintCurrentValue(mReader, mValueBuilder.Reset(), mPayloadPosition);
     610          191 :     if (info != nullptr)
     611              :     {
     612           46 :         mValueBuilder.Add(" == '").Add(info->name).Add("'");
     613              :     }
     614              : 
     615          191 :     mPayloadPosition.Exit();
     616          191 :     entry = PayloadEntry::SimpleValue(data->name, mValueBuilder.c_str());
     617              : }
     618              : 
     619              : } // namespace Decoders
     620              : } // namespace chip
        

Generated by: LCOV version 2.0-1