#ifndef BDL_DARRAY_H #define BDL_DARRAY_H #include typedef struct ArrayHeader { size_t size; size_t cap; } ArrayHeader; // Header/Size/capacity accessors. #define array_head(ARR) ((ArrayHeader *)((char *)(ARR) - sizeof(ArrayHeader))) #define array_size(ARR) ((ARR) ? array_head(ARR)->size : 0) #define array_cap(ARR) ((ARR) ? array_head(ARR)->cap : 0) // Initialize a dynamic array ARR with N elements. The initialization doesn't // zero out the data, so thread carefully.. #define array_init(ARR,N) ((ARR) = _array_reserve(N, sizeof(*(ARR)))) // Push a given element T to the dynamic array ARR. #define array_push(ARR, T) \ ((ARR) = _array_maybe_grow(ARR, sizeof(T)), \ (ARR)[array_head(ARR)->size++] = (T)) // Return the last element of the array. Can be used to build stacks. #define array_pop(ARR) (ARR)[--array_head(ARR)->size] // Return the value stored at the OFFSET position from the tail of the array. #define array_peek(ARR, OFFSET) (ARR)[array_head(ARR)->size - 1 - (OFFSET)] // Insert N bytes from the SRC array into the ARR dynamic array. #define array_insert(ARR, SRC, N) \ ((ARR) = _array_insert(ARR, SRC, N, sizeof(*(ARR)))) // Free the memory from the original allocated position. #define array_free(ARR) ((ARR) ? free(array_head(ARR)), (ARR) = NULL : 0) static inline void * _array_reserve(size_t num_elem, size_t type_size) { char *p = malloc(num_elem * type_size + sizeof(ArrayHeader)); p += sizeof(ArrayHeader); array_head(p)->size = 0; array_head(p)->cap = num_elem; return p; } static inline void * _array_maybe_grow(void *arr, size_t type_size) { ArrayHeader *head = array_head(arr); if (head->cap == head->size) { if (head->cap == 0) { head->cap++; } else { head->cap *= 2; } head = realloc(head, head->cap * type_size + sizeof(ArrayHeader)); } arr = (char *)head + sizeof(ArrayHeader); return arr; } static inline char * _array_insert(char *arr, const char *src, size_t n_bytes, size_t type_size) { ArrayHeader *head = array_head(arr); size_t new_size = n_bytes + head->size; if (new_size > head->cap * type_size) { if (head->cap == 0) { head->cap = 1; } while (new_size >= head->cap * type_size) { head->cap *= 2; } head = realloc(head, head->cap * type_size + sizeof(ArrayHeader)); } arr = (char *)head + sizeof(ArrayHeader); memcpy((arr + head->size), src, n_bytes); head->size = new_size; return arr; } #endif // BDL_DARRAY_H