]> git.proxmox.com Git - mirror_frr.git/blame - lib/ringbuf.c
zebra, lib: fix the ZEBRA_INTERFACE_VRF_UPDATE zapi message
[mirror_frr.git] / lib / ringbuf.c
CommitLineData
5318d896
QY
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
25DEFINE_MTYPE_STATIC(LIB, RINGBUFFER, "Ring buffer")
26
27struct ringbuf *ringbuf_new(size_t size)
28{
29 struct ringbuf *buf = XCALLOC(MTYPE_RINGBUFFER, sizeof(struct ringbuf));
30 buf->data = XCALLOC(MTYPE_RINGBUFFER, size);
31 buf->size = size;
32 buf->empty = true;
33 return buf;
34}
35
36void ringbuf_del(struct ringbuf *buf)
37{
38 XFREE(MTYPE_RINGBUFFER, buf->data);
39 XFREE(MTYPE_RINGBUFFER, buf);
40}
41
42size_t ringbuf_remain(struct ringbuf *buf)
43{
44 ssize_t diff = buf->end - buf->start;
45 diff += ((diff == 0) && !buf->empty) ? buf->size : 0;
46 diff += (diff < 0) ? buf->size : 0;
47 return (size_t)diff;
48}
49
50size_t ringbuf_space(struct ringbuf *buf)
51{
52 return buf->size - ringbuf_remain(buf);
53}
54
55size_t ringbuf_put(struct ringbuf *buf, const void *data, size_t size)
56{
57 const uint8_t *dp = data;
58 size_t space = ringbuf_space(buf);
59 size_t copysize = MIN(size, space);
60 size_t tocopy = copysize;
74e4a329 61 if (tocopy >= buf->size - buf->end) {
5318d896
QY
62 size_t ts = buf->size - buf->end;
63 memcpy(buf->data + buf->end, dp, ts);
64 buf->end = 0;
65 tocopy -= ts;
66 dp += ts;
67 }
68 memcpy(buf->data + buf->end, dp, tocopy);
69 buf->end += tocopy;
70 buf->empty = (buf->start == buf->end) && (buf->empty && !copysize);
71 return copysize;
72}
73
74size_t ringbuf_get(struct ringbuf *buf, void *data, size_t size)
75{
76 uint8_t *dp = data;
77 size_t remain = ringbuf_remain(buf);
78 size_t copysize = MIN(remain, size);
79 size_t tocopy = copysize;
a5080622 80 if (tocopy >= buf->size - buf->start) {
5318d896
QY
81 size_t ts = buf->size - buf->start;
82 memcpy(dp, buf->data + buf->start, ts);
83 buf->start = 0;
84 tocopy -= ts;
85 dp += ts;
86 }
87 memcpy(dp, buf->data + buf->start, tocopy);
88 buf->start = buf->start + tocopy;
89 buf->empty = (buf->start == buf->end) && (buf->empty || copysize);
90 return copysize;
91}
92
a5080622
QY
93size_t ringbuf_peek(struct ringbuf *buf, size_t offset, void *data, size_t size)
94{
95 uint8_t *dp = data;
96 size_t remain = ringbuf_remain(buf);
97 if (offset >= remain)
98 return 0;
996c9314 99 size_t copysize = MAX(MIN(remain - offset, size), (size_t)0);
a5080622
QY
100 size_t tocopy = copysize;
101 size_t cstart = (buf->start + offset) % buf->size;
102 if (tocopy >= buf->size - cstart) {
103 size_t ts = buf->size - cstart;
104 memcpy(dp, buf->data + cstart, ts);
74e4a329 105 cstart = 0;
a5080622
QY
106 tocopy -= ts;
107 dp += ts;
108 }
109 memcpy(dp, buf->data + cstart, tocopy);
110 return copysize;
111}
112
cb94eaeb
QY
113size_t ringbuf_copy(struct ringbuf *to, struct ringbuf *from, size_t size)
114{
115 size_t tocopy = MIN(ringbuf_space(to), size);
116 uint8_t *cbuf = XCALLOC(MTYPE_TMP, tocopy);
117 tocopy = ringbuf_peek(from, 0, cbuf, tocopy);
74e4a329 118 size_t put = ringbuf_put(to, cbuf, tocopy);
cb94eaeb 119 XFREE(MTYPE_TMP, cbuf);
74e4a329 120 return put;
cb94eaeb
QY
121}
122
5318d896
QY
123void ringbuf_reset(struct ringbuf *buf)
124{
125 buf->start = buf->end = 0;
126 buf->empty = true;
127}
128
129void ringbuf_wipe(struct ringbuf *buf)
130{
131 memset(buf->data, 0x00, buf->size);
132 ringbuf_reset(buf);
5318d896 133}