ucx
UAP Common Extensions
Loading...
Searching...
No Matches
Data Structures | Macros | Typedefs | Functions
buffer.h File Reference

Advanced buffer implementation. More...

#include "common.h"
#include "allocator.h"

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.
 
CxBuffercxBufferCreate (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.
 

Detailed Description

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.

Author
Mike Becker
Olaf Wintermann

Macro Definition Documentation

◆ CX_BUFFER_COPY_ON_EXTEND

#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.

◆ CX_BUFFER_COPY_ON_WRITE

#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.

◆ CX_BUFFER_FREE_CONTENTS

#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.

◆ cxBufferReadFunc

#define cxBufferReadFunc   ((cx_read_func) cxBufferRead)

Function pointer for cxBufferRead that is compatible with cx_read_func.

See also
cx_read_func

◆ cxBufferWriteFunc

#define cxBufferWriteFunc   ((cx_write_func) cxBufferWrite)

Function pointer for cxBufferWrite that is compatible with cx_write_func.

See also
cx_write_func

Typedef Documentation

◆ CxBufferFlushConfig

Type alias for the flush configuration struct.

size_t threshold;
size_t blksize;
size_t blkmax;
void *target;
};
size_t(* cx_write_func)(const void *, size_t, size_t, void *)
Function pointer compatible with fwrite-like functions.
Definition common.h:295
Configuration for automatic flushing.
Definition buffer.h:105
cx_write_func wfunc
The write-function used for flushing.
Definition buffer.h:138
size_t blkmax
The maximum number of blocks to flush in one cycle.
Definition buffer.h:127
size_t threshold
The buffer may not extend beyond this threshold before starting to flush.
Definition buffer.h:113
void * target
The target for write function.
Definition buffer.h:132
size_t blksize
The block size for the elements to flush.
Definition buffer.h:117

Function Documentation

◆ cxBufferAppend()

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.

Note
The signature is compatible with the fwrite() family of functions.
Parameters
ptra pointer to the memory area containing the bytes to be written
sizethe length of one element
nitemsthe element count
bufferthe CxBuffer to write to
Returns
the total count of elements written
See also
cxBufferWrite()
cxBufferRead()

◆ cxBufferClear()

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().

Note
If the CX_BUFFER_COPY_ON_WRITE flag is set, this function will not erase the data and behave exactly as cxBufferReset().
Parameters
bufferthe buffer to be cleared
See also
cxBufferReset()

◆ cxBufferCreate()

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.

Note
You may provide NULL as argument for space. Then this function will allocate the space and enforce the CX_BUFFER_FREE_CONTENTS flag.
Parameters
spacepointer to the memory area, or NULL to allocate new memory
capacitythe capacity of the buffer
allocatorthe allocator to use for allocating the structure and the automatic memory management within the buffer (if NULL, a default stdlib allocator will be used)
flagsbuffer features (see cx_buffer_s.flags)
Returns
a pointer to the buffer on success, NULL if a required allocation failed

◆ cxBufferDestroy()

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().

Parameters
bufferthe buffer which contents shall be destroyed
See also
cxBufferInit()

◆ cxBufferEnableFlushing()

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.

Parameters
bufferthe buffer
configthe flush configuration
Return values
zerosuccess
non-zerofailure
See also
cxBufferFlush()
cxBufferWrite()

◆ cxBufferEof()

bool cxBufferEof ( const CxBuffer * buffer)

Tests, if the buffer position has exceeded the buffer size.

Parameters
bufferthe buffer to test
Return values
trueif the current buffer position has exceeded the last byte of the buffer's contents
falseotherwise

◆ cxBufferFlush()

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.

Example 1
Assume you have a buffer with size 340 and you are at position 200. The flush configuration is 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.
Example 2
Same as Example 1, but now the blkmax is 1. The size of the buffer is now 276 and the position is 136.
Example 3
Same as Example 1, but now assume the flush target only accepts 100 bytes before returning zero. That means, the flush operations manages to flush one complete block and one partial block, ending up with a buffer with size 240 and position 100.
Remarks
Just returns zero when flushing was not enabled with cxBufferEnableFlushing().
When the buffer uses copy-on-write, the memory is copied first, before attempting any flush. This is, however, considered an erroneous use of the buffer, because it does not make much sense to put readonly data into an UCX buffer for flushing, instead of writing it directly to the target.
Parameters
bufferthe buffer
Returns
the number of successfully flushed bytes
See also
cxBufferEnableFlushing()

