Lucciefr
Lua code caving, injection and exploration framework
Functions
ringbuffer.c File Reference

Code to manage "ring" buffer logic. More...

#include "ringbuffer.h"
#include <stdlib.h>
#include <string.h>

Functions

void ringbuffer_init (ringbuffer_t *rb, size_t capacity, free_func_t free_func)
 "constructor", prepare a ringbuffer_t before usage More...
 
void ringbuffer_done (ringbuffer_t *rb)
 "destructor", free up a ringbuffer_t's resources after you're done
 
void ringbuffer_push (ringbuffer_t *rb, void *element)
 push an element pointer to the ring buffer (new "head" entry)
 
void ringbuffer_push_copy (ringbuffer_t *rb, void *buffer, size_t size)
 push a copy of a (temporary) memory buffer. More...
 
void ringbuffer_pop (ringbuffer_t *rb)
 discard the oldest entry ("tail" element) from the buffer. More...
 
void ringbuffer_clear (ringbuffer_t *rb)
 remove (pop) all entries from the buffer, until it's empty again (count == 0)
 
void ringbuffer_resize (ringbuffer_t *rb, size_t new_capacity)
 resize the ring buffer (assign a new capacity). More...
 
void * ringbuffer_element (ringbuffer_t *rb, size_t index)
 Retrieve the n-th entry (element pointer) from the ring buffer. More...
 
void * ringbuffer_tail (ringbuffer_t *rb)
 shortcut to retrieve "tail" element More...
 
void * ringbuffer_head (ringbuffer_t *rb)
 shortcut to retrieve "head" element
 

Detailed Description

Code to manage "ring" buffer logic.

A ring buffer is a 'cyclic' list of pointers that will normally be used as a "queue" / FIFO stack (first in, first out).

We're assuming that all elements in the list have been allocated in a uniform way, and that it may be necessary to call a specific "free" function before discarding them (to release any associated memory). E.g. for elements allocated via stdlib malloc or calloc, the corresponding function would of course be free.

Removing elements from the list happens on two occasions: either with a regular "pop", or in case you try to "push" a new element to a ring buffer that is currently full. (The latter will overwrite the oldest entry to make room for the new one.)

With "tail" we refer to the oldest element currently in the buffer (the one that was pushed earliest), and "head" means the most recent one (the 'top' element pushed last). The ring buffer keeps track of the number of elements and their associated pointers, as long as the element count doesn't exceed the capacity (maximum count = "size" of the buffer). As mentioned above, pushing a new element to a buffer that's full will overwrite the current "tail" (i.e. drop the oldest entry).

Function Documentation

void* ringbuffer_element ( ringbuffer_t rb,
size_t  index 
)

Retrieve the n-th entry (element pointer) from the ring buffer.

Any invalid index will result in a NULL return value. Specifically, with an empty buffer you'll always get back NULL (for any value of index).

Note
Here the index parameter is relative to the current buffer position - meaning ringbuffer_element(rb, 0) will always refer to the "tail", and ringbuffer_element(rb, count - 1) is the "head" entry.
void ringbuffer_init ( ringbuffer_t rb,
size_t  capacity,
free_func_t  free_func 
)

"constructor", prepare a ringbuffer_t before usage

Parameters
rbthe ring buffer to use
capacitymaximum number of elements (pointers) the buffer can hold
free_funcfree function to use on an element before discarding it. optional, may be NULL
void ringbuffer_pop ( ringbuffer_t rb)

discard the oldest entry ("tail" element) from the buffer.

This decrements count (i.e. frees up one 'slot'), and moves the tail pointer.

void ringbuffer_push_copy ( ringbuffer_t rb,
void *  buffer,
size_t  size 
)

push a copy of a (temporary) memory buffer.

This is a helper function that will first do a malloc(size) and then copy the buffer contents. You may use this if you wish to ringbuffer_push() some "volatile" data, where the buffer pointer gets invalidated afterwards.

void ringbuffer_resize ( ringbuffer_t rb,
size_t  new_capacity 
)

resize the ring buffer (assign a new capacity).

This is done by allocating some new "entries" memory, copying over all existing pointers using ringbuffer_element() and then replacing the old "entries" with the new pointers memory. "position" gets reset to 0. With sufficient new capacity the buffer count stays unchanged, otherwise an appropriate amount will be discarded ("pop"ping the oldest elements).

void* ringbuffer_tail ( ringbuffer_t rb)
inline

shortcut to retrieve "tail" element

Note
non-destructive, i.e. this does not pop the element!
See also
ringbuffer_pop