Coverage Report

Created: 2026-05-25 06:55

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/frr/lib/ringbuf.c
Line
Count
Source
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
8
DEFINE_MTYPE_STATIC(LIB, RINGBUFFER, "Ring buffer");
13
8
14
8
struct ringbuf *ringbuf_new(size_t size)
15
8
{
16
2
  struct ringbuf *buf = XCALLOC(MTYPE_RINGBUFFER, sizeof(struct ringbuf));
17
2
  buf->data = XCALLOC(MTYPE_RINGBUFFER, size);
18
2
  buf->size = size;
19
2
  buf->empty = true;
20
2
  return buf;
21
2
}
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
5.02k
{
31
5.02k
  ssize_t diff = buf->end - buf->start;
32
5.02k
  diff += ((diff == 0) && !buf->empty) ? buf->size : 0;
33
5.02k
  diff += (diff < 0) ? buf->size : 0;
34
5.02k
  return (size_t)diff;
35
5.02k
}
36
37
size_t ringbuf_space(struct ringbuf *buf)
38
741
{
39
741
  return buf->size - ringbuf_remain(buf);
40
741
}
41
42
size_t ringbuf_put(struct ringbuf *buf, const void *data, size_t size)
43
741
{
44
741
  const uint8_t *dp = data;
45
741
  size_t space = ringbuf_space(buf);
46
741
  size_t copysize = MIN(size, space);
47
741
  size_t tocopy = copysize;
48
741
  if (tocopy >= buf->size - buf->end) {
49
33
    size_t ts = buf->size - buf->end;
50
33
    memcpy(buf->data + buf->end, dp, ts);
51
33
    buf->end = 0;
52
33
    tocopy -= ts;
53
33
    dp += ts;
54
33
  }
55
741
  memcpy(buf->data + buf->end, dp, tocopy);
56
741
  buf->end += tocopy;
57
741
  buf->empty = (buf->start == buf->end) && (buf->empty && !copysize);
58
741
  return copysize;
59
741
}
60
61
size_t ringbuf_get(struct ringbuf *buf, void *data, size_t size)
62
702
{
63
702
  uint8_t *dp = data;
64
702
  size_t remain = ringbuf_remain(buf);
65
702
  size_t copysize = MIN(remain, size);
66
702
  size_t tocopy = copysize;
67
702
  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
702
  memcpy(dp, buf->data + buf->start, tocopy);
75
702
  buf->start = buf->start + tocopy;
76
702
  buf->empty = (buf->start == buf->end) && (buf->empty || copysize);
77
702
  return copysize;
78
702
}
79
80
size_t ringbuf_peek(struct ringbuf *buf, size_t offset, void *data, size_t size)
81
2.87k
{
82
2.87k
  uint8_t *dp = data;
83
2.87k
  size_t remain = ringbuf_remain(buf);
84
2.87k
  if (offset >= remain)
85
0
    return 0;
86
2.87k
  size_t copysize = MAX(MIN(remain - offset, size), (size_t)0);
87
2.87k
  size_t tocopy = copysize;
88
2.87k
  size_t cstart = (buf->start + offset) % buf->size;
89
2.87k
  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
2.87k
  memcpy(dp, buf->data + cstart, tocopy);
97
2.87k
  return copysize;
98
2.87k
}
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
741
{
112
741
  buf->start = buf->end = 0;
113
741
  buf->empty = true;
114
741
}
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
}