ucx
UAP Common Extensions
Loading...
Searching...
No Matches
buffer.h File Reference

Advanced buffer implementation. More...

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

Go to the source code of this file.

Data Structures

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 CX_BUFFER_DO_NOT_FREE   0x10
 If this flag is enabled, the buffer will never free its contents regardless of CX_BUFFER_FREE_CONTENTS.
 
#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.
 
#define cxBufferPutString(buffer, str)
 Writes a string to a buffer with cxBufferWrite().
 
#define cxBufferAppendString(buffer, str)
 Appends a string to a buffer with cxBufferAppend().
 

Typedefs

typedef struct cx_buffer_s CxBuffer
 UCX buffer.
 

Functions

int cxBufferInit (CxBuffer *buffer, const CxAllocator *allocator, void *space, size_t capacity, int flags)
 Initializes a fresh buffer.
 
void cxBufferDestroy (CxBuffer *buffer)
 Destroys the buffer contents.
 
void cxBufferFree (CxBuffer *buffer)
 Deallocates the buffer.
 
CxBuffercxBufferCreate (const CxAllocator *allocator, void *space, size_t capacity, 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.
 
size_t cxBufferPop (CxBuffer *buffer, size_t size, size_t nitems)
 Discards items from the end 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 cxBufferReserve (CxBuffer *buffer, size_t capacity)
 Ensures that the buffer has the required capacity.
 
int cxBufferMaximumCapacity (CxBuffer *buffer, size_t capacity)
 Limits the buffer's capacity.
 
int cxBufferMinimumCapacity (CxBuffer *buffer, size_t capacity)
 Ensures that the buffer has a minimum capacity.
 
void cxBufferShrink (CxBuffer *buffer, size_t reserve)
 Shrinks the capacity of the buffer to fit its current size.
 
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 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 cx_buffer_put_string (CxBuffer *buffer, cxstring str)
 Internal function - do not use.
 
size_t cx_buffer_append_string (CxBuffer *buffer, cxstring str)
 Internal function - do not use.
 
int cxBufferGet (CxBuffer *buffer)
 Gets a character from a buffer.
 
static cxstring cx_bstr (CxBuffer *buffer)
 Gets the data in a buffer as a cxstring.
 
static cxmutstr cx_bstr_m (CxBuffer *buffer)
 Gets the data in a buffer as a cxmutstr.
 

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_DO_NOT_FREE

#define CX_BUFFER_DO_NOT_FREE   0x10

If this flag is enabled, the buffer will never free its contents regardless of CX_BUFFER_FREE_CONTENTS.

This is useful, for example, when you want to keep a pointer to the data after destroying the buffer.

◆ 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 operation is performed.

◆ cxBufferAppendString

#define cxBufferAppendString ( buffer,
str )
Value:
size_t cx_buffer_append_string(CxBuffer *buffer, cxstring str)
Internal function - do not use.
#define cx_strcast(str)
Converts any string to a cxstring.
Definition string.h:393

Appends a string to a buffer with cxBufferAppend().

Parameters
buffer(CxBuffer*) the buffer
str(any string) the zero-terminated string
Returns
(size_t) the number of bytes written
See also
cxBufferAppend()
cx_strcast()

◆ cxBufferPutString

#define cxBufferPutString ( buffer,
str )
Value:
size_t cx_buffer_put_string(CxBuffer *buffer, cxstring str)
Internal function - do not use.

Writes a string to a buffer with cxBufferWrite().

Parameters
buffer(CxBuffer*) the buffer
str(any string) the zero-terminated string
Returns
(size_t) the number of bytes written
See also
cxBufferWrite()
cx_strcast()

◆ 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

Function Documentation

◆ cx_bstr()

static cxstring cx_bstr ( CxBuffer * buffer)
inlinestatic

Gets the data in a buffer as a cxstring.

Parameters
bufferthe buffer
Returns
the data in the buffer interpreted as a cxstring

◆ cx_bstr_m()

static cxmutstr cx_bstr_m ( CxBuffer * buffer)
inlinestatic

Gets the data in a buffer as a cxmutstr.

Parameters
bufferthe buffer
Returns
the data in the buffer interpreted as a cxmutstr

◆ cx_buffer_append_string()

size_t cx_buffer_append_string ( CxBuffer * buffer,
cxstring str )

Internal function - do not use.

Parameters
bufferthe buffer
strthe string
Returns
the number of bytes written
See also
cxBufferPutString()

◆ cx_buffer_put_string()

size_t cx_buffer_put_string ( CxBuffer * buffer,
cxstring str )

