Matter SDK Coverage Report
Current view: top level - app/MessageDef - AttributePathIB.cpp (source / functions) Coverage Total Hit
Test: SHA:b879ecb8e99e175eea0a293a888bda853da2b19c Lines: 96.3 % 163 157
Test Date: 2025-01-17 19:00:11 Functions: 100.0 % 21 21

            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              : #include "AttributePathIB.h"
      20              : #include "MessageDefHelper.h"
      21              : 
      22              : #include <inttypes.h>
      23              : #include <stdarg.h>
      24              : #include <stdio.h>
      25              : 
      26              : #include <app/AppConfig.h>
      27              : #include <app/data-model/Encode.h>
      28              : #include <app/data-model/Nullable.h>
      29              : 
      30              : namespace chip {
      31              : namespace app {
      32              : #if CHIP_CONFIG_IM_PRETTY_PRINT
      33        11252 : CHIP_ERROR AttributePathIB::Parser::PrettyPrint() const
      34              : {
      35        11252 :     CHIP_ERROR err = CHIP_NO_ERROR;
      36        11252 :     TLV::TLVReader reader;
      37              : 
      38        11252 :     PRETTY_PRINT("AttributePathIB =");
      39        11252 :     PRETTY_PRINT("{");
      40              : 
      41              :     // make a copy of the Path reader
      42        11252 :     reader.Init(mReader);
      43              : 
      44        47903 :     while (CHIP_NO_ERROR == (err = reader.Next()))
      45              :     {
      46        36651 :         if (!TLV::IsContextTag(reader.GetTag()))
      47              :         {
      48            0 :             continue;
      49              :         }
      50        36651 :         uint32_t tagNum = TLV::TagNumFromTag(reader.GetTag());
      51        36651 :         switch (tagNum)
      52              :         {
      53           14 :         case to_underlying(Tag::kEnableTagCompression):
      54              : #if CHIP_DETAIL_LOGGING
      55              :         {
      56              :             bool enableTagCompression;
      57           14 :             ReturnErrorOnFailure(reader.Get(enableTagCompression));
      58           14 :             PRETTY_PRINT("\tenableTagCompression = %s, ", enableTagCompression ? "true" : "false");
      59              :         }
      60              : #endif // CHIP_DETAIL_LOGGING
      61           14 :         break;
      62           27 :         case to_underlying(Tag::kNode):
      63           27 :             VerifyOrReturnError(TLV::kTLVType_UnsignedInteger == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
      64              : 
      65              : #if CHIP_DETAIL_LOGGING
      66              :             {
      67              :                 NodeId node;
      68           27 :                 reader.Get(node);
      69           27 :                 PRETTY_PRINT("\tNode = 0x" ChipLogFormatX64 ",", ChipLogValueX64(node));
      70              :             }
      71              : #endif // CHIP_DETAIL_LOGGING
      72           27 :             break;
      73        10838 :         case to_underlying(Tag::kEndpoint):
      74        10838 :             VerifyOrReturnError(TLV::kTLVType_UnsignedInteger == reader.GetType(), CHIP_ERROR_WRONG_TLV_TYPE);
      75              : #if CHIP_DETAIL_LOGGING
      76              :             {
      77              :                 EndpointId endpoint;
      78        10838 :                 reader.Get(endpoint);
      79        10838 :                 PRETTY_PRINT("\tEndpoint = 0x%x,", endpoint);
      80              :             }
      81              : #endif // CHIP_DETAIL_LOGGING
      82        10838 :             break;
      83        10775 :         case to_underlying(Tag::kCluster):
      84        10775 :             VerifyOrReturnError(TLV::kTLVType_UnsignedInteger == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
      85              : 
      86              : #if CHIP_DETAIL_LOGGING
      87              :             {
      88              :                 ClusterId cluster;
      89        10775 :                 ReturnErrorOnFailure(reader.Get(cluster));
      90        10775 :                 PRETTY_PRINT("\tCluster = 0x%" PRIx32 ",", cluster);
      91              :             }
      92              : #endif // CHIP_DETAIL_LOGGING
      93        10775 :             break;
      94        10558 :         case to_underlying(Tag::kAttribute):
      95        10558 :             VerifyOrReturnError(TLV::kTLVType_UnsignedInteger == reader.GetType(), CHIP_ERROR_WRONG_TLV_TYPE);
      96              : #if CHIP_DETAIL_LOGGING
      97              :             {
      98              :                 AttributeId attribute;
      99        10558 :                 ReturnErrorOnFailure(reader.Get(attribute));
     100        10558 :                 PRETTY_PRINT("\tAttribute = " ChipLogFormatMEI ",", ChipLogValueMEI(attribute));
     101              :             }
     102              : #endif // CHIP_DETAIL_LOGGING
     103        10558 :             break;
     104         4439 :         case to_underlying(Tag::kListIndex):
     105         4439 :             VerifyOrReturnError(TLV::kTLVType_UnsignedInteger == reader.GetType() || TLV::kTLVType_Null == reader.GetType(),
     106              :                                 CHIP_ERROR_WRONG_TLV_TYPE);
     107              : #if CHIP_DETAIL_LOGGING
     108              :             // We have checked the element is either uint or null
     109         4439 :             if (TLV::kTLVType_UnsignedInteger == reader.GetType())
     110              :             {
     111              :                 uint16_t listIndex;
     112           28 :                 ReturnErrorOnFailure(reader.Get(listIndex));
     113           28 :                 PRETTY_PRINT("\tListIndex = 0x%x,", listIndex);
     114              :             }
     115              :             else
     116              :             {
     117         4411 :                 PRETTY_PRINT("\tListIndex = Null,");
     118              :             }
     119              : #endif // CHIP_DETAIL_LOGGING
     120         4439 :             break;
     121            0 :         default:
     122            0 :             PRETTY_PRINT("Unknown tag num %" PRIu32, tagNum);
     123            0 :             break;
     124              :         }
     125              :     }
     126              : 
     127        11252 :     PRETTY_PRINT("}");
     128        11252 :     PRETTY_PRINT("\t");
     129              :     // if we have exhausted this container
     130        11252 :     if (CHIP_END_OF_TLV == err)
     131              :     {
     132        11252 :         err = CHIP_NO_ERROR;
     133              :     }
     134        11252 :     ReturnErrorOnFailure(err);
     135        11252 :     return reader.ExitContainer(mOuterContainerType);
     136              : }
     137              : #endif // CHIP_CONFIG_IM_PRETTY_PRINT
     138              : 
     139            1 : CHIP_ERROR AttributePathIB::Parser::GetEnableTagCompression(bool * const apEnableTagCompression) const
     140              : {
     141            1 :     return GetSimpleValue(to_underlying(Tag::kEnableTagCompression), TLV::kTLVType_Boolean, apEnableTagCompression);
     142              : }
     143              : 
     144            1 : CHIP_ERROR AttributePathIB::Parser::GetNode(NodeId * const apNode) const
     145              : {
     146            1 :     return GetUnsignedInteger(to_underlying(Tag::kNode), apNode);
     147              : }
     148              : 
     149        11140 : CHIP_ERROR AttributePathIB::Parser::GetEndpoint(EndpointId * const apEndpoint) const
     150              : {
     151        11140 :     return GetUnsignedInteger(to_underlying(Tag::kEndpoint), apEndpoint);
     152              : }
     153              : 
     154        11142 : CHIP_ERROR AttributePathIB::Parser::GetCluster(ClusterId * const apCluster) const
     155              : {
     156        11142 :     return GetUnsignedInteger(to_underlying(Tag::kCluster), apCluster);
     157              : }
     158              : 
     159        11142 : CHIP_ERROR AttributePathIB::Parser::GetAttribute(AttributeId * const apAttribute) const
     160              : {
     161        11142 :     return GetUnsignedInteger(to_underlying(Tag::kAttribute), apAttribute);
     162              : }
     163              : 
     164         1763 : CHIP_ERROR AttributePathIB::Parser::GetListIndex(ListIndex * const apListIndex) const
     165              : {
     166         1763 :     return GetUnsignedInteger(to_underlying(Tag::kListIndex), apListIndex);
     167              : }
     168              : 
     169         9377 : CHIP_ERROR AttributePathIB::Parser::GetListIndex(DataModel::Nullable<ListIndex> * const apListIndex) const
     170              : {
     171         9377 :     return GetNullableUnsignedInteger(to_underlying(Tag::kListIndex), apListIndex);
     172              : }
     173              : 
     174         9379 : CHIP_ERROR AttributePathIB::Parser::GetGroupAttributePath(ConcreteDataAttributePath & aAttributePath,
     175              :                                                           ValidateIdRanges aValidateRanges) const
     176              : {
     177         9379 :     ReturnErrorOnFailure(GetCluster(&aAttributePath.mClusterId));
     178         9379 :     ReturnErrorOnFailure(GetAttribute(&aAttributePath.mAttributeId));
     179              : 
     180         9377 :     if (aValidateRanges == ValidateIdRanges::kYes)
     181              :     {
     182         4967 :         VerifyOrReturnError(IsValidClusterId(aAttributePath.mClusterId), CHIP_IM_GLOBAL_STATUS(InvalidAction));
     183         4967 :         VerifyOrReturnError(IsValidAttributeId(aAttributePath.mAttributeId), CHIP_IM_GLOBAL_STATUS(InvalidAction));
     184              :     }
     185              : 
     186         9377 :     CHIP_ERROR err = CHIP_NO_ERROR;
     187         9377 :     DataModel::Nullable<ListIndex> listIndex;
     188         9377 :     err = GetListIndex(&(listIndex));
     189         9377 :     if (err == CHIP_NO_ERROR)
     190              :     {
     191         4420 :         if (listIndex.IsNull())
     192              :         {
     193         4420 :             aAttributePath.mListOp = ConcreteDataAttributePath::ListOperation::AppendItem;
     194              :         }
     195              :         else
     196              :         {
     197              :             // TODO: Add ListOperation::ReplaceItem support. (Attribute path with valid list index)
     198            0 :             err = CHIP_ERROR_IM_MALFORMED_ATTRIBUTE_PATH_IB;
     199              :         }
     200              :     }
     201         4957 :     else if (CHIP_END_OF_TLV == err)
     202              :     {
     203              :         // We do not have the context for the actual data type here. We always set the list operation to not list and the users
     204              :         // should interpret it as ReplaceAll when the attribute type is a list.
     205         4957 :         aAttributePath.mListOp = ConcreteDataAttributePath::ListOperation::NotList;
     206         4957 :         err                    = CHIP_NO_ERROR;
     207              :     }
     208         9377 :     return err;
     209              : }
     210              : 
     211         9379 : CHIP_ERROR AttributePathIB::Parser::GetConcreteAttributePath(ConcreteDataAttributePath & aAttributePath,
     212              :                                                              ValidateIdRanges aValidateRanges) const
     213              : {
     214         9379 :     ReturnErrorOnFailure(GetGroupAttributePath(aAttributePath, aValidateRanges));
     215              : 
     216              :     // And now read our endpoint.
     217         9377 :     return GetEndpoint(&aAttributePath.mEndpointId);
     218              : }
     219              : 
     220         1762 : CHIP_ERROR AttributePathIB::Parser::ParsePath(AttributePathParams & aAttribute) const
     221              : {
     222         1762 :     CHIP_ERROR err = CHIP_NO_ERROR;
     223              : 
     224         1762 :     err = GetEndpoint(&(aAttribute.mEndpointId));
     225         1762 :     if (err == CHIP_NO_ERROR)
     226              :     {
     227         1740 :         VerifyOrReturnError(!aAttribute.HasWildcardEndpointId(), CHIP_IM_GLOBAL_STATUS(InvalidAction));
     228              :     }
     229           22 :     else if (err == CHIP_END_OF_TLV)
     230              :     {
     231           22 :         err = CHIP_NO_ERROR;
     232              :     }
     233         1762 :     VerifyOrReturnError(err == CHIP_NO_ERROR, CHIP_IM_GLOBAL_STATUS(InvalidAction));
     234              : 
     235         1762 :     err = GetCluster(&aAttribute.mClusterId);
     236         1762 :     if (err == CHIP_NO_ERROR)
     237              :     {
     238         1679 :         VerifyOrReturnError(IsValidClusterId(aAttribute.mClusterId), CHIP_IM_GLOBAL_STATUS(InvalidAction));
     239              :     }
     240           83 :     else if (err == CHIP_END_OF_TLV)
     241              :     {
     242           83 :         err = CHIP_NO_ERROR;
     243              :     }
     244         1762 :     VerifyOrReturnError(err == CHIP_NO_ERROR, CHIP_IM_GLOBAL_STATUS(InvalidAction));
     245              : 
     246         1762 :     err = GetAttribute(&aAttribute.mAttributeId);
     247         1762 :     if (err == CHIP_NO_ERROR)
     248              :     {
     249         1462 :         VerifyOrReturnError(IsValidAttributeId(aAttribute.mAttributeId), CHIP_IM_GLOBAL_STATUS(InvalidAction));
     250              :     }
     251          300 :     else if (err == CHIP_END_OF_TLV)
     252              :     {
     253          300 :         err = CHIP_NO_ERROR;
     254              :     }
     255         1762 :     VerifyOrReturnError(err == CHIP_NO_ERROR, CHIP_IM_GLOBAL_STATUS(InvalidAction));
     256              : 
     257              :     // A wildcard cluster requires that the attribute path either be
     258              :     // wildcard or a global attribute.
     259         1762 :     VerifyOrReturnError(!aAttribute.HasWildcardClusterId() || aAttribute.HasWildcardAttributeId() ||
     260              :                             IsGlobalAttribute(aAttribute.mAttributeId),
     261              :                         CHIP_IM_GLOBAL_STATUS(InvalidAction));
     262              : 
     263         1762 :     err = GetListIndex(&aAttribute.mListIndex);
     264         1762 :     if (err == CHIP_NO_ERROR)
     265              :     {
     266           16 :         VerifyOrReturnError(!aAttribute.HasWildcardAttributeId() && !aAttribute.HasWildcardListIndex(),
     267              :                             CHIP_IM_GLOBAL_STATUS(InvalidAction));
     268              :     }
     269         1746 :     else if (err == CHIP_END_OF_TLV)
     270              :     {
     271         1746 :         err = CHIP_NO_ERROR;
     272              :     }
     273         1762 :     VerifyOrReturnError(err == CHIP_NO_ERROR, CHIP_IM_GLOBAL_STATUS(InvalidAction));
     274         1762 :     return CHIP_NO_ERROR;
     275              : }
     276              : 
     277           15 : AttributePathIB::Builder & AttributePathIB::Builder::EnableTagCompression(const bool aEnableTagCompression)
     278              : {
     279              :     // skip if error has already been set
     280           15 :     if (mError == CHIP_NO_ERROR)
     281              :     {
     282           15 :         mError = mpWriter->PutBoolean(TLV::ContextTag(Tag::kEnableTagCompression), aEnableTagCompression);
     283              :     }
     284           15 :     return *this;
     285              : }
     286              : 
     287           42 : AttributePathIB::Builder & AttributePathIB::Builder::Node(const NodeId aNode)
     288              : {
     289              :     // skip if error has already been set
     290           42 :     if (mError == CHIP_NO_ERROR)
     291              :     {
     292           42 :         mError = mpWriter->Put(TLV::ContextTag(Tag::kNode), aNode);
     293              :     }
     294           42 :     return *this;
     295              : }
     296              : 
     297        12576 : AttributePathIB::Builder & AttributePathIB::Builder::Endpoint(const EndpointId aEndpoint)
     298              : {
     299              :     // skip if error has already been set
     300        12576 :     if (mError == CHIP_NO_ERROR)
     301              :     {
     302        12558 :         mError = mpWriter->Put(TLV::ContextTag(Tag::kEndpoint), aEndpoint);
     303              :     }
     304        12576 :     return *this;
     305              : }
     306              : 
     307        12513 : AttributePathIB::Builder & AttributePathIB::Builder::Cluster(const ClusterId aCluster)
     308              : {
     309              :     // skip if error has already been set
     310        12513 :     if (mError == CHIP_NO_ERROR)
     311              :     {
     312        12449 :         mError = mpWriter->Put(TLV::ContextTag(Tag::kCluster), aCluster);
     313              :     }
     314        12513 :     return *this;
     315              : }
     316              : 
     317        12300 : AttributePathIB::Builder & AttributePathIB::Builder::Attribute(const AttributeId aAttribute)
     318              : {
     319              :     // skip if error has already been set
     320        12300 :     if (mError == CHIP_NO_ERROR)
     321              :     {
     322        12144 :         mError = mpWriter->Put(TLV::ContextTag(Tag::kAttribute), aAttribute);
     323              :     }
     324        12300 :     return *this;
     325              : }
     326              : 
     327         5866 : AttributePathIB::Builder & AttributePathIB::Builder::ListIndex(const DataModel::Nullable<chip::ListIndex> & aListIndex)
     328              : {
     329              :     // skip if error has already been set
     330         5866 :     if (mError == CHIP_NO_ERROR)
     331              :     {
     332         5710 :         mError = DataModel::Encode(*mpWriter, TLV::ContextTag(Tag::kListIndex), aListIndex);
     333              :     }
     334         5866 :     return *this;
     335              : }
     336              : 
     337           35 : AttributePathIB::Builder & AttributePathIB::Builder::ListIndex(const chip::ListIndex aListIndex)
     338              : {
     339              :     // skip if error has already been set
     340           35 :     if (mError == CHIP_NO_ERROR)
     341              :     {
     342           35 :         mError = mpWriter->Put(TLV::ContextTag(Tag::kListIndex), aListIndex);
     343              :     }
     344           35 :     return *this;
     345              : }
     346              : 
     347        12996 : CHIP_ERROR AttributePathIB::Builder::EndOfAttributePathIB()
     348              : {
     349        12996 :     EndOfContainer();
     350        12996 :     return GetError();
     351              : }
     352              : 
     353         1923 : CHIP_ERROR AttributePathIB::Builder::Encode(const AttributePathParams & aAttributePathParams)
     354              : {
     355         1923 :     if (!(aAttributePathParams.HasWildcardEndpointId()))
     356              :     {
     357         1503 :         Endpoint(aAttributePathParams.mEndpointId);
     358              :     }
     359              : 
     360         1923 :     if (!(aAttributePathParams.HasWildcardClusterId()))
     361              :     {
     362         1440 :         Cluster(aAttributePathParams.mClusterId);
     363              :     }
     364              : 
     365         1923 :     if (!(aAttributePathParams.HasWildcardAttributeId()))
     366              :     {
     367         1231 :         Attribute(aAttributePathParams.mAttributeId);
     368              :     }
     369              : 
     370         1923 :     if (!(aAttributePathParams.HasWildcardListIndex()))
     371              :     {
     372           14 :         ListIndex(aAttributePathParams.mListIndex);
     373              :     }
     374              : 
     375         1923 :     return EndOfAttributePathIB();
     376              : }
     377              : 
     378         2490 : CHIP_ERROR AttributePathIB::Builder::Encode(const ConcreteDataAttributePath & aAttributePath)
     379              : {
     380         2490 :     Endpoint(aAttributePath.mEndpointId);
     381         2490 :     Cluster(aAttributePath.mClusterId);
     382         2490 :     Attribute(aAttributePath.mAttributeId);
     383              : 
     384         2490 :     if (!aAttributePath.IsListOperation() || aAttributePath.mListOp == ConcreteDataAttributePath::ListOperation::ReplaceAll)
     385              :     {
     386              :         /* noop */
     387              :     }
     388         2059 :     else if (aAttributePath.mListOp == ConcreteDataAttributePath::ListOperation::AppendItem)
     389              :     {
     390         2059 :         ListIndex(DataModel::NullNullable);
     391              :     }
     392              :     else
     393              :     {
     394              :         // TODO: Add ListOperation::ReplaceItem support. (Attribute path with valid list index)
     395            0 :         return CHIP_ERROR_INVALID_ARGUMENT;
     396              :     }
     397              : 
     398         2490 :     return EndOfAttributePathIB();
     399              : }
     400              : 
     401              : } // namespace app
     402              : } // namespace chip
        

Generated by: LCOV version 2.0-1