added extract function

Wed, 10 Oct 2012 10:46:20 +0200

author
Mike Becker <universe@uap-core.de>
date
Wed, 10 Oct 2012 10:46:20 +0200
changeset 62
6814aea8462d
parent 61
fb07a0ab9a17
child 63
1d3500806565

added extract function

test/buffer_tests.c file | annotate | diff | comparison | revisions
test/buffer_tests.h file | annotate | diff | comparison | revisions
test/main.c file | annotate | diff | comparison | revisions
ucx/buffer.c file | annotate | diff | comparison | revisions
ucx/buffer.h file | annotate | diff | comparison | revisions
--- a/test/buffer_tests.c	Wed Oct 10 10:04:01 2012 +0200
+++ b/test/buffer_tests.c	Wed Oct 10 10:46:20 2012 +0200
@@ -62,7 +62,8 @@
     ucx_buffer_putc(b, 48); ucx_buffer_putc(b, 48); ucx_buffer_putc(b, 48);
     UCX_TEST_ASSERT(ucx_buffer_tell(b) == 16, "pos wrong after last 3 puts");
     UCX_TEST_ASSERT(ucx_buffer_eof(b), "eof not set");
-    UCX_TEST_ASSERT(ucx_buffer_putc(b, 48) == EOF, "put shall return EOF on memof");
+    UCX_TEST_ASSERT(ucx_buffer_putc(b, 48) == EOF,
+            "put shall return EOF when buffer is full");
     UCX_TEST_ASSERT(memcmp(buffer, "000          000", 16) == 0,
             "buffer contains incorrect content");
 
@@ -184,3 +185,28 @@
     ucx_buffer_free(b);
     free(buffer);
 }
+
+UCX_TEST_IMPLEMENT(test_ucx_buffer_extract) {
+    char *buffer = malloc(16);
+    strcpy(buffer, "this is a test!");
+
+    UcxBuffer *src = ucx_buffer_new(buffer, 16, UCX_BUFFER_AUTOFREE),
+            *dst = ucx_buffer_extract(src, 5, 5, UCX_BUFFER_DEFAULT);
+
+    UCX_TEST_BEGIN
+    UCX_TEST_ASSERT(ucx_buffer_testflags(dst, UCX_BUFFER_AUTOFREE),
+            "autofree flag shall be enforced");
+    UCX_TEST_ASSERT(ucx_buffer_size(dst) == 5, "wrong size for new buffer");
+    char rb[5];
+    ucx_buffer_read(rb, 1, 5, dst);
+    UCX_TEST_ASSERT(memcmp(rb, "is a ", 5) == 0,
+            "new buffer has incorrect content");
+
+    UCX_TEST_ASSERT(ucx_buffer_extract(dst, 3, 3, UCX_BUFFER_DEFAULT) == NULL,
+            "extract shall fail on invalid bounds");
+
+    UCX_TEST_END
+
+    ucx_buffer_free(dst);
+    ucx_buffer_free(src);
+}
--- a/test/buffer_tests.h	Wed Oct 10 10:04:01 2012 +0200
+++ b/test/buffer_tests.h	Wed Oct 10 10:46:20 2012 +0200
@@ -19,6 +19,7 @@
 UCX_TEST_DECLARE(test_ucx_buffer_getc);
 UCX_TEST_DECLARE(test_ucx_buffer_write);
 UCX_TEST_DECLARE(test_ucx_buffer_read);
+UCX_TEST_DECLARE(test_ucx_buffer_extract);
 
 #ifdef	__cplusplus
 }
--- a/test/main.c	Wed Oct 10 10:04:01 2012 +0200
+++ b/test/main.c	Wed Oct 10 10:46:20 2012 +0200
@@ -169,6 +169,7 @@
         ucx_test_register(suite, test_ucx_buffer_getc);
         ucx_test_register(suite, test_ucx_buffer_write);
         ucx_test_register(suite, test_ucx_buffer_read);
+        ucx_test_register(suite, test_ucx_buffer_extract);
 
         ucx_test_run(suite, stdout);
         fflush(stdout);
--- a/ucx/buffer.c	Wed Oct 10 10:04:01 2012 +0200
+++ b/ucx/buffer.c	Wed Oct 10 10:46:20 2012 +0200
@@ -5,8 +5,8 @@
 
 struct UcxBuffer {
     void *space;
-    off_t pos;
-    size_t length;
+    size_t pos;
+    size_t size;
     int flags;
 };
 
