#ifndef ARRAY_CC #define ARRAY_CC #include "memory.cc" #define ARRAY_INIT 4 #define ARRAY_GROWTH 2 template struct Array { usize capacity, size; T* data; const Allocator* allocator; }; #define array_init(T, allocator) \ Array { 0, 0, nullptr, allocator } template static inline usize array_nbytes(usize size) { assert_neq(size, 0); return size * sizeof(T); } template static inline usize array_next_capacity(const Array* array) { assert_neq(array, nullptr); return array->capacity == 0 ? ARRAY_INIT : array->capacity * ARRAY_GROWTH; } template bool array_resize(Array* array, usize new_capacity) { assert_neq(array, nullptr); assert_st(array->size, new_capacity); T* new_data = (T*)allocate(array->allocator, array_nbytes(new_capacity), alignof(T)); if(new_data == nullptr) return false; memcpy(new_data, array->data, array_nbytes(new_capacity)); deallocate(array->allocator, (u8*)array->data); array->data = new_data; array->capacity = new_capacity; return true; } template static inline bool array_grow_if_needed(Array* array) { assert_neq(array, nullptr); assert_ste(array->size, array->capacity); if(array->size < array->capacity) return true; usize new_capacity = array_next_capacity(array); return array_resize(array, new_capacity); } template static inline T* array_at(const Array* array, usize index) { assert_neq(array, nullptr); assert_st(index, array->capacity); return array->data + index; } template inline T* array_last(const Array* array) { assert_neq(array, nullptr); if(array->size == 0) return nullptr; return array_at(array, array->size - 1); } template bool array_push(Array* array, T* item) { assert_neq(array, nullptr); assert_neq(item, nullptr); bool ret = array_grow_if_needed(array); if(!ret) return false; T* loc = array_at(array, array->size); memcpy(loc, item, sizeof(T)); array->size += 1; return true; } template void array_deinit(Array* array) { assert_neq(array, nullptr); if (unlikely(array->data == nullptr)) return; deallocate(array->allocator, (u8*)array->data); memset(array, 0, sizeof(*array)); } #endif