Matter SDK Coverage Report
Current view: top level - app/persistence - PascalString.h (source / functions) Coverage Total Hit
Test: SHA:02d5c4a2a4954211029a6453d554e1269733873d Lines: 0.0 % 6 0
Test Date: 2025-07-04 07:09:36 Functions: 0.0 % 4 0

            Line data    Source code
       1              : /**
       2              :  *    Copyright (c) 2025 Project CHIP Authors
       3              :  *
       4              :  *    Licensed under the Apache License, Version 2.0 (the "License");
       5              :  *    you may not use this file except in compliance with the License.
       6              :  *    You may obtain a copy of the License at
       7              :  *
       8              :  *        http://www.apache.org/licenses/LICENSE-2.0
       9              :  *
      10              :  *    Unless required by applicable law or agreed to in writing, software
      11              :  *    distributed under the License is distributed on an "AS IS" BASIS,
      12              :  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      13              :  *    See the License for the specific language governing permissions and
      14              :  *    limitations under the License.
      15              :  */
      16              : #pragma once
      17              : 
      18              : #include <app/ConcreteAttributePath.h>
      19              : #include <lib/core/CHIPEncoding.h>
      20              : #include <lib/core/CHIPError.h>
      21              : #include <lib/core/CHIPSafeCasts.h>
      22              : #include <lib/support/CodeUtils.h>
      23              : #include <lib/support/Span.h>
      24              : 
      25              : #include <algorithm>
      26              : #include <cstdint>
      27              : 
      28              : namespace chip {
      29              : namespace app {
      30              : namespace Storage {
      31              : 
      32              : /// Describes how to set/get the length of pascal strings
      33              : /// given a PREFIX_LEN in bytes.
      34              : template <size_t PREFIX_LEN>
      35              : struct PascalPrefixOperations;
      36              : 
      37              : template <>
      38              : struct PascalPrefixOperations<1>
      39              : {
      40              :     using LengthType                           = uint8_t;
      41              :     static constexpr LengthType kInvalidLength = 0xFF;
      42              : 
      43            0 :     static LengthType GetLength(const uint8_t * buffer) { return *buffer; }
      44              :     static void SetLength(uint8_t * buffer, LengthType size) { *buffer = static_cast<uint8_t>(size); }
      45              : 
      46              :     // Casts for chars as well
      47              :     static LengthType GetLength(const char * buffer) { return GetLength(Uint8::from_const_char(buffer)); }
      48              :     static void SetLength(char * buffer, LengthType size) { SetLength(Uint8::from_char(buffer), size); }
      49              : };
      50              : 
      51              : template <>
      52              : struct PascalPrefixOperations<2>
      53              : {
      54              :     using LengthType                           = uint16_t;
      55              :     static constexpr LengthType kInvalidLength = 0xFFFF;
      56              : 
      57            0 :     static LengthType GetLength(const uint8_t * buffer) { return Encoding::LittleEndian::Get16(buffer); }
      58              :     static void SetLength(uint8_t * buffer, LengthType size) { Encoding::LittleEndian::Put16(buffer, size); }
      59              : 
      60              :     // Casts for chars as well
      61              :     static LengthType GetLength(const char * buffer) { return GetLength(Uint8::from_const_char(buffer)); }
      62              :     static void SetLength(char * buffer, LengthType size) { SetLength(Uint8::from_char(buffer), size); }
      63              : };
      64              : 
      65              : /// Interprets a byte buffer as a pascal buffer:
      66              : ///   - a prefix that specifies the length of the data
      67              : ///   - the following characters that contain the data
      68              : ///
      69              : /// Parameters:
      70              : ///   T - the underlying data type, generally uint8_t for bytes or char for strings
      71              : ///   PREFIX_LEN - the size of the pascal prefix (generally 1 or 2 bytes)
      72              : template <typename T, uint8_t PREFIX_LEN>
      73              : class PascalBuffer
      74              : {
      75              : public:
      76              :     using LengthType                           = typename PascalPrefixOperations<PREFIX_LEN>::LengthType;
      77              :     static constexpr LengthType kInvalidLength = PascalPrefixOperations<PREFIX_LEN>::kInvalidLength;
      78              : 
      79              :     static_assert(sizeof(T) == 1);
      80              : 
      81              :     PascalBuffer(PascalBuffer &&)      = default;
      82              :     PascalBuffer(const PascalBuffer &) = default;
      83              : 
      84              :     template <size_t N>
      85              :     PascalBuffer(T (&data)[N]) : mData(data), mMaxSize(N - PREFIX_LEN)
      86              :     {
      87              :         static_assert(N >= PREFIX_LEN);
      88              :         static_assert(N <= kInvalidLength);
      89              :     }
      90              : 
      91              :     /// Returns the content of the pascal string.
      92              :     /// Uses the prefix size information
      93              :     Span<T> Content() { return { mData + PREFIX_LEN, GetLength() }; }
      94              :     Span<const T> Content() const { return { mData + PREFIX_LEN, GetLength() }; }
      95              : 
      96              :     /// Accesses the "PASCAL" string (i.e. valid data including the string prefix)
      97              :     Span<const T> PascalContent() const { return { mData, static_cast<size_t>(GetLength() + PREFIX_LEN) }; }
      98              : 
      99              :     /// Access to the full buffer. does NOT take into account current size
     100              :     /// and includes the "size prefix"
     101              :     Span<T> Buffer() { return { mData, static_cast<size_t>(mMaxSize + PREFIX_LEN) }; }
     102              : 
     103              :     LengthType GetLength() const
     104              :     {
     105              :         const LengthType length = PascalPrefixOperations<PREFIX_LEN>::GetLength(mData);
     106              :         if (length == kInvalidLength)
     107              :         {
     108              :             return 0;
     109              :         }
     110              :         return std::min<LengthType>(mMaxSize, length);
     111              :     }
     112              : 
     113              :     // Returns true if the length was valid and could be set
     114              :     bool SetLength(LengthType len)
     115              :     {
     116              :         if (len != kInvalidLength)
     117              :         {
     118              :             VerifyOrReturnError(len <= mMaxSize, false);
     119              :         }
     120              :         PascalPrefixOperations<PREFIX_LEN>::SetLength(mData, len);
     121              :         return true;
     122              :     }
     123              :     void SetNull() { (void) SetLength(kInvalidLength); }
     124              :     bool IsNull() const { return PascalPrefixOperations<PREFIX_LEN>::GetLength(mData) == kInvalidLength; }
     125              : 
     126              :     // Returns true if the length of the input buffer fit in the
     127              :     // pascal buffer (and could be set)
     128              :     bool SetValue(Span<const T> value)
     129              :     {
     130              :         VerifyOrReturnValue(value.size() < kInvalidLength, false);
     131              :         VerifyOrReturnValue(SetLength(static_cast<LengthType>(value.size())), false);
     132              :         memcpy(mData + PREFIX_LEN, value.data(), value.size());
     133              :         return true;
     134              :     }
     135              : 
     136              :     /// Checks if the given span is a valid Pascal string: i.e. its size prefix
     137              :     /// is either Invalid (i.e. null marker) or it has a size that fits in the buffer
     138            0 :     static bool IsValid(Span<const T> span)
     139              :     {
     140            0 :         VerifyOrReturnValue(span.size() >= PREFIX_LEN, false);
     141            0 :         LengthType len = PascalPrefixOperations<PREFIX_LEN>::GetLength(span.data());
     142            0 :         return len == kInvalidLength || (static_cast<size_t>(len + PREFIX_LEN) <= span.size());
     143              :     }
     144              : 
     145              : private:
     146              :     T * mData;
     147              :     const LengthType mMaxSize;
     148              : };
     149              : 
     150              : using ShortPascalString = PascalBuffer<char, 1>;
     151              : using ShortPascalBytes  = PascalBuffer<uint8_t, 1>;
     152              : using LongPascalString  = PascalBuffer<char, 2>;
     153              : using LongPascalBytes   = PascalBuffer<uint8_t, 2>;
     154              : 
     155              : } // namespace Storage
     156              : } // namespace app
     157              : } // namespace chip
        

Generated by: LCOV version 2.0-1