![]() |
ucx
UAP Common Extensions
|
Advanced buffer implementation. More...
Go to the source code of this file.
Data Structures | |
struct | cx_buffer_flush_config_s |
Configuration for automatic flushing. More... | |
struct | cx_buffer_s |
Structure for the UCX buffer data. More... | |
Macros | |
#define | CX_BUFFER_DEFAULT 0x00 |
No buffer features enabled (all flags cleared). | |
#define | CX_BUFFER_FREE_CONTENTS 0x01 |
If this flag is enabled, the buffer will automatically free its contents when destroyed. | |
#define | CX_BUFFER_AUTO_EXTEND 0x02 |
If this flag is enabled, the buffer will automatically extend its capacity. | |
#define | CX_BUFFER_COPY_ON_WRITE 0x04 |
If this flag is enabled, the buffer will allocate new memory when written to. | |
#define | CX_BUFFER_COPY_ON_EXTEND 0x08 |
If this flag is enabled, the buffer will copy its contents to a new memory area on reallocation. | |
#define | cxBufferWriteFunc ((cx_write_func) cxBufferWrite) |
Function pointer for cxBufferWrite that is compatible with cx_write_func. | |
#define | cxBufferReadFunc ((cx_read_func) cxBufferRead) |
Function pointer for cxBufferRead that is compatible with cx_read_func. | |
Typedefs | |
typedef struct cx_buffer_flush_config_s | CxBufferFlushConfig |
Type alias for the flush configuration struct. | |
typedef struct cx_buffer_s | CxBuffer |
UCX buffer. | |
Functions | |
int | cxBufferInit (CxBuffer *buffer, void *space, size_t capacity, const CxAllocator *allocator, int flags) |
Initializes a fresh buffer. | |
int | cxBufferEnableFlushing (CxBuffer *buffer, CxBufferFlushConfig config) |
Configures the buffer for flushing. | |
void | cxBufferDestroy (CxBuffer *buffer) |
Destroys the buffer contents. | |
void | cxBufferFree (CxBuffer *buffer) |
Deallocates the buffer. | |
CxBuffer * | cxBufferCreate (void *space, size_t capacity, const CxAllocator *allocator, int flags) |
Allocates and initializes a fresh buffer. | |
int | cxBufferShift (CxBuffer *buffer, off_t shift) |
Shifts the contents of the buffer by the given offset. | |
int | cxBufferShiftRight (CxBuffer *buffer, size_t shift) |
Shifts the buffer to the right. | |
int | cxBufferShiftLeft (CxBuffer *buffer, size_t shift) |
Shifts the buffer to the left. | |
int | cxBufferSeek (CxBuffer *buffer, off_t offset, int whence) |
Moves the position of the buffer. | |
void | cxBufferClear (CxBuffer *buffer) |
Clears the buffer by resetting the position and deleting the data. | |
void | cxBufferReset (CxBuffer *buffer) |
Resets the buffer by resetting the position and size to zero. | |
bool | cxBufferEof (const CxBuffer *buffer) |
Tests, if the buffer position has exceeded the buffer size. | |
int | cxBufferMinimumCapacity (CxBuffer *buffer, size_t capacity) |
Ensures that the buffer has a minimum capacity. | |
size_t | cxBufferWrite (const void *ptr, size_t size, size_t nitems, CxBuffer *buffer) |
Writes data to a CxBuffer. | |
size_t | cxBufferAppend (const void *ptr, size_t size, size_t nitems, CxBuffer *buffer) |
Appends data to a CxBuffer. | |
size_t | cxBufferFlush (CxBuffer *buffer) |
Performs a single flush-run on the specified buffer. | |
size_t | cxBufferRead (void *ptr, size_t size, size_t nitems, CxBuffer *buffer) |
Reads data from a CxBuffer. | |
int | cxBufferPut (CxBuffer *buffer, int c) |
Writes a character to a buffer. | |
int | cxBufferTerminate (CxBuffer *buffer) |
Writes a terminating zero to a buffer at the current position. | |
size_t | cxBufferPutString (CxBuffer *buffer, const char *str) |
Writes a string to a buffer. | |
int | cxBufferGet (CxBuffer *buffer) |
Gets a character from a buffer. | |
Advanced buffer implementation.
Instances of CxBuffer can be used to read from or to write to like one would do with a stream.
Some features for convenient use of the buffer can be enabled. See the documentation of the macro constants for more information.
#define CX_BUFFER_COPY_ON_EXTEND 0x08 |
If this flag is enabled, the buffer will copy its contents to a new memory area on reallocation.
After performing the copy, the flag is automatically cleared. This flag has no effect on buffers which do not have CX_BUFFER_AUTO_EXTEND set, which is why buffers automatically admit the auto-extend flag when initialized with copy-on-extend enabled.
#define CX_BUFFER_COPY_ON_WRITE 0x04 |
If this flag is enabled, the buffer will allocate new memory when written to.
The current contents of the buffer will be copied to the new memory and the flag will be cleared while the CX_BUFFER_FREE_CONTENTS flag will be set automatically.
#define CX_BUFFER_FREE_CONTENTS 0x01 |
If this flag is enabled, the buffer will automatically free its contents when destroyed.
Do NOT set this flag together with CX_BUFFER_COPY_ON_WRITE. It will be automatically set when the copy-on-write operations is performed.
#define cxBufferReadFunc ((cx_read_func) cxBufferRead) |
Function pointer for cxBufferRead that is compatible with cx_read_func.
#define cxBufferWriteFunc ((cx_write_func) cxBufferWrite) |
Function pointer for cxBufferWrite that is compatible with cx_write_func.
typedef struct cx_buffer_flush_config_s CxBufferFlushConfig |
Type alias for the flush configuration struct.
size_t cxBufferAppend | ( | const void * | ptr, |
size_t | size, | ||
size_t | nitems, | ||
CxBuffer * | buffer ) |
Appends data to a CxBuffer.
The data is always appended to current data within the buffer, regardless of the current position. This is especially useful when the buffer is primarily meant for reading while additional data is added to the buffer occasionally. Consequently, the position of the buffer is unchanged after this operation.
ptr | a pointer to the memory area containing the bytes to be written |
size | the length of one element |
nitems | the element count |
buffer | the CxBuffer to write to |
void cxBufferClear | ( | CxBuffer * | buffer | ) |
Clears the buffer by resetting the position and deleting the data.
The data is deleted by zeroing it with a call to memset(). If you do not need that, you can use the faster cxBufferReset().
buffer | the buffer to be cleared |
CxBuffer * cxBufferCreate | ( | void * | space, |
size_t | capacity, | ||
const CxAllocator * | allocator, | ||
int | flags ) |
Allocates and initializes a fresh buffer.
You may also provide a read-only space
, in which case you will need to cast the pointer, and you should set the CX_BUFFER_COPY_ON_WRITE flag. When you specify stack memory as space
and decide to use the auto-extension feature, you must use the CX_BUFFER_COPY_ON_EXTEND flag, instead of the CX_BUFFER_AUTO_EXTEND flag.
NULL
as argument for space
. Then this function will allocate the space and enforce the CX_BUFFER_FREE_CONTENTS flag.space | pointer to the memory area, or NULL to allocate new memory |
capacity | the capacity of the buffer |
allocator | the allocator to use for allocating the structure and the automatic memory management within the buffer (if NULL , a default stdlib allocator will be used) |
flags | buffer features (see cx_buffer_s.flags) |
NULL
if a required allocation failed void cxBufferDestroy | ( | CxBuffer * | buffer | ) |
Destroys the buffer contents.
Has no effect if the CX_BUFFER_FREE_CONTENTS feature is not enabled. If you want to free the memory of the entire buffer, use cxBufferFree().
buffer | the buffer which contents shall be destroyed |
int cxBufferEnableFlushing | ( | CxBuffer * | buffer, |
CxBufferFlushConfig | config ) |
Configures the buffer for flushing.
Flushing can happen automatically when data is written to the buffer (see cxBufferWrite()) or manually when cxBufferFlush() is called.
buffer | the buffer |
config | the flush configuration |
zero | success |
non-zero | failure |
bool cxBufferEof | ( | const CxBuffer * | buffer | ) |
Tests, if the buffer position has exceeded the buffer size.
buffer | the buffer to test |
true | if the current buffer position has exceeded the last byte of the buffer's contents |
false | otherwise |
size_t cxBufferFlush | ( | CxBuffer * | buffer | ) |
Performs a single flush-run on the specified buffer.
Does nothing when the position in the buffer is zero. Otherwise, the data until the current position minus one is considered for flushing. Note carefully that flushing will never exceed the current position, even when the size of the buffer is larger than the current position.
One flush run will try to flush blkmax
many blocks of size blksize
until either the buffer
has no more data to flush or the write function used for flushing returns zero.
The buffer is shifted left for that many bytes the flush operation has successfully flushed.
blkmax=4
and blksize=64
. Assume that the entire flush operation is successful. All 200 bytes on the left hand-side from the current position are written. That means, the size of the buffer is now 140 and the position is zero.blkmax
is 1. The size of the buffer is now 276 and the position is 136.buffer | the buffer |
void cxBufferFree | ( | CxBuffer * | buffer | ) |
Deallocates the buffer.
If the CX_BUFFER_FREE_CONTENTS feature is enabled, this function also destroys the contents. If you only want to destroy the contents, use cxBufferDestroy().
NULL
arguments in which case it does nothing.buffer | the buffer to deallocate |
int cxBufferGet | ( | CxBuffer * | buffer | ) |
Gets a character from a buffer.
The current position of the buffer is increased after a successful read.
buffer | the buffer to read from |
EOF
, if the end of the buffer is reached int cxBufferInit | ( | CxBuffer * | buffer, |
void * | space, | ||
size_t | capacity, | ||
const CxAllocator * | allocator, | ||
int | flags ) |
Initializes a fresh buffer.
You may also provide a read-only space
, in which case you will need to cast the pointer, and you should set the CX_BUFFER_COPY_ON_WRITE flag.
You need to set the size manually after initialization, if you provide space
which already contains data.
When you specify stack memory as space
and decide to use the auto-extension feature, you must use the CX_BUFFER_COPY_ON_EXTEND flag, instead of the CX_BUFFER_AUTO_EXTEND flag.
NULL
as argument for space
. Then this function will allocate the space and enforce the CX_BUFFER_FREE_CONTENTS flag. In that case, specifying copy-on-write should be avoided, because the allocated space will be leaking after the copy-on-write operation.buffer | the buffer to initialize |
space | pointer to the memory area, or NULL to allocate new memory |
capacity | the capacity of the buffer |
allocator | the allocator this buffer shall use for automatic memory management (if NULL , a default stdlib allocator will be used) |
flags | buffer features (see cx_buffer_s.flags) |
int cxBufferMinimumCapacity | ( | 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.
buffer | the buffer |
capacity | the minimum required capacity for this buffer |
zero | the capacity was already sufficient or successfully increased |
non-zero | on allocation failure |
int cxBufferPut | ( | CxBuffer * | buffer, |
int | c ) |
Writes a character to a buffer.
The least significant byte of the argument is written to the buffer. If the end of the buffer is reached and CX_BUFFER_AUTO_EXTEND feature is enabled, the buffer capacity is extended by cxBufferMinimumCapacity(). If the feature is disabled or buffer extension fails, EOF
is returned.
On successful write, the position of the buffer is increased.
If you just want to write a null-terminator at the current position, you should use cxBufferTerminate() instead.
buffer | the buffer to write to |
c | the character to write |
EOF
when the end of the stream is reached and automatic extension is not enabled or not possible size_t cxBufferPutString | ( | CxBuffer * | buffer, |
const char * | str ) |
Writes a string to a buffer.
This is a convenience function for cxBufferWrite(str, 1, strlen(str), buffer)
.
buffer | the buffer |
str | the zero-terminated string |
size_t cxBufferRead | ( | void * | ptr, |
size_t | size, | ||
size_t | nitems, | ||
CxBuffer * | buffer ) |
Reads data from a CxBuffer.
The position of the buffer is increased by the number of bytes read.
ptr | a pointer to the memory area where to store the read data |
size | the length of one element |
nitems | the element count |
buffer | the CxBuffer to read from |
void cxBufferReset | ( | CxBuffer * | buffer | ) |
Resets the buffer by resetting the position and size to zero.
The data in the buffer is not deleted. If you need a safe reset of the buffer, use cxBufferClear().
buffer | the buffer to be cleared |
int cxBufferSeek | ( | CxBuffer * | buffer, |
off_t | offset, | ||
int | whence ) |
Moves the position of the buffer.
The new position is relative to the whence
argument.
SEEK_SET
marks the start of the buffer. SEEK_CUR
marks the current position. SEEK_END
marks the end of the buffer.With an offset of zero, this function sets the buffer position to zero (SEEK_SET
), the buffer size (SEEK_END
) or leaves the buffer position unchanged (SEEK_CUR
).
buffer | the buffer |
offset | position offset relative to whence |
whence | one of SEEK_SET , SEEK_CUR or SEEK_END |
zero | success |
non-zero | if the position is invalid |
int cxBufferShift | ( | CxBuffer * | buffer, |
off_t | shift ) |
Shifts the contents of the buffer by the given offset.
If the offset is positive, the contents are shifted to the right. If auto extension is enabled, the buffer grows, if necessary. In case the auto extension fails, this function returns a non-zero value and no contents are changed. If auto extension is disabled, the contents that do not fit into the buffer are discarded.
If the offset is negative, the contents are shifted to the left where the first shift
bytes are discarded. The new size of the buffer is the old size minus the absolute shift value. If this value is larger than the buffer size, the buffer is emptied (but not cleared, see the security note below).
The buffer position gets shifted alongside with the content but is kept within the boundaries of the buffer.
off_t
is not large enough, there are specialized cxBufferShiftLeft() and cxBufferShiftRight() functions using a size_t
as parameter type.memset(buffer->bytes, 0, shift)
for a right shift or memset(buffer->bytes + buffer->size, 0, buffer->capacity - buffer->size)
for a left shift.buffer | the buffer |
shift | the shift offset (negative means left shift) |
zero | success |
non-zero | if a required auto-extension or copy-on-write fails |
int cxBufferShiftLeft | ( | CxBuffer * | buffer, |
size_t | shift ) |
Shifts the buffer to the left.
See cxBufferShift() for details.
buffer | the buffer |
shift | the positive shift offset |
zero | success |
non-zero | if the buffer uses copy-on-write and the allocation fails |
int cxBufferShiftRight | ( | CxBuffer * | buffer, |
size_t | shift ) |
Shifts the buffer to the right.
See cxBufferShift() for details.
buffer | the buffer |
shift | the shift offset |
zero | success |
non-zero | if a required auto-extension or copy-on-write fails |
int cxBufferTerminate | ( | CxBuffer * | buffer | ) |
Writes a terminating zero to a buffer at the current position.
On successful write, neither the position nor the size of the buffer is increased.
The purpose of this function is to have the written data ready to be used as a C string.
buffer | the buffer to write to |
size_t cxBufferWrite | ( | const void * | ptr, |
size_t | size, | ||
size_t | nitems, | ||
CxBuffer * | buffer ) |
Writes data to a CxBuffer.
If automatic flushing is not enabled, the data is simply written into the buffer at the current position and the position of the buffer is increased by the number of bytes written.
If flushing is enabled and the buffer needs to flush, the data is flushed to the target until the target signals that it cannot take more data by returning zero via the respective write function. In that case, the remaining data in this buffer is shifted to the beginning of this buffer so that the newly available space can be used to append as much data as possible.
This function only stops writing more elements, when the flush target and this buffer are both incapable of taking more data or all data has been written.
If, after flushing, the number of items that shall be written still exceeds the capacity or flush threshold, this function tries to write all items directly to the flush target, if possible.
The number returned by this function is the number of elements from ptr
that could be written to either the flush target or the buffer (so it does not include the number of items that had been already in the buffer in were flushed during the process).
size
is larger than one and the contents of the buffer are not aligned with size
, flushing stops after all complete items have been flushed, leaving the mis-aligned part in the buffer. Afterward, this function only writes as many items as possible to the buffer.ptr | a pointer to the memory area containing the bytes to be written |
size | the length of one element |
nitems | the element count |
buffer | the CxBuffer to write to |