Internal function - do not use.

Parameters
bufferthe buffer
strthe string
Returns
the number of bytes written
See also
cxBufferPutString()

◆ 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 ( const CxAllocator * allocator,
void * space,
size_t capacity,
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 the argument for space. Then this function will allocate the space and enforce the CX_BUFFER_FREE_CONTENTS flag.
Parameters
allocatorthe allocator to use for allocating the structure and the automatic memory management within the buffer (if NULL, the cxDefaultAllocator will be used)
spacepointer to the memory area, or NULL to allocate new memory
capacitythe capacity of the buffer
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()

◆ 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

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

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,
const CxAllocator * allocator,
void * space,
size_t capacity,
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 the 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
allocatorthe allocator this buffer shall use for automatic memory management (if NULL, the cxDefaultAllocator will be used)
spacepointer to the memory area, or NULL to allocate new memory
capacitythe capacity of the buffer
flagsbuffer features (see cx_buffer_s.flags)
Returns
zero on success, non-zero if a required allocation failed

◆ cxBufferMaximumCapacity()

int cxBufferMaximumCapacity ( CxBuffer * buffer,
size_t capacity )

Limits the buffer's capacity.

If the current capacity is already larger, this function fails and returns non-zero.

The capacity limit will affect auto-extension features, as well as future calls to cxBufferMinimumCapacity() and cxBufferReserve().

Parameters
bufferthe buffer
capacitythe maximum allowed capacity for this buffer
Return values
zerothe limit is applied
non-zerothe new limit is smaller than the current capacity
See also
cxBufferReserve()
cxBufferMinimumCapacity()

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

Parameters
bufferthe buffer
capacitythe minimum required capacity for this buffer
Return values
zerothe capacity was already sufficient or successfully increased
non-zeroon allocation failure
See also
cxBufferMaximumCapacity()
cxBufferReserve()
cxBufferShrink()

◆ cxBufferPop()

size_t cxBufferPop ( CxBuffer * buffer,
size_t size,
size_t nitems )

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.

Parameters
bufferthe buffer
sizethe size of one item
nitemsthe number of items to discard
Returns
the actual number of discarded items

◆ 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, unless a limit set by cxBufferMaximumCapacity() is reached. If the feature is disabled or the buffer extension fails, EOF is returned.

On successful writing, 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()

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

◆ cxBufferReserve()

int cxBufferReserve ( CxBuffer * buffer,
size_t capacity )

Ensures that the buffer has the required capacity.

If the current capacity is not sufficient, the buffer will be extended. If the current capacity is larger, the buffer is shrunk and superfluous content is discarded.

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.

Parameters
bufferthe buffer
capacitythe required capacity for this buffer
Return values
zeroon success
non-zeroon allocation failure
See also
cxBufferShrink()
cxBufferMinimumCapacity()

◆ 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. When the 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 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 the parameter type.
Attention
Security Note: The shifting operation does not erase the previously occupied memory cells. But you can do that manually 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()

◆ cxBufferShrink()

void cxBufferShrink ( CxBuffer * buffer,
size_t reserve )

Shrinks the capacity of the buffer to fit its current size.

If reserve is larger than zero, the buffer is shrunk to its size plus the number of reserved bytes.

If the current capacity is not larger than the size plus the reserved bytes, nothing happens.

If the CX_BUFFER_COPY_ON_WRITE or CX_BUFFER_COPY_ON_EXTEND flag is set, this function does nothing.

Parameters
bufferthe buffer
reservethe number of bytes that shall remain reserved
See also
cxBufferReserve()
cxBufferMinimumCapacity()

◆ cxBufferTerminate()

int cxBufferTerminate ( CxBuffer * buffer)

Writes a terminating zero to a buffer at the current position.

If successful, also sets the size to the current position and shrinks the buffer.

The purpose of this function is to have the written data ready to be used as a C string with the buffer's size being the length of that string.

Parameters
bufferthe buffer to write to
Returns
zero, if the terminator could be written, non-zero otherwise
See also
cxBufferShrink()

◆ cxBufferWrite()

size_t cxBufferWrite ( const void * ptr,
size_t size,
size_t nitems,
CxBuffer * buffer )

Writes data to a CxBuffer.

If auto-extension is enabled, the buffer's capacity is automatically increased when it is not large enough to hold all data. By default, the capacity grows indefinitely, unless limited with cxBufferMaximumCapacity(). When auto-extension fails, this function writes no data and returns zero.

The position of the buffer is moved alongside the written data.

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