AxlRingBuf – Ring Buffer

See AxlData – Data Structures for an overview of all data modules including the ring buffer (circular byte buffer).

Header: <axl/axl-ring-buf.h>

API Reference

Defines

AXL_RING_BUF_OVERWRITE

Overwrite oldest data when buffer is full.

Functions

int axl_ring_buf_init(AxlRingBuf *rb, void *buf, uint32_t size, uint32_t flags, void (*buf_free)(void*))

Initialize an embedded ring buffer with a caller-provided buffer.

No heap allocation. The caller owns both the AxlRingBuf struct and the backing buffer. Pass a buf_free function to have deinit free the buffer, or NULL if the caller manages the buffer lifetime.

Parameters:
  • rb – caller-allocated struct

  • buf – backing buffer (must be power-of-2 sized)

  • size – buffer size in bytes (must be power of 2)

  • flags – AXL_RING_BUF_OVERWRITE or 0

  • buf_free – buffer deallocator, or NULL

Returns:

0 on success, -1 if size is not a power of 2 or args NULL.

void axl_ring_buf_deinit(AxlRingBuf *rb)

Release resources for an initialized ring buffer.

Calls the buf_free function (if set) to free the backing buffer. Does NOT free the AxlRingBuf struct itself (use axl_ring_buf_free for heap-allocated ring buffers).

Parameters:
  • rb – ring buffer (NULL-safe)

AxlRingBuf *axl_ring_buf_new(uint32_t min_size)

Create a ring buffer with at least min_size bytes capacity.

Capacity is rounded up to the next power of 2. Rejects writes when full (use axl_ring_buf_new_full for overwrite mode).

Parameters:
  • min_size – minimum capacity in bytes (rounded up to power of 2)

Returns:

new AxlRingBuf, or NULL on allocation failure.

AxlRingBuf *axl_ring_buf_new_full(uint32_t min_size, uint32_t flags)

Create a ring buffer with flags.

Parameters:
  • min_size – minimum capacity in bytes (rounded up to power of 2)

  • flags – AXL_RING_BUF_OVERWRITE or 0

Returns:

new AxlRingBuf, or NULL on allocation failure.

AxlRingBuf *axl_ring_buf_new_with_buffer(void *buf, uint32_t size, uint32_t flags)

Create a ring buffer using a caller-provided backing buffer.

The struct is heap-allocated but the backing buffer is owned by the caller. axl_ring_buf_free will NOT free the buffer.

Parameters:
  • buf – caller-provided buffer (must be power-of-2 sized)

  • size – buffer size in bytes (must be power of 2)

  • flags – AXL_RING_BUF_OVERWRITE or 0

Returns:

new AxlRingBuf, or NULL on failure.

void axl_ring_buf_free(AxlRingBuf *rb)

Free a heap-allocated ring buffer.

Frees the backing buffer if owned (new/new_full), then frees the struct. For embedded ring buffers, use axl_ring_buf_deinit instead.

Parameters:
  • rb – ring buffer (NULL-safe)

uint32_t axl_ring_buf_write(AxlRingBuf *rb, const void *data, uint32_t len)

Write bytes to the ring buffer.

In reject mode (default), writes up to the available space and returns the number of bytes actually written (may be less than len). In overwrite mode, always writes all bytes, advancing the read position to discard the oldest data as needed.

Parameters:
  • rb – ring buffer

  • data – source data

  • len – number of bytes to write

Returns:

number of bytes written.

uint32_t axl_ring_buf_read(AxlRingBuf *rb, void *dest, uint32_t len)

Read and consume bytes from the ring buffer.

Parameters:
  • rb – ring buffer

  • dest – destination buffer

  • len – maximum bytes to read

Returns:

number of bytes read (may be less than len).

uint32_t axl_ring_buf_peek(AxlRingBuf *rb, void *dest, uint32_t len)

Read bytes without consuming them.

Parameters:
  • rb – ring buffer

  • dest – destination buffer

  • len – maximum bytes to peek

Returns:

number of bytes copied to dest.

uint32_t axl_ring_buf_discard(AxlRingBuf *rb, uint32_t len)

Discard bytes from the read side without copying.

Parameters:
  • rb – ring buffer

  • len – maximum bytes to discard

Returns:

number of bytes discarded.

uint32_t axl_ring_buf_peek_regions(AxlRingBuf *rb, AxlRingBufRegion regions[2])

Get contiguous readable regions for zero-copy access.

Returns up to 2 regions covering all readable data. After processing, call axl_ring_buf_read_advance to consume.

Parameters:
  • rb – ring buffer

  • regions – receives up to 2 regions

Returns:

number of regions (0, 1, or 2).

uint32_t axl_ring_buf_write_regions(AxlRingBuf *rb, AxlRingBufRegion regions[2])

Get contiguous writable regions for zero-copy access.

Returns up to 2 regions covering all writable space. After filling, call axl_ring_buf_write_advance to commit.

Parameters:
  • rb – ring buffer

  • regions – receives up to 2 regions

Returns:

number of regions (0, 1, or 2).

void axl_ring_buf_read_advance(AxlRingBuf *rb, uint32_t len)

Advance the read position after zero-copy access.

Parameters:
  • rb – ring buffer

  • len – bytes consumed

