add cxBufferReserve()

Wed, 26 Nov 2025 23:22:03 +0100

author
Mike Becker <universe@uap-core.de>
date
Wed, 26 Nov 2025 23:22:03 +0100
changeset 1515
f024313c08f1
parent 1514
ee5d668a71e4
child 1516
95b094472e9a

add cxBufferReserve()

docs/Writerside/topics/buffer.h.md file | annotate | diff | comparison | revisions
src/buffer.c file | annotate | diff | comparison | revisions
src/cx/buffer.h file | annotate | diff | comparison | revisions
--- a/docs/Writerside/topics/buffer.h.md	Wed Nov 26 23:06:12 2025 +0100
+++ b/docs/Writerside/topics/buffer.h.md	Wed Nov 26 23:22:03 2025 +0100
@@ -122,16 +122,22 @@
 ```C
 #include <cx/buffer.h>
 
+int cxBufferReserve(CxBuffer *buffer, size_t capacity);
+
 int cxBufferMinimumCapacity(CxBuffer *buffer, size_t capacity);
 
 void cxBufferShrink(CxBuffer *buffer, size_t reserve);
 ```
 
-The function `cxBufferMinimumCapacity()` guarantees a buffer capacity of _at least_ `capacity`.
-The actual capacity will be a power of two until the system's page size is reached.
+The functions `cxBufferReserve()` and `cxBufferMinimumCapacity()` guarantee a buffer capacity of _at least_ `capacity`.
+The difference is, that `cxBufferReserve()` will not increase the capacity beyond the specified `capacity`,
+while `cxBufferMinimumCapacity()` will grow the capacity in powers of two until the system's page size is reached.
 Then, the new capacity will be a multiple of the page size.
 The function returns non-zero if increasing the capacity was attempted unsuccessfully.
 
+You should use `cxBufferReserve()` when you know precisely the required capacity beforehand
+and `cxBufferMinimumCapacity()` when it is likely that the buffer needs to regrow soon.
+
 The function `cxBufferShrink()` can be used to shrink the capacity of the buffer to its current size
 plus a number of `reserve` bytes.
 If the current capacity is not larger than the size plus the reserve bytes, the function will do nothing.
--- a/src/buffer.c	Wed Nov 26 23:06:12 2025 +0100
+++ b/src/buffer.c	Wed Nov 26 23:22:03 2025 +0100
@@ -238,10 +238,30 @@
     return buffer->pos >= buffer->size;
 }
 
-int cxBufferMinimumCapacity(
-        CxBuffer *buffer,
-        size_t newcap
-) {
+int cxBufferReserve(CxBuffer *buffer, size_t newcap) {
+    if (newcap <= buffer->capacity) {
+        return 0;
+    }
+    const int force_copy_flags = CX_BUFFER_COPY_ON_WRITE | CX_BUFFER_COPY_ON_EXTEND;
+    if (buffer->flags & force_copy_flags) {
+        void *newspace = cxMalloc(buffer->allocator, newcap);
+        if (NULL == newspace) return -1;
+        memcpy(newspace, buffer->space, buffer->size);
+        buffer->space = newspace;
+        buffer->capacity = newcap;
+        buffer->flags &= ~force_copy_flags;
+        buffer->flags |= CX_BUFFER_FREE_CONTENTS;
+        return 0;
+    } else if (cxReallocate(buffer->allocator,
+                     (void **) &buffer->bytes, newcap) == 0) {
+        buffer->capacity = newcap;
+        return 0;
+    } else {
+        return -1; // LCOV_EXCL_LINE
+    }
+}
+
+int cxBufferMinimumCapacity(CxBuffer *buffer, size_t newcap) {
     if (newcap <= buffer->capacity) {
         return 0;
     }
@@ -267,24 +287,7 @@
         // this gives a full additional page (which is good)
     }
 
-
-    const int force_copy_flags = CX_BUFFER_COPY_ON_WRITE | CX_BUFFER_COPY_ON_EXTEND;
-    if (buffer->flags & force_copy_flags) {
-        void *newspace = cxMalloc(buffer->allocator, newcap);
-        if (NULL == newspace) return -1;
-        memcpy(newspace, buffer->space, buffer->size);
-        buffer->space = newspace;
-        buffer->capacity = newcap;
-        buffer->flags &= ~force_copy_flags;
-        buffer->flags |= CX_BUFFER_FREE_CONTENTS;
-        return 0;
-    } else if (cxReallocate(buffer->allocator,
-                     (void **) &buffer->bytes, newcap) == 0) {
-        buffer->capacity = newcap;
-        return 0;
-    } else {
-        return -1; // LCOV_EXCL_LINE
-    }
+    return cxBufferReserve(buffer, newcap);
 }
 
 void cxBufferShrink(
--- a/src/cx/buffer.h	Wed Nov 26 23:06:12 2025 +0100
+++ b/src/cx/buffer.h	Wed Nov 26 23:22:03 2025 +0100
@@ -439,11 +439,30 @@
 cx_attr_nonnull cx_attr_nodiscard
 CX_EXPORT bool cxBufferEof(const CxBuffer *buffer);
 
+/**
+ * Ensures that the buffer has the required capacity.
+ *
+ * If the current capacity is not sufficient, the buffer will be extended.
+ *
+ * This function will reserve no more bytes than requested, in contrast to
+ * cxBufferMinimumCapacity(), which may reserve more bytes to improve the
+ * number of future necessary reallocations.
+ *
+ * @param buffer the buffer
+ * @param capacity the required capacity for this buffer
+ * @retval zero the capacity was already sufficient or successfully increased
+ * @retval non-zero on allocation failure
+ * @see cxBufferShrink()
+ * @see cxBufferMinimumCapacity()
+ */
+cx_attr_nonnull
+CX_EXPORT int cxBufferReserve(CxBuffer *buffer, size_t capacity);
 
 /**
  * Ensures that the buffer has a minimum capacity.
  *
- * If the current capacity is not sufficient, the buffer will be extended.
+ * If the current capacity is not sufficient, the buffer will be generously
+ * extended.
  *
  * The new capacity will be a power of two until the system's page size is reached.
  * Then, the new capacity will be a multiple of the page size.
@@ -452,6 +471,7 @@
  * @param capacity the minimum required capacity for this buffer
  * @retval zero the capacity was already sufficient or successfully increased
  * @retval non-zero on allocation failure
+ * @see cxBufferReserve()
  * @see cxBufferShrink()
  */
 cx_attr_nonnull
@@ -471,6 +491,7 @@
  *
  * @param buffer the buffer
  * @param reserve the number of bytes that shall remain reserved
+ * @see cxBufferReserve()
  * @see cxBufferMinimumCapacity()
  */
 cx_attr_nonnull

mercurial