#define ARRAY_GROW_FORMULA(x) (2*(x) + 8) template struct Array { gbAllocator allocator; T *data; isize count; isize capacity; T &operator[](isize index) { GB_ASSERT_MSG(0 <= index && index < count, "Index out of bounds"); return data[index]; } T const &operator[](isize index) const { GB_ASSERT_MSG(0 <= index && index < count, "Index out of bounds"); return data[index]; } }; template void array_init (Array *array, gbAllocator a, isize init_capacity = 8); template void array_free (Array *array); template void array_add (Array *array, T const &t); template T array_pop (Array *array); template void array_clear (Array *array); template void array_reserve (Array *array, isize capacity); template void array_resize (Array *array, isize count); template void array_set_capacity(Array *array, isize capacity); template void array_init(Array *array, gbAllocator a, isize init_capacity) { array->allocator = a; array->data = gb_alloc_array(a, T, init_capacity); array->count = 0; array->capacity = init_capacity; } template void array_free(Array *array) { gb_free(array->allocator, array->data); array->count = 0; array->capacity = 0; } template void array__grow(Array *array, isize min_capacity) { isize new_capacity = ARRAY_GROW_FORMULA(array->capacity); if (new_capacity < min_capacity) { new_capacity = min_capacity; } array_set_capacity(array, new_capacity); } template void array_add(Array *array, T const &t) { if (array->capacity < array->count+1) { array__grow(array, 0); } array->data[array->count] = t; array->count++; } template T array_pop(Array *array) { GB_ASSERT(array->count > 0); array->count--; return array->data[array->count]; } template void array_clear(Array *array) { array->count = 0; } template void array_reserve(Array *array, isize capacity) { if (array->capacity < capacity) { array_set_capacity(array, capacity); } } template void array_resize(Array *array, isize count) { if (array->capacity < count) { array__grow(array, count); } array->count = count; } template void array_set_capacity(Array *array, isize capacity) { if (capacity == array->capacity) { return; } if (capacity < array->count) { array_resize(array, capacity); } T *new_data = NULL; if (capacity > 0) { new_data = gb_alloc_array(array->allocator, T, capacity); gb_memmove(new_data, array->data, gb_size_of(T) * array->capacity); } gb_free(array->allocator, array->data); array->data = new_data; array->capacity = capacity; }