◆ cxBufferFree()

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().

Remarks
As with all free() functions, this accepts NULL arguments in which case it does nothing.
Parameters
bufferthe buffer to deallocate
See also
cxBufferCreate()

◆ cxBufferGet()

int cxBufferGet ( CxBuffer * buffer)

Gets a character from a buffer.

The current position of the buffer is increased after a successful read.

Parameters
bufferthe buffer to read from
Returns
the character or EOF, if the end of the buffer is reached

◆ cxBufferInit()

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.

Note
You may provide 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.
Parameters
bufferthe buffer to initialize
spacepointer to the memory area, or NULL to allocate new memory
capacitythe capacity of the buffer
allocatorthe allocator this buffer shall use for automatic memory management (if NULL, a default stdlib allocator will be used)
flagsbuffer features (see cx_buffer_s.flags)
Returns
zero on success, non-zero if a required allocation failed

◆ cxBufferMinimumCapacity()

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.

Parameters
bufferthe buffer
capacitythe minimum required capacity for this buffer
Return values
zerothe capacity was already sufficient or successfully increased
non-zeroon allocation failure

◆ cxBufferPut()

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.

Parameters
bufferthe buffer to write to
cthe character to write
Returns
the byte that has been written or EOF when the end of the stream is reached and automatic extension is not enabled or not possible
See also
cxBufferTerminate()

◆ cxBufferPutString()

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).

Parameters
bufferthe buffer
strthe zero-terminated string
Returns
the number of bytes written

◆ cxBufferRead()

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.

Note
The signature is compatible with the fread() family of functions.
Parameters
ptra pointer to the memory area where to store the read data
sizethe length of one element
nitemsthe element count
bufferthe CxBuffer to read from
Returns
the total number of elements read
See also
cxBufferWrite()
cxBufferAppend()

◆ cxBufferReset()

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().

Parameters
bufferthe buffer to be cleared
See also
cxBufferClear()

◆ cxBufferSeek()

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).

Parameters
bufferthe buffer
offsetposition offset relative to whence
whenceone of SEEK_SET, SEEK_CUR or SEEK_END
Return values
zerosuccess
non-zeroif the position is invalid

◆ cxBufferShift()

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.

Note
For situations where off_t is not large enough, there are specialized cxBufferShiftLeft() and cxBufferShiftRight() functions using a size_t as parameter type.
Attention
Security Note: The shifting operation does not erase the previously occupied memory cells. But you can easily do that manually, e.g. by calling memset(buffer->bytes, 0, shift) for a right shift or memset(buffer->bytes + buffer->size, 0, buffer->capacity - buffer->size) for a left shift.
Parameters
bufferthe buffer
shiftthe shift offset (negative means left shift)
Return values
zerosuccess
non-zeroif a required auto-extension or copy-on-write fails
See also
cxBufferShiftLeft()
cxBufferShiftRight()

◆ cxBufferShiftLeft()

int cxBufferShiftLeft ( CxBuffer * buffer,
size_t shift )

Shifts the buffer to the left.

See cxBufferShift() for details.

Parameters
bufferthe buffer
shiftthe positive shift offset
Return values
zerosuccess
non-zeroif the buffer uses copy-on-write and the allocation fails
See also
cxBufferShift()

◆ cxBufferShiftRight()

int cxBufferShiftRight ( CxBuffer * buffer,
size_t shift )

Shifts the buffer to the right.

See cxBufferShift() for details.

Parameters
bufferthe buffer
shiftthe shift offset
Return values
zerosuccess
non-zeroif a required auto-extension or copy-on-write fails
See also
cxBufferShift()

◆ cxBufferTerminate()

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.

Parameters
bufferthe buffer to write to
Returns
zero, if the terminator could be written, non-zero otherwise

◆ cxBufferWrite()

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).

Attention
When 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.
Note
The signature is compatible with the fwrite() family of functions.
Parameters
ptra pointer to the memory area containing the bytes to be written
sizethe length of one element
nitemsthe element count
bufferthe CxBuffer to write to
Returns
the total count of elements written
See also
cxBufferAppend()
cxBufferRead()