1.2.1
Classes | Typedefs | Enumerations | Functions
Buffer

Classes

struct  nb_buffer_memory_context
 A structure containing memory-related pointers. More...
 
struct  nb_buffer_iterator
 Structure returned by nb_iterator containing enough information to control a for-loop. More...
 
struct  nb_buffer
 a structure holding the buffer data and metadata about the blocks. More...
 

Typedefs

typedef void *(* nb_alloc_fn) (size_t size, void *context)
 Type of a function able to allocate a block of memory that will be called when the buffer gets initialized. It should function as malloc.
 
typedef void *(* nb_realloc_fn) (void *ptr, size_t new_size, void *context)
 Type of a function able to realloc a memory block, to be called when a buffer needs to enlarge its internal memory it will call this function. It should function as realloc.
 
typedef void *(* nb_copy_fn) (void *destination, const void *source, size_t size, void *context)
 Type of a function able to copy a chunk of memory from source to destination, to be called when inserting, assigning or pushing data. It will never be called with overlapping memory. It should function as memcpy.
 
typedef void *(* nb_move_fn) (void *destination, const void *source, size_t size, void *context)
 Type of a function able to move a chunk of memory from source to destination, to be called when inserting or removing data from the buffer. It needs to handle overlapping memory and should function like memmove.
 
typedef void(* nb_free_fn) (void *ptr, void *context)
 Type of a function able to release memory pointed by ptr, to be called when the buffer gets released. It should function like free.
 
typedef int(* nb_compare_fn) (const void *ptr_a, const void *ptr_b)
 Type of a function that can compare two blocks, returning < 0 if *ptr_a < *ptr_b, 0 if *ptr_a == *ptr_b or > 0 if *ptr_a > *ptr_b.
 

Enumerations

enum  NB_PUSH_RESULT { NB_PUSH_OUT_OF_MEMORY , NB_PUSH_OK }
 Result of calling nb_push.
 
enum  NB_ASSIGN_RESULT { NB_ASSIGN_OUT_OF_MEMORY , NB_ASSIGN_OK }
 Result of calling nb_assign.
 
enum  NB_INSERT_RESULT { NB_INSERT_OUT_OF_MEMORY , NB_INSERT_OK }
 Result of calling nb_insert.
 

Functions

void nb_init (struct nb_buffer *buffer, size_t block_size)
 Initializes a nb_buffer struct with default values and pointers. More...
 
void nb_init_advanced (struct nb_buffer *buffer, size_t block_size, struct nb_buffer_memory_context *memory_context)
 Initializes a nb_buffer struct with custom memory functions and memory_context. More...
 
enum NB_PUSH_RESULT nb_push (struct nb_buffer *buffer, void *data)
 Copies data to the end of the buffer, possibly reallocating it if more space needed. More...
 
size_t nb_block_count (const struct nb_buffer *buffer)
 Returns the block count of the buffer. More...
 
void * nb_at (const struct nb_buffer *buffer, size_t index)
 Returns a pointer to the block at position index or NULL if the index is out of bounds. More...
 
void * nb_front (const struct nb_buffer *buffer)
 Returns a pointer to the first block or NULL if the buffer is empty. This is equivalent to calling nb_at with index 0. More...
 
void * nb_back (const struct nb_buffer *buffer)
 Returns a pointer to the last block or NULL if the buffer is empty This is equivalent to calling nb_at with index nb_block_count(&buffer) -1 More...
 
enum NB_ASSIGN_RESULT nb_assign (struct nb_buffer *buffer, size_t index, void *data)
 Copies data to the block at index index. More...
 
enum NB_ASSIGN_RESULT nb_assign_many (struct nb_buffer *buffer, size_t index, void *data, size_t block_count)
 Copies block_count blocks from data to the buffer starting at index. More...
 
enum NB_INSERT_RESULT nb_insert (struct nb_buffer *buffer, size_t index, void *data)
 Inserts data to the block at index index moving all blocks past the index forward one position. More...
 
void nb_remove_front (struct nb_buffer *buffer)
 Removes the block at index 0 from the array moving all other blocks to the beginning. More...
 
void nb_remove_back (struct nb_buffer *buffer)
 Removes the block at the last index from the array. More...
 
void nb_remove_at (struct nb_buffer *buffer, size_t index)
 Removes the block at the specified index. More...
 
void nb_sort (struct nb_buffer *buffer, nb_compare_fn compare_fn)
 Sorts the buffer using stdlib's qsort function. More...
 
