summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordzwdz2022-05-15 15:26:13 +0200
committerdzwdz2022-05-15 15:26:13 +0200
commit6219918e020c6255ab854306478a2ee4876cc8c7 (patch)
tree1e7c3fada18fc4ce35a48f63734d63c8d0c617f7
parent27d8fa24b875f2bbcc73dad0795519ef2f5e9cd7 (diff)
shared/ring: ring_contig
-rw-r--r--src/kernel/tests/util.c13
-rw-r--r--src/shared/container/ring.c33
-rw-r--r--src/shared/container/ring.h4
3 files changed, 43 insertions, 7 deletions
diff --git a/src/kernel/tests/util.c b/src/kernel/tests/util.c
index cf16b75..b7123b4 100644
--- a/src/kernel/tests/util.c
+++ b/src/kernel/tests/util.c
@@ -32,12 +32,23 @@ TEST(strcmp) {
}
TEST(ring) {
- char backbuf[16];
+ char backbuf[16], cmpbuf[16];
size_t num_read = 0, num_written = 0;
uint8_t c;
ring_t r = {backbuf, 16, 0, 0};
+ // test aliasing
+ for (size_t i = 0; i < 16; i++) {
+ TEST_COND(ring_size(&r) == 0);
+ ring_put(&r, "11 bytes...", 11);
+ TEST_COND(ring_size(&r) == 11);
+
+ memset(cmpbuf, 0, sizeof cmpbuf);
+ TEST_COND(ring_get(&r, cmpbuf, 16) == 11);
+ TEST_COND(memcmp(cmpbuf, "11 bytes...", 11) == 0);
+ }
+
TEST_COND(ring_size(&r) == 0);
for (size_t i = 0; i < 7; i++)
ring_put1b(&r, num_written++);
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);