ucx/buffer.c

changeset 31
287484519844
parent 30
d33eaaec15da
--- a/ucx/buffer.c	Fri Dec 12 10:42:53 2025 +0100
+++ b/ucx/buffer.c	Fri Dec 19 17:22:03 2025 +0100
@@ -45,11 +45,11 @@
 
 int cxBufferInit(
         CxBuffer *buffer,
+        const CxAllocator *allocator,
         void *space,
         size_t capacity,
-        const CxAllocator *allocator,
         int flags
-) {
+        ) {
     if (allocator == NULL) {
         allocator = cxDefaultAllocator;
     }
@@ -74,24 +74,25 @@
 }
 
 void cxBufferDestroy(CxBuffer *buffer) {
-    if (buffer->flags & CX_BUFFER_FREE_CONTENTS) {
+    if ((buffer->flags & (CX_BUFFER_FREE_CONTENTS | CX_BUFFER_DO_NOT_FREE))
+            == CX_BUFFER_FREE_CONTENTS) {
         cxFree(buffer->allocator, buffer->bytes);
     }
     memset(buffer, 0, sizeof(CxBuffer));
 }
 
 CxBuffer *cxBufferCreate(
+        const CxAllocator *allocator,
         void *space,
         size_t capacity,
-        const CxAllocator *allocator,
         int flags
-) {
+        ) {
     if (allocator == NULL) {
         allocator = cxDefaultAllocator;
     }
     CxBuffer *buf = cxMalloc(allocator, sizeof(CxBuffer));
     if (buf == NULL) return NULL; // LCOV_EXCL_LINE
-    if (0 == cxBufferInit(buf, space, capacity, allocator, flags)) {
+    if (0 == cxBufferInit(buf, allocator, space, capacity, flags)) {
         return buf;
     } else {
         // LCOV_EXCL_START
@@ -298,6 +299,9 @@
         size_t nitems,
         CxBuffer *buffer
 ) {
+    // trivial case
+    if (size == 0 || nitems == 0) return 0;
+
     // optimize for easy case
     if (size == 1 && (buffer->capacity - buffer->pos) >= nitems) {
         if (buffer_copy_on_write(buffer)) return 0;
@@ -363,20 +367,13 @@
         size_t nitems,
         CxBuffer *buffer
 ) {
-    size_t pos = buffer->pos;
-    size_t append_pos = buffer->size;
-    buffer->pos = append_pos;    
-    size_t written = cxBufferWrite(ptr, size, nitems, buffer);
-    // 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;
-    }
+    // trivial case
+    if (size == 0 || nitems == 0) return 0;
+
+    const size_t pos = buffer->pos;
+    buffer->pos = buffer->size;
+    const size_t written = cxBufferWrite(ptr, size, nitems, buffer);
+    buffer->pos = pos;
     return written;
 }
 
@@ -394,19 +391,35 @@
 }
 
 int cxBufferTerminate(CxBuffer *buffer) {
-    if (0 == cxBufferPut(buffer, 0)) {
-        buffer->size = buffer->pos - 1;
-        return 0;
+    // try to extend / shrink the buffer
+    if (buffer->pos >= buffer->capacity) {
+        if ((buffer->flags & CX_BUFFER_AUTO_EXTEND) == 0) {
+            return -1;
+        }
+        if (cxBufferReserve(buffer, buffer->pos + 1)) {
+            return -1; // LCOV_EXCL_LINE
+        }
     } else {
-        return -1;
+        buffer->size = buffer->pos;
+        cxBufferShrink(buffer, 1);
+        // set the capacity explicitly, in case shrink was skipped due to CoW
+        buffer->capacity = buffer->size + 1;
     }
+
+    // check if we are still on read-only memory
+    if (buffer_copy_on_write(buffer)) return -1;
+
+    // write the terminator and exit
+    buffer->space[buffer->pos] = '\0';
+    return 0;
 }
 
-size_t cxBufferPutString(
-        CxBuffer *buffer,
-        const char *str
-) {
-    return cxBufferWrite(str, 1, strlen(str), buffer);
+size_t cx_buffer_put_string(CxBuffer *buffer, cxstring str) {
+    return cxBufferWrite(str.ptr, 1, str.length, buffer);
+}
+
+size_t cx_buffer_append_string(CxBuffer *buffer, cxstring str) {
+    return cxBufferAppend(str.ptr, 1, str.length, buffer);
 }
 
 size_t cxBufferRead(

mercurial