docs/Writerside/topics/buffer.h.md

Mon, 24 Mar 2025 20:16:36 +0100

author
Mike Becker <universe@uap-core.de>
date
Mon, 24 Mar 2025 20:16:36 +0100
changeset 1260
56a019cdb055
parent 1259
7bc999fe285d
child 1261
6bbc308b7a20
permissions
-rw-r--r--

add documentation for the shift functions

relates to #451

# Buffer

<warning>
Outdated Section - will be updated soon!
</warning>

Instances of this buffer implementation can be used to read from or write to memory like you would do with a stream.
This allows the use of `cx_stream_copy()` (see [](streams.h.md)) to copy contents from one buffer to another,
or from a file or network streams to the buffer and vice versa.

More features for convenient use of the buffer can be enabled, like automatic memory management and automatic
resizing of the buffer space.

Since UCX 3.0, the buffer also supports automatic flushing of contents to another stream (or buffer) as an alternative
to automatically resizing the buffer space.
Please refer to the API doc for the fields prefixed with `flush_` to learn more. 

## Example

<warning>
TODO: add example
</warning>

## Create

```C
#include <cx/buffer.h>

int cxBufferInit(CxBuffer *buffer, void *space, size_t capacity,
        const CxAllocator *allocator, int flags);

CxBuffer *cxBufferCreate(void *space,size_t capacity,
        const CxAllocator *allocator, int flags);

// available flags:
#define CX_BUFFER_DEFAULT
#define CX_BUFFER_FREE_CONTENTS
#define CX_BUFFER_AUTO_EXTEND
#define CX_BUFFER_COPY_ON_WRITE
#define CX_BUFFER_COPY_ON_EXTEND
```

<warning>
TODO: document
</warning>

## Destroy

```C
#include <cx/buffer.h>

void cxBufferDestroy(CxBuffer *buffer);

void cxBufferFree(CxBuffer *buffer);
```

The above functions destroy the buffer and deallocate the buffer's memory when the `CX_BUFFER_FREE_CONTENTS` flag is set.

The function `cxBufferDestroy()` is to be used when the buffer was initialized with `cxBufferInit()`,
and the function `cxBufferFree()` is to be used when the buffer was created with `cxBufferCreate()`.
The only difference is, that `cxBufferFree()` additionally deallocates the memory of the `CxBuffer` structure. 

## Write

```C
#include <cx/buffer.h>

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

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

int cxBufferPut(CxBuffer *buffer, int c);

size_t cxBufferPutString(CxBuffer *buffer, const char *str);

int cxBufferTerminate(CxBuffer *buffer);

int cxBufferMinimumCapacity(CxBuffer *buffer, size_t capacity);
```

<warning>
TODO: document
</warning>

## Read

```C
#include <cx/buffer.h>

size_t cxBufferRead(void *ptr, size_t size, size_t nitems,
        CxBuffer *buffer);

int cxBufferGet(CxBuffer *buffer);

bool cxBufferEof(const CxBuffer *buffer);
```

<warning>
TODO: document
</warning>

## Reset and Clear

```C
#include <cx/buffer.h>

void cxBufferReset(CxBuffer *buffer);

void cxBufferClear(CxBuffer *buffer);
```

<warning>
TODO: document
</warning>

## Random Access

```C
#include <cx/buffer.h>

int cxBufferSeek(CxBuffer *buffer, off_t offset, int whence);
```

The function `cxBufferSeek()` is a `fseek()`-like function that sets the current position in the buffer
relative to the start (when `whence` is `SEEK_SET`), the current position (when `whence` is `SEEK_CUR`),
or end (when `whence` is `SEEK_END`) of the buffer.

If the resulting position is negative, or larger than the size (i.e. the first unused byte),
this function returns non-zero and sets `errno` to `EOVERFLOW`.

> Note that the error behavior of `cxBufferSeek()` is not exactly the same as for POSIX `fseek()`.

## Shift Contents

```C
#include <cx/buffer.h>

int cxBufferShift(CxBuffer *buffer, off_t shift);

int cxBufferShiftRight(CxBuffer *buffer, size_t shift);

int cxBufferShiftLeft(CxBuffer *buffer, size_t shift);
```

The function `cxBufferShift()` moves the contents within the buffer by the specified `shift` offset,
where a negative offset means a shift to the left, and a positive offset means a shift to the right.
It also adjusts the current position within the buffer, and in case of a right shift also the size, by the same offset.

Data that is shift to the left, is always discarded when the new position of a byte would be smaller than zero.
If the new position would be smaller than zero, it is set exactly to zero.

When data is shift to the right, the behavior depends on the `CX_BUFFER_AUTO_EXTEND` flag.
If set, the function extends the buffer's capacity before moving the data.
Otherwise, the function discards all data that would exceed the buffer's capacity, and both the size and the position are equal to the capacity
(which means, `cxBufferEof()` returns `true` after the operation). 

The functions `cxBufferShiftRight()` and `cxBufferShiftLeft()` accept a larger (but in both cases positive) shift offset,
which usually does not make much sense on a 64-bit platform where `off_t` is already large enough to represent any reasonable offset.
You may, however, still use those function to express more explicitly in your code in which direction you want the contents to be shifted.

## Flushing

```C
#include <cx/buffer.h>

typedef struct cx_buffer_flush_config_s {
    size_t threshold;
    size_t blksize;
    size_t blkmax;
    void *target;
    cx_write_func wfunc;
} CxBufferFlushConfig;

int cxBufferEnableFlushing(CxBuffer *buffer,
        CxBufferFlushConfig config);

size_t cxBufferFlush(CxBuffer *buffer);
```

<warning>
TODO: document
</warning>

<seealso>
<category ref="apidoc">
<a href="https://ucx.sourceforge.io/api/buffer_8h.html">buffer.h</a>
</category>
</seealso>

mercurial