Matter SDK Coverage Report
Current view: top level - lib/support - BytesCircularBuffer.cpp (source / functions) Coverage Total Hit
Test: SHA:b879ecb8e99e175eea0a293a888bda853da2b19c Lines: 77.8 % 81 63
Test Date: 2025-01-17 19:00:11 Functions: 91.7 % 12 11

            Line data    Source code
       1              : /*
       2              :  *
       3              :  *    Copyright (c) 2021 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              : 
      19              : #include <lib/support/BytesCircularBuffer.h>
      20              : 
      21              : #include <algorithm>
      22              : #include <limits>
      23              : #include <string.h>
      24              : 
      25              : #include <lib/support/CodeUtils.h>
      26              : 
      27              : namespace chip {
      28              : 
      29         7362 : size_t BytesCircularBuffer::Advance(size_t dataLocation, size_t amount) const
      30              : {
      31         7362 :     dataLocation += amount;
      32         7362 :     if (dataLocation >= mCapacity)
      33         1174 :         dataLocation -= mCapacity;
      34         7362 :     return dataLocation;
      35              : }
      36              : 
      37         3804 : void BytesCircularBuffer::Read(uint8_t * dest, size_t length, size_t offset) const
      38              : {
      39              :     // length is an instance of SizeType
      40              :     // offset is maximized at sizeof(SizeType) for all use cases.
      41              :     static_assert(std::numeric_limits<SizeType>::max() < std::numeric_limits<size_t>::max() - sizeof(SizeType),
      42              :                   "SizeType too large, may cause overflow");
      43         3804 :     VerifyOrDie(StorageUsed() >= offset + length);
      44              : 
      45         3804 :     size_t start       = Advance(mDataStart, offset);
      46         3804 :     size_t firstPiece  = std::min(mCapacity - start, length);
      47         3804 :     size_t secondPiece = length - firstPiece;
      48         3804 :     ::memcpy(dest, mStorage + start, firstPiece);
      49         3804 :     ::memcpy(dest + firstPiece, mStorage, secondPiece);
      50         3804 : }
      51              : 
      52         1788 : void BytesCircularBuffer::Write(const uint8_t * source, size_t length)
      53              : {
      54              :     // Always reserve 1 byte to prevent mDataStart == mDataEnd because then it would be
      55              :     // ambiguous whether we have 0 bytes or mCapacity bytes stored.
      56         1788 :     VerifyOrDie(StorageAvailable() - 1 >= length);
      57              : 
      58         1788 :     size_t firstPiece  = std::min(mCapacity - mDataEnd, length);
      59         1788 :     size_t secondPiece = length - firstPiece;
      60         1788 :     ::memcpy(mStorage + mDataEnd, source, firstPiece);
      61         1788 :     ::memcpy(mStorage, source + firstPiece, secondPiece);
      62         1788 :     mDataEnd = Advance(mDataEnd, length);
      63         1788 : }
      64              : 
      65         1770 : void BytesCircularBuffer::Drop(size_t length)
      66              : {
      67         1770 :     VerifyOrDie(StorageUsed() >= length);
      68         1770 :     mDataStart = Advance(mDataStart, length);
      69         1770 : }
      70              : 
      71         3242 : size_t BytesCircularBuffer::StorageAvailable() const
      72              : {
      73         3242 :     return mCapacity - StorageUsed();
      74              : }
      75              : 
      76        15944 : size_t BytesCircularBuffer::StorageUsed() const
      77              : {
      78        15944 :     if (mDataStart <= mDataEnd)
      79              :     {
      80         7754 :         return mDataEnd - mDataStart;
      81              :     }
      82              : 
      83         8190 :     return mCapacity + mDataEnd - mDataStart;
      84              : }
      85              : 
      86          897 : CHIP_ERROR BytesCircularBuffer::Push(const ByteSpan & payload)
      87              : {
      88          897 :     size_t length = payload.size();
      89          897 :     if (length > std::numeric_limits<SizeType>::max())
      90            1 :         return CHIP_ERROR_INVALID_ARGUMENT;
      91              : 
      92              :     static_assert(std::numeric_limits<SizeType>::max() < std::numeric_limits<size_t>::max() - (sizeof(SizeType) + 1),
      93              :                   "SizeType too large, may cause overflow");
      94          896 :     size_t storageNeed = length + sizeof(SizeType) + 1;
      95          896 :     if (storageNeed > mCapacity)
      96            2 :         return CHIP_ERROR_INVALID_ARGUMENT;
      97              : 
      98              :     // Free up space until there is enough space.
      99         1454 :     while (storageNeed > StorageAvailable())
     100              :     {
     101          560 :         VerifyOrDie(Pop() == CHIP_NO_ERROR);
     102              :     }
     103              : 
     104          894 :     SizeType size = static_cast<SizeType>(length);
     105          894 :     Write(reinterpret_cast<uint8_t *>(&size), sizeof(size));
     106          894 :     Write(payload.data(), length);
     107              : 
     108          894 :     return CHIP_NO_ERROR;
     109              : }
     110              : 
     111            0 : CHIP_ERROR BytesCircularBuffer::Push(const ByteSpan & payload1, const ByteSpan & payload2)
     112              : {
     113            0 :     size_t length = payload1.size() + payload2.size();
     114            0 :     if (length > std::numeric_limits<SizeType>::max())
     115              :     {
     116            0 :         return CHIP_ERROR_INVALID_ARGUMENT;
     117              :     }
     118              : 
     119              :     static_assert(std::numeric_limits<SizeType>::max() < std::numeric_limits<size_t>::max() - (sizeof(SizeType) + 1),
     120              :                   "SizeType too large, may cause overflow");
     121            0 :     size_t storageNeed = length + sizeof(SizeType) + 1;
     122            0 :     if (storageNeed > mCapacity)
     123              :     {
     124            0 :         return CHIP_ERROR_INVALID_ARGUMENT;
     125              :     }
     126              : 
     127              :     // Free up space until there is enough space.
     128            0 :     while (storageNeed > StorageAvailable())
     129              :     {
     130            0 :         VerifyOrDie(Pop() == CHIP_NO_ERROR);
     131              :     }
     132              : 
     133            0 :     SizeType size = static_cast<SizeType>(length);
     134            0 :     Write(reinterpret_cast<uint8_t *>(&size), sizeof(size));
     135            0 :     Write(payload1.data(), payload1.size());
     136            0 :     Write(payload2.data(), payload2.size());
     137              : 
     138            0 :     return CHIP_NO_ERROR;
     139              : }
     140              : 
     141          885 : CHIP_ERROR BytesCircularBuffer::Pop()
     142              : {
     143          885 :     if (IsEmpty())
     144            0 :         return CHIP_ERROR_INCORRECT_STATE;
     145              : 
     146          885 :     size_t length = GetFrontSize();
     147          885 :     Drop(sizeof(SizeType));
     148          885 :     Drop(length);
     149              : 
     150          885 :     return CHIP_NO_ERROR;
     151              : }
     152              : 
     153         7128 : bool BytesCircularBuffer::IsEmpty() const
     154              : {
     155         7128 :     return StorageUsed() == 0;
     156              : }
     157              : 
     158         2831 : size_t BytesCircularBuffer::GetFrontSize() const
     159              : {
     160         2831 :     if (IsEmpty())
     161            0 :         return 0;
     162              : 
     163              :     SizeType length;
     164         2831 :     Read(reinterpret_cast<uint8_t *>(&length), sizeof(length), 0 /* offset */);
     165         2831 :     return length;
     166              : }
     167              : 
     168          973 : CHIP_ERROR BytesCircularBuffer::ReadFront(MutableByteSpan & dest) const
     169              : {
     170          973 :     if (IsEmpty())
     171            0 :         return CHIP_ERROR_INCORRECT_STATE;
     172              : 
     173          973 :     size_t length = GetFrontSize();
     174          973 :     if (dest.size() < length)
     175            0 :         return CHIP_ERROR_INVALID_ARGUMENT;
     176              : 
     177          973 :     dest = dest.SubSpan(0, length);
     178              : 
     179          973 :     Read(dest.data(), length, sizeof(SizeType) /* offset */);
     180          973 :     return CHIP_NO_ERROR;
     181              : }
     182              : 
     183              : } // namespace chip
        

Generated by: LCOV version 2.0-1