Matter SDK Coverage Report
Current view: top level - data-model-providers/codegen - EmberAttributeDataBuffer.cpp (source / functions) Coverage Total Hit
Test: SHA:2a48c1efeab1c0f76f3adb3a0940b0f7de706453 Lines: 99.4 % 179 178
Test Date: 2026-01-31 08:14:20 Functions: 100.0 % 9 9

            Line data    Source code
       1              : /*
       2              :  *    Copyright (c) 2024 Project CHIP Authors
       3              :  *    All rights reserved.
       4              :  *
       5              :  *    Licensed under the Apache License, Version 2.0 (the "License");
       6              :  *    you may not use this file except in compliance with the License.
       7              :  *    You may obtain a copy of the License at
       8              :  *
       9              :  *        http://www.apache.org/licenses/LICENSE-2.0
      10              :  *
      11              :  *    Unless required by applicable law or agreed to in writing, software
      12              :  *    distributed under the License is distributed on an "AS IS" BASIS,
      13              :  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      14              :  *    See the License for the specific language governing permissions and
      15              :  *    limitations under the License.
      16              :  */
      17              : #include <data-model-providers/codegen/EmberAttributeDataBuffer.h>
      18              : 
      19              : #include <app-common/zap-generated/attribute-type.h>
      20              : #include <app/AttributeValueEncoder.h>
      21              : #include <app/util/attribute-metadata.h>
      22              : #include <lib/core/CHIPError.h>
      23              : #include <lib/core/TLVTags.h>
      24              : #include <lib/core/TLVTypes.h>
      25              : #include <lib/core/TLVWriter.h>
      26              : #include <lib/support/CodeUtils.h>
      27              : #include <lib/support/odd-sized-integers.h>
      28              : #include <protocols/interaction_model/Constants.h>
      29              : #include <protocols/interaction_model/StatusCode.h>
      30              : 
      31              : #include <cstdint>
      32              : #include <limits>
      33              : 
      34              : namespace chip {
      35              : namespace app {
      36              : namespace Ember {
      37              : 
      38              : namespace {
      39              : 
      40              : /// Maximum length of a string, inclusive
      41              : ///
      42              : /// the max size value (0xFF and 0xFFFF) is reserved for NULL representation so
      43              : /// it is not available
      44           34 : constexpr uint32_t MaxLength(EmberAttributeDataBuffer::PascalStringType s)
      45              : {
      46           34 :     if (s == EmberAttributeDataBuffer::PascalStringType::kShort)
      47              :     {
      48           17 :         return std::numeric_limits<uint8_t>::max() - 1;
      49              :     }
      50              :     // EmberAttributeDataBuffer::PascalStringType::kLong:
      51           17 :     return std::numeric_limits<uint16_t>::max() - 1;
      52              : }
      53              : 
      54          329 : constexpr unsigned GetByteCountOfIntegerType(EmberAfAttributeType type)
      55              : {
      56              :     // This TERRIBLE bit fiddling, however it is small in flash
      57              :     // and we assert statically the actual values we care about
      58              : 
      59              :     // ZCL_INT8U_ATTRIBUTE_TYPE             = 0x20, // Unsigned 8-bit integer
      60              :     // ZCL_INT16U_ATTRIBUTE_TYPE            = 0x21, // Unsigned 16-bit integer
      61              :     // ZCL_INT24U_ATTRIBUTE_TYPE            = 0x22, // Unsigned 24-bit integer
      62              :     // ZCL_INT32U_ATTRIBUTE_TYPE            = 0x23, // Unsigned 32-bit integer
      63              :     // ZCL_INT40U_ATTRIBUTE_TYPE            = 0x24, // Unsigned 40-bit integer
      64              :     // ZCL_INT48U_ATTRIBUTE_TYPE            = 0x25, // Unsigned 48-bit integer
      65              :     // ZCL_INT56U_ATTRIBUTE_TYPE            = 0x26, // Unsigned 56-bit integer
      66              :     // ZCL_INT64U_ATTRIBUTE_TYPE            = 0x27, // Unsigned 64-bit integer
      67              :     //
      68              :     // ZCL_INT8S_ATTRIBUTE_TYPE             = 0x28, // Signed 8-bit integer
      69              :     // ZCL_INT16S_ATTRIBUTE_TYPE            = 0x29, // Signed 16-bit integer
      70              :     // ZCL_INT24S_ATTRIBUTE_TYPE            = 0x2A, // Signed 24-bit integer
      71              :     // ZCL_INT32S_ATTRIBUTE_TYPE            = 0x2B, // Signed 32-bit integer
      72              :     // ZCL_INT40S_ATTRIBUTE_TYPE            = 0x2C, // Signed 40-bit integer
      73              :     // ZCL_INT48S_ATTRIBUTE_TYPE            = 0x2D, // Signed 48-bit integer
      74              :     // ZCL_INT56S_ATTRIBUTE_TYPE            = 0x2E, // Signed 56-bit integer
      75              :     // ZCL_INT64S_ATTRIBUTE_TYPE            = 0x2F, // Signed 64-bit integer
      76              : 
      77          329 :     return (static_cast<unsigned>(type) % 8) + 1;
      78              : }
      79              : static_assert(GetByteCountOfIntegerType(ZCL_INT8U_ATTRIBUTE_TYPE) == 1);
      80              : static_assert(GetByteCountOfIntegerType(ZCL_INT8S_ATTRIBUTE_TYPE) == 1);
      81              : static_assert(GetByteCountOfIntegerType(ZCL_INT16U_ATTRIBUTE_TYPE) == 2);
      82              : static_assert(GetByteCountOfIntegerType(ZCL_INT16S_ATTRIBUTE_TYPE) == 2);
      83              : static_assert(GetByteCountOfIntegerType(ZCL_INT24U_ATTRIBUTE_TYPE) == 3);
      84              : static_assert(GetByteCountOfIntegerType(ZCL_INT24S_ATTRIBUTE_TYPE) == 3);
      85              : static_assert(GetByteCountOfIntegerType(ZCL_INT32U_ATTRIBUTE_TYPE) == 4);
      86              : static_assert(GetByteCountOfIntegerType(ZCL_INT32S_ATTRIBUTE_TYPE) == 4);
      87              : static_assert(GetByteCountOfIntegerType(ZCL_INT40U_ATTRIBUTE_TYPE) == 5);
      88              : static_assert(GetByteCountOfIntegerType(ZCL_INT40S_ATTRIBUTE_TYPE) == 5);
      89              : static_assert(GetByteCountOfIntegerType(ZCL_INT48U_ATTRIBUTE_TYPE) == 6);
      90              : static_assert(GetByteCountOfIntegerType(ZCL_INT48S_ATTRIBUTE_TYPE) == 6);
      91              : static_assert(GetByteCountOfIntegerType(ZCL_INT56U_ATTRIBUTE_TYPE) == 7);
      92              : static_assert(GetByteCountOfIntegerType(ZCL_INT56S_ATTRIBUTE_TYPE) == 7);
      93              : static_assert(GetByteCountOfIntegerType(ZCL_INT64U_ATTRIBUTE_TYPE) == 8);
      94              : static_assert(GetByteCountOfIntegerType(ZCL_INT64S_ATTRIBUTE_TYPE) == 8);
      95              : 
      96              : /// Encodes the string of type stringType pointed to by `reader` into the TLV `writer`.
      97              : /// Then encoded string will be at tag `tag` and of type `tlvType`
      98           29 : CHIP_ERROR EncodeString(EmberAttributeDataBuffer::PascalStringType stringType, TLV::TLVType tlvType, TLV::TLVWriter & writer,
      99              :                         TLV::Tag tag, EmberAttributeDataBuffer::EndianReader & reader, bool nullable)
     100              : {
     101              :     unsigned stringLen;
     102           29 :     if (stringType == EmberAttributeDataBuffer::PascalStringType::kShort)
     103              :     {
     104              :         uint8_t len;
     105           15 :         if (!reader.Read8(&len).IsSuccess())
     106              :         {
     107            2 :             return reader.StatusCode();
     108              :         }
     109           15 :         if (len == NumericAttributeTraits<uint8_t>::kNullValue)
     110              :         {
     111            2 :             VerifyOrReturnError(nullable, CHIP_ERROR_INVALID_ARGUMENT);
     112            2 :             return writer.PutNull(tag);
     113              :         }
     114           13 :         stringLen = len;
     115              :     }
     116              :     else
     117              :     {
     118              :         uint16_t len;
     119           14 :         if (!reader.Read16(&len).IsSuccess())
     120              :         {
     121            3 :             return reader.StatusCode();
     122              :         }
     123           14 :         if (len == NumericAttributeTraits<uint16_t>::kNullValue)
     124              :         {
     125            3 :             VerifyOrReturnError(nullable, CHIP_ERROR_INVALID_ARGUMENT);
     126            3 :             return writer.PutNull(tag);
     127              :         }
     128           11 :         stringLen = len;
     129              :     }
     130              : 
     131              :     const uint8_t * data;
     132           24 :     if (!reader.ZeroCopyProcessBytes(stringLen, &data).IsSuccess())
     133              :     {
     134            2 :         return reader.StatusCode();
     135              :     }
     136              : 
     137           22 :     if (tlvType == TLV::kTLVType_UTF8String)
     138              :     {
     139           11 :         return writer.PutString(tag, reinterpret_cast<const char *>(data), stringLen);
     140              :     }
     141              : 
     142           11 :     return writer.PutBytes(tag, data, stringLen);
     143              : }
     144              : 
     145              : } // namespace
     146              : 
     147           87 : CHIP_ERROR EmberAttributeDataBuffer::DecodeUnsignedInteger(chip::TLV::TLVReader & reader, EndianWriter & writer)
     148              : {
     149           87 :     const unsigned byteCount = GetByteCountOfIntegerType(mAttributeType);
     150           87 :     const uint64_t maxValue  = NumericLimits::MaxUnsignedValue(byteCount);
     151              : 
     152              :     // Any size of integer can be read by TLV getting 64-bit integers
     153              :     uint64_t value;
     154              : 
     155           87 :     if (reader.GetType() == TLV::kTLVType_Null)
     156              :     {
     157              :         // we know mIsNullable due to the check at the top of ::Decode
     158           22 :         value = NumericLimits::UnsignedMaxValueToNullValue(maxValue);
     159              :     }
     160              :     else
     161              :     {
     162           65 :         ReturnErrorOnFailure(reader.Get(value));
     163              : 
     164              :         bool valid =
     165              :             // Value is in [0, max] RANGE
     166           64 :             (value <= maxValue)
     167              :             // Nullable values reserve a specific value to mean NULL
     168           64 :             && !(mIsNullable && (value == NumericLimits::UnsignedMaxValueToNullValue(maxValue)));
     169              : 
     170           64 :         VerifyOrReturnError(valid, CHIP_IM_GLOBAL_STATUS(ConstraintError));
     171              :     }
     172              : 
     173           74 :     writer.EndianPut(value, byteCount);
     174           74 :     return CHIP_NO_ERROR;
     175              : }
     176              : 
     177          120 : CHIP_ERROR EmberAttributeDataBuffer::DecodeSignedInteger(chip::TLV::TLVReader & reader, EndianWriter & writer)
     178              : {
     179          120 :     const unsigned byteCount = GetByteCountOfIntegerType(mAttributeType);
     180          120 :     const int64_t minValue   = NumericLimits::MinSignedValue(byteCount);
     181          120 :     const int64_t maxValue   = NumericLimits::MaxSignedValue(byteCount);
     182              : 
     183              :     // Any size of integer can be read by TLV getting 64-bit integers
     184              :     int64_t value;
     185              : 
     186          120 :     if (reader.GetType() == TLV::kTLVType_Null)
     187              :     {
     188              :         // we know mIsNullable due to the check at the top of ::Decode
     189           27 :         value = NumericLimits::SignedMinValueToNullValue(minValue);
     190              :     }
     191              :     else
     192              :     {
     193           93 :         ReturnErrorOnFailure(reader.Get(value));
     194              : 
     195              :         bool valid =
     196              :             // Value is in [min, max] RANGE
     197           89 :             ((value >= minValue) && (value <= maxValue))
     198              :             // Nullable values reserve a specific value to mean NULL
     199          182 :             && !(mIsNullable && (value == NumericLimits::SignedMinValueToNullValue(minValue)));
     200              : 
     201           93 :         VerifyOrReturnError(valid, CHIP_IM_GLOBAL_STATUS(ConstraintError));
     202              :     }
     203          107 :     writer.EndianPutSigned(value, byteCount);
     204          107 :     return CHIP_NO_ERROR;
     205              : }
     206              : 
     207           42 : CHIP_ERROR EmberAttributeDataBuffer::DecodeAsString(chip::TLV::TLVReader & reader, PascalStringType stringType,
     208              :                                                     TLV::TLVType tlvType, EndianWriter & writer)
     209              : {
     210              :     // Handle null first, then the actual data
     211           42 :     if (reader.GetType() == TLV::kTLVType_Null)
     212              :     {
     213              :         // we know mIsNullable due to the check at the top of ::Decode
     214            7 :         switch (stringType)
     215              :         {
     216            3 :         case PascalStringType::kShort:
     217            3 :             writer.Put8(NumericAttributeTraits<uint8_t>::kNullValue);
     218            3 :             break;
     219            4 :         case PascalStringType::kLong:
     220            4 :             writer.Put16(NumericAttributeTraits<uint16_t>::kNullValue);
     221            4 :             break;
     222              :         }
     223              : 
     224            7 :         return CHIP_NO_ERROR;
     225              :     }
     226              : 
     227           35 :     const uint32_t stringLength = reader.GetLength();
     228              : 
     229           35 :     VerifyOrReturnError(reader.GetType() == tlvType, CHIP_ERROR_WRONG_TLV_TYPE);
     230           34 :     VerifyOrReturnError(stringLength <= MaxLength(stringType), CHIP_ERROR_INVALID_ARGUMENT);
     231              : 
     232              :     // Size is a prefix, where 0xFF/0xFFFF is the null marker (if applicable)
     233           34 :     switch (stringType)
     234              :     {
     235           17 :     case PascalStringType::kShort:
     236           17 :         writer.Put8(static_cast<uint8_t>(stringLength));
     237           17 :         break;
     238           17 :     case PascalStringType::kLong:
     239           17 :         writer.Put16(static_cast<uint16_t>(stringLength));
     240           17 :         break;
     241              :     }
     242              : 
     243              :     // data copy
     244              :     const uint8_t * tlvData;
     245           34 :     ReturnErrorOnFailure(reader.GetDataPtr(tlvData));
     246           34 :     writer.Put(tlvData, stringLength);
     247              : 
     248           34 :     return CHIP_NO_ERROR;
     249              : }
     250              : 
     251          297 : CHIP_ERROR EmberAttributeDataBuffer::Decode(chip::TLV::TLVReader & reader)
     252              : {
     253              :     // all methods below assume that nullable setting matches (this is to reduce code size
     254              :     // even though clarity suffers)
     255          297 :     VerifyOrReturnError(mIsNullable || reader.GetType() != TLV::kTLVType_Null, CHIP_ERROR_WRONG_TLV_TYPE);
     256              : 
     257          277 :     EndianWriter endianWriter(mDataBuffer.data(), mDataBuffer.size());
     258              : 
     259          277 :     switch (mAttributeType)
     260              :     {
     261           12 :     case ZCL_BOOLEAN_ATTRIBUTE_TYPE: // Boolean
     262              :         // Boolean values:
     263              :         //   0x00 is FALSE
     264              :         //   0x01 is TRUE
     265              :         //   0xFF is NULL
     266           12 :         if (reader.GetType() == TLV::kTLVType_Null)
     267              :         {
     268              :             // we know mIsNullable due to the check at the top of ::Decode
     269            4 :             endianWriter.Put8(NumericAttributeTraits<bool>::kNullValue);
     270              :         }
     271              :         else
     272              :         {
     273              :             bool value;
     274            8 :             ReturnErrorOnFailure(reader.Get(value));
     275            8 :             endianWriter.Put8(value ? 1 : 0);
     276              :         }
     277           12 :         break;
     278           87 :     case ZCL_INT8U_ATTRIBUTE_TYPE:  // Unsigned 8-bit integer
     279              :     case ZCL_INT16U_ATTRIBUTE_TYPE: // Unsigned 16-bit integer
     280              :     case ZCL_INT24U_ATTRIBUTE_TYPE: // Unsigned 24-bit integer
     281              :     case ZCL_INT32U_ATTRIBUTE_TYPE: // Unsigned 32-bit integer
     282              :     case ZCL_INT40U_ATTRIBUTE_TYPE: // Unsigned 40-bit integer
     283              :     case ZCL_INT48U_ATTRIBUTE_TYPE: // Unsigned 48-bit integer
     284              :     case ZCL_INT56U_ATTRIBUTE_TYPE: // Unsigned 56-bit integer
     285              :     case ZCL_INT64U_ATTRIBUTE_TYPE: // Unsigned 64-bit integer
     286           87 :         ReturnErrorOnFailure(DecodeUnsignedInteger(reader, endianWriter));
     287           74 :         break;
     288          120 :     case ZCL_INT8S_ATTRIBUTE_TYPE:  // Signed 8-bit integer
     289              :     case ZCL_INT16S_ATTRIBUTE_TYPE: // Signed 16-bit integer
     290              :     case ZCL_INT24S_ATTRIBUTE_TYPE: // Signed 24-bit integer
     291              :     case ZCL_INT32S_ATTRIBUTE_TYPE: // Signed 32-bit integer
     292              :     case ZCL_INT40S_ATTRIBUTE_TYPE: // Signed 40-bit integer
     293              :     case ZCL_INT48S_ATTRIBUTE_TYPE: // Signed 48-bit integer
     294              :     case ZCL_INT56S_ATTRIBUTE_TYPE: // Signed 56-bit integer
     295              :     case ZCL_INT64S_ATTRIBUTE_TYPE: // Signed 64-bit integer
     296          120 :         ReturnErrorOnFailure(DecodeSignedInteger(reader, endianWriter));
     297          107 :         break;
     298            7 :     case ZCL_SINGLE_ATTRIBUTE_TYPE: { // 32-bit float
     299              :         float value;
     300            7 :         if (reader.GetType() == TLV::kTLVType_Null)
     301              :         {
     302              :             // we know mIsNullable due to the check at the top of ::Decode
     303            3 :             NumericAttributeTraits<float>::SetNull(value);
     304              :         }
     305              :         else
     306              :         {
     307              : 
     308            4 :             ReturnErrorOnFailure(reader.Get(value));
     309              :         }
     310            7 :         endianWriter.Put(&value, sizeof(value));
     311            7 :         break;
     312              :     }
     313            7 :     case ZCL_DOUBLE_ATTRIBUTE_TYPE: { // 64-bit float
     314              :         double value;
     315            7 :         if (reader.GetType() == TLV::kTLVType_Null)
     316              :         {
     317              :             // we know mIsNullable due to the check at the top of ::Decode
     318            3 :             NumericAttributeTraits<double>::SetNull(value);
     319              :         }
     320              :         else
     321              :         {
     322            4 :             ReturnErrorOnFailure(reader.Get(value));
     323              :         }
     324            7 :         endianWriter.Put(&value, sizeof(value));
     325            7 :         break;
     326              :     }
     327           15 :     case ZCL_CHAR_STRING_ATTRIBUTE_TYPE: // Char string
     328           15 :         ReturnErrorOnFailure(DecodeAsString(reader, PascalStringType::kShort, TLV::kTLVType_UTF8String, endianWriter));
     329           14 :         break;
     330           15 :     case ZCL_LONG_CHAR_STRING_ATTRIBUTE_TYPE:
     331           15 :         ReturnErrorOnFailure(DecodeAsString(reader, PascalStringType::kLong, TLV::kTLVType_UTF8String, endianWriter));
     332           15 :         break;
     333            6 :     case ZCL_OCTET_STRING_ATTRIBUTE_TYPE: // Octet string
     334            6 :         ReturnErrorOnFailure(DecodeAsString(reader, PascalStringType::kShort, TLV::kTLVType_ByteString, endianWriter));
     335            6 :         break;
     336            6 :     case ZCL_LONG_OCTET_STRING_ATTRIBUTE_TYPE:
     337            6 :         ReturnErrorOnFailure(DecodeAsString(reader, PascalStringType::kLong, TLV::kTLVType_ByteString, endianWriter));
     338            6 :         break;
     339            2 :     default:
     340            2 :         ChipLogError(DataManagement, "Attribute type 0x%x not handled", mAttributeType);
     341            2 :         return CHIP_IM_GLOBAL_STATUS(Failure);
     342              :     }
     343              : 
     344              :     size_t written;
     345          248 :     if (!endianWriter.Fit(written))
     346              :     {
     347            6 :         return CHIP_ERROR_NO_MEMORY;
     348              :     }
     349              : 
     350          242 :     mDataBuffer.reduce_size(written);
     351          242 :     return CHIP_NO_ERROR;
     352              : }
     353              : 
     354          122 : CHIP_ERROR EmberAttributeDataBuffer::EncodeInteger(chip::TLV::TLVWriter & writer, TLV::Tag tag, EndianReader & reader) const
     355              : {
     356              :     // Encodes an integer by first reading as raw bytes and then
     357              :     // bitshift-convert
     358              :     //
     359              :     // This optimizes code size rather than readability at this point.
     360              : 
     361              :     uint8_t raw_bytes[8];
     362              : 
     363          122 :     const bool isSigned      = IsSignedAttributeType(mAttributeType);
     364          122 :     const unsigned byteCount = GetByteCountOfIntegerType(mAttributeType);
     365              : 
     366              :     const uint64_t nullValueAsU64 = isSigned
     367          122 :         ? static_cast<uint64_t>(NumericLimits::SignedMinValueToNullValue(NumericLimits::MinSignedValue(byteCount)))
     368           60 :         : NumericLimits::UnsignedMaxValueToNullValue(NumericLimits::MaxUnsignedValue(byteCount));
     369              : 
     370          122 :     VerifyOrDie(sizeof(raw_bytes) >= byteCount);
     371          122 :     if (!reader.ReadBytes(raw_bytes, byteCount).IsSuccess())
     372              :     {
     373            1 :         return reader.StatusCode();
     374              :     }
     375              : 
     376              :     // At this point, RAW_VALUE contains the actual value, need to make it "real"
     377              :     union
     378              :     {
     379              :         int64_t int_value;
     380              :         uint64_t uint_value;
     381              :     } value;
     382              : 
     383          121 :     value.uint_value = 0;
     384              : 
     385              : #if CHIP_CONFIG_BIG_ENDIAN_TARGET
     386              :     bool isNegative = isSigned && (raw_bytes[0] >= 0x80);
     387              :     if (isNegative)
     388              :     {
     389              :         value.int_value = -1;
     390              :     }
     391              :     for (int i = 0; i < static_cast<int>(byteCount); i++)
     392              :     {
     393              : #else
     394          121 :     bool isNegative = isSigned && (raw_bytes[byteCount - 1] >= 0x80);
     395          121 :     if (isNegative)
     396              :     {
     397           42 :         value.int_value = -1;
     398              :     }
     399          559 :     for (int i = static_cast<int>(byteCount) - 1; i >= 0; i--)
     400              :     {
     401              : #endif
     402          438 :         value.uint_value <<= 8;
     403          438 :         value.uint_value = (value.uint_value & ~0xFFULL) | raw_bytes[i];
     404              :     }
     405              : 
     406              :     // We place the null value as either int_value or uint_value into a union that is
     407              :     // bit-formatted as both int64 and uint64. When we define the nullValue,
     408              :     // it is bitcast into u64 hence this comparison. This is ugly, however this
     409              :     // code prioritizes code size over readability here.
     410          121 :     if (mIsNullable && (value.uint_value == nullValueAsU64))
     411              :     {
     412           29 :         return writer.PutNull(tag);
     413              :     }
     414              : 
     415           92 :     if (isSigned)
     416              :     {
     417           49 :         return writer.Put(tag, value.int_value);
     418              :     }
     419              : 
     420           43 :     return writer.Put(tag, value.uint_value);
     421              : }
     422              : 
     423          181 : CHIP_ERROR EmberAttributeDataBuffer::Encode(chip::TLV::TLVWriter & writer, TLV::Tag tag) const
     424              : {
     425          181 :     EndianReader endianReader(mDataBuffer.data(), mDataBuffer.size());
     426              : 
     427          181 :     switch (mAttributeType)
     428              :     {
     429            3 :     case ZCL_NO_DATA_ATTRIBUTE_TYPE: // No data
     430            3 :         return writer.PutNull(tag);
     431           11 :     case ZCL_BOOLEAN_ATTRIBUTE_TYPE: { // Boolean
     432              :         uint8_t value;
     433           11 :         if (!endianReader.Read8(&value).IsSuccess())
     434              :         {
     435            0 :             return endianReader.StatusCode();
     436              :         }
     437           11 :         switch (value)
     438              :         {
     439            6 :         case 0:
     440              :         case 1:
     441            6 :             return writer.PutBoolean(tag, value != 0);
     442            4 :         case 0xFF:
     443            4 :             VerifyOrReturnError(mIsNullable, CHIP_ERROR_INVALID_ARGUMENT);
     444            2 :             return writer.PutNull(tag);
     445            1 :         default:
     446              :             // Unknown types
     447            1 :             return CHIP_ERROR_INVALID_ARGUMENT;
     448              :         }
     449              :     }
     450          122 :     case ZCL_INT8U_ATTRIBUTE_TYPE:  // Unsigned 8-bit integer
     451              :     case ZCL_INT16U_ATTRIBUTE_TYPE: // Unsigned 16-bit integer
     452              :     case ZCL_INT24U_ATTRIBUTE_TYPE: // Unsigned 24-bit integer
     453              :     case ZCL_INT32U_ATTRIBUTE_TYPE: // Unsigned 32-bit integer
     454              :     case ZCL_INT40U_ATTRIBUTE_TYPE: // Unsigned 40-bit integer
     455              :     case ZCL_INT48U_ATTRIBUTE_TYPE: // Unsigned 48-bit integer
     456              :     case ZCL_INT56U_ATTRIBUTE_TYPE: // Unsigned 56-bit integer
     457              :     case ZCL_INT64U_ATTRIBUTE_TYPE: // Unsigned 64-bit integer
     458              :     case ZCL_INT8S_ATTRIBUTE_TYPE:  // Signed 8-bit integer
     459              :     case ZCL_INT16S_ATTRIBUTE_TYPE: // Signed 16-bit integer
     460              :     case ZCL_INT24S_ATTRIBUTE_TYPE: // Signed 24-bit integer
     461              :     case ZCL_INT32S_ATTRIBUTE_TYPE: // Signed 32-bit integer
     462              :     case ZCL_INT40S_ATTRIBUTE_TYPE: // Signed 40-bit integer
     463              :     case ZCL_INT48S_ATTRIBUTE_TYPE: // Signed 48-bit integer
     464              :     case ZCL_INT56S_ATTRIBUTE_TYPE: // Signed 56-bit integer
     465              :     case ZCL_INT64S_ATTRIBUTE_TYPE: // Signed 64-bit integer
     466          122 :         return EncodeInteger(writer, tag, endianReader);
     467            7 :     case ZCL_SINGLE_ATTRIBUTE_TYPE: { // 32-bit float
     468              :         union
     469              :         {
     470              :             uint8_t raw[sizeof(float)];
     471              :             float value;
     472              :         } value;
     473              : 
     474            7 :         if (!endianReader.ReadBytes(value.raw, sizeof(value)).IsSuccess())
     475              :         {
     476            1 :             return endianReader.StatusCode();
     477              :         }
     478            6 :         if (mIsNullable && NumericAttributeTraits<float>::IsNullValue(value.value))
     479              :         {
     480            2 :             return writer.PutNull(tag);
     481              :         }
     482            4 :         return writer.Put(tag, value.value);
     483              :     }
     484            8 :     case ZCL_DOUBLE_ATTRIBUTE_TYPE: { // 64-bit float
     485              :         union
     486              :         {
     487              :             uint8_t raw[sizeof(double)];
     488              :             double value;
     489              :         } value;
     490              : 
     491            8 :         if (!endianReader.ReadBytes(value.raw, sizeof(value)).IsSuccess())
     492              :         {
     493            1 :             return endianReader.StatusCode();
     494              :         }
     495            7 :         if (mIsNullable && NumericAttributeTraits<double>::IsNullValue(value.value))
     496              :         {
     497            2 :             return writer.PutNull(tag);
     498              :         }
     499            5 :         return writer.Put(tag, value.value);
     500              :     }
     501              : 
     502            9 :     case ZCL_CHAR_STRING_ATTRIBUTE_TYPE: // Char string
     503            9 :         return EncodeString(PascalStringType::kShort, TLV::kTLVType_UTF8String, writer, tag, endianReader, mIsNullable);
     504            6 :     case ZCL_LONG_CHAR_STRING_ATTRIBUTE_TYPE:
     505            6 :         return EncodeString(PascalStringType::kLong, TLV::kTLVType_UTF8String, writer, tag, endianReader, mIsNullable);
     506            6 :     case ZCL_OCTET_STRING_ATTRIBUTE_TYPE: // Octet string
     507            6 :         return EncodeString(PascalStringType::kShort, TLV::kTLVType_ByteString, writer, tag, endianReader, mIsNullable);
     508            8 :     case ZCL_LONG_OCTET_STRING_ATTRIBUTE_TYPE:
     509            8 :         return EncodeString(PascalStringType::kLong, TLV::kTLVType_ByteString, writer, tag, endianReader, mIsNullable);
     510            1 :     default:
     511            1 :         ChipLogError(DataManagement, "Attribute type 0x%x not handled", static_cast<int>(mAttributeType));
     512            1 :         return CHIP_IM_GLOBAL_STATUS(Failure);
     513              :     }
     514              : }
     515              : 
     516              : } // namespace Ember
     517              : } // namespace app
     518              : } // namespace chip
        

Generated by: LCOV version 2.0-1