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