fix cxBufferAppend() not adjusting position after flush default tip

Fri, 17 Jan 2025 17:55:21 +0100

author
Mike Becker <universe@uap-core.de>
date
Fri, 17 Jan 2025 17:55:21 +0100
changeset 1131
644f77f903b1
parent 1130
5bcb725119b6

fix cxBufferAppend() not adjusting position after flush

fixes #565

src/buffer.c file | annotate | diff | comparison | revisions
tests/test_buffer.c file | annotate | diff | comparison | revisions
--- a/src/buffer.c	Fri Jan 17 17:41:29 2025 +0100
+++ b/src/buffer.c	Fri Jan 17 17:55:21 2025 +0100
@@ -356,9 +356,19 @@
         CxBuffer *buffer
 ) {
     size_t pos = buffer->pos;
-    buffer->pos = buffer->size;
+    size_t append_pos = buffer->size;
+    buffer->pos = append_pos;    
     size_t written = cxBufferWrite(ptr, size, nitems, buffer);
-    buffer->pos = pos;
+    // the buffer might have been flushed
+    // we must compute a possible delta for the position
+    // expected: pos = append_pos + written
+    // -> if this is not the case, there is a delta
+    size_t delta = append_pos + written*size - buffer->pos;
+    if (delta > pos) {
+        buffer->pos = 0;
+    } else {
+        buffer->pos = pos - delta;
+    }
     return written;
 }
 
--- a/tests/test_buffer.c	Fri Jan 17 17:41:29 2025 +0100
+++ b/tests/test_buffer.c	Fri Jan 17 17:55:21 2025 +0100
@@ -792,6 +792,47 @@
     cxBufferDestroy(&buf);
 }
 
+CX_TEST(test_buffer_append_flush) {
+    CxBuffer buf, target;
+    cxBufferInit(&buf, NULL, 8, cxDefaultAllocator, CX_BUFFER_DEFAULT);
+    cxBufferInit(&target, NULL, 8, cxDefaultAllocator, CX_BUFFER_AUTO_EXTEND);
+    memcpy(buf.space, "prepXXXX", 8);
+    buf.capacity = 8;
+    buf.size = 6;
+    buf.pos = 4;
+    CxBufferFlushConfig flush;
+    flush.threshold = 0;
+    flush.blksize = 4;
+    flush.blkmax = 1;
+    flush.target = &target;
+    flush.wfunc = cxBufferWriteFunc;
+    cxBufferEnableFlushing(&buf, flush);
+    CX_TEST_DO{
+        size_t written = cxBufferAppend("testing", 1, 7, &buf);
+        CX_TEST_ASSERT(written == 7);
+        CX_TEST_ASSERT(buf.size == 7);
+        CX_TEST_ASSERTM(buf.pos == 0, "position not correctly reset");
+        CX_TEST_ASSERT(buf.capacity == 8);
+        CX_TEST_ASSERT(target.size == 6);
+        CX_TEST_ASSERT(target.pos == 6);
+        CX_TEST_ASSERT(0 == memcmp(buf.space, "testing", 7));
+        CX_TEST_ASSERT(0 == memcmp(target.space, "prepXX", 6));
+        // second test - position only shifted by one block
+        buf.pos = 6;
+        written = cxBufferAppend("foo", 1, 3, &buf);
+        CX_TEST_ASSERT(written == 3);
+        CX_TEST_ASSERT(buf.size == 6);
+        CX_TEST_ASSERTM(buf.pos == 2, "position not correctly adjusted");
+        CX_TEST_ASSERT(buf.capacity == 8);
+        CX_TEST_ASSERT(target.size == 10);
+        CX_TEST_ASSERT(target.pos == 10);
+        CX_TEST_ASSERT(0 == memcmp(buf.space, "ingfoo", 6));
+        CX_TEST_ASSERT(0 == memcmp(target.space, "prepXXtest", 10));
+    }
+    cxBufferDestroy(&buf);
+    cxBufferDestroy(&target);
+}
+
 CX_TEST(test_buffer_put_fit) {
     CxBuffer buf;
     cxBufferInit(&buf, NULL, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT);
@@ -1448,6 +1489,7 @@
     cx_test_register(suite, test_buffer_write_multibyte_extend);
     cx_test_register(suite, test_buffer_write_copy_on_write);
     cx_test_register(suite, test_buffer_append);
+    cx_test_register(suite, test_buffer_append_flush);
     cx_test_register(suite, test_buffer_put_fit);
     cx_test_register(suite, test_buffer_put_discard);
     cx_test_register(suite, test_buffer_put_extend);

mercurial