add cxBufferPop()

Wed, 26 Nov 2025 23:06:12 +0100

author
Mike Becker <universe@uap-core.de>
date
Wed, 26 Nov 2025 23:06:12 +0100
changeset 1514
ee5d668a71e4
parent 1513
4d641c6a2f82
child 1515
f024313c08f1

add cxBufferPop()

CHANGELOG file | annotate | diff | comparison | revisions
docs/Writerside/topics/about.md file | annotate | diff | comparison | revisions
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/CHANGELOG	Tue Nov 25 20:35:27 2025 +0100
+++ b/CHANGELOG	Wed Nov 26 23:06:12 2025 +0100
@@ -20,6 +20,7 @@
  * adds cxCollectionCompareFunc() to conveniently set a compare function for a collection
    without needing to access the base struct manually
  * adds cxBufferShrink()
+ * adds cxBufferPop()
  * adds cxTreeSize()
  * adds CX_PRIstr and CX_SFMT macros for formatting UCX strings
  * adds cx_strcpy() and cx_strcpy_a()
--- a/docs/Writerside/topics/about.md	Tue Nov 25 20:35:27 2025 +0100
+++ b/docs/Writerside/topics/about.md	Wed Nov 26 23:06:12 2025 +0100
@@ -47,6 +47,7 @@
 * adds cxCollectionCompareFunc() to conveniently set a compare function for a collection
   without needing to access the base struct manually
 * adds cxBufferShrink()
+* adds cxBufferPop()
 * adds cxTreeSize()
 * adds CX_PRIstr and CX_SFMT macros for formatting UCX strings
 * adds cx_strcpy() and cx_strcpy_a()
--- a/docs/Writerside/topics/buffer.h.md	Tue Nov 25 20:35:27 2025 +0100
+++ b/docs/Writerside/topics/buffer.h.md	Wed Nov 26 23:06:12 2025 +0100
@@ -220,6 +220,9 @@
 void cxBufferReset(CxBuffer *buffer);
 
 void cxBufferClear(CxBuffer *buffer);
+
+size_t cxBufferPop(CxBuffer *buffer,
+        size_t size, size_t nitems);
 ```
 
 The function `cxBufferReset()` sets both size and position of the buffer to zero,
@@ -228,6 +231,10 @@
 > When clearing the buffer, only the "live" data, i.e., bytes with indices `[0..size)`, are cleared.
 > If you want to clear the entire buffer's memory, you would need to set the size to the capacity, first.
 
+The function `cxBufferPop()` erases the last `nitems` with the given `size` and returns the number of items that could be erased.
+When the buffer contains fewer bytes than requested and the number of bytes is not divisible by the item `size`, 
+the remainder will stay in the buffer. 
+
 > If the `CX_BUFFER_COPY_ON_WRITE` flag is set, `cxBufferClear()` behaves exactly like `cxBufferReset()`,
 > because writing to the contents is disallowed.
 >{style="note"}
--- a/src/buffer.c	Tue Nov 25 20:35:27 2025 +0100
+++ b/src/buffer.c	Wed Nov 26 23:06:12 2025 +0100
@@ -192,6 +192,35 @@
 
 }
 
+size_t cxBufferPop(CxBuffer *buffer, size_t size, size_t nitems) {
+    size_t len;
+    if (cx_szmul(size, nitems, &len)) {
+        // LCOV_EXCL_START
+        errno = EOVERFLOW;
+        return 0;
+        // LCOV_EXCL_STOP
+    }
+    if (len == 0) return 0;
+    if (len > buffer->size) {
+        if (size == 1) {
+            // simple case: everything can be discarded
+            len = buffer->size;
+        } else {
+            // complicated case: misaligned bytes must stay
+            size_t misalignment = buffer->size % size;
+            len = buffer->size - misalignment;
+        }
+    }
+    buffer->size -= len;
+
+    // adjust position, if required
+    if (buffer->pos > buffer->size) {
+        buffer->pos = buffer->size;
+    }
+
+    return len / size;
+}
+
 void cxBufferClear(CxBuffer *buffer) {
     if (0 == (buffer->flags & CX_BUFFER_COPY_ON_WRITE)) {
         memset(buffer->bytes, 0, buffer->size);
--- a/src/cx/buffer.h	Tue Nov 25 20:35:27 2025 +0100
+++ b/src/cx/buffer.h	Wed Nov 26 23:06:12 2025 +0100
@@ -118,7 +118,7 @@
     /**
      * The maximum number of blocks to flush in one cycle.
      *
-     * @attention while it is guaranteed that cxBufferFlush() will not flush
+     * @attention While it is guaranteed that cxBufferFlush() will not flush
      * more blocks, this is not necessarily the case for cxBufferWrite().
      * After performing a flush cycle, cxBufferWrite() will retry the write
      * operation and potentially trigger another flush cycle, until the
@@ -388,6 +388,20 @@
 CX_EXPORT int cxBufferSeek(CxBuffer *buffer, off_t offset, int whence);
 
 /**
+ * Discards items from the end of the buffer.
+ *
+ * When the current position points to a byte that gets discarded,
+ * the position is set to the buffer size.
+ *
+ * @param buffer the buffer
+ * @param size the size of one item
+ * @param nitems the number of items to discard
+ * @return the actual number of discarded items
+ */
+cx_attr_nonnull
+CX_EXPORT size_t cxBufferPop(CxBuffer *buffer, size_t size, size_t nitems);
+
+/**
  * Clears the buffer by resetting the position and deleting the data.
  *
  * The data is deleted by zeroing it with a call to memset().

mercurial