ucx/buffer.c

changeset 995
2f811eae2424
parent 992
f421aef8f865
--- a/ucx/buffer.c	Fri Dec 12 12:44:03 2025 +0100
+++ b/ucx/buffer.c	Sat Dec 13 12:11:40 2025 +0100
@@ -74,7 +74,8 @@
 }
 
 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));
@@ -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