Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
Leonardo committed Nov 19, 2023
2 parents 394af46 + 738f0eb commit 7bc2645
Show file tree
Hide file tree
Showing 7 changed files with 138 additions and 114 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.26)
project(naughty-buffers LANGUAGES C VERSION 1.0.0)
project(naughty-buffers LANGUAGES C VERSION 1.1.0)
include(CTest)

set(CMAKE_C_STANDARD 99)
Expand Down
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,11 @@ int main(void) {
```c
#include "naughty-buffers/buffer.h"
void * my_alloc(size_t memory_size, void * context);
void my_release(void * ptr, void * context);
void * my_realloc(void * ptr, size_t memory_size, void * context);
void * my_copy(void * destination, const void * source, size_t size, void * context);
void * my_move(void * destination, const void * source, size_t size, void * context);
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;
Expand Down
15 changes: 3 additions & 12 deletions include/naughty-buffers/array-generator.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,7 @@
struct nb_buffer buffer; \
}; \
void __NB_ARRAY_TYPE__##_init(struct __NB_ARRAY_TYPE__ * array); \
void __NB_ARRAY_TYPE__##_init_advanced( \
struct __NB_ARRAY_TYPE__ * array, nb_alloc_fn alloc_fn, nb_realloc_fn realloc_fn, nb_free_fn free_fn, \
nb_copy_fn copy_fn, nb_move_fn move_fn, void * memory_context \
); \
void __NB_ARRAY_TYPE__##_init_advanced(struct __NB_ARRAY_TYPE__ * array, struct nb_buffer_memory_context * ctx); \
enum NB_PUSH_RESULT __NB_ARRAY_TYPE__##_push(struct __NB_ARRAY_TYPE__ * array, const __NB_ARRAY_BLOCK_TYPE__ item); \
enum NB_PUSH_RESULT __NB_ARRAY_TYPE__##_push_ptr( \
struct __NB_ARRAY_TYPE__ * array, const __NB_ARRAY_BLOCK_TYPE__ * item \
Expand Down Expand Up @@ -125,14 +122,8 @@
void __NB_ARRAY_TYPE__##_init(struct __NB_ARRAY_TYPE__ * array) { \
nb_init(&array->buffer, sizeof(__NB_ARRAY_BLOCK_TYPE__)); \
} \
void __NB_ARRAY_TYPE__##_init_advanced( \
struct __NB_ARRAY_TYPE__ * array, nb_alloc_fn alloc_fn, nb_realloc_fn realloc_fn, nb_free_fn free_fn, \
nb_copy_fn copy_fn, nb_move_fn move_fn, void * memory_context \
) { \
nb_init_advanced( \
&array->buffer, sizeof(__NB_ARRAY_BLOCK_TYPE__), alloc_fn, realloc_fn, free_fn, copy_fn, move_fn, \
memory_context \
); \
void __NB_ARRAY_TYPE__##_init_advanced(struct __NB_ARRAY_TYPE__ * array, struct nb_buffer_memory_context * ctx) { \
nb_init_advanced(&array->buffer, sizeof(__NB_ARRAY_BLOCK_TYPE__), ctx); \
} \
enum NB_PUSH_RESULT __NB_ARRAY_TYPE__##_push(struct __NB_ARRAY_TYPE__ * array, const __NB_ARRAY_BLOCK_TYPE__ item) { \
return nb_push(&array->buffer, (void *)&item); \
Expand Down
96 changes: 62 additions & 34 deletions include/naughty-buffers/buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,48 @@ typedef void (*nb_free_fn)(void * ptr, void * context);
*/
typedef int (*nb_compare_fn)(const void * ptr_a, const void * ptr_b);

/**
* @brief A structure containing memory-related pointers
*
* This is only useful if you have your own allocator or custom memory management.
*
* @sa nb_init_advanced
* @sa nb_alloc_fn
* @sa nb_realloc_fn
* @sa nb_free_fn
* @sa nb_copy_fn
* @sa nb_move_fn
* @ingroup buffer
*/
struct nb_buffer_memory_context {
/** A function to allocate a memory block. It needs to have the same semantics of `malloc` */
nb_alloc_fn alloc_fn;

/** A function to reallocate a memory block. It needs to have the same semantics of `realloc` */
nb_realloc_fn realloc_fn;

/**
* A function to release a memory block allocated by `alloc_fn` or `realloc_fn`. Needs to have the same
* semantics of `free`
*/
nb_free_fn free_fn;

/**
* A function to copy non-overlapping data from a block to another. It needs to have the same semantics
* of `memcpy`
*/
nb_copy_fn copy_fn;

/**
* A function to copy possibly overlapping data from a block to another. It needs to have the same
* semantics of `memmove`
*/
nb_move_fn move_fn;

/** A pointer to a user-data that will be passed in every memory-related call */
void * context;
};

/**
* @brief a structure holding the buffer data and metadata about the blocks.
*
Expand All @@ -99,12 +141,7 @@ struct nb_buffer {
size_t block_count;
size_t block_capacity;

nb_alloc_fn alloc_fn;
nb_realloc_fn realloc_fn;
nb_free_fn free_fn;
nb_copy_fn copy_fn;
nb_move_fn move_fn;
void * memory_context;
struct nb_buffer_memory_context * memory_context;

void * data;
};
Expand Down Expand Up @@ -151,44 +188,40 @@ enum NB_INSERT_RESULT { NB_INSERT_OUT_OF_MEMORY, NB_INSERT_OK };
NAUGHTY_BUFFERS_EXPORT void nb_init(struct nb_buffer * buffer, size_t block_size);

/**
* @brief Initializes a ::nb_buffer struct with custom memory functions and context.
* @brief Initializes a ::nb_buffer struct with custom memory functions and memory_context.
*
* You need to provide all custom memory functions and optionally a 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`
*
* @param buffer A pointer to a ::nb_buffer struct to be initialized
* @param block_size Size, in bytes, for each buffer block
* @param alloc_fn A function to allocate a memory block. It needs to have the same semantics of `malloc`
* @param realloc_fn A function to reallocate a memory block. It needs to have the same semantics of `realloc`
* @param free_fn A function to release a memory block allocated by `alloc_fn` or `realloc_fn`. Needs to have the same
* semantics of `free`
* @param copy_fn A function to copy non-overlapping data from a block to another. It needs to have the same semantics
* of `memcpy`
* @param move_fn A function to copy possibly overlapping data from a block to another. It needs to have the same
* semantics of `memmove`
* @param memory_context A pointer to an optional context that will be passed to each memory function.
* @param memory_context A pointer to a `struct nb_buffer_memory_context` that will be used when memory management is needed.
*
* **Example**
* @code
void * my_alloc(size_t memory_size, void * context);
void my_release(void * ptr, void * context);
void * my_realloc(void * ptr, size_t memory_size, void * context);
void * my_copy(void * destination, const void * source, size_t size, void * context);
void * my_move(void * destination, const void * source, size_t size, void * context);
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;
struct nb_buffer_memory_context ctx = {
.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;
nb_init_advanced(
&buffer,
sizeof(int),
my_alloc,
my_realloc,
my_release,
my_copy,
my_move,
memory_context
&ctx
);
nb_release(&buffer);
Expand All @@ -202,12 +235,7 @@ NAUGHTY_BUFFERS_EXPORT void nb_init(struct nb_buffer * buffer, size_t block_size
NAUGHTY_BUFFERS_EXPORT void nb_init_advanced(
struct nb_buffer * buffer,
size_t block_size,
nb_alloc_fn alloc_fn,
nb_realloc_fn realloc_fn,
nb_free_fn free_fn,
nb_copy_fn copy_fn,
nb_move_fn move_fn,
void * memory_context
struct nb_buffer_memory_context * memory_context
);

/**
Expand Down
75 changes: 42 additions & 33 deletions src/naughty-buffers/buffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,43 +2,56 @@
#include "memory.h"
#include <stdlib.h>

static size_t size_t_max(size_t a, size_t b) {
static inline void * ctx_alloc(struct nb_buffer * buffer, size_t size) {
return buffer->memory_context->alloc_fn(size, buffer->memory_context->context);
}

static inline void * ctx_realloc(struct nb_buffer * buffer, void * ptr, size_t size) {
return buffer->memory_context->realloc_fn(ptr, size, buffer->memory_context->context);
}

static inline void * ctx_copy(struct nb_buffer * buffer, void * destination, void * source, size_t size) {
return buffer->memory_context->copy_fn(destination, source, size, buffer->memory_context->context);
}

static inline void * ctx_move(struct nb_buffer * buffer, void * destination, void * source, size_t size) {
return buffer->memory_context->move_fn(destination, source, size, buffer->memory_context->context);
}

static inline void ctx_release(struct nb_buffer * buffer, void * ptr) {
buffer->memory_context->free_fn(ptr, buffer->memory_context->context);
}

struct nb_buffer_memory_context default_memory_context = {
.context = NULL,
.free_fn = nb_memory_release,
.copy_fn = nb_memory_copy,
.realloc_fn = nb_memory_realloc,
.alloc_fn = nb_memory_alloc,
.move_fn = nb_memory_move
};

static inline size_t size_t_max(size_t a, size_t b) {
if (a > b) return a;
else return b;
}

void nb_init(struct nb_buffer * buffer, size_t block_size) {
nb_init_advanced(
buffer, block_size, nb_memory_alloc, nb_memory_realloc, nb_memory_release, nb_memory_copy, nb_memory_move, NULL
);
}

void nb_init_advanced(
struct nb_buffer * buffer,
size_t block_size,
nb_alloc_fn alloc_fn,
nb_realloc_fn realloc_fn,
nb_free_fn free_fn,
nb_copy_fn copy_fn,
nb_move_fn move_fn,
void * memory_context
) {
nb_init_advanced(buffer, block_size, &default_memory_context);
}

void nb_init_advanced(struct nb_buffer * buffer, size_t block_size, struct nb_buffer_memory_context * memory_context) {
buffer->block_size = block_size;
buffer->block_capacity = 2;
buffer->block_count = 0;
buffer->alloc_fn = alloc_fn;
buffer->realloc_fn = realloc_fn;
buffer->free_fn = free_fn;
buffer->copy_fn = copy_fn;
buffer->move_fn = move_fn;
buffer->memory_context = memory_context;
buffer->data = buffer->alloc_fn(buffer->block_size * 2, buffer->memory_context);
buffer->data = ctx_alloc(buffer, buffer->block_size * 2);
}

uint8_t nb_grow(struct nb_buffer * buffer, size_t desired_capacity) {
size_t new_block_capacity = buffer->block_capacity * 2;
while (new_block_capacity <= desired_capacity) new_block_capacity *= 2;
void * new_data = buffer->realloc_fn(buffer->data, buffer->block_size * new_block_capacity, buffer->memory_context);
void * new_data = ctx_realloc(buffer, buffer->data, buffer->block_size * new_block_capacity);
if (!new_data) return 0;
buffer->data = new_data;
buffer->block_capacity = new_block_capacity;
Expand All @@ -53,7 +66,7 @@ enum NB_PUSH_RESULT nb_push(struct nb_buffer * buffer, void * data) {

uint8_t * buffer_data = buffer->data;
void * block_data = buffer_data + (buffer->block_count * buffer->block_size);
buffer->copy_fn(block_data, data, buffer->block_size, buffer->memory_context);
ctx_copy(buffer, block_data, data, buffer->block_size);
buffer->block_count += 1;
return NB_PUSH_OK;
}
Expand All @@ -72,15 +85,11 @@ void * nb_front(struct nb_buffer * buffer) { return nb_at(buffer, 0); }
void * nb_back(struct nb_buffer * buffer) { return nb_at(buffer, buffer->block_count - 1); }

void nb_release(struct nb_buffer * buffer) {
buffer->free_fn(buffer->data, buffer->memory_context);
ctx_release(buffer, buffer->data);

buffer->block_size = 0;
buffer->block_capacity = 0;
buffer->block_count = 0;
buffer->alloc_fn = NULL;
buffer->realloc_fn = NULL;
buffer->free_fn = NULL;
buffer->copy_fn = NULL;
buffer->memory_context = NULL;
buffer->data = NULL;
}
Expand All @@ -92,7 +101,7 @@ enum NB_ASSIGN_RESULT nb_assign(struct nb_buffer * buffer, size_t index, void *
}
uint8_t * buffer_data = buffer->data;
void * block_data = buffer_data + (index * buffer->block_size);
buffer->copy_fn(block_data, data, buffer->block_size, buffer->memory_context);
ctx_copy(buffer, block_data, data, buffer->block_size);
if (index >= buffer->block_count) buffer->block_count = index + 1;
return NB_ASSIGN_OK;
}
Expand All @@ -109,9 +118,9 @@ enum NB_INSERT_RESULT nb_insert(struct nb_buffer * buffer, size_t index, void *
uint8_t * dest = buffer_data + ((index + 1) * buffer->block_size);
uint8_t * src = block_data;
size_t move_size = (buffer->block_count - index) * buffer->block_size;
buffer->move_fn(dest, src, move_size, buffer->memory_context);
ctx_move(buffer, dest, src, move_size);
}
buffer->copy_fn(block_data, data, buffer->block_size, buffer->memory_context);
ctx_copy(buffer, block_data, data, buffer->block_size);
if (index >= buffer->block_count) buffer->block_count = index + 1;
else buffer->block_count += 1;
return NB_INSERT_OK;
Expand All @@ -133,7 +142,7 @@ void nb_remove_at(struct nb_buffer * buffer, size_t index) {
uint8_t * src = buffer_data + ((index + 1) * buffer->block_size);
size_t move_count = buffer->block_count - index - 1;
size_t move_size = move_count * buffer->block_size;
buffer->move_fn(dest, src, move_size, buffer->memory_context);
ctx_move(buffer, dest, src, move_size);
buffer->block_count--;
}

Expand Down
20 changes: 11 additions & 9 deletions src/tests/array-generator.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,14 @@ void * nb_test_move(void * destination, const void * source, size_t size, void *
return memmove(destination, source, size);
}

struct nb_buffer_memory_context ctx = {
.move_fn = nb_test_move,
.alloc_fn = nb_test_alloc,
.realloc_fn = nb_test_realloc,
.copy_fn = nb_test_copy,
.free_fn = nb_test_release
};

void array_generator_init_works() {
struct test_array test_array;
test_array_init(&test_array);
Expand All @@ -56,15 +64,9 @@ void array_generator_init_works() {

void array_generator_init_advanced_works() {
struct test_array test_array;
test_array_init_advanced(
&test_array, nb_test_alloc, nb_test_realloc, nb_test_release, nb_test_copy, nb_test_move, &test_array
);

assert(test_array.buffer.alloc_fn == nb_test_alloc);
assert(test_array.buffer.realloc_fn == nb_test_realloc);
assert(test_array.buffer.free_fn == nb_test_release);
assert(test_array.buffer.copy_fn == nb_test_copy);
assert(test_array.buffer.memory_context == &test_array);
test_array_init_advanced(&test_array, &ctx);

assert(test_array.buffer.memory_context == &ctx);

assert(test_array.buffer.block_size == sizeof(struct nb_test));

Expand Down
Loading

0 comments on commit 7bc2645

Please sign in to comment.