back to topotato report
topotato coverage report
Current view: top level - lib - ringbuf.c (source / functions) Hit Total Coverage
Test: test_mld_basic.py::MLDBasic Lines: 1 78 1.3 %
Date: 2023-02-24 18:38:01 Functions: 2 12 16.7 %

          Line data    Source code
       1             : /*
       2             :  * Circular buffer implementation.
       3             :  * Copyright (C) 2017 Cumulus Networks
       4             :  * Quentin Young
       5             :  *
       6             :  * This program is free software; you can redistribute it and/or modify it
       7             :  * under the terms of the GNU General Public License as published by the Free
       8             :  * Software Foundation; either version 2 of the License, or (at your option)
       9             :  * any later version.
      10             :  *
      11             :  * This program is distributed in the hope that it will be useful, but WITHOUT
      12             :  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
      13             :  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
      14             :  * more details.
      15             :  *
      16             :  * You should have received a copy of the GNU General Public License along
      17             :  * with this program; see the file COPYING; if not, write to the Free Software
      18             :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
      19             :  */
      20             : #include <zebra.h>
      21             : 
      22             : #include "ringbuf.h"
      23             : #include "memory.h"
      24             : 
      25           8 : DEFINE_MTYPE_STATIC(LIB, RINGBUFFER, "Ring buffer");
      26             : 
      27           0 : struct ringbuf *ringbuf_new(size_t size)
      28             : {
      29           0 :         struct ringbuf *buf = XCALLOC(MTYPE_RINGBUFFER, sizeof(struct ringbuf));
      30           0 :         buf->data = XCALLOC(MTYPE_RINGBUFFER, size);
      31           0 :         buf->size = size;
      32           0 :         buf->empty = true;
      33           0 :         return buf;
      34             : }
      35             : 
      36           0 : void ringbuf_del(struct ringbuf *buf)
      37             : {
      38           0 :         XFREE(MTYPE_RINGBUFFER, buf->data);
      39           0 :         XFREE(MTYPE_RINGBUFFER, buf);
      40           0 : }
      41             : 
      42           0 : size_t ringbuf_remain(struct ringbuf *buf)
      43             : {
      44           0 :         ssize_t diff = buf->end - buf->start;
      45           0 :         diff += ((diff == 0) && !buf->empty) ? buf->size : 0;
      46           0 :         diff += (diff < 0) ? buf->size : 0;
      47           0 :         return (size_t)diff;
      48             : }
      49             : 
      50           0 : size_t ringbuf_space(struct ringbuf *buf)
      51             : {
      52           0 :         return buf->size - ringbuf_remain(buf);
      53             : }
      54             : 
      55           0 : size_t ringbuf_put(struct ringbuf *buf, const void *data, size_t size)
      56             : {
      57           0 :         const uint8_t *dp = data;
      58           0 :         size_t space = ringbuf_space(buf);
      59           0 :         size_t copysize = MIN(size, space);
      60           0 :         size_t tocopy = copysize;
      61           0 :         if (tocopy >= buf->size - buf->end) {
      62           0 :                 size_t ts = buf->size - buf->end;
      63           0 :                 memcpy(buf->data + buf->end, dp, ts);
      64           0 :                 buf->end = 0;
      65           0 :                 tocopy -= ts;
      66           0 :                 dp += ts;
      67             :         }
      68           0 :         memcpy(buf->data + buf->end, dp, tocopy);
      69           0 :         buf->end += tocopy;
      70           0 :         buf->empty = (buf->start == buf->end) && (buf->empty && !copysize);
      71           0 :         return copysize;
      72             : }
      73             : 
      74           0 : size_t ringbuf_get(struct ringbuf *buf, void *data, size_t size)
      75             : {
      76           0 :         uint8_t *dp = data;
      77           0 :         size_t remain = ringbuf_remain(buf);
      78           0 :         size_t copysize = MIN(remain, size);
      79           0 :         size_t tocopy = copysize;
      80           0 :         if (tocopy >= buf->size - buf->start) {
      81           0 :                 size_t ts = buf->size - buf->start;
      82           0 :                 memcpy(dp, buf->data + buf->start, ts);
      83           0 :                 buf->start = 0;
      84           0 :                 tocopy -= ts;
      85           0 :                 dp += ts;
      86             :         }
      87           0 :         memcpy(dp, buf->data + buf->start, tocopy);
      88           0 :         buf->start = buf->start + tocopy;
      89           0 :         buf->empty = (buf->start == buf->end) && (buf->empty || copysize);
      90           0 :         return copysize;
      91             : }
      92             : 
      93           0 : size_t ringbuf_peek(struct ringbuf *buf, size_t offset, void *data, size_t size)
      94             : {
      95           0 :         uint8_t *dp = data;
      96           0 :         size_t remain = ringbuf_remain(buf);
      97           0 :         if (offset >= remain)
      98             :                 return 0;
      99           0 :         size_t copysize = MAX(MIN(remain - offset, size), (size_t)0);
     100           0 :         size_t tocopy = copysize;
     101           0 :         size_t cstart = (buf->start + offset) % buf->size;
     102           0 :         if (tocopy >= buf->size - cstart) {
     103           0 :                 size_t ts = buf->size - cstart;
     104           0 :                 memcpy(dp, buf->data + cstart, ts);
     105           0 :                 cstart = 0;
     106           0 :                 tocopy -= ts;
     107           0 :                 dp += ts;
     108             :         }
     109           0 :         memcpy(dp, buf->data + cstart, tocopy);
     110           0 :         return copysize;
     111             : }
     112             : 
     113           0 : size_t ringbuf_copy(struct ringbuf *to, struct ringbuf *from, size_t size)
     114             : {
     115           0 :         size_t tocopy = MIN(ringbuf_space(to), size);
     116           0 :         uint8_t *cbuf = XCALLOC(MTYPE_TMP, tocopy);
     117           0 :         tocopy = ringbuf_peek(from, 0, cbuf, tocopy);
     118           0 :         size_t put = ringbuf_put(to, cbuf, tocopy);
     119           0 :         XFREE(MTYPE_TMP, cbuf);
     120           0 :         return put;
     121             : }
     122             : 
     123           0 : void ringbuf_reset(struct ringbuf *buf)
     124             : {
     125           0 :         buf->start = buf->end = 0;
     126           0 :         buf->empty = true;
     127           0 : }
     128             : 
     129           0 : void ringbuf_wipe(struct ringbuf *buf)
     130             : {
     131           0 :         memset(buf->data, 0x00, buf->size);
     132           0 :         ringbuf_reset(buf);
     133           0 : }

Generated by: LCOV version v1.16-topotato