@@ -25,7 +25,7 @@
         } else {
             buffer->space = space;
         }
-        buffer->length = length;
+        buffer->size = length;
 
         buffer->pos = 0;
     }
@@ -34,12 +34,36 @@
 }
 
 void ucx_buffer_free(UcxBuffer *buffer) {
-    if ((buffer->flags & UCX_BUFFER_AUTOFREE) > 0) {
+    if (ucx_buffer_testflags(buffer, UCX_BUFFER_AUTOFREE)) {
         free(buffer->space);
     }
     free(buffer);
 }
 
+UcxBuffer *ucx_buffer_extract(
+        UcxBuffer *src, size_t start, size_t length, int flags) {
+    if (length == 0) {
+        length = src->size - start;
+    }
+    if (start+length > src->size) {
+        return NULL;
+    }
+
+    UcxBuffer *dst = (UcxBuffer*) malloc(sizeof(UcxBuffer));
+    if (dst) {
+        dst->space = malloc(length);
+        if (!dst->space) {
+            free(dst);
+            return NULL;
+        }
+        dst->size = length;
+        dst->flags = flags | UCX_BUFFER_AUTOFREE;
+        dst->pos = 0;
+        memcpy(dst->space, (char*)src->space+start, length);
+    }
+    return dst;
+}
+
 int ucx_buffer_seek(UcxBuffer *buffer, off_t offset, int whence) {
     off_t npos;
     switch (whence) {
@@ -56,7 +80,7 @@
 
     npos += offset;
 
-    if (npos < 0 || npos > buffer->length) {
+    if (npos < 0 || npos > buffer->size) {
         return -1;
     } else {
         buffer->pos = npos;
@@ -66,17 +90,25 @@
 }
 
 int ucx_buffer_eof(UcxBuffer *buffer) {
-    return buffer->pos >= buffer->length;
+    return buffer->pos >= buffer->size;
 }
 
 size_t ucx_buffer_tell(UcxBuffer *buffer) {
     return buffer->pos;
 }
 
+size_t ucx_buffer_size(UcxBuffer *buffer) {
+    return buffer->size;
+}
+
+int ucx_buffer_testflags(UcxBuffer *buffer, int flags) {
+    return (buffer->flags & flags) == flags;
+}
+
 size_t ucx_bufio(void* d, size_t s, size_t n, UcxBuffer *b, _Bool read) {
     size_t len;
-    if (b->pos + s*n > b->length) {
-        len = b->length - b->pos;
+    if (b->pos + s*n > b->size) {
+        len = b->size - b->pos;
         if (s > 1) len -= len%s;
     } else {
         len = s*n;
--- a/ucx/buffer.h	Wed Oct 10 10:04:01 2012 +0200
+++ b/ucx/buffer.h	Wed Oct 10 10:46:20 2012 +0200
@@ -1,6 +1,7 @@
 #ifndef BUFFER_H
 #define	BUFFER_H
 
+#include <sys/types.h>
 #include <stdio.h>
 
 #ifdef	__cplusplus
@@ -18,6 +19,16 @@
 void ucx_buffer_free(UcxBuffer* buffer);
 
 /*
+ * the autofree flag is enforced for the new buffer
+ * if length is zero, the whole remaining buffer shall be extracted
+ * the position of the new buffer is set to zero
+ */
+UcxBuffer *ucx_buffer_extract(UcxBuffer *src,
+        size_t start, size_t length, int flags);
+#define ucx_buffer_clone(src,flags) \
+    ucx_buffer_extract(src, 0, 0, flags)
+
+/*
  * Moves the position of the buffer to a new position relative to whence.
  *
  * SEEK_SET marks the start of the buffer
@@ -31,6 +42,9 @@
  */
 int ucx_buffer_seek(UcxBuffer *buffer, off_t offset, int whence);
 size_t ucx_buffer_tell(UcxBuffer *buffer);
+size_t ucx_buffer_size(UcxBuffer *buffer);
+/* returns non-zero, if at least the specified flags are set */
+int ucx_buffer_testflags(UcxBuffer *buffer, int flags);
 
 /*
  * returns non-zero, iff the current buffer position has exceeded the last

mercurial