LCOV - code coverage report
Current view: top level - lib/format - protocol_decoder.cpp (source / functions) Hit Total Coverage
Test: lcov_final.info Lines: 279 329 84.8 %
Date: 2024-02-15 08:20:41 Functions: 14 14 100.0 %

          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        2853 :     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 1.14