# HG changeset patch # User Mike Becker # Date 1764194772 -3600 # Node ID ee5d668a71e4bee416594007e9ab347d3b2a078b # Parent 4d641c6a2f820922eb5149afac2226164d0cd9ab add cxBufferPop() diff -r 4d641c6a2f82 -r ee5d668a71e4 CHANGELOG --- 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() diff -r 4d641c6a2f82 -r ee5d668a71e4 docs/Writerside/topics/about.md --- 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() diff -r 4d641c6a2f82 -r ee5d668a71e4 docs/Writerside/topics/buffer.h.md --- 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"} diff -r 4d641c6a2f82 -r ee5d668a71e4 src/buffer.c --- 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); diff -r 4d641c6a2f82 -r ee5d668a71e4 src/cx/buffer.h --- 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().