#include "tlibc/collections/List.h" #include List_ _List_alloc(u32 initial_capacity, u32 elem_t_size){ assert(elem_t_size != 0); if(initial_capacity == 0) return _List_construct(NULL, 0, 0, elem_t_size); u32 initial_size = initial_capacity * elem_t_size; u32 aligned_capacity = ALIGN_TO(initial_size, sizeof(void*)); return _List_construct(malloc(aligned_capacity), 0, aligned_capacity, elem_t_size); } List_ _List_copy(const List_* src){ assert(src->elem_t_size != 0); List_ copy = _List_alloc(src->capacity, src->elem_t_size); if(copy.data != NULL){ memcpy(copy.data, src->data, src->len * src->elem_t_size); } return copy; } void _List_increaseCapacity(List_* self, u32 len_to_add){ assert(self->elem_t_size != 0); u32 expanded_len = self->len + len_to_add; if(self->capacity > expanded_len) return; u32 expanded_capacity = self->capacity; if(expanded_capacity == 0) expanded_capacity = 32; while(expanded_capacity < expanded_len){ expanded_capacity *= 2; } // if self->data is null, realloc acts like malloc self->data = realloc(self->data, expanded_capacity * self->elem_t_size); self->capacity = expanded_capacity; } void* _List_expand(List_* self, u32 len_to_add){ assert(self->elem_t_size != 0); _List_increaseCapacity(self, len_to_add); u8* empty_cell_ptr = (u8*)self->data + self->len * self->elem_t_size; self->len += len_to_add; return empty_cell_ptr; } void _List_push(List_* self, void* values, u32 len){ assert(self->elem_t_size != 0); void* empty_cell_ptr = _List_expand(self, len); memcpy(empty_cell_ptr, values, len * self->elem_t_size); } bool _List_tryRemoveAt(List_* self, u32 i, u32 remove_len){ assert(self->elem_t_size != 0); if(i >= self->len) return false; if(remove_len + i > self->len) remove_len = self->len - i; u32 move_back_n_elements = self->len - i - remove_len; if(move_back_n_elements > 0){ u32 move_back_size = move_back_n_elements * self->elem_t_size; u8* dst = (u8*)self->data + i * self->elem_t_size; u8* src = (u8*)self->data + (i + remove_len) * self->elem_t_size; memmove(dst, src, move_back_size); } self->len -= remove_len; return true; }