# HG changeset patch # User Mike Becker # Date 1681673708 -7200 # Node ID aa0d09f2d81c62d210d9e011773b89a810c6106e # Parent 34120a385fc835a06477a7aae4c30ddbacefb1fc add convenience functions for allocating a buffer on the heap diff -r 34120a385fc8 -r aa0d09f2d81c src/buffer.c --- a/src/buffer.c Sun Apr 16 21:09:25 2023 +0200 +++ b/src/buffer.c Sun Apr 16 21:35:08 2023 +0200 @@ -70,6 +70,29 @@ } } +CxBuffer *cxBufferCreate( + void *space, + size_t capacity, + CxAllocator const *allocator, + int flags +) { + CxBuffer *buf = cxMalloc(allocator, sizeof(CxBuffer)); + if (buf == NULL) return NULL; + if (0 == cxBufferInit(buf, space, capacity, allocator, flags)) { + return buf; + } else { + cxFree(allocator, buf); + return NULL; + } +} + +void cxBufferFree(CxBuffer *buffer) { + if ((buffer->flags & CX_BUFFER_FREE_CONTENTS) == CX_BUFFER_FREE_CONTENTS) { + cxFree(buffer->allocator, buffer->bytes); + } + cxFree(buffer->allocator, buffer); +} + int cxBufferSeek( CxBuffer *buffer, off_t offset, diff -r 34120a385fc8 -r aa0d09f2d81c src/cx/buffer.h --- a/src/cx/buffer.h Sun Apr 16 21:09:25 2023 +0200 +++ b/src/cx/buffer.h Sun Apr 16 21:35:08 2023 +0200 @@ -164,16 +164,52 @@ ); /** + * Allocates and initializes a fresh buffer. + * + * \note You may provide \c NULL as argument for \p space. + * Then this function will allocate the space and enforce + * the #CX_BUFFER_FREE_CONTENTS flag. + * + * @param space pointer to the memory area, or \c NULL to allocate + * new memory + * @param capacity the capacity of the buffer + * @param allocator the allocator to use for allocating the structure and the automatic + * memory management within the buffer. If \c NULL, the default heap allocator will be used. + * @param flags buffer features (see cx_buffer_s.flags) + * @return a pointer to the buffer on success, \c NULL if a required allocation failed + */ +CxBuffer *cxBufferCreate( + void *space, + size_t capacity, + CxAllocator const *allocator, + int flags +); + +/** * Destroys the buffer contents. * * Has no effect if the #CX_BUFFER_FREE_CONTENTS feature is not enabled. + * If you want to free the memory of the entire buffer, use cxBufferFree(). * * @param buffer the buffer which contents shall be destroyed + * @see cxBufferInit() */ __attribute__((__nonnull__)) void cxBufferDestroy(CxBuffer *buffer); /** + * Deallocates the buffer. + * + * If the #CX_BUFFER_FREE_CONTENTS feature is enabled, this function also destroys + * the contents. If you \em only want to destroy the contents, use cxBufferDestroy(). + * + * @param buffer the buffer to deallocate + * @see cxBufferCreate() + */ +__attribute__((__nonnull__)) +void cxBufferFree(CxBuffer *buffer); + +/** * Shifts the contents of the buffer by the given offset. * * If the offset is positive, the contents are shifted to the right. diff -r 34120a385fc8 -r aa0d09f2d81c tests/test_buffer.cpp --- a/tests/test_buffer.cpp Sun Apr 16 21:09:25 2023 +0200 +++ b/tests/test_buffer.cpp Sun Apr 16 21:35:08 2023 +0200 @@ -127,6 +127,24 @@ EXPECT_TRUE(alloc.verify()); } +TEST(BufferInit, OnHeap) { + CxTestingAllocator alloc; + CxBuffer *buf; + void *space = cxMalloc(&alloc, 16); + buf = cxBufferCreate(space, 16, &alloc, CX_BUFFER_FREE_CONTENTS); + EXPECT_NE(buf, nullptr); + expect_default_flush_config(buf); + EXPECT_EQ(buf->space, space); + EXPECT_EQ(buf->flags & CX_BUFFER_AUTO_EXTEND, 0); + EXPECT_EQ(buf->flags & CX_BUFFER_FREE_CONTENTS, CX_BUFFER_FREE_CONTENTS); + EXPECT_EQ(buf->pos, 0); + EXPECT_EQ(buf->size, 0); + EXPECT_EQ(buf->capacity, 16); + EXPECT_EQ(buf->allocator, &alloc); + cxBufferFree(buf); + EXPECT_TRUE(alloc.verify()); +} + class BufferShiftFixture : public ::testing::Test { protected: void SetUp() override {