# carray.inl ## Overview
This file implements a growing array in C. It's based on Sean Barrett's [stretchy buffer](https://github.com/nothings/stb/blob/master/stretchy_buffer.h) implementation. An array is represented just by a regular pointer to the array object type: ~~~c uint32_t *a = 0; ~~~ Size and capacity of the array are stored in a header before the array pointer itself. The case where the array is `NULL` is handled correctly. Note that the functions here will modify the array pointer itself, so if you pass the carray to a function for modification, you must pass a pointer to it. You can also use static memory for the initial setup of an array, as long as you set the capacity to zero. This signals that the memory is statically allocated and should not be freed: ~~~c // b[-1] is the size and b[-2] the capacity. uint64_t b_data[] = {0, 3, 1, 2, 3}; uint64_t *b = b_data + 2; ~~~
## Index
`struct tm_carray_header_t`

Generic carray functions
`tm_carray_header()`
`tm_carray_size()`
`tm_carray_bytes()`
`tm_carray_end()`
`tm_carray_last()`
`tm_carray_capacity()`
`tm_carray_needs_to_grow()`
`tm_carray_pop()`
`tm_carray_shrink()`
`tm_carray_erase()`

tm_allocator_i interface
`tm_carray_grow()`
`tm_carray_ensure()`
`tm_carray_set_capacity()`
`tm_carray_push()`
`tm_carray_insert()`
`tm_carray_push_array()`
`tm_carray_resize()`
`tm_carray_resize_geom()`
`tm_carray_from()`
`tm_carray_create()`
`tm_carray_free()`

Explicit file and line interface
`tm_carray_grow_at()`
`tm_carray_ensure_at()`
`tm_carray_set_capacity_at()`
`tm_carray_push_at()`
`tm_carray_insert_at()`
`tm_carray_push_array_at()`
`tm_carray_resize_at()`
`tm_carray_resize_geom_at()`
`tm_carray_from_at()`
`tm_carray_create_at()`
`tm_carray_free_at()`

tm_temp_allocator_i interface
`tm_carray_temp_grow()`
`tm_carray_temp_ensure()`
`tm_carray_temp_set_capacity()`
`tm_carray_temp_push()`
`tm_carray_temp_insert()`
`tm_carray_temp_push_array()`
`tm_carray_temp_resize()`
`tm_carray_temp_resize_geom()`
## API
### `struct tm_carray_header_t`
Header placed in front of the array data. ~~~c typedef struct tm_carray_header_t { uint64_t capacity; uint64_t size; } tm_carray_header_t; ~~~

Generic carray functions

### `tm_carray_header()`
~~~c #define tm_carray_header(a) ((tm_carray_header_t *)((uint8_t *)(a) - sizeof(tm_carray_header_t))) ~~~ Returns the header data for `a`.
### `tm_carray_size()`
~~~c #define tm_carray_size(a) ((a) ? tm_carray_header(a)->size : 0) ~~~ Returns the number of elements of `a`.
### `tm_carray_bytes()`
~~~c #define tm_carray_bytes(a) (tm_carray_size(a) * sizeof(*(a))) ~~~ Returns the number of bytes used by `a`'s items (not including header data). This is the amount of bytes you need to `memcpy()` to copy all the items.
### `tm_carray_end()`
~~~c #define tm_carray_end(a) ((a) ? (a) + tm_carray_size(a) : 0) ~~~ Returns a pointer past the end of `a`. Returns NULL if `a` is not allocated.
### `tm_carray_last()`
~~~c #define tm_carray_last(a) ((a && tm_carray_header(a)->size) ? tm_carray_end(a) - 1 : 0) ~~~ Returns a pointer to the last element of `a` or `NULL` if `a` is empty.
### `tm_carray_capacity()`
~~~c #define tm_carray_capacity(a) ((a) ? tm_carray_header(a)->capacity : 0) ~~~ Returns the number of elements allocated for `a`.
### `tm_carray_needs_to_grow()`
~~~c #define tm_carray_needs_to_grow(a, n) ((n) > tm_carray_capacity(a)) ~~~ Returns *true* if `a` needs to grow to hold `n` elements.
### `tm_carray_pop()`
~~~c #define tm_carray_pop(a) ((a)[--tm_carray_header(a)->size]) ~~~ Pops the last item from `a` and returns it.
### `tm_carray_shrink()`
~~~c #define tm_carray_shrink(a, n) ((a) ? tm_carray_header(a)->size = n : 0) ~~~ As `tm_carray_resize()` but can only shrink the array. Since this won't reallocate memory, you don't need to pass an allocator.
### `tm_carray_erase()`
~~~c #define tm_carray_erase(a, i, n) (((a && n) ? memmove((a) + (i), (a) + (i) + (n), (tm_carray_size(a) - (i) - (n)) * sizeof(*(a))) : 0), (a && n) ? tm_carray_header(a)->size -= (n) : 0) ~~~ Erases `n` elements from `a` starting at `i`.

tm_allocator_i interface

### `tm_carray_grow()`
~~~c #define tm_carray_grow(a, n, allocator) tm_carray_grow_at(a, n, allocator, __FILE__, __LINE__) ~~~ Grows the capacity of `a` geometrically to hold at least `n` elements. `a` is updated in-place by the macro.
### `tm_carray_ensure()`
~~~c #define tm_carray_ensure(a, n, allocator) tm_carray_ensure_at(a, n, allocator, __FILE__, __LINE__) ~~~ Ensures that `a` has capacity to to hold at least `n` elements. Grows `a` as needed (geometrically) to hold the specified number of elements. `a` is updated in-place by the macro.
### `tm_carray_set_capacity()`
~~~c #define tm_carray_set_capacity(a, n, allocator) tm_carray_set_capacity_at(a, n, allocator, __FILE__, __LINE__) ~~~ Sets the capacity of `a` to exactly `n`. `a` is updated in-place by the macro.
### `tm_carray_push()`
~~~c #define tm_carray_push(a, item, allocator) tm_carray_push_at(a, item, allocator, __FILE__, __LINE__) ~~~ Pushes `item` to the end of `a`, growing it geometrically if needed. `a` is updated in-place by the macro. Returns a pointer to the pushed item in `a`.
### `tm_carray_insert()`
~~~c #define tm_carray_insert(a, idx, item, allocator) (tm_carray_push(a, item, allocator), memmove(a + idx + 1, a + idx, (tm_carray_size(a) - idx - 1) * sizeof(*(a))), a[idx] = (item), a + idx) ~~~ Inserts `item` at the specified `idx` in `a`, growing it geometrically if needed. `a` is updated in-place by the macro. Returns a pointer to the inserted item in `a`.
### `tm_carray_push_array()`
~~~c #define tm_carray_push_array(a, items, n, allocator) tm_carray_push_array_at(a, items, n, allocator, __FILE__, __LINE__) ~~~ Pushes an array of `n` items to the end of `a`, growing it geometrically if needed. `a` is updated in-place by the macro.
### `tm_carray_resize()`
~~~c #define tm_carray_resize(a, n, allocator) tm_carray_resize_at(a, n, allocator, __FILE__, __LINE__) ~~~ Resizes `a` to `n` elements. If `a` needs to grow, it will grow to exactly `n` elements. Note that this growth is not geometric. Use `tm_carray_resize_geom()` instead if you want geometric growth. `a` is updated in-place by the macro.
### `tm_carray_resize_geom()`
~~~c #define tm_carray_resize_geom(a, n, allocator) tm_carray_resize_geom_at(a, n, allocator, __FILE__, __LINE__) ~~~ As `tm_carray_resize()` but uses geometric growth.
### `tm_carray_from()`
~~~c #define tm_carray_from(ptr, n, allocator) (tm_carray_from_at(ptr, n, allocator, __FILE__, __LINE__)) ~~~ Creates a carray from the array `ptr` of `n` elements. The carray is allocated using `allocator`.
### `tm_carray_create()`
~~~c #define tm_carray_create(T, n, allocator) (tm_carray_create_at(T, n, allocator, __FILE__, __LINE__)) ~~~ Creates an empty carray of type T with `n` zero-initialized elements. The carray is allocated using `allocator`.
### `tm_carray_free()`
~~~c #define tm_carray_free(a, allocator) tm_carray_free_at(a, allocator, __FILE__, __LINE__) ~~~ Frees the memory used by the carray.

Explicit file and line interface

These macros correspond to the regular macros, but take explicit file and line arguments instead of using the current `__FILE__` and `__LINE__`. This can be useful when you want to report memory leaks in a higher level system. ### `tm_carray_grow_at()`
~~~c #define tm_carray_grow_at(a, n, allocator, file, line) ((*(void **)&(a)) = tm_carray_grow_internal((void *)a, n, sizeof(*(a)), allocator, file, line)) ~~~
### `tm_carray_ensure_at()`
~~~c #define tm_carray_ensure_at(a, n, allocator, file, line) (tm_carray_needs_to_grow(a, n) ? tm_carray_grow_at(a, n, allocator, file, line) : 0) ~~~
### `tm_carray_set_capacity_at()`
~~~c #define tm_carray_set_capacity_at(a, n, allocator, file, line) ((*(void **)&(a)) = tm_carray_set_capacity_internal((void *)a, n, sizeof(*(a)), allocator, file, line)) ~~~
### `tm_carray_push_at()`
~~~c #define tm_carray_push_at(a, item, allocator, file, line) (tm_carray_ensure_at(a, tm_carray_size(a) + 1, allocator, file, line), (a)[tm_carray_header(a)->size++] = (item), (a) + tm_carray_header(a)->size - 1) ~~~
### `tm_carray_insert_at()`
~~~c #define tm_carray_insert_at(a, idx, item, allocator, file, line) (tm_carray_push_at(a, item, allocator, file, line), memmove(a + idx + 1, a + idx, (tm_carray_size(a) - idx - 1) * sizeof(*(a))), a[idx] = (item), a + idx) ~~~
### `tm_carray_push_array_at()`
~~~c #define tm_carray_push_array_at(a, items, n, allocator, file, line) ((n) ? ((tm_carray_ensure_at(a, tm_carray_size(a) + n, allocator, file, line), memcpy(a + tm_carray_size(a), items, n * sizeof(*(a))), tm_carray_header(a)->size += n), 0) : 0) ~~~
### `tm_carray_resize_at()`
~~~c #define tm_carray_resize_at(a, n, allocator, file, line) ((tm_carray_needs_to_grow(a, n) ? tm_carray_set_capacity_at(a, n, allocator, file, line) : 0), (a) ? tm_carray_header(a)->size = n : 0) ~~~
### `tm_carray_resize_geom_at()`
~~~c #define tm_carray_resize_geom_at(a, n, allocator, file, line) (tm_carray_ensure_at(a, n, allocator, file, line), (a) ? tm_carray_header(a)->size = n : 0) ~~~
### `tm_carray_from_at()`
~~~c #define tm_carray_from_at(ptr, n, allocator, file, line) {...} ~~~
### `tm_carray_create_at()`
~~~c #define tm_carray_create_at(T, n, allocator, file, line) {...} ~~~
### `tm_carray_free_at()`
~~~c #define tm_carray_free_at(a, allocator, file, line) ((*(void **)&(a)) = tm_carray_set_capacity_internal((void *)a, 0, sizeof(*(a)), allocator, file, line)) ~~~

tm_temp_allocator_i interface

### `tm_carray_temp_grow()`
~~~c #define tm_carray_temp_grow(a, n, ta) ((*(void **)&(a)) = tm_carray_temp_grow_internal((void *)a, n, sizeof(*(a)), ta)) ~~~ As `tm_carray_grow()` for arrays allocated using a temp allocator.
### `tm_carray_temp_ensure()`
~~~c #define tm_carray_temp_ensure(a, n, ta) (tm_carray_needs_to_grow(a, n) ? tm_carray_temp_grow(a, n, ta) : 0) ~~~ As `tm_carray_ensure()` for arrays allocated using a temp allocator.
### `tm_carray_temp_set_capacity()`
~~~c #define tm_carray_temp_set_capacity(a, n, ta) ((*(void **)&(a)) = tm_carray_temp_set_capacity_internal((void *)a, n, sizeof(*(a)), ta)) ~~~ As `tm_carray_set_capacity()` for arrays allocated using a temp allocator.
### `tm_carray_temp_push()`
~~~c #define tm_carray_temp_push(a, item, ta) (tm_carray_temp_ensure(a, tm_carray_size(a) + 1, ta), (a)[tm_carray_header(a)->size++] = (item), (a) + tm_carray_header(a)->size - 1) ~~~ As `tm_carray_push()` for arrays allocated using a temp allocator.
### `tm_carray_temp_insert()`
~~~c #define tm_carray_temp_insert(a, idx, item, ta) (tm_carray_temp_push(a, item, ta), memmove(a + idx + 1, a + idx, (tm_carray_size(a) - idx - 1) * sizeof(*(a))), a[idx] = (item), a + idx) ~~~ As `tm_carray_insert()` for arrays allocated using a temp allocator.
### `tm_carray_temp_push_array()`
~~~c #define tm_carray_temp_push_array(a, items, n, ta) ((n) ? ((tm_carray_temp_ensure(a, tm_carray_size(a) + n, ta), memcpy(a + tm_carray_size(a), items, n * sizeof(*(a))), tm_carray_header(a)->size += n), 0) : 0) ~~~
### `tm_carray_temp_resize()`
~~~c #define tm_carray_temp_resize(a, n, ta) ((tm_carray_needs_to_grow(a, n) ? tm_carray_temp_set_capacity(a, n, ta) : 0), (a) ? tm_carray_header(a)->size = n : 0) ~~~ As `tm_carray_resize()` for arrays allocated using a temp allocator.
### `tm_carray_temp_resize_geom()`
~~~c #define tm_carray_temp_resize_geom(a, n, ta) (tm_carray_temp_ensure(a, n, ta), (a) ? tm_carray_header(a)->size = n : 0) ~~~