add cxBufferAppend() - fixes #534

Fri, 20 Dec 2024 15:00:05 +0100

author
Mike Becker <universe@uap-core.de>
date
Fri, 20 Dec 2024 15:00:05 +0100
changeset 1030
06091e067bee
parent 1029
c065d196a2c8
child 1031
8a90552bba29

add cxBufferAppend() - fixes #534

CHANGELOG file | annotate | diff | comparison | revisions
src/buffer.c file | annotate | diff | comparison | revisions
src/cx/buffer.h file | annotate | diff | comparison | revisions
tests/test_buffer.c file | annotate | diff | comparison | revisions
--- a/CHANGELOG	Fri Dec 20 13:13:38 2024 +0100
+++ b/CHANGELOG	Fri Dec 20 15:00:05 2024 +0100
@@ -9,6 +9,7 @@
  * adds cx_array_reallocator() and cx_array_default_reallocator
  * adds several new array and list functions
  * adds cxBufferReset()
+ * adds cxBufferAppend()
  * adds CX_BUFFER_COPY_ON_WRITE and CX_BUFFER_COPY_ON_EXTEND flags
  * adds cx_cmp_ptr()
  * adds cx_sprintf() and several more variants
--- a/src/buffer.c	Fri Dec 20 13:13:38 2024 +0100
+++ b/src/buffer.c	Fri Dec 20 15:00:05 2024 +0100
@@ -83,6 +83,7 @@
     if (buffer->flags & CX_BUFFER_FREE_CONTENTS) {
         cxFree(buffer->allocator, buffer->bytes);
     }
+    memset(buffer, 0, sizeof(CxBuffer));
 }
 
 CxBuffer *cxBufferCreate(
@@ -106,8 +107,9 @@
 
 void cxBufferFree(CxBuffer *buffer) {
     if (buffer == NULL) return;
+    const CxAllocator *allocator = buffer->allocator;
     cxBufferDestroy(buffer);
-    cxFree(buffer->allocator, buffer);
+    cxFree(allocator, buffer);
 }
 
 int cxBufferSeek(
@@ -331,6 +333,19 @@
 
 }
 
+size_t cxBufferAppend(
+        const void *ptr,
+        size_t size,
+        size_t nitems,
+        CxBuffer *buffer
+) {
+    size_t pos = buffer->pos;
+    buffer->pos = buffer->size;
+    size_t written = cxBufferWrite(ptr, size, nitems, buffer);
+    buffer->pos = pos;
+    return written;
+}
+
 int cxBufferPut(
         CxBuffer *buffer,
         int c
--- a/src/cx/buffer.h	Fri Dec 20 13:13:38 2024 +0100
+++ b/src/cx/buffer.h	Fri Dec 20 15:00:05 2024 +0100
@@ -443,6 +443,32 @@
 );
 
 /**
+ * Appends data to a CxBuffer.
+ *
+ * The data is always appended to current data within the buffer,
+ * regardless of the current position.
+ * This is especially useful when the buffer is primarily meant for reading
+ * while additional data is added to the buffer occasionally.
+ * Consequently, the position of the buffer is unchanged after this operation.
+ *
+ * \note The signature is compatible with the fwrite() family of functions.
+ *
+ * @param ptr a pointer to the memory area containing the bytes to be written
+ * @param size the length of one element
+ * @param nitems the element count
+ * @param buffer the CxBuffer to write to
+ * @return the total count of elements written
+ * @see cxBufferWrite()
+ */
+cx_attr_nonnull
+size_t cxBufferAppend(
+        const void *ptr,
+        size_t size,
+        size_t nitems,
+        CxBuffer *buffer
+);
+
+/**
  * Reads data from a CxBuffer.
  *
  * The position of the buffer is increased by the number of bytes read.
--- a/tests/test_buffer.c	Fri Dec 20 13:13:38 2024 +0100
+++ b/tests/test_buffer.c	Fri Dec 20 15:00:05 2024 +0100
@@ -790,6 +790,24 @@
     cxBufferDestroy(&buf);
 }
 
+CX_TEST(test_buffer_append) {
+    CxBuffer buf;
+    cxBufferInit(&buf, NULL, 16, cxDefaultAllocator, CX_BUFFER_AUTO_EXTEND);
+    memcpy(buf.space, "prepXXXX\0\0\0\0\0\0\0\0", 16);
+    buf.capacity = 8;
+    buf.size = 6;
+    buf.pos = 4;
+    CX_TEST_DO {
+        size_t written = cxBufferAppend("testing", 1, 7, &buf);
+        CX_TEST_ASSERT(written == 7);
+        CX_TEST_ASSERT(buf.size == 13);
+        CX_TEST_ASSERT(buf.pos == 4);
+        CX_TEST_ASSERT(buf.capacity >= 13);
+        CX_TEST_ASSERT(0 == memcmp(buf.space, "prepXXtesting", 13));
+    }
+    cxBufferDestroy(&buf);
+}
+
 CX_TEST(test_buffer_put_fit) {
     CxBuffer buf;
     cxBufferInit(&buf, NULL, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT);
@@ -1314,6 +1332,7 @@
     cx_test_register(suite, test_buffer_write_multibyte_discard);
     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_put_fit);
     cx_test_register(suite, test_buffer_put_discard);
     cx_test_register(suite, test_buffer_put_extend);

mercurial