summaryrefslogtreecommitdiffstats
path: root/lib/ringbuf.c
diff options
context:
space:
mode:
authorQuentin Young <qlyoung@cumulusnetworks.com>2017-12-27 00:47:19 +0100
committerQuentin Young <qlyoung@cumulusnetworks.com>2017-12-27 00:50:56 +0100
commita5080622b2de7c09393daa208a56606c068db1f3 (patch)
treeb4b4a8077fbfc45fbb1964686028f028eb097eca /lib/ringbuf.c
parentlib: add ring buffer (diff)
downloadfrr-a5080622b2de7c09393daa208a56606c068db1f3.tar.xz
frr-a5080622b2de7c09393daa208a56606c068db1f3.zip
lib: add ringbuf_peek()
Peek functionality for ring buffers and associated tests. Also: * Slight optimization to avoid 0-byte memcpy() by changing > to >= * Add rv checks for some ringbuf_[put|get] calls that were missing them in the test Signed-off-by: Quentin Young <qlyoung@cumulusnetworks.com>
Diffstat (limited to 'lib/ringbuf.c')
-rw-r--r--lib/ringbuf.c22
1 files changed, 21 insertions, 1 deletions
diff --git a/lib/ringbuf.c b/lib/ringbuf.c
index fee5b5d69..f8e9a9bd8 100644
--- a/lib/ringbuf.c
+++ b/lib/ringbuf.c
@@ -77,7 +77,7 @@ size_t ringbuf_get(struct ringbuf *buf, void *data, size_t size)
size_t remain = ringbuf_remain(buf);
size_t copysize = MIN(remain, size);
size_t tocopy = copysize;
- if (tocopy > buf->size - buf->start) {
+ if (tocopy >= buf->size - buf->start) {
size_t ts = buf->size - buf->start;
memcpy(dp, buf->data + buf->start, ts);
buf->start = 0;
@@ -90,6 +90,26 @@ size_t ringbuf_get(struct ringbuf *buf, void *data, size_t size)
return copysize;
}
+size_t ringbuf_peek(struct ringbuf *buf, size_t offset, void *data, size_t size)
+{
+ uint8_t *dp = data;
+ size_t remain = ringbuf_remain(buf);
+ if (offset >= remain)
+ return 0;
+ size_t copysize = MAX(MIN(remain - offset, size), (size_t) 0);
+ size_t tocopy = copysize;
+ size_t cstart = (buf->start + offset) % buf->size;
+ if (tocopy >= buf->size - cstart) {
+ size_t ts = buf->size - cstart;
+ memcpy(dp, buf->data + cstart, ts);
+ buf->start = cstart = 0;
+ tocopy -= ts;
+ dp += ts;
+ }
+ memcpy(dp, buf->data + cstart, tocopy);
+ return copysize;
+}
+
void ringbuf_reset(struct ringbuf *buf)
{
buf->start = buf->end = 0;