]> git.puffer.fish Git - mirror/frr.git/commitdiff
lib: add ringbuf_peek() 1569/head
authorQuentin Young <qlyoung@cumulusnetworks.com>
Tue, 26 Dec 2017 23:47:19 +0000 (18:47 -0500)
committerQuentin Young <qlyoung@cumulusnetworks.com>
Tue, 26 Dec 2017 23:50:56 +0000 (18:50 -0500)
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>
lib/ringbuf.c
lib/ringbuf.h
tests/lib/test_ringbuf.c

index fee5b5d69127d86bc8dea33a6984b7ccd56b7fe7..f8e9a9bd8a2a8aec4b4f01cac62270e64c2aca60 100644 (file)
@@ -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;
index af07c93a66dbf35bb02dcd55fe11a5cdaea3f9f8..2288a2716fcbd042fcc3f6b4e8c7db78709d0a7a 100644 (file)
@@ -83,6 +83,21 @@ size_t ringbuf_put(struct ringbuf *buf, const void *data, size_t size);
  */
 size_t ringbuf_get(struct ringbuf *buf, void *data, size_t size);
 
+/*
+ * Peek data from the ring buffer.
+ *
+ * @param offset       where to get the data from, in bytes offset from the
+ *                     start of the data
+ * @param data         where to put the data
+ * @param size         how much data to get
+ * @return             number of bytes read into data; will be less than size
+ *                     if there was not enough data to read; will be -1 if the
+ *                     offset exceeds the amount of data left in the ring
+ *                     buffer
+ */
+size_t ringbuf_peek(struct ringbuf *buf, size_t offset, void *data,
+                   size_t size);
+
 /*
  * Reset buffer. Does not wipe.
  *
index c689563dd6708ea9d2eb8d149179d4396765be01..c2f4f76a6fcaf70a52122e6e5bc2c2968e025129 100644 (file)
@@ -77,7 +77,7 @@ int main(int argc, char **argv)
 
        /* put another 10 bytes and validate wraparound */
        printf("Validating wraparound...\n");
-       assert(ringbuf_put(soil, &compost[BUFSIZ / 2], 10) == 10);
+       assert(ringbuf_put(soil, &compost[BUFSIZ/2], 10) == 10);
 
        validate_state(soil, BUFSIZ, BUFSIZ - 15 + 10);
        assert(soil->start == 15);
@@ -131,9 +131,9 @@ int main(int argc, char **argv)
        /* validate simple data encode / decode */
        const char *organ = "seed";
        printf("Encoding: '%s'\n", organ);
-       ringbuf_put(soil, organ, strlen(organ));
+       assert(ringbuf_put(soil, organ, strlen(organ)) == 4);
        char water[strlen(organ) + 1];
-       ringbuf_get(soil, &water, strlen(organ));
+       assert(ringbuf_get(soil, &water, strlen(organ)) == 4);
        water[strlen(organ)] = '\0';
        printf("Retrieved: '%s'\n", water);
 
@@ -144,12 +144,27 @@ int main(int argc, char **argv)
        soil->end = soil->start;
        const char *phloem = "root";
        printf("Encoding: '%s'\n", phloem);
-       ringbuf_put(soil, phloem, strlen(phloem));
+       assert(ringbuf_put(soil, phloem, strlen(phloem)) == 4);
        char xylem[strlen(phloem) + 1];
-       ringbuf_get(soil, &xylem, 100);
+       assert(ringbuf_get(soil, &xylem, 100) == 4);
        xylem[strlen(phloem)] = '\0';
        printf("Retrieved: '%s'\n", xylem);
 
+       ringbuf_wipe(soil);
+
+       /* validate simple data peek across ring boundary */
+       soil->start = soil->size - 2;
+       soil->end = soil->start;
+       const char *cytoplasm = "tree";
+       printf("Encoding: '%s'\n", cytoplasm);
+       assert(ringbuf_put(soil, cytoplasm, strlen(cytoplasm)) == 4);
+       char chloroplast[strlen(cytoplasm) + 1];
+       assert(ringbuf_peek(soil, 2, &chloroplast[0], 100) == 2);
+       assert(ringbuf_peek(soil, 0, &chloroplast[2], 2) == 2);
+       chloroplast[strlen(cytoplasm)] = '\0';
+       assert(!strcmp(chloroplast, "eetr"));
+       printf("Retrieved: '%s'\n", chloroplast);
+
        printf("Deleting...\n");
        ringbuf_del(soil);