diff --git a/main.cpp b/main.cpp index 3ea7f9d..81a675b 100644 --- a/main.cpp +++ b/main.cpp @@ -765,354 +765,6 @@ UI_SIGNAL_CALLBACK(scene_callback) { scene = (Scene)(((int)scene + 1) % Scene_Count); } -const int ARRAY_LIST_DEFAULT_CAP = 32; -const int ARRAY_LIST_DEFAULT_ALLOCATION_MUL = 2; -template struct Array_List_Iter; - -template -struct Array_Node{ - Array_Node *next; - Array_Node *prev; - int cap; - int len; - T data[]; -}; - -template -struct Array_List{ - int block_size = 0; - int allocation_multiplier = 0; - Array_Node *first = 0; - Array_Node *last = 0; - Array_Node *first_free = 0; - - // Iterator method - Array_List_Iter iter(); -}; - -template -struct Array_List_Iter{ - T *item; - int index; - Array_Node *node; - int node_index; - - // Methods - void next(); - force_inline B32 is_valid(); -}; - -template -void Array_List_Iter::next(){ - if(node_index + 1 >= node->len){ - node = node->next; - node_index = -1; - item = 0; - } - - if(node){ - node_index += 1; - index += 1; - item = node->data + node_index; - } -} - -template -B32 Array_List_Iter::is_valid(){ - return item != 0; -} - -template -Array_List_Iter Array_List::iter(){ - Array_List_Iter result = {}; - result.node = this->first; - result.index = result.node_index = -1; - result.next(); - return result; -} - -template -Array_Node *array_allocate_node(Arena *arena, int size){ - auto node = (Array_Node *)arena_push_size(arena, sizeof(Array_Node) + size*sizeof(T)); - node->cap = size; - node->len = 0; - return node; -} - -template -void array_alloc_free_node(Arena *arena, Array_List *array, int size){ - Array_Node *node = array_allocate_node(arena, size); - DLLFreeListAdd(array->first_free, node); -} - -template -void make_sure_there_is_room_for_item_count(Arena *arena, Array_List *array, int item_count){ - if(array->last == 0 || array->last->len + item_count > array->last->cap){ - // Not enough space we need to get a new block - Array_Node *node = 0; - - // Iterate the free list to check if we have a block of required size there - For_List(array->first_free){ - if(it->cap >= item_count){ - DLLFreeListRemove(array->first_free, it); - node = it; - node->len = 0; - break; - } - } - - // We don't have a block on the free list need to allocate - if(!node){ - if(!array->allocation_multiplier) array->allocation_multiplier = ARRAY_LIST_DEFAULT_ALLOCATION_MUL; - if(!array->block_size) array->block_size = ARRAY_LIST_DEFAULT_CAP; - if(item_count > array->block_size) - array->block_size = item_count*2; - node = array_allocate_node(arena, array->block_size); - array->block_size *= array->allocation_multiplier; - } - - assert(node); - DLLQueueAddLast(array->first, array->last, node); - } -} - -template -T *array_get(Array_List *array, int index){ - int i = 0; - For_List(array->first){ - int lookup_i = index - i; - if(lookup_i < it->len) { - return it->data + lookup_i; - } - i += it->cap; - } - return 0; -} - -template -void array_add(Arena *arena, Array_List *array, T item){ - make_sure_there_is_room_for_item_count(arena, array, 1); - array->last->data[array->last->len++] = item; -} - -template -T *array_alloc(Arena *arena, Array_List *array, int count){ - make_sure_there_is_room_for_item_count(arena, array, count); - T *result = array->last->data; - array->last->len += count; - return result; -} - -template -void array_free_node(Array_List *array, Array_Node *node){ - -#if 1 - // Make sure it's actually in array list - B32 found = false; - For_List(array->first){ - if(it == node){ - found = true; - break; - } - } - assert(found); -#endif - - DLLQueueRemove(array->first, array->last, node); - DLLFreeListAdd(array->first_free, node); -} - -template -void array_free_all_nodes(Array_List *array){ - assert(!array->last->next); - assert(!array->first->prev); - array->last->next = array->first_free; - if(array->first_free) array->first_free->prev = array->last; - array->first_free = array->first; - array->last = array->first = 0; -} - -template -T array_ordered_remove(Array_List *array, int index){ - Array_Node *node = 0; - int i = 0; - T *item = 0; - - // Get node from array - For_List(array->first){ - int lookup_i = index - i; - if(lookup_i < it->len) { - node = it; - i = lookup_i; - item = it->data + lookup_i; - break; - } - i += it->cap; - } - - assert(node); - assert(item); - T result = *item; - - // Check if we need to deallocate the block - if(node->len == 1) { - array_free_node(array, node); - return result; - } - - - // We need to move part of the block to fill the new empty spot - int right_count = (--node->len) - i; - memory_copy(item, item+1, sizeof(T)*right_count); - return result; -} - -template -T array_unordered_remove(Array_List *array, int index){ - auto last = array->last; - assert(last); - assert(last->data); - assert(last->len != 0); - T *indexed_value = array_get(array, index); - T *last_value = last->data + (last->len-1); - - T temp = *indexed_value; - *indexed_value = *last_value; - *last_value = temp; - - return array_pop(array); -} - -template -T array_pop(Array_List *array){ - assert(array->last != 0); - assert(array->last->len > 0); - T result = array->last->data[--array->last->len]; - if(array->last->len == 0){ - array_free_node(array, array->last); - } - return result; -} - -void array_print(Array_List *array){ - log_info("\nNodes: "); - for(Array_Node *it = array->first; it; it=it->next){ - log_info("%d", it->cap); - if(it->next) log_info("->"); - } - - log_info("\nFree: "); - for(Array_Node *it = array->first_free; it; it=it->next){ - log_info("%d", it->cap); - if(it->next) log_info("->"); - } - - log_info("\nNodes_Reverse: "); - for(Array_Node *it = array->last; it; it=it->prev){ - log_info("%d", it->cap); - if(it->prev) log_info("<-"); - } - - // - // Make sure going backwards yields same results as going forward - // - Scratch scratch; - Array *> nodes = {scratch}; - for(Array_Node *it = array->first; it; it=it->next){ - nodes.add(it); - } - - S32 array_i = nodes.len; - for(Array_Node *it = array->last; it; it=it->prev){ - Array_Node *node_from_array = nodes.data[--array_i]; - assert(it == node_from_array); - } - - // - // Same test but for free list - // - nodes.clear(); - Array_Node *last = 0; - for(auto it = array->first_free; it; it=it->next){ - nodes.add(it); - if(!it->next) last = it; - } - - array_i = nodes.len; - for(Array_Node *it = last; it; it=it->prev){ - Array_Node *node_from_array = nodes.data[--array_i]; - assert(it == node_from_array); - } - -} - -function void -test_array_list(){ - Scratch scratch; - log_info("\nArray_List:%d Array_Node:%d Array:%d", (int)sizeof(Array_List), (int)sizeof(Array_Node), (int)sizeof(Array)); - - { - Array_List array{32,1}; - for(int i = 0; i < 33; i++){ - array_add(scratch, &array, i); - } - assert(array_pop(&array) == 32); - assert(array_pop(&array) == 31); - array_add(scratch, &array, 31); - array_add(scratch, &array, 32); - assert(array_pop(&array) == 32); - assert(array_pop(&array) == 31); - - array_add(scratch, &array, 31); - array_add(scratch, &array, 32); - - array_unordered_remove(&array, 31); - array_unordered_remove(&array, 31); - - assert(array_pop(&array) == 30); - assert(array_pop(&array) == 29); - array_add(scratch, &array, 29); - array_add(scratch, &array, 30); - array_add(scratch, &array, 31); - array_add(scratch, &array, 32); - array_ordered_remove(&array, 32); - array_ordered_remove(&array, 0); - array_ordered_remove(&array, 16); - array_ordered_remove(&array, 29); - array_print(&array); - } - - { - Array_List array; - for(int i = 0; i < 100000; i++){ - array_add(scratch, &array, i); - } - - For_It(array){ - assert(it.index == *it.item); - } - - assert(*array_get(&array, 22) == 22); - assert(*array_get(&array, 65) == 65); - assert(*array_get(&array, 200) == 200); - - array_print(&array); - array_free_node(&array, array.last->prev); - array_free_node(&array, array.last->prev); - array_free_node(&array, array.last->prev); - array_free_node(&array, array.last->prev); - array_free_node(&array, array.last->prev->prev); - array_print(&array); - - for(int i = 0; i < 10000; i++){ - array_add(scratch, &array, i); - } - - array_print(&array); - } - // __debugbreak(); -} - FILE *global_file; function void windows_log(Log_Kind kind, String string, char *file, int line){