void axl_ring_buf_write_advance(AxlRingBuf *rb, uint32_t len)

Advance the write position after zero-copy access.

Parameters:
  • rb – ring buffer

  • len – bytes produced

uint32_t axl_ring_buf_readable(AxlRingBuf *rb)

Get the number of readable bytes.

Parameters:
  • rb – ring buffer

Returns:

byte count available for reading.

uint32_t axl_ring_buf_writable(AxlRingBuf *rb)

Get the number of writable bytes.

Parameters:
  • rb – ring buffer

Returns:

byte count available for writing.

uint32_t axl_ring_buf_capacity(AxlRingBuf *rb)

Get the total buffer capacity.

Parameters:
  • rb – ring buffer

Returns:

capacity in bytes (always a power of 2).

bool axl_ring_buf_is_empty(AxlRingBuf *rb)

Check if the ring buffer is empty.

Parameters:
  • rb – ring buffer

Returns:

true if no data is available to read.

bool axl_ring_buf_is_full(AxlRingBuf *rb)

Check if the ring buffer is full.

Parameters:
  • rb – ring buffer

Returns:

true if no space is available for writing.

void axl_ring_buf_clear(AxlRingBuf *rb)

Discard all data and reset to empty.

Parameters:
  • rb – ring buffer

int axl_ring_buf_write_elem(AxlRingBuf *rb, const void *elem, uint32_t elem_size)

Write a fixed-size element (all-or-nothing).

In reject mode, fails if insufficient space. In overwrite mode, always succeeds by discarding the oldest data.

Parameters:
  • rb – ring buffer

  • elem – element to push

  • elem_size – element size in bytes

Returns:

0 on success, -1 if not enough space (reject mode only).

int axl_ring_buf_read_elem(AxlRingBuf *rb, void *elem, uint32_t elem_size)

Read a fixed-size element (all-or-nothing).

Parameters:
  • rb – ring buffer

  • elem – receives the element

  • elem_size – element size in bytes

Returns:

0 on success, -1 if not enough data.

int axl_ring_buf_get_element(AxlRingBuf *rb, uint32_t index, void *dest, uint32_t elem_size)

Read an element by index without consuming.

Index 0 is the oldest element, element_count - 1 is the newest.

Parameters:
  • rb – ring buffer

  • index – element index (0 = oldest)

  • dest – receives the element

  • elem_size – element size in bytes

Returns:

0 on success, -1 if index out of range.

int axl_ring_buf_set_element(AxlRingBuf *rb, uint32_t index, const void *src, uint32_t elem_size)

Overwrite an element by index.

Index 0 is the oldest element, element_count - 1 is the newest.

Parameters:
  • rb – ring buffer

  • index – element index (0 = oldest)

  • src – element data to write

  • elem_size – element size in bytes

Returns:

0 on success, -1 if index out of range.

uint32_t axl_ring_buf_element_count(AxlRingBuf *rb, uint32_t elem_size)

Get the number of complete elements.

Parameters:
  • rb – ring buffer

  • elem_size – element size in bytes

Returns:

readable bytes / elem_size.

int axl_ring_buf_write_msg(AxlRingBuf *rb, const void *data, uint32_t len)

Write a length-prefixed message atomically.

Stores [uint32_t len][data] in the ring buffer. The write is all-or-nothing in reject mode. In overwrite mode, the write always succeeds but may corrupt the oldest message framing.

Parameters:
  • rb – ring buffer

  • data – message payload

  • len – payload length in bytes

Returns:

0 on success, -1 if not enough space.

int axl_ring_buf_read_msg(AxlRingBuf *rb, void *dest, uint32_t max_len, uint32_t *actual_len)

Read the next length-prefixed message.

Consumes the length header and payload. If max_len is too small for the message, returns -1 without consuming.

Parameters:
  • rb – ring buffer

  • dest – destination buffer

  • max_len – destination buffer size

  • actual_len – receives actual message length (may be NULL)

Returns:

0 on success, -1 if no message or buffer too small.

uint32_t axl_ring_buf_peek_msg_size(AxlRingBuf *rb)

Peek at the size of the next message without consuming.

Parameters:
  • rb – ring buffer

Returns:

message payload size, or 0 if no complete header available.

struct AxlRingBuf
#include <axl-ring-buf.h>

Ring buffer with power-of-2 sizing and monotonic indices.

Can be heap-allocated (via axl_ring_buf_new) or embedded in another struct/stack (via axl_ring_buf_init). Fields prefixed with _ are private — use the API functions, not direct access.

Public Members

uint8_t *buf

backing buffer

uint32_t size

capacity in bytes (power of 2)

uint32_t mask

size - 1

uint32_t read_pos

monotonically increasing read index

uint32_t write_pos

monotonically increasing write index

uint32_t flags

AXL_RING_BUF_OVERWRITE etc.

void (*buf_free)(void*)

buffer deallocator, or NULL if caller-owned

struct AxlRingBufRegion
#include <axl-ring-buf.h>

Contiguous memory region for zero-copy access.

Ring buffer data may span two regions (before and after the internal wrap point). Use with peek_regions / write_regions.

Public Members

void *data

pointer into the ring buffer

uint32_t len

number of bytes in this region