[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/felipeek/rawhttps/master/include/light_array.h [Back]  [Original]

#ifndef H_LIGHT_ARRAY
#define H_LIGHT_ARRAY

/*
    Author: Pedro Sassen Veiga
    The MIT License

    This library is C89 compatible

    ----------------------------------------------------------------------------------

    define LIGHT_ARRAY_NO_CRT if you don't want the c runtime library included
    if that is defined, you must provide implementations for the following functions:

    void* calloc(size_t num, size_t size)
    void* realloc(void* ptr, size_t new_size)
    void  free(void* block)
    void* memmove(void* dest, void* src, size_t count)

    ----------------------------------------------------------------------------------

    Usage:
    An example usage of creating, pushing, popping, removing and freeing an array:

    #include "light_array.h"

    int main(int argc, char** argv)
    {
        int* buffer = array_new(int);

        array_push(buffer, 1);
        array_push(buffer, 2);
        array_push(buffer, 3);
        array_push(buffer, 4);
        array_push(buffer, 5);
        
        int five = array_pop(buffer);

        array_remove(buffer, 1);
        array_free(buffer);

        return 0;
    }

    array_remove is an unordered remove, if you want an ordered version, which is more expensive
    use array_remove_ordered instead

    To get the length of an array just use array_length, this will work as an lvalue, meaning you
    can do as follows:

    array_length(buffer)++;
    array_length(buffer) = 0;

    And it should work as expected, incrementing the array length artificially or setting it to
    zero, which is also the behaviour of array_clear

*/

#if !defined(LIGHT_ARRAY_NO_CRT)
#include 
#include 
#include 
#endif

typedef struct {
    size_t capacity;
    size_t length;
} Dynamic_ArrayBase;

#define LIGHT_ARRAY_MIN(x, y) (y ^ ((x ^ y) & -(x < y)))
#define LIGHT_ARRAY_MAX(x, y) (x ^ ((x ^ y) & -(x < y)))
#if defined(__GNUC__)
#define LIGHT_ARRAY_API __attribute__((unused))
#else
#define LIGHT_ARRAY_API
#endif

/* gets the base of the array where the capacity and length info are, not recommended to use (internal of the library). */
#define array_base(A) ((Dynamic_ArrayBase*)(((char*)(A)) - sizeof(Dynamic_ArrayBase)))
/* gets the length of the array. */
#define array_length(A) array_base(A)->length
/* gets the capacity currently allocated of the array, that is, the array won't grow while the capacity isn't reached. */
#define array_capacity(A) array_base(A)->capacity

#if defined(__cplusplus)
/* creates a new array of type T */
#define array_new(T) (T*)((char*)&(((Dynamic_ArrayBase*)calloc(1, sizeof(Dynamic_ArrayBase) + sizeof(T)))->capacity = 1) + sizeof(Dynamic_ArrayBase))
#else
static LIGHT_ARRAY_API void* array_dyn_allocate(size_t size) {
    void* res = calloc(1, size);
    ((Dynamic_ArrayBase*)res)->capacity = 1;
    return (void*)((char*)res + sizeof(Dynamic_ArrayBase));
}
static LIGHT_ARRAY_API void* array_dyn_allocate_capacity(size_t size_element, size_t capacity) {
    void* res = calloc(1, size_element * capacity + sizeof(Dynamic_ArrayBase));
    ((Dynamic_ArrayBase*)res)->capacity = capacity;
    return (void*)((char*)res + sizeof(Dynamic_ArrayBase));
}
#define array_new(T) array_dyn_allocate(sizeof(T) + sizeof(Dynamic_ArrayBase))
/* creates a new array of type T with starting capacity L */
#define array_new_len(T, L) array_dyn_allocate_capacity(sizeof(T), L)
#endif

/* given an array created by array_new and a value (rvalue) of the base type of the array, puts that value in the last
   position of the current array, it allocates memory automatically when the capacity is reached. The policy to allocate
   is exponential (doubles every allocation). */
#define array_push(A, V) ((array_length(A) == array_capacity(A)) \
    ? *((void**)&(A)) = (void*)((Dynamic_ArrayBase*)realloc((Dynamic_ArrayBase*)(A) - 1, sizeof(Dynamic_ArrayBase) + sizeof(*(A)) * array_capacity(A) * 2) + 1), \
    array_capacity(A) = array_capacity(A) * 2 : 0, \
    (A)[array_length(A)++] = (V))

/* given an array created by array_new and an integer value V. Allocates on top of the existing memory V additional
   bytes of memory, changing the array capacity but not its length.
 */
#define array_allocate(A, V) ((array_length(A) + (V) >= array_capacity(A)) \
    ? *((void**)&(A)) = (void*)((Dynamic_ArrayBase*)realloc((Dynamic_ArrayBase*)(A) - 1, sizeof(Dynamic_ArrayBase) + sizeof(*(A)) * (array_length(A) + (V))) + 1), \
    array_capacity(A) = (array_length(A) + (V)) : 0)

/* inserts into a given array A the value V (rvalue of type of the array) in the index I and pushes every value after
   the index forward in the array. */
#define array_insert(A, V, I) array_push(A, V), memmove((A) + (I) + 1, (A) + (I), sizeof(*A) * (array_length(A) - (I) - 1)), (A)[I] = (V)

/* returns and removes the last value in the array. */
#define array_pop(A) (array_length(A) > 0) ? (A)[--array_length(A)] : 0

/* frees the memory of the array, the array pointer becomes invalid. */
#define array_free(A) free(array_base(A))

/* clears the array but keeps the current capacity, that is, keeps the memory allocated. */
#define array_clear(A) array_length(A) = 0

/* removes the value in a given Index from the array moving every value after it back. */
#define array_remove_ordered(A, Index) ((Index) < (array_length(A) - 1) && array_length(A) > 0) ? \
    memmove((A) + Index, (A) + Index + 1, (array_length(A) - 1 - Index) * sizeof(*A)) : 0, array_length(A)--

/* removes the last value of the array in an unordered way, putting the last element in its place. */
#define array_remove(A, Index) (array_length(A)--, (A)[Index] = (A)[array_length(A)])

/* copies an array to a new one, its capacity and length are also preserved */
#define array_copy(A) ((void*)((Dynamic_ArrayBase*) \
    memmove((Dynamic_ArrayBase*)array_dyn_allocate_capacity(sizeof(*A), array_capacity(A)) - 1, \
    array_base(A), sizeof(Dynamic_ArrayBase) + array_length(A) * sizeof(*A)) + 1))

#endif /* H_LIGHT_ARRAY */

Web Proxy Viewer  |  New URL  |  Original Page