Coverage Report

Created: 2025-08-03 06:36

/src/frr/lib/ringbuf.c
Line
Count
Source (jump to first uncovered line)
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
DEFINE_MTYPE_STATIC(LIB, RINGBUFFER, "Ring buffer");
13
14
struct ringbuf *ringbuf_new(size_t size)
15
0
{
16
0
  struct ringbuf *buf = XCALLOC(MTYPE_RINGBUFFER, sizeof(struct ringbuf));
17
0
  buf->data = XCALLOC(MTYPE_RINGBUFFER, size);
18
0
  buf->size = size;
19
0
  buf->empty = true;
20
0
  return buf;
21
0
}
22
23
void ringbuf_del(struct ringbuf *buf)
24
0
{
25
0
  XFREE(MTYPE_RINGBUFFER, buf->data);
26
0
  XFREE(MTYPE_RINGBUFFER, buf);
27
0
}
28
29
size_t ringbuf_remain(struct ringbuf *buf)
30
0
{
31
0
  ssize_t diff = buf->end - buf->start;
32
0
  diff += ((diff == 0) && !buf->empty) ? buf->size : 0;
33
0
  diff += (diff < 0) ? buf->size : 0;
34
0
  return (size_t)diff;
35
0
}
36
37
size_t ringbuf_space(struct ringbuf *buf)
38
0
{
39
0
  return buf->size - ringbuf_remain(buf);
40
0
}
41
42
size_t ringbuf_put(struct ringbuf *buf, const void *data, size_t size)
43
0
{
44
0
  const uint8_t *dp = data;
45
0
  size_t space = ringbuf_space(buf);
46
0
  size_t copysize = MIN(size, space);
47
0
  size_t tocopy = copysize;
48
0
  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
0
  }
55
0
  memcpy(buf->data + buf->end, dp, tocopy);
56
0
  buf->end += tocopy;
57
0
  buf->empty = (buf->start == buf->end) && (buf->empty && !copysize);
58
0
  return copysize;
59
0
}
60
61
size_t ringbuf_get(struct ringbuf *buf, void *data, size_t size)
62
0
{
63
0
  uint8_t *dp = data;
64
0
  size_t remain = ringbuf_remain(buf);
65
0
  size_t copysize = MIN(remain, size);
66
0
  size_t tocopy = copysize;
67
0
  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
0
  }
74
0
  memcpy(dp, buf->data + buf->start, tocopy);
75
0
  buf->start = buf->start + tocopy;
76
0
  buf->empty = (buf->start == buf->end) && (buf->empty || copysize);
77
0
  return copysize;
78
0
}
79
80
size_t ringbuf_peek(struct ringbuf *buf, size_t offset, void *data, size_t size)
81
0
{
82
0
  uint8_t *dp = data;
83
0
  size_t remain = ringbuf_remain(buf);
84
0
  if (offset >= remain)
85
0
    return 0;
86
0
  size_t copysize = MAX(MIN(remain - offset, size), (size_t)0);
87
0
  size_t tocopy = copysize;
88
0
  size_t cstart = (buf->start + offset) % buf->size;
89
0
  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
0
  }
96
0
  memcpy(dp, buf->data + cstart, tocopy);
97
0
  return copysize;
98
0
}
99
100
size_t ringbuf_copy(struct ringbuf *to, struct ringbuf *from, size_t size)
101
0
{
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
0
}
109
110
void ringbuf_reset(struct ringbuf *buf)
111
0
{
112
0
  buf->start = buf->end = 0;
113
0
  buf->empty = true;
114
0
}
115
116
void ringbuf_wipe(struct ringbuf *buf)
117
0
{
118
0
  memset(buf->data, 0x00, buf->size);
119
0
  ringbuf_reset(buf);
120
0
}