Matter SDK Coverage Report
Current view: top level - lib/support - ReadOnlyBuffer.h (source / functions) Coverage Total Hit
Test: SHA:4cbce7f768f16e614f5a8ccb8cd93c92cbeae70d Lines: 100.0 % 18 18
Test Date: 2025-04-26 07:09:35 Functions: 90.5 % 42 38

            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 detail {
      31              : 
      32              : class GenericAppendOnlyBuffer
      33              : {
      34              : public:
      35        36216 :     GenericAppendOnlyBuffer(size_t elementSize) : mElementSize(elementSize) {}
      36              :     ~GenericAppendOnlyBuffer();
      37              : 
      38              :     GenericAppendOnlyBuffer(GenericAppendOnlyBuffer && other);
      39              :     GenericAppendOnlyBuffer & operator=(GenericAppendOnlyBuffer &&);
      40              : 
      41              :     GenericAppendOnlyBuffer()                                            = delete;
      42              :     GenericAppendOnlyBuffer & operator=(const GenericAppendOnlyBuffer &) = delete;
      43              : 
      44              :     /// Ensure that at least the specified number of elements
      45              :     /// can be appended to the internal buffer;
      46              :     ///
      47              :     /// This will cause the internal buffer to become an allocated buffer
      48              :     [[nodiscard]] CHIP_ERROR EnsureAppendCapacity(size_t numElements);
      49              : 
      50              :     [[nodiscard]] bool IsEmpty() const { return mElementCount == 0; }
      51              : 
      52              :     /// Number of elements stored in the object.
      53           13 :     [[nodiscard]] size_t Size() const { return mElementCount; }
      54              : 
      55              : protected:
      56              :     /// Appends a single element of mElementSize size.
      57              :     ///
      58              :     /// ALWAYS COPIES the given element internally.
      59              :     /// Sufficient capacity MUST exist to append.
      60              :     CHIP_ERROR AppendSingleElementRaw(const void * buffer);
      61              : 
      62              :     /// Appends a list of elements from a raw array.
      63              :     ///
      64              :     /// This ALWAYS COPIES the elements internally.
      65              :     /// Additional capacity is AUTOMATICALLY ADDED.
      66              :     ///
      67              :     /// buffer MUST NOT point inside "own" buffer as mBuffer may be reallocated
      68              :     /// as part of the appending.
      69              :     CHIP_ERROR AppendElementArrayRaw(const void * __restrict__ buffer, size_t numElements);
      70              : 
      71              :     /// Appends a list of elements from a raw array.
      72              :     ///
      73              :     /// If the buffer contains no elements, this will just REFERENCE the given
      74              :     /// buffer, so its lifetime MUST be longer than the lifetime of this buffer and
      75              :     /// its usage.
      76              :     ///
      77              :     /// If the buffer already contains some elements, this will AUTOMATICALLY
      78              :     /// add additional capacity and COPY the elements at the end of the internal array.
      79              :     CHIP_ERROR ReferenceExistingElementArrayRaw(const void * buffer, size_t numElements);
      80              : 
      81              :     /// release ownership of any used buffer.
      82              :     ///
      83              :     /// Returns the current buffer details and releases ownership of it (clears internal state)
      84              :     void ReleaseBuffer(void *& buffer, size_t & size, bool & allocated);
      85              : 
      86              : private:
      87              :     const size_t mElementSize; // size of one element in the buffer
      88              :     uint8_t * mBuffer       = nullptr;
      89              :     size_t mElementCount    = 0;     // how many elements are stored in the class
      90              :     size_t mCapacity        = 0;     // how many elements can be stored in total in mBuffer
      91              :     bool mBufferIsAllocated = false; // if mBuffer is an allocated buffer
      92              : };
      93              : 
      94              : /// Represents a RAII instance owning a buffer.
      95              : ///
      96              : /// It auto-frees the owned buffer on destruction via `Platform::MemoryFree`.
      97              : ///
      98              : /// This class is designed to be a storage class for `GenericAppendOnlyBuffer` and
      99              : /// its subclasses (i.e. GenericAppendOnlyBuffer uses PlatformMemory and this class
     100              : /// does the same. They MUST be kept in sync.)
     101              : class ScopedBuffer
     102              : {
     103              : public:
     104        59467 :     ScopedBuffer(void * buffer) : mBuffer(buffer) {}
     105              :     ~ScopedBuffer();
     106              : 
     107              :     ScopedBuffer(const ScopedBuffer &)             = delete;
     108              :     ScopedBuffer & operator=(const ScopedBuffer &) = delete;
     109              : 
     110              :     ScopedBuffer(ScopedBuffer && other) : mBuffer(other.mBuffer) { other.mBuffer = nullptr; }
     111              :     ScopedBuffer & operator=(ScopedBuffer && other);
     112              : 
     113              : private:
     114              :     void * mBuffer;
     115              : };
     116              : 
     117              : } // namespace detail
     118              : 
     119              : template <typename T>
     120              : class ReadOnlyBuffer : public Span<const T>, detail::ScopedBuffer
     121              : {
     122              : public:
     123        23243 :     ReadOnlyBuffer() : ScopedBuffer(nullptr) {}
     124        36195 :     ReadOnlyBuffer(const T * buffer, size_t size, bool allocated) :
     125        36195 :         Span<const T>(buffer, size), ScopedBuffer(allocated ? const_cast<void *>(static_cast<const void *>(buffer)) : nullptr)
     126        36195 :     {}
     127        58591 :     ~ReadOnlyBuffer() = default;
     128              : 
     129        26519 :     ReadOnlyBuffer & operator=(ReadOnlyBuffer && other)
     130              :     {
     131        26519 :         *static_cast<Span<const T> *>(this) = other;
     132        26519 :         *static_cast<ScopedBuffer *>(this)  = std::move(other);
     133        26519 :         return *this;
     134              :     }
     135              : };
     136              : 
     137              : template <typename T>
     138              : class ReadOnlyBufferBuilder : public detail::GenericAppendOnlyBuffer
     139              : {
     140              : public:
     141              :     using SpanType = Span<const T>;
     142              : 
     143              :     // we do not call destructors, just malloc things.
     144              :     // Note that classes should also be trivially assignable (we do NOT call the assignment operator)
     145              :     // This makes this class somewhat dangerous...
     146              :     //
     147              :     // Note: ideally we would want `is_trivially_copyable_v` as well however our chip::Optional
     148              :     //       implementation does not actually report that.
     149              :     static_assert(std::is_trivially_destructible_v<T>);
     150              : 
     151        36194 :     ReadOnlyBufferBuilder() : GenericAppendOnlyBuffer(sizeof(T)) {}
     152              : 
     153              :     ReadOnlyBufferBuilder(const ReadOnlyBufferBuilder &)                   = delete;
     154              :     ReadOnlyBufferBuilder & operator=(const ReadOnlyBufferBuilder & other) = delete;
     155              : 
     156              :     ReadOnlyBufferBuilder(ReadOnlyBufferBuilder && other) : GenericAppendOnlyBuffer{ std::move(other) } {}
     157              : 
     158              :     ReadOnlyBufferBuilder & operator=(ReadOnlyBufferBuilder && other)
     159              :     {
     160              :         detail::GenericAppendOnlyBuffer::operator=(std::move(other));
     161              :         return *this;
     162              :     }
     163              : 
     164              :     /// Reference methods attempt to reference the existing array IN PLACE
     165              :     /// so its lifetime is assumed to be longer than the usage of this list.
     166            8 :     [[nodiscard]] CHIP_ERROR ReferenceExisting(SpanType span) { return ReferenceExistingElementArrayRaw(span.data(), span.size()); }
     167              : 
     168              :     /// Append always attempts to append/extend existing memory.
     169              :     ///
     170              :     /// Automatically attempts to allocate sufficient space to fulfill the element
     171              :     /// requirements.
     172              :     ///
     173              :     /// `span` MUST NOT point inside "own" buffer (and generally will not
     174              :     /// as this class does not expose buffer access except by releasing ownership
     175              :     /// via `Take`)
     176              :     [[nodiscard]] CHIP_ERROR AppendElements(SpanType span) { return AppendElementArrayRaw(span.data(), span.size()); }
     177              : 
     178              :     /// Append a single element.
     179              :     /// Sufficent append capacity MUST exist.
     180       129136 :     [[nodiscard]] CHIP_ERROR Append(const T & value) { return AppendSingleElementRaw(&value); }
     181              : 
     182              :     /// Once a list is built, the data is taken as a scoped SPAN that owns its data
     183              :     /// and the original list is cleared
     184        36195 :     ReadOnlyBuffer<T> TakeBuffer()
     185              :     {
     186              :         void * buffer;
     187              :         size_t size;
     188              :         bool allocated;
     189        36195 :         ReleaseBuffer(buffer, size, allocated);
     190              : 
     191        36195 :         return ReadOnlyBuffer<T>(static_cast<const T *>(buffer), size, allocated);
     192              :     }
     193              : };
     194              : 
     195              : } // namespace chip
        

Generated by: LCOV version 2.0-1