From 6219918e020c6255ab854306478a2ee4876cc8c7 Mon Sep 17 00:00:00 2001
From: dzwdz
Date: Sun, 15 May 2022 15:26:13 +0200
Subject: shared/ring: ring_contig

---
 src/shared/container/ring.c | 33 +++++++++++++++++++++++++++------
 src/shared/container/ring.h |  4 ++++
 2 files changed, 31 insertions(+), 6 deletions(-)

(limited to 'src/shared/container')

diff --git a/src/shared/container/ring.c b/src/shared/container/ring.c
index 5073b4a..67944b0 100644
--- a/src/shared/container/ring.c
+++ b/src/shared/container/ring.c
@@ -1,6 +1,6 @@
 #include <shared/container/ring.h>
+#include <shared/mem.h>
 #include <stdbool.h>
-// TODO use memcpy
 
 static bool at_end(ring_t *r) {
 	return  r->_head + 1 == r->_tail
@@ -15,6 +15,7 @@ size_t ring_size(ring_t *r) {
 }
 
 void ring_put(ring_t *r, void *buf, size_t len) {
+	// TODO do something similar to ring_get
 	for (size_t i = 0; i < len; i++)
 		ring_put1b(r, ((uint8_t*)buf)[i]);
 }
@@ -26,10 +27,30 @@ void ring_put1b(ring_t *r, uint8_t byte) {
 }
 
 size_t ring_get(ring_t *r, void *buf, size_t len) {
-	for (size_t i = 0; i < len; i++) {
-		if (r->_head == r->_tail || at_end(r)) return i;
-		((uint8_t*)buf)[i] = r->buf[r->_tail++];
-		if (r->_tail >= r->capacity) r->_tail = 0;
+	size_t read = 0;
+	size_t plen;
+	void *pbuf;
+	for (size_t i = 0; i < 2; i++) {
+		plen = len - read;
+		pbuf = ring_contig(r, &plen);
+		if (buf) memcpy(buf + read, pbuf, plen);
+		read += plen;
 	}
-	return len;
+	return read;
+}
+
+void *ring_contig(ring_t *r, size_t *len) {
+	void *ret = &r->buf[r->_tail];
+	size_t avail;
+	if (r->_head >= r->_tail)
+		avail = r->_head - r->_tail;
+	else
+		avail = r->capacity - r->_tail;
+
+	if (*len > avail)
+		*len = avail;
+
+	r->_tail += *len;
+	if (r->_tail >= r->capacity) r->_tail = 0;
+	return ret;
 }
diff --git a/src/shared/container/ring.h b/src/shared/container/ring.h
index 219f4fb..bc978ce 100644
--- a/src/shared/container/ring.h
+++ b/src/shared/container/ring.h
@@ -14,3 +14,7 @@ void	ring_put(ring_t*, void*, size_t);
 void	ring_put1b(ring_t*, uint8_t);
 
 size_t	ring_get(ring_t*, void*, size_t);
+
+/** Consumes up to `len` bytes, and returns a pointer to the buffer where it's stored.
+ * Not thread-safe. */
+void*	ring_contig(ring_t*, size_t *len);
-- 
cgit v1.2.3