void nb_release (struct nb_buffer *buffer)
 Releases all allocated memory by the buffer and resets all internal metadata effectively making it an uninitialized buffer. More...
 
struct nb_buffer_iterator nb_iterator (const struct nb_buffer *buffer)
 Creates and returns an iterator that allows for performance-friendly traversal. More...
 

Detailed Description

All the functions and types to manage a buffer are here. Buffers can automatically grow to handle pushes and insertions. They start with enough space for 2 blocks and grow by powers of 2 (4, 8, 16, 32, etc)

Function Documentation

◆ nb_init()

void nb_init ( struct nb_buffer buffer,
size_t  block_size 
)

Initializes a nb_buffer struct with default values and pointers.

It will allocate enough memory to contain two blocks. All memory functions will be set to end up calling the default ones (malloc/realloc/etc).

Parameters
bufferA pointer to a nb_buffer struct to be initialized
block_sizeThe size, in bytes, for each buffer block

Example

// initializes and releases a buffer to hold int-sized blocks
void main() {
struct nb_buffer buffer;
nb_init(&buffer, sizeof(int));
nb_release(&buffer);
}
void nb_release(struct nb_buffer *buffer)
Releases all allocated memory by the buffer and resets all internal metadata effectively making it an...
void nb_init(struct nb_buffer *buffer, size_t block_size)
Initializes a nb_buffer struct with default values and pointers.
a structure holding the buffer data and metadata about the blocks.
Definition: buffer.h:156

◆ nb_init_advanced()

void nb_init_advanced ( struct nb_buffer buffer,
size_t  block_size,
struct nb_buffer_memory_context memory_context 
)

Initializes a nb_buffer struct with custom memory functions and memory_context.

You need to provide all custom memory functions and optionally a memory memory_context.

It will allocate enough memory to contain two blocks with alloc_fn

Parameters
bufferA pointer to a nb_buffer struct to be initialized
block_sizeSize, in bytes, for each buffer block
memory_contextA pointer to a struct nb_buffer_memory_context that will be used when memory management is needed.

Example

void * my_alloc(size_t memory_size, void * memory_context);
void my_release(void * ptr, void * memory_context);
void * my_realloc(void * ptr, size_t memory_size, void * memory_context);
void * my_copy(void * destination, const void * source, size_t size, void * memory_context);
void * my_move(void * destination, const void * source, size_t size, void * memory_context);
void * memory_context;
.alloc = my_alloc,
.free = my_release,
.realloc = my_realloc,
.copy = my_copy,
.move = my_move,
.context = memory_context
};
int main(void) {
struct nb_buffer buffer;
&buffer,
sizeof(int),
&ctx
);
nb_release(&buffer);
return 0;
}
void nb_init_advanced(struct nb_buffer *buffer, size_t block_size, struct nb_buffer_memory_context *memory_context)
Initializes a nb_buffer struct with custom memory functions and memory_context.
A structure containing memory-related pointers.
Definition: buffer.h:98
void * context
Definition: buffer.h:124

◆ nb_push()

enum NB_PUSH_RESULT nb_push ( struct nb_buffer buffer,
void *  data 
)

Copies data to the end of the buffer, possibly reallocating it if more space needed.

Parameters
bufferA pointer to a nb_buffer struct
dataThe data to copy.
Returns
NB_PUSH_OK if successful, NB_PUSH_OUT_OF_MEMORY if no more memory could be allocated.
Warning
Because the buffer when reallocated can change places, all previous pointers returned by nb_at may be invalid after calling this function.

Example

int main(void) {
struct nb_buffer buffer;
nb_init(&buffer, sizeof(int));
int value = 0;
nb_push(&buffer, &value);
assert(nb_block_count(&buffer) == 1);
nb_release(&buffer);
return 0;
}
size_t nb_block_count(const struct nb_buffer *buffer)
Returns the block count of the buffer.
enum NB_PUSH_RESULT nb_push(struct nb_buffer *buffer, void *data)
Copies data to the end of the buffer, possibly reallocating it if more space needed.

◆ nb_block_count()

size_t nb_block_count ( const struct nb_buffer buffer)

Returns the block count of the buffer.

Parameters
bufferA pointer to a nb_buffer struct
Returns
The block count of the buffer

Example

See nb_push example

◆ nb_at()

void * nb_at ( const struct nb_buffer buffer,
size_t  index 
)

Returns a pointer to the block at position index or NULL if the index is out of bounds.

