LCOV - code coverage report
Current view: top level - AP_HAL/utility - RingBuffer.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 129 139 92.8 %
Date: 2026-09-09 11:02:08 Functions: 19 19 100.0 %

          Line data    Source code
       1             : #include <stdlib.h>
       2             : #include <string.h>
       3             : 
       4             : #include "RingBuffer.h"
       5             : 
       6      143011 : ByteBuffer::ByteBuffer(uint32_t _size)
       7             : {
       8      143011 :     buf = (uint8_t*)calloc(1, _size);
       9      143011 :     size = buf ? _size : 0;
      10      143011 :     external_buf = false;
      11      143011 : }
      12             : 
      13       19747 : ByteBuffer::~ByteBuffer(void)
      14             : {
      15       19747 :     if (!external_buf) {
      16       19745 :         free(buf);
      17             :     }
      18       19747 : }
      19             : 
      20             : /*
      21             :  * Caller is responsible for locking in set_size()
      22             :  */
      23        2314 : bool ByteBuffer::set_size(uint32_t _size)
      24             : {
      25        2314 :     if (external_buf) {
      26             :         // resize not supported with external buffer
      27          26 :         return false;
      28             :     }
      29        2288 :     head = tail = 0;
      30        2288 :     if (_size != size) {
      31        2288 :         free(buf);
      32        2288 :         buf = (uint8_t*)calloc(1, _size);
      33        2288 :         if (!buf) {
      34           0 :             size = 0;
      35           0 :             return false;
      36             :         }
      37             : 
      38        2288 :         size = _size;
      39             :     }
      40             : 
      41        2288 :     return true;
      42             : }
      43             : 
      44             : /*
      45             :   set buffer size, accepting a smaller size if desired size isn't achievable
      46             :  */
      47           4 : bool ByteBuffer::set_size_best(uint32_t _size)
      48             : {
      49          30 :     while (_size > 0) {
      50          28 :         if (set_size(_size)) {
      51           2 :             return true;
      52             :         }
      53          26 :         _size = (3 * _size)/4;
      54             :     }
      55           2 :     return false;
      56             : }
      57             : 
      58  3805489715 : uint32_t ByteBuffer::available(void) const
      59             : {
      60             :     /* use a copy on stack to avoid race conditions of @tail being updated by
      61             :      * the writer thread */
      62  3805489715 :     uint32_t _tail = tail;
      63             : 
      64  3805224495 :     if (head > _tail) {
      65   606455402 :         return size - head + _tail;
      66             :     }
      67  3199657231 :     return _tail - head;
      68             : }
      69             : 
      70      250623 : void ByteBuffer::clear(void)
      71             : {
      72      250623 :     head = tail = 0;
      73      250623 : }
      74             : 
      75  2115053114 : uint32_t ByteBuffer::space(void) const
      76             : {
      77  2115053114 :     if (size == 0) {
      78           0 :         return 0;
      79             :     }
      80             : 
      81             :     /* use a copy on stack to avoid race conditions of @head being updated by
      82             :      * the reader thread */
      83  2115053114 :     uint32_t _head = head;
      84  2115050503 :     uint32_t ret = 0;
      85             : 
      86  2115050503 :     if (_head <= tail) {
      87  2007565329 :         ret = size;
      88             :     }
      89             : 
      90  2115049379 :     ret += _head - tail - 1;
      91             : 
      92  2115046991 :     return ret;
      93             : }
      94             : 
      95        2874 : bool ByteBuffer::is_empty(void) const
      96             : {
      97        2874 :     return head == tail;
      98             : }
      99             : 
     100   266382772 : uint32_t ByteBuffer::write(const uint8_t *data, uint32_t len)
     101             : {
     102             :     ByteBuffer::IoVec vec[2];
     103   266382772 :     const auto n_vec = reserve(vec, len);
     104   266382633 :     uint32_t ret = 0;
     105             : 
     106   530662709 :     for (int i = 0; i < n_vec; i++) {
     107   264280076 :         memcpy(vec[i].data, data + ret, vec[i].len);
     108   264280076 :         ret += vec[i].len;
     109             :     }
     110             : 
     111   266382633 :     commit(ret);
     112   266382544 :     return ret;
     113             : }
     114             : 
     115             : /*
     116             :   update bytes at the read pointer. Used to update an object without
     117             :   popping it
     118             :  */
     119           6 : bool ByteBuffer::update(const uint8_t *data, uint32_t len)
     120             : {
     121           6 :     if (len > available()) {
     122           2 :         return false;
     123             :     }
     124             :     // perform as two memcpy calls
     125           4 :     uint32_t n = size - head;
     126           4 :     if (n > len) {
     127           2 :         n = len;
     128             :     }
     129           4 :     memcpy(&buf[head], data, n);
     130           4 :     data += n;
     131           4 :     if (len > n) {
     132           2 :         memcpy(&buf[0], data, len-n);
     133             :     }
     134           4 :     return true;
     135             : }
     136             : 
     137  1335599227 : bool ByteBuffer::advance(uint32_t n)
     138             : {
     139  1335599227 :     if (n > available()) {
     140           0 :         return false;
     141             :     }
     142  1335593225 :     head = (head + n) % size;
     143  1335589605 :     return true;
     144             : }
     145             : 
     146  1332019218 : uint8_t ByteBuffer::peekiovec(ByteBuffer::IoVec iovec[2], uint32_t len)
     147             : {
     148  1332019218 :     uint32_t n = available();
     149             : 
     150  1332012875 :     if (len > n) {
     151   839735034 :         len = n;
     152             :     }
     153  1332012875 :     if (len == 0) {
     154   837846344 :         return 0;
     155             :     }
     156             : 
     157   494166531 :     auto b = readptr(n);
     158   494175247 :     if (n == 0) {
     159           0 :         iovec[0].data = buf;
     160           0 :         iovec[0].len = len;
     161           0 :         iovec[1].data = nullptr;
     162           0 :         iovec[1].len = 0;
     163           0 :         return 1;
     164             :     }
     165   494175247 :     if (n > len) {
     166   486230413 :         n = len;
     167             :     }
     168             : 
     169   494175247 :     iovec[0].data = const_cast<uint8_t *>(b);
     170   494175247 :     iovec[0].len = n;
     171             : 
     172   494175247 :     if (len <= n) {
     173   493882893 :         return 1;
     174             :     }
     175             : 
     176      292354 :     iovec[1].data = buf;
     177      292354 :     iovec[1].len = len - n;
     178             : 
     179      292354 :     return 2;
     180             : }
     181             : 
     182             : /*
     183             :   read len bytes without advancing the read pointer
     184             :  */
     185  1332018588 : uint32_t ByteBuffer::peekbytes(uint8_t *data, uint32_t len)
     186             : {
     187             :     ByteBuffer::IoVec vec[2];
     188  1332018588 :     const auto n_vec = peekiovec(vec, len);
     189  1332013551 :     uint32_t ret = 0;
     190             : 
     191  1826481383 :     for (int i = 0; i < n_vec; i++) {
     192   494467832 :         memcpy(data + ret, vec[i].data, vec[i].len);
     193   494467832 :         ret += vec[i].len;
     194             :     }
     195             : 
     196  1332013551 :     return ret;
     197             : }
     198             : 
     199   266382751 : uint8_t ByteBuffer::reserve(ByteBuffer::IoVec iovec[2], uint32_t len)
     200             : {
     201   266382751 :     uint32_t n = space();
     202             : 
     203   266382640 :     if (len > n) {
     204     2220648 :         len = n;
     205             :     }
     206             : 
     207   266382640 :     if (!len) {
     208     2314358 :         return 0;
     209             :     }
     210             : 
     211   264068282 :     iovec[0].data = &buf[tail];
     212             : 
     213   264068274 :     n = size - tail;
     214   264068289 :     if (len <= n) {
     215   263856379 :         iovec[0].len = len;
     216   263856379 :         return 1;
     217             :     }
     218             : 
     219      211910 :     iovec[0].len = n;
     220             : 
     221      211910 :     iovec[1].data = buf;
     222      211910 :     iovec[1].len = len - n;
     223             : 
     224      211910 :     return 2;
     225             : }
     226             : 
     227             : /*
     228             :  * Advance the writer pointer by 'len'
     229             :  */
     230   266382487 : bool ByteBuffer::commit(uint32_t len)
     231             : {
     232   266382487 :     if (len > space()) {
     233           0 :         return false; //Someone broke the agreement
     234             :     }
     235             : 
     236   266382533 :     tail = (tail + len) % size;
     237   266382769 :     return true;
     238             : }
     239             : 
     240  1329985719 : uint32_t ByteBuffer::read(uint8_t *data, uint32_t len)
     241             : {
     242  1329985719 :     uint32_t ret = peekbytes(data, len);
     243  1329981073 :     advance(ret);
     244  1329967725 :     return ret;
     245             : }
     246             : 
     247           8 : bool ByteBuffer::read_byte(uint8_t *data)
     248             : {
     249           8 :     if (!data) {
     250           2 :         return false;
     251             :     }
     252             : 
     253           6 :     int16_t ret = peek(0);
     254           6 :     if (ret < 0) {
     255           2 :         return false;
     256             :     }
     257             : 
     258           4 :     *data = ret;
     259             : 
     260           4 :     return advance(1);
     261             : }
     262             : 
     263             : /*
     264             :  * Returns the pointer and size to a contiguous read in the buffer
     265             :  */
     266  1243584146 : const uint8_t *ByteBuffer::readptr(uint32_t &available_bytes)
     267             : {
     268  1243584146 :     uint32_t _tail = tail;
     269  1243579848 :     available_bytes = (head > _tail) ? size - head : _tail - head;
     270             : 
     271  1243579103 :     return available_bytes ? &buf[head] : nullptr;
     272             : }
     273             : 
     274      151512 : int16_t ByteBuffer::peek(uint32_t ofs) const
     275             : {
     276      151512 :     if (ofs >= available()) {
     277       64851 :         return -1;
     278             :     }
     279       86656 :     return buf[(head+ofs)%size];
     280             : }

Generated by: LCOV version 1.14