Fri, 20 Dec 2024 15:00:05 +0100
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);