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

Generated by: LCOV version 2.0-1