back to topotato report
topotato coverage report
Current view: top level - lib - ringbuf.c (source / functions) Hit Total Coverage
Test: test_bgp_ecmp_enhe.py::BGP_Unnumbered_ECMP Lines: 56 78 71.8 %
Date: 2023-11-16 17:19:14 Functions: 11 23 47.8 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0-or-later
       2             : /*
       3             :  * Circular buffer implementation.
       4             :  * Copyright (C) 2017 Cumulus Networks
       5             :  * Quentin Young
       6             :  */
       7             : #include <zebra.h>
       8             : 
       9             : #include "ringbuf.h"
      10             : #include "memory.h"
      11             : 
      12          12 : DEFINE_MTYPE_STATIC(LIB, RINGBUFFER, "Ring buffer");
      13             : 
      14           8 : struct ringbuf *ringbuf_new(size_t size)
      15             : {
      16           8 :         struct ringbuf *buf = XCALLOC(MTYPE_RINGBUFFER, sizeof(struct ringbuf));
      17           8 :         buf->data = XCALLOC(MTYPE_RINGBUFFER, size);
      18           8 :         buf->size = size;
      19           8 :         buf->empty = true;
      20           8 :         return buf;
      21             : }
      22             : 
      23           4 : void ringbuf_del(struct ringbuf *buf)
      24             : {
      25           4 :         XFREE(MTYPE_RINGBUFFER, buf->data);
      26           4 :         XFREE(MTYPE_RINGBUFFER, buf);
      27           4 : }
      28             : 
      29         198 : size_t ringbuf_remain(struct ringbuf *buf)
      30             : {
      31         198 :         ssize_t diff = buf->end - buf->start;
      32         198 :         diff += ((diff == 0) && !buf->empty) ? buf->size : 0;
      33         198 :         diff += (diff < 0) ? buf->size : 0;
      34         198 :         return (size_t)diff;
      35             : }
      36             : 
      37          30 : size_t ringbuf_space(struct ringbuf *buf)
      38             : {
      39          30 :         return buf->size - ringbuf_remain(buf);
      40             : }
      41             : 
      42          14 : size_t ringbuf_put(struct ringbuf *buf, const void *data, size_t size)
      43             : {
      44          14 :         const uint8_t *dp = data;
      45          14 :         size_t space = ringbuf_space(buf);
      46          14 :         size_t copysize = MIN(size, space);
      47          14 :         size_t tocopy = copysize;
      48          14 :         if (tocopy >= buf->size - buf->end) {
      49           0 :                 size_t ts = buf->size - buf->end;
      50           0 :                 memcpy(buf->data + buf->end, dp, ts);
      51           0 :                 buf->end = 0;
      52           0 :                 tocopy -= ts;
      53           0 :                 dp += ts;
      54             :         }
      55          14 :         memcpy(buf->data + buf->end, dp, tocopy);
      56          14 :         buf->end += tocopy;
      57          14 :         buf->empty = (buf->start == buf->end) && (buf->empty && !copysize);
      58          14 :         return copysize;
      59             : }
      60             : 
      61          22 : size_t ringbuf_get(struct ringbuf *buf, void *data, size_t size)
      62             : {
      63          22 :         uint8_t *dp = data;
      64          22 :         size_t remain = ringbuf_remain(buf);
      65          22 :         size_t copysize = MIN(remain, size);
      66          22 :         size_t tocopy = copysize;
      67          22 :         if (tocopy >= buf->size - buf->start) {
      68           0 :                 size_t ts = buf->size - buf->start;
      69           0 :                 memcpy(dp, buf->data + buf->start, ts);
      70           0 :                 buf->start = 0;
      71           0 :                 tocopy -= ts;
      72           0 :                 dp += ts;
      73             :         }
      74          22 :         memcpy(dp, buf->data + buf->start, tocopy);
      75          22 :         buf->start = buf->start + tocopy;
      76          22 :         buf->empty = (buf->start == buf->end) && (buf->empty || copysize);
      77          22 :         return copysize;
      78             : }
      79             : 
      80          88 : size_t ringbuf_peek(struct ringbuf *buf, size_t offset, void *data, size_t size)
      81             : {
      82          88 :         uint8_t *dp = data;
      83          88 :         size_t remain = ringbuf_remain(buf);
      84          88 :         if (offset >= remain)
      85             :                 return 0;
      86          88 :         size_t copysize = MAX(MIN(remain - offset, size), (size_t)0);
      87          88 :         size_t tocopy = copysize;
      88          88 :         size_t cstart = (buf->start + offset) % buf->size;
      89          88 :         if (tocopy >= buf->size - cstart) {
      90           0 :                 size_t ts = buf->size - cstart;
      91           0 :                 memcpy(dp, buf->data + cstart, ts);
      92           0 :                 cstart = 0;
      93           0 :                 tocopy -= ts;
      94           0 :                 dp += ts;
      95             :         }
      96          88 :         memcpy(dp, buf->data + cstart, tocopy);
      97          88 :         return copysize;
      98             : }
      99             : 
     100           0 : size_t ringbuf_copy(struct ringbuf *to, struct ringbuf *from, size_t size)
     101             : {
     102           0 :         size_t tocopy = MIN(ringbuf_space(to), size);
     103           0 :         uint8_t *cbuf = XCALLOC(MTYPE_TMP, tocopy);
     104           0 :         tocopy = ringbuf_peek(from, 0, cbuf, tocopy);
     105           0 :         size_t put = ringbuf_put(to, cbuf, tocopy);
     106           0 :         XFREE(MTYPE_TMP, cbuf);
     107           0 :         return put;
     108             : }
     109             : 
     110          20 : void ringbuf_reset(struct ringbuf *buf)
     111             : {
     112          20 :         buf->start = buf->end = 0;
     113          20 :         buf->empty = true;
     114          20 : }
     115             : 
     116          20 : void ringbuf_wipe(struct ringbuf *buf)
     117             : {
     118          20 :         memset(buf->data, 0x00, buf->size);
     119          20 :         ringbuf_reset(buf);
     120          20 : }

Generated by: LCOV version v1.16-topotato