Skip to content

Extremely simple and rudimental implementation of a dynamic-size array in C.

License

Notifications You must be signed in to change notification settings

GlitchedPolygons/chillbuff

Repository files navigation

Codacy Badge Build status API Docs License Shield

ChillBuff

A super simple, header-only and Apache-2.0 licensed dynamic-size array

ᐳᐳ Check out the API docs here on github.io

How to build

Just add the include/chillbuff.h header file to your project and you're good to go!

If you want to provide some custom implementation of malloc, calloc or realloc, please define the below pre-processor definitions and set their corresponding value to 1. Additionally, you would also need to provide the alternate implementation for the API via function pointer defined at the top of the chillbuff header file.

Method Pre-processor Function pointer
malloc CHILLBUFF_PLATFORM_MALLOC_ALT chillbuff_malloc
calloc CHILLBUFF_PLATFORM_CALLOC_ALT chillbuff_calloc
realloc CHILLBUFF_PLATFORM_REALLOC_ALT chillbuff_realloc

What is this?

An array that resizes itself when its maximum capacity is reached. Nothing super fancy either: you can only add and not remove.

Mostly useful as a string builder of some sort, but you can obviously also use it for ints, structs, etc...

How to use

Let's say you want to build an array of integers, characters or whatever, whose total element count you don't know yet.

Without needing to manually check the available slots, keep track/decrease/increase some values, etc... you can just init a chillbuff instance (try to give a rough guess when it comes to initial capacity, growth method, etc...) and then push_back and chill! No need to worry about resizing or any of that stuff. It's all taken care of for you in the background. How comfortable!

When you're done adding to the buffer, you can access its underlying array using the chillbuff.array and chillbuff.length fields.

You can also clear the buffer: this will reset its length to 0 and delete all of its content (the capacity remains untouched though: the underlying array won't be shrinked!).

If you want you can set up an error message callback using the set_error_callback function: pass in a void function pointer that takes 1 const char* parameter. If a chillbuff error occurs, its human-readable error message will be passed as a string into the provided callback function. Could be some sort of printf, or one of your own error log file writer functions.

To remove the callback (stop calling the callback and passing error messages into it), just call unset_error_callback.

Strings

    #include <chillbuff.h>

    chillbuff stringbuilder;
    
    /* 
     * Initialize a chillbuff that stores a C-style string. 
     * You can append one character or entire strings to it using the push_back function!
     */
    chillbuff_init(&stringbuilder, 1024, sizeof(char), CHILLBUFF_GROW_DUPLICATIVE);

    const char* add1 = "Hello ";
    const char* add2 = "World!";

    /* Add some strings to the buffer. NUL-terminator is appended automatically. */
    chillbuff_push_back(&stringbuilder, add1, strlen(add1));
    chillbuff_push_back(&stringbuilder, add2, strlen(add1));

    /* Do something with the constructed string. */
    printf("%s \n", stringbuilder.array);
    printf("String length: %d \n", (int)stringbuilder.length);

    /* Never forget to free the buffer once you're done using it! */
    chillbuff_free(&stringbuilder);

Other types

    #include <chillbuff.h>
    
    chillbuff buffer;
    
    /* 
     * Initialize a chillbuff that stores elements of type `uint16_t` 
     * and duplicates its capacity once it's full. Give it an initial 
     * capacity of 2, just to demonstrate that it resizes correctly.
     */
    chillbuff_init(&buffer, 2, sizeof(uint16_t), CHILLBUFF_GROW_DUPLICATIVE);

    uint16_t add1[] = { 1, 2, 3 };
    uint16_t add2[] = { 4, 5, 6, 7, 8, 9, 100, 200, 300 };

    /* r1 and r2 will contain the returned exit code. If something fails, that is >0 */
    int r1 = chillbuff_push_back(&buffer, add1, sizeof(add1) / sizeof(uint16_t));
    int r2 = chillbuff_push_back(&buffer, add2, sizeof(add2) / sizeof(uint16_t));

    /* 
     * Check out the numbers in the buffer: they match the added ones! 
     * Now you can do something with this array 
     */
    uint16_t n0 = ((uint16_t*)buffer.array)[0];
    uint16_t n1 = ((uint16_t*)buffer.array)[1]; /* This syntax is how you need to dereference/access the array. */
    uint16_t n2 = ((uint16_t*)buffer.array)[2];
    uint16_t n3 = ((uint16_t*)buffer.array)[3];
    uint16_t n4 = ((uint16_t*)buffer.array)[4];
    uint16_t n5 = ((uint16_t*)buffer.array)[5];
    /* (etc...) */
    
    /* Never forget to free the buffer once you're done using it! */
    chillbuff_free(&buffer);