]>
git.proxmox.com Git - mirror_frr.git/blob - lib/ringbuf.c
2 * Circular buffer implementation.
3 * Copyright (C) 2017 Cumulus Networks
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)
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
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
25 DEFINE_MTYPE_STATIC(LIB
, RINGBUFFER
, "Ring buffer")
27 struct ringbuf
*ringbuf_new(size_t size
)
29 struct ringbuf
*buf
= XCALLOC(MTYPE_RINGBUFFER
, sizeof(struct ringbuf
));
30 buf
->data
= XCALLOC(MTYPE_RINGBUFFER
, size
);
36 void ringbuf_del(struct ringbuf
*buf
)
38 XFREE(MTYPE_RINGBUFFER
, buf
->data
);
39 XFREE(MTYPE_RINGBUFFER
, buf
);
42 size_t ringbuf_remain(struct ringbuf
*buf
)
44 ssize_t diff
= buf
->end
- buf
->start
;
45 diff
+= ((diff
== 0) && !buf
->empty
) ? buf
->size
: 0;
46 diff
+= (diff
< 0) ? buf
->size
: 0;
50 size_t ringbuf_space(struct ringbuf
*buf
)
52 return buf
->size
- ringbuf_remain(buf
);
55 size_t ringbuf_put(struct ringbuf
*buf
, const void *data
, size_t size
)
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
;
61 if (tocopy
>= buf
->size
- buf
->end
) {
62 size_t ts
= buf
->size
- buf
->end
;
63 memcpy(buf
->data
+ buf
->end
, dp
, ts
);
68 memcpy(buf
->data
+ buf
->end
, dp
, tocopy
);
70 buf
->empty
= (buf
->start
== buf
->end
) && (buf
->empty
&& !copysize
);
74 size_t ringbuf_get(struct ringbuf
*buf
, void *data
, size_t size
)
77 size_t remain
= ringbuf_remain(buf
);
78 size_t copysize
= MIN(remain
, size
);
79 size_t tocopy
= copysize
;
80 if (tocopy
>= buf
->size
- buf
->start
) {
81 size_t ts
= buf
->size
- buf
->start
;
82 memcpy(dp
, buf
->data
+ buf
->start
, ts
);
87 memcpy(dp
, buf
->data
+ buf
->start
, tocopy
);
88 buf
->start
= buf
->start
+ tocopy
;
89 buf
->empty
= (buf
->start
== buf
->end
) && (buf
->empty
|| copysize
);
93 size_t ringbuf_peek(struct ringbuf
*buf
, size_t offset
, void *data
, size_t size
)
96 size_t remain
= ringbuf_remain(buf
);
99 size_t copysize
= MAX(MIN(remain
- offset
, size
), (size_t)0);
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
);
109 memcpy(dp
, buf
->data
+ cstart
, tocopy
);
113 size_t ringbuf_copy(struct ringbuf
*to
, struct ringbuf
*from
, size_t size
)
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
);
118 size_t put
= ringbuf_put(to
, cbuf
, tocopy
);
119 XFREE(MTYPE_TMP
, cbuf
);
123 void ringbuf_reset(struct ringbuf
*buf
)
125 buf
->start
= buf
->end
= 0;
129 void ringbuf_wipe(struct ringbuf
*buf
)
131 memset(buf
->data
, 0x00, buf
->size
);