added autoextend feature to buffer

Wed, 10 Oct 2012 14:18:06 +0200

author
Mike Becker <universe@uap-core.de>
date
Wed, 10 Oct 2012 14:18:06 +0200
changeset 64
16590c9c497c
parent 63
1d3500806565
child 65
7b2f2cab6348

added autoextend feature to buffer

and we celebrate the 50th test case

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 13:58:51 2012 +0200
+++ b/test/buffer_tests.c	Wed Oct 10 14:18:06 2012 +0200
@@ -145,6 +145,30 @@
     free(buffer);
 }
 
+UCX_TEST_IMPLEMENT(test_ucx_buffer_write_ax) {
+    char *buffer = malloc(4);
+
+    UcxBuffer *b = ucx_buffer_new(buffer, 16,
+            UCX_BUFFER_AUTOEXTEND | UCX_BUFFER_AUTOFREE);
+    int r;
+
+    UCX_TEST_BEGIN
+
+    char* teststring = "this is way too much";
+    r = ucx_buffer_write(teststring, 1, 20, b);
+    buffer = b->space; /* autoextend is enabled, so we MUST retrieve pointer */
+    UCX_TEST_ASSERT(r == 20, "not all characters written");
+    UCX_TEST_ASSERT(b->size == 32, "buffer not properly extended");
+    UCX_TEST_ASSERT(b->pos == 20, "position incorrect");
+    UCX_TEST_ASSERT(memcmp(buffer,
+            "this is way too much\0\0\0\0\0\0\0\0\0\0\0\0", 32) == 0,
+            "incorrect buffer content");
+
+    UCX_TEST_END
+
+    ucx_buffer_free(b);
+}
+
 UCX_TEST_IMPLEMENT(test_ucx_buffer_read) {
     char *buffer = malloc(16);
     memset(buffer, 56, 8);
--- a/test/buffer_tests.h	Wed Oct 10 13:58:51 2012 +0200
+++ b/test/buffer_tests.h	Wed Oct 10 14:18:06 2012 +0200
@@ -18,6 +18,7 @@
 UCX_TEST_DECLARE(test_ucx_buffer_putc);
 UCX_TEST_DECLARE(test_ucx_buffer_getc);
 UCX_TEST_DECLARE(test_ucx_buffer_write);
+UCX_TEST_DECLARE(test_ucx_buffer_write_ax);
 UCX_TEST_DECLARE(test_ucx_buffer_read);
 UCX_TEST_DECLARE(test_ucx_buffer_extract);
 
--- a/test/main.c	Wed Oct 10 13:58:51 2012 +0200
+++ b/test/main.c	Wed Oct 10 14:18:06 2012 +0200
@@ -168,6 +168,7 @@
         ucx_test_register(suite, test_ucx_buffer_putc);
         ucx_test_register(suite, test_ucx_buffer_getc);
         ucx_test_register(suite, test_ucx_buffer_write);
+        ucx_test_register(suite, test_ucx_buffer_write_ax);
         ucx_test_register(suite, test_ucx_buffer_read);
         ucx_test_register(suite, test_ucx_buffer_extract);
 
--- a/ucx/buffer.c	Wed Oct 10 13:58:51 2012 +0200
+++ b/ucx/buffer.c	Wed Oct 10 14:18:06 2012 +0200
@@ -87,16 +87,27 @@
 }
 
 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->size) {
-        len = b->size - b->pos;
-        if (s > 1) len -= len%s;
-    } else {
-        len = s*n;
+    size_t len = s*n;
+    if (b->pos + len > b->size) {
+        if ((b->flags & UCX_BUFFER_AUTOEXTEND) == UCX_BUFFER_AUTOEXTEND) {
+            size_t newsize = b->size;
+            while (b->pos + len > newsize) newsize <<= 1;
+            void *newspace = realloc(b->space, newsize);
+            if (newspace) {
+                memset((char*)newspace+b->size, 0, newsize-b->size);
+                b->space = newspace;
+                b->size = newsize;
+            } else {
+                len = -1;
+            }
+        } else {
+            len = b->size - b->pos;
+            if (s > 1) len -= len%s;
+        }
     }
 
-    if (len == 0) {
-        return 0;
+    if (len <= 0) {
+        return len;
     }
 
     if (read) {
--- a/ucx/buffer.h	Wed Oct 10 13:58:51 2012 +0200
+++ b/ucx/buffer.h	Wed Oct 10 14:18:06 2012 +0200
@@ -10,9 +10,10 @@
 
 #define UCX_BUFFER_DEFAULT      0x00
 #define UCX_BUFFER_AUTOFREE     0x01
+/* the buffer may automatically double its size on write operations */
 #define UCX_BUFFER_AUTOEXTEND   0x02
 
-/* the user shall not modify values, but can get an up to date space pointer */
+/* the user shall not modify values, but may get the latest pointer */
 typedef struct {
     void *space;
     size_t pos;
@@ -56,6 +57,7 @@
 int ucx_buffer_eof(UcxBuffer *buffer);
 
 size_t ucx_bufio(void *d, size_t s, size_t n, UcxBuffer* b, _Bool read);
+/* when autoextend is enabled, ensure you get the latest pointer to the data */
 #define ucx_buffer_write(data, itemsize, nitems, buffer) \
     ucx_bufio(data, itemsize, nitems, buffer, 0)
 #define ucx_buffer_read(data, itemsize, nitems, buffer) \

mercurial