Matter SDK Coverage Report
Current view: top level - app/data-model-provider - MetadataList.h (source / functions) Coverage Total Hit
Test: SHA:f84fe08d06f240e801b5d923f8a938a9938ca110 Lines: 100.0 % 18 18
Test Date: 2025-02-22 08:08:07 Functions: 90.2 % 41 37

            Line data    Source code
       1              : /*
       2              :  *
       3              :  *    Copyright (c) 2024 Project CHIP Authors
       4              :  *    All rights reserved.
       5              :  *
       6              :  *    Licensed under the Apache License, Version 2.0 (the "License");
       7              :  *    you may not use this file except in compliance with the License.
       8              :  *    You may obtain a copy of the License at
       9              :  *
      10              :  *        http://www.apache.org/licenses/LICENSE-2.0
      11              :  *
      12              :  *    Unless required by applicable law or agreed to in writing, software
      13              :  *    distributed under the License is distributed on an "AS IS" BASIS,
      14              :  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      15              :  *    See the License for the specific language governing permissions and
      16              :  *    limitations under the License.
      17              :  */
      18              : #pragma once
      19              : 
      20              : #include <lib/core/CHIPError.h>
      21              : #include <lib/support/CHIPMem.h>
      22              : #include <lib/support/CodeUtils.h>
      23              : #include <lib/support/ScopedBuffer.h>
      24              : #include <lib/support/Span.h>
      25              : 
      26              : #include <cstdint>
      27              : #include <type_traits>
      28              : 
      29              : namespace chip {
      30              : namespace app {
      31              : namespace DataModel {
      32              : 
      33              : namespace detail {
      34              : 
      35              : class GenericAppendOnlyBuffer
      36              : {
      37              : public:
      38        25492 :     GenericAppendOnlyBuffer(size_t elementSize) : mElementSize(elementSize) {}
      39              :     ~GenericAppendOnlyBuffer();
      40              : 
      41              :     GenericAppendOnlyBuffer(GenericAppendOnlyBuffer && other);
      42              :     GenericAppendOnlyBuffer & operator=(GenericAppendOnlyBuffer &&);
      43              : 
      44              :     GenericAppendOnlyBuffer()                                            = delete;
      45              :     GenericAppendOnlyBuffer & operator=(const GenericAppendOnlyBuffer &) = delete;
      46              : 
      47              :     /// Ensure that at least the specified number of elements
      48              :     /// can be appended to the internal buffer;
      49              :     ///
      50              :     /// This will cause the internal buffer to become an allocated buffer
      51              :     CHIP_ERROR EnsureAppendCapacity(size_t numElements);
      52              : 
      53              :     bool IsEmpty() const { return mElementCount == 0; }
      54              : 
      55              :     /// Number of elements stored in the object.
      56           13 :     size_t Size() const { return mElementCount; }
      57              : 
      58              : protected:
      59              :     /// Appends a single element of mElementSize size.
      60              :     ///
      61              :     /// ALWAYS COPIES the given element internally.
      62              :     /// Sufficient capacity MUST exist to append.
      63              :     CHIP_ERROR AppendSingleElementRaw(const void * buffer);
      64              : 
      65              :     /// Appends a list of elements from a raw array.
      66              :     ///
      67              :     /// This ALWAYS COPIES the elements internally.
      68              :     /// Additional capacity is AUTOMATICALLY ADDED.
      69              :     ///
      70              :     /// buffer MUST NOT point inside "own" buffer as mBuffer may be reallocated
      71              :     /// as part of the appending.
      72              :     CHIP_ERROR AppendElementArrayRaw(const void * __restrict__ buffer, size_t numElements);
      73              : 
      74              :     /// Appends a list of elements from a raw array.
      75              :     ///
      76              :     /// If the buffer contains no elements, this will just REFERENCE the given
      77              :     /// buffer, so its lifetime MUST be longer than the lifetime of this buffer and
      78              :     /// its usage.
      79              :     ///
      80              :     /// If the buffer already contains some elements, this will AUTOMATICALLY
      81              :     /// add additional capacity and COPY the elements at the end of the internal array.
      82              :     CHIP_ERROR ReferenceExistingElementArrayRaw(const void * buffer, size_t numElements);
      83              : 
      84              :     /// release ownership of any used buffer.
      85              :     ///
      86              :     /// Returns the current buffer details and releases ownership of it (clears internal state)
      87              :     void ReleaseBuffer(void *& buffer, size_t & size, bool & allocated);
      88              : 
      89              : private:
      90              :     const size_t mElementSize; // size of one element in the buffer
      91              :     uint8_t * mBuffer       = nullptr;
      92              :     size_t mElementCount    = 0;     // how many elements are stored in the class
      93              :     size_t mCapacity        = 0;     // how many elements can be stored in total in mBuffer
      94              :     bool mBufferIsAllocated = false; // if mBuffer is an allocated buffer
      95              : };
      96              : 
      97              : /// Represents a RAII instance owning a buffer.
      98              : ///
      99              : /// It auto-frees the owned buffer on destruction via `Platform::MemoryFree`.
     100              : ///
     101              : /// This class is designed to be a storage class for `GenericAppendOnlyBuffer` and
     102              : /// its subclasses (i.e. GenericAppendOnlyBuffer uses PlatformMemory and this class
     103              : /// does the same. They MUST be kept in sync.)
     104              : class ScopedBuffer
     105              : {
     106              : public:
     107        46499 :     ScopedBuffer(void * buffer) : mBuffer(buffer) {}
     108              :     ~ScopedBuffer();
     109              : 
     110              :     ScopedBuffer(const ScopedBuffer &)             = delete;
     111              :     ScopedBuffer & operator=(const ScopedBuffer &) = delete;
     112              : 
     113              :     ScopedBuffer(ScopedBuffer && other) : mBuffer(other.mBuffer) { other.mBuffer = nullptr; }
     114              :     ScopedBuffer & operator=(ScopedBuffer && other);
     115              : 
     116              : private:
     117              :     void * mBuffer;
     118              : };
     119              : 
     120              : } // namespace detail
     121              : 
     122              : template <typename T>
     123              : class ReadOnlyBuffer : public Span<const T>, detail::ScopedBuffer
     124              : {
     125              : public:
     126        21011 :     ReadOnlyBuffer() : ScopedBuffer(nullptr) {}
     127        25482 :     ReadOnlyBuffer(const T * buffer, size_t size, bool allocated) :
     128        25482 :         Span<const T>(buffer, size), ScopedBuffer(allocated ? const_cast<void *>(static_cast<const void *>(buffer)) : nullptr)
     129        25482 :     {}
     130        45646 :     ~ReadOnlyBuffer() = default;
     131              : 
     132        24266 :     ReadOnlyBuffer & operator=(ReadOnlyBuffer && other)
     133              :     {
     134        24266 :         *static_cast<Span<const T> *>(this) = other;
     135        24266 :         *static_cast<ScopedBuffer *>(this)  = std::move(other);
     136        24266 :         return *this;
     137              :     }
     138              : };
     139              : 
     140              : template <typename T>
     141              : class ListBuilder : public detail::GenericAppendOnlyBuffer
     142              : {
     143              : public:
     144              :     using SpanType = Span<const T>;
     145              : 
     146              :     // we do not call destructors, just malloc things.
     147              :     // Note that classes should also be trivially assignable (we do NOT call the assignment operator)
     148              :     // This makes this class somewhat dangerous...
     149              :     //
     150              :     // Note: ideally we would want `is_trivially_copyable_v` as well however our chip::Optional
     151              :     //       implementation does not actually report that.
     152              :     static_assert(std::is_trivially_destructible_v<T>);
     153              : 
     154        25482 :     ListBuilder() : GenericAppendOnlyBuffer(sizeof(T)) {}
     155              : 
     156              :     ListBuilder(const ListBuilder &)                   = delete;
     157              :     ListBuilder & operator=(const ListBuilder & other) = delete;
     158              : 
     159              :     ListBuilder(ListBuilder && other) : GenericAppendOnlyBuffer(sizeof(T)) { *this = std::move(other); }
     160              : 
     161              :     ListBuilder & operator=(ListBuilder && other)
     162              :     {
     163              :         *static_cast<GenericAppendOnlyBuffer *>(this) = std::move(other);
     164              :         return *this;
     165              :     }
     166              : 
     167              :     /// Reference methods attempt to reference the existing array IN PLACE
     168              :     /// so its lifetime is assumed to be longer than the usage of this list.
     169            5 :     CHIP_ERROR ReferenceExisting(SpanType span) { return ReferenceExistingElementArrayRaw(span.data(), span.size()); }
     170              : 
     171              :     /// Append always attempts to append/extend existing memory.
     172              :     ///
     173              :     /// Automatically attempts to allocate sufficient space to fulfill the element
     174              :     /// requirements.
     175              :     ///
     176              :     /// `span` MUST NOT point inside "own" buffer (and generally will not
     177              :     /// as this class does not expose buffer access except by releasing ownership
     178              :     /// via `Take`)
     179              :     CHIP_ERROR AppendElements(SpanType span) { return AppendElementArrayRaw(span.data(), span.size()); }
     180              : 
     181              :     /// Append a single element.
     182              :     /// Sufficent append capacity MUST exist.
     183       115611 :     CHIP_ERROR Append(const T & value) { return AppendSingleElementRaw(&value); }
     184              : 
     185              :     /// Once a list is built, the data is taken as a scoped SPAN that owns its data
     186              :     /// and the original list is cleared
     187        25482 :     ReadOnlyBuffer<T> TakeBuffer()
     188              :     {
     189              :         void * buffer;
     190              :         size_t size;
     191              :         bool allocated;
     192        25482 :         ReleaseBuffer(buffer, size, allocated);
     193              : 
     194        25482 :         return ReadOnlyBuffer<T>(static_cast<const T *>(buffer), size, allocated);
     195              :     }
     196              : };
     197              : 
     198              : } // namespace DataModel
     199              : } // namespace app
     200              : } // namespace chip
        

Generated by: LCOV version 2.0-1