#pragma once #include "../std.h" // minimal max_len after initial (0) #define __List_min_size 16 #define List_declare(T)\ typedef struct List_##T {\ T* data;\ u32 len;\ u32 max_len;\ } List_##T;\ \ static inline List_##T List_##T##_construct(T* data_ptr, u32 len, u32 max_len) {\ return (List_##T){ .data = data_ptr, .len = len, .max_len = max_len };\ }\ \ List_##T List_##T##_alloc(u32 initial_len);\ \ T* List_##T##_expand(List_##T* ptr, u32 count);\ void List_##T##_push(List_##T* ptr, T value);\ void List_##T##_pushMany(List_##T* ptr, T* values, u32 count);\ bool List_##T##_tryRemoveAt(List_##T* ptr, u32 i);\ #define List_define(T)\ List_##T List_##T##_alloc(u32 initial_len){\ if(initial_len == 0)\ return List_##T##_construct((T*)NULL, 0, 0);\ u32 max_len = ALIGN_TO(initial_len, sizeof(void*)/sizeof(T));\ /* branchless version of max(max_len, __List_min_size) */\ max_len += (max_len < __List_min_size) * (__List_min_size - max_len);\ return List_##T##_construct((T*)malloc(initial_len * sizeof(T)), 0, max_len);\ }\ \ T* List_##T##_expand(List_##T* ptr, u32 count){\ u32 occupied_len = ptr->len;\ u32 expanded_max_len = ptr->max_len;\ ptr->len += count;\ while(ptr->len > ptr->max_len){\ expanded_max_len *= 2;\ }\ ptr->data = (T*)realloc(ptr->data, expanded_max_len * sizeof(T));\ return ptr->data + occupied_len;\ }\ \ void List_##T##_push(List_##T* ptr, T value){\ T* empty_cell_ptr = List_##T##_expand(ptr, 1);\ *empty_cell_ptr = value;\ }\ \ void List_##T##_pushMany(List_##T* ptr, T* values, u32 count){\ T* empty_cell_ptr = List_##T##_expand(ptr, count);\ memcpy(empty_cell_ptr, values, count * sizeof(T));\ }\ \ bool List_##T##_tryRemoveAt(List_##T* ptr, u32 i){\ if(ptr->len == 0 || i >= ptr->len)\ return false;\ \ ptr->len--;\ for(; i < ptr->len; i++){\ ptr->data[i] = ptr->data[i + 1];\ }\ return true;\ }\ List_declare(u32); List_declare(u8);