Parameters
bufferA pointer to a nb_buffer struct
indexThe index to read
Returns
A pointer to the block data or NULL if the index is out of bounds
Warning
Using nb_push, nb_insert or nb_assign might invalidate previous pointers returned by this function

Example

int main(void) {
struct nb_buffer buffer;
nb_init(&buffer, sizeof(int));
int value = 10;
int * read_value;
nb_push(&buffer, &value);
read_value = (int*) nb_at(&buffer, 0);
assert(*read_value = 10);
nb_release(&buffer);
return 0;
}
void * nb_at(const struct nb_buffer *buffer, size_t index)
Returns a pointer to the block at position index or NULL if the index is out of bounds.

◆ nb_front()

void * nb_front ( const struct nb_buffer buffer)

Returns a pointer to the first block or NULL if the buffer is empty. This is equivalent to calling nb_at with index 0.

Parameters
bufferA pointer to a nb_buffer struct
Returns
A pointer to the block data or NULL if the buffer is empty
Warning
Using nb_push, nb_insert or nb_assign might invalidate previous pointers returned by this function

◆ nb_back()

void * nb_back ( const struct nb_buffer buffer)

Returns a pointer to the last block or NULL if the buffer is empty This is equivalent to calling nb_at with index nb_block_count(&buffer) -1

Parameters
bufferA pointer to a nb_buffer struct
Returns
A pointer to the block data or NULL if the buffer is empty
Warning
Using nb_push, nb_insert or nb_assign might invalidate previous pointers returned by this function

◆ nb_assign()

enum NB_ASSIGN_RESULT nb_assign ( struct nb_buffer buffer,
size_t  index,
void *  data 
)

Copies data to the block at index index.

If index is larger than the buffer capacity the buffer data will be reallocated to accommodate the new data. Uninitialized data will be present in the blocks preceding the new data if they were not present before.

Parameters
bufferA pointer to a nb_buffer struct
indexThe block index to assign the data to
dataA pointer to the data to be copied in the buffer at the specified index.
Returns
NB_ASSIGN_OK if assignment was successful or NB_ASSIGN_OUT_OF_MEMORY if out of memory

Example

int main(void) {
struct nb_buffer buffer;
nb_init(&buffer, sizeof(int));
int value = 10;
int * read_value;
nb_assign(&buffer, 20, &value);
read_value = (int*) nb_at(&buffer, 20);
assert(*read_value = 10);
nb_release(&buffer);
return 0;
}
enum NB_ASSIGN_RESULT nb_assign(struct nb_buffer *buffer, size_t index, void *data)
Copies data to the block at index index.

◆ nb_assign_many()

enum NB_ASSIGN_RESULT nb_assign_many ( struct nb_buffer buffer,
size_t  index,
void *  data,
size_t  block_count 
)

Copies block_count blocks from data to the buffer starting at index.

If index or index + block_count is larger than the buffer capacity the buffer data will be reallocated to accommodate the new data. Uninitialized data will be present in the blocks preceding the new data if they were not present before.

Caller is expected to ensure that data points at the first block to be copied from and that it has at least block_count * block_size bytes.

Parameters
bufferA pointer to a nb_buffer struct
indexThe block index to assign the data to
dataA pointer to the data to be copied in the buffer at the specified index.
block_countAmount of blocks to copy from data into the buffer
Returns
NB_ASSIGN_OK if assignment was successful or NB_ASSIGN_OUT_OF_MEMORY if out of memory

Example

int main(void) {
struct nb_buffer buffer;
nb_init(&buffer, sizeof(int));
int value[3] = { 20, 21, 22 };
int * read_value;
nb_assign_many(&buffer, 20, value, 3);
read_value = (int*) nb_at(&buffer, 20);
assert(*read_value = 20);
read_value = (int*) nb_at(&buffer, 21);
assert(*read_value = 21);
read_value = (int*) nb_at(&buffer, 22);
assert(*read_value = 22);
nb_release(&buffer);
return 0;
}
enum NB_ASSIGN_RESULT nb_assign_many(struct nb_buffer *buffer, size_t index, void *data, size_t block_count)
Copies block_count blocks from data to the buffer starting at index.

◆ nb_insert()

enum NB_INSERT_RESULT nb_insert ( struct nb_buffer buffer,
size_t  index,
void *  data 
)

Inserts data to the block at index index moving all blocks past the index forward one position.

If index is larger than the buffer capacity the buffer data will be reallocated to accommodate the new data. Uninitialized data will be present in the blocks preceding the new data if they were not present before.

All blocks in positions greater or equal than the one specified with index will be moved forward by 1 position.

Parameters
bufferA pointer to a nb_buffer struct
indexThe block index to assign the data to
dataA pointer to the data to be copied in the buffer at the specified index.
Returns
NB_INSERT_OK if assignment was successful or NB_INSERT_OUT_OF_MEMORY if out of memory

Example

int main(void) {
struct nb_buffer buffer;
nb_init(&buffer, sizeof(int));
int value = 0;
nb_push(&buffer, &value);
value = 10;
nb_insert(&buffer, 0, &value);
assert(nb_block_count(&buffer) == 2);
nb_release(&buffer);
return 0;
}
enum NB_INSERT_RESULT nb_insert(struct nb_buffer *buffer, size_t index, void *data)
Inserts data to the block at index index moving all blocks past the index forward one position.

◆ nb_remove_front()

void nb_remove_front ( struct nb_buffer buffer)

Removes the block at index 0 from the array moving all other blocks to the beginning.

This is equivalent of calling nb_remove_at with index nb_block_count(&buffer) -1.

Warning
This function will invalidate all previously returned pointers with nb_at
Parameters
bufferA pointer to a nb_buffer struct
See also
nb_remove_at
nb_remove_back

◆ nb_remove_back()

void nb_remove_back ( struct nb_buffer buffer)

Removes the block at the last index from the array.

This is equivalent of calling nb_remove_at with index nb_block_count(&buffer) -1.

Warning
This function will invalidate pointers to the last block of the buffer previously returned by nb_at
Parameters
bufferA pointer to a nb_buffer struct
See also
nb_remove_at
nb_remove_front

◆ nb_remove_at()

void nb_remove_at ( struct nb_buffer buffer,
size_t  index 
)

Removes the block at the specified index.

Warning
This function will invalidate pointers previously returned by nb_at for blocks at the index and past it
Parameters
bufferA pointer to a nb_buffer struct
indexThe block index to remove
See also
nb_remove_front
nb_remove_back

Example

int main(void) {
struct nb_buffer buffer;
nb_init(&buffer, sizeof(int));
int value = 0;
nb_push(&buffer, &value);
value = 10;
nb_push(&buffer, &value);
assert(nb_block_count(&buffer) == 2);
nb_remove_at(&buffer, 0);
assert(nb_block_count(&buffer) == 1);
nb_release(&buffer);
return 0;
}
void nb_remove_at(struct nb_buffer *buffer, size_t index)
Removes the block at the specified index.

◆ nb_sort()

void nb_sort ( struct nb_buffer buffer,
nb_compare_fn  compare_fn 
)

Sorts the buffer using stdlib's qsort function.

Parameters
bufferA pointer to a nb_buffer struct
compare_fnA comparison fuction returnin < 0 if the first element should come before the second, 0 if they're equal and > 0 if the first element should come after the second

◆ nb_release()

void nb_release ( struct nb_buffer buffer)

Releases all allocated memory by the buffer and resets all internal metadata effectively making it an uninitialized buffer.

You can reuse the same buffer after another call to nb_init or nb_init_advanced.

Parameters
bufferA pointer to a nb_buffer struct

◆ nb_iterator()

struct nb_buffer_iterator nb_iterator ( const struct nb_buffer buffer)

Creates and returns an iterator that allows for performance-friendly traversal.

If you intend to access a lot of elements in sequence, this is the preferred method to do so as it offers better performance in comparison to nb_at

Parameters
bufferA pointer to a nb_buffer struct
Returns
A nb_buffer_iterator struct with values that can be used to control a for-loop.

Example

int main(void) {
struct nb_buffer buffer;
nb_init(&buffer, sizeof(int));
int value;
value = 0; nb_push(&buffer, &value);
value = 10; nb_push(&buffer, &value);
value = 20; nb_push(&buffer, &value);
struct nb_buffer_iterator itr = nb_iterator(&buffer);
for (uint8_t * block = itr.begin; block != itr.end; block += itr.increment) {
int * data = (int *) block;
printf("data: %d\n", *data);
}
nb_release(&buffer);
return 0;
}
struct nb_buffer_iterator nb_iterator(const struct nb_buffer *buffer)
Creates and returns an iterator that allows for performance-friendly traversal.
Structure returned by nb_iterator containing enough information to control a for-loop.
Definition: buffer.h:133
void * begin
Definition: buffer.h:135
size_t increment
Definition: buffer.h:141
void * end
Definition: buffer.h:138