Actually add growing array

This commit is contained in:
Charlie Malmqvist 2024-07-23 21:37:34 +02:00
parent c7daaac338
commit 04ca22a0ed
2 changed files with 335 additions and 0 deletions

View file

@ -0,0 +1,74 @@
typedef struct Circle {
Vector2 pos;
float radius;
} Circle;
int entry(int argc, char **argv) {
window.title = STR("Minimal Game Example");
window.scaled_width = 1280; // We need to set the scaled size if we want to handle system scaling (DPI)
window.scaled_height = 720;
window.x = 200;
window.y = 90;
window.clear_color = hex_to_rgba(0x6495EDff);
Circle *circles;
growing_array_init((void**)&circles, sizeof(Circle), get_heap_allocator());
const int num_circles = 10000;
const float radius_min = 8.0;
const float radius_max = 32.0;
const float hover_radius = 200;
os_update(); // We set scaled window size, os_update updates the pixel window size values for us
for (int i = 0; i < num_circles; i++) {
Circle c;
c.radius = get_random_float32_in_range(radius_min, radius_max);
c.pos.x = get_random_float32_in_range(-(f32)window.width/2.0+c.radius, (f32)window.width/2.0-c.radius);
c.pos.y = get_random_float32_in_range(-(f32)window.height/2.0+c.radius, (f32)window.height/2.0-c.radius);
growing_array_add((void**)&circles, &c);
assert(circles[i].radius == c.radius);
assert(circles[i].pos.x == c.pos.x);
assert(circles[i].pos.y == c.pos.y);
}
float64 last_time = os_get_current_time_in_seconds();
while (!window.should_close) {
float64 now = os_get_current_time_in_seconds();
if ((int)now != (int)last_time) log("%.2f FPS\n%.2fms", 1.0/(now-last_time), (now-last_time)*1000);
last_time = now;
reset_temporary_storage();
draw_frame.projection = m4_make_orthographic_projection(window.pixel_width * -0.5, window.pixel_width * 0.5, window.pixel_height * -0.5, window.pixel_height * 0.5, -1, 10);
float mx = input_frame.mouse_x - window.width/2;
float my = input_frame.mouse_y - window.height/2;
// We build an array on the fly each frame for all the hovered circles
Circle *circles_hovered;
growing_array_init_reserve((void**)&circles_hovered, sizeof(Circle), num_circles, get_temporary_allocator());
for (int i = 0; i < num_circles; i++) {
float distance = v2_length(v2_sub(v2(mx, my), circles[i].pos));
if (distance <= hover_radius) {
growing_array_add((void**)&circles_hovered, &circles[i]);
}
}
for (int i = 0; i < growing_array_get_valid_count(circles_hovered); i++) {
Circle c = circles_hovered[i];
draw_circle(v2_sub(c.pos, v2(c.radius, c.radius)), v2(c.radius, c.radius), COLOR_GREEN);
}
os_update();
gfx_update();
}
return 0;
}

261
oogabooga/growing_array.c Normal file
View file

@ -0,0 +1,261 @@
/*
Thing *things;
growing_array_init(&things, sizeof(Thing));
growing_array_deinit(&things);
Thing new_thing;
growing_array_add(&things, &new_thing); // 'thing' is copied
Thing *nth_thing = &things[n];
growing_array_reserve_count(&things, 690);
growing_array_resize_count(&things, 69);
// "Slow", but stuff in the array keeps the same order
growing_array_ordered_remove_by_index(&things, i);
// Fast, but will not keep stuff ordered
growing_array_unordered_remove_by_index(&things, i);
growing_array_ordered_remove_by_pointer(&things, nth_thing);
growing_array_unordered_remove_by_pointer(&things, nth_thing);
Thing thing_prototype;
growing_array_ordered_remove_one_by_value(&things, thing_prototype);
growing_array_unordered_remove_one_by_value(&things, thing_prototype);
growing_array_ordered_remove_all_by_value(&things, thing_prototype);
growing_array_unordered_remove_all_by_value(&things, thing_prototype);
growing_array_get_valid_count(&things);
growing_array_get_allocated_count(&things);
*/
typedef struct Growing_Array_Header {
u32 valid_count;
u32 allocated_count;
u32 block_size_in_bytes;
Allocator allocator;
} Growing_Array_Header;
void
growing_array_init_reserve(void **array, u64 block_size_in_bytes, u64 count_to_reserve, Allocator allocator) {
count_to_reserve = get_next_power_of_two(count_to_reserve);
u64 bytes_to_allocate = count_to_reserve*block_size_in_bytes + sizeof(Growing_Array_Header);
Growing_Array_Header *header = (Growing_Array_Header*)alloc(allocator, bytes_to_allocate);
header->allocator = allocator;
header->block_size_in_bytes = block_size_in_bytes;
header->valid_count = 0;
header->allocated_count = count_to_reserve;
*array = header+1;
}
void
growing_array_init(void **array, u64 block_size_in_bytes, Allocator allocator) {
growing_array_init_reserve(array, block_size_in_bytes, 8, allocator);
}
void
growing_array_deinit(void **array) {
Growing_Array_Header *header = ((Growing_Array_Header*)*array) - 1;
dealloc(header->allocator, header);
}
void
growing_array_reserve(void **array, u64 count_to_reserve) {
Growing_Array_Header *header = ((Growing_Array_Header*)*array) - 1;
if (header->allocated_count >= count_to_reserve) return;
u64 old_allocated_bytes = header->allocated_count*header->block_size_in_bytes+sizeof(Growing_Array_Header);
count_to_reserve = get_next_power_of_two(count_to_reserve);
u64 bytes_to_allocate = count_to_reserve*header->block_size_in_bytes+sizeof(Growing_Array_Header);
Growing_Array_Header *new_header = (Growing_Array_Header*)alloc(header->allocator, bytes_to_allocate);
memcpy(new_header, header, old_allocated_bytes);
*array = new_header+1;
new_header->allocated_count = count_to_reserve;
dealloc(header->allocator, header);
}
void*
growing_array_add_empty(void **array) {
Growing_Array_Header *header = ((Growing_Array_Header*)*array) - 1;
growing_array_reserve(array, header->valid_count+1);
// Pointer might have been invalidated after reserve
header = ((Growing_Array_Header*)*array) - 1;
void *item = (u8*)*array + header->valid_count*header->block_size_in_bytes;
header->valid_count += 1;
return item;
}
void
growing_array_add(void **array, void *item) {
void *new = growing_array_add_empty(array);
Growing_Array_Header *header = ((Growing_Array_Header*)*array) - 1;
memcpy(new, item, header->block_size_in_bytes);
}
void growing_array_resize(void **array, u64 new_count) {
growing_array_reserve(array, new_count);
Growing_Array_Header *header = ((Growing_Array_Header*)*array) - 1;
header->valid_count = new_count;
}
void growing_array_pop(void **array) {
Growing_Array_Header *header = ((Growing_Array_Header*)*array) - 1;
assert(header->valid_count > 0, "No items to pop in growing array");
header->valid_count -= 1;
}
void growing_array_clear(void **array) {
Growing_Array_Header *header = ((Growing_Array_Header*)*array) - 1;
header->valid_count = 0;
}
void
growing_array_ordered_remove_by_index(void **array, u32 index) {
Growing_Array_Header *header = ((Growing_Array_Header*)*array) - 1;
assert(index < header->valid_count, "Growing array index out of range");
if (index == header->valid_count-1) {
growing_array_pop(array);
return;
}
u64 byte_index = header->block_size_in_bytes*index;
memcpy(
(u8*)*array + byte_index,
(u8*)*array + byte_index + header->block_size_in_bytes,
(header->valid_count-index-1)*header->block_size_in_bytes
);
header->valid_count -= 1;
}
void
growing_array_unordered_remove_by_index(void **array, u32 index) {
Growing_Array_Header *header = ((Growing_Array_Header*)*array) - 1;
assert(index < header->valid_count, "Growing array index out of range");
if (index == header->valid_count-1) {
growing_array_pop(array);
return;
}
u64 byte_index = header->block_size_in_bytes*index;
u64 last_item_index = header->block_size_in_bytes*header->valid_count-header->block_size_in_bytes;
memcpy(
(u8*)*array + byte_index,
(u8*)*array + last_item_index,
header->block_size_in_bytes
);
header->valid_count -= 1;
}
s32
growing_array_find_index_from_left_by_pointer(void **array, void *p) {
Growing_Array_Header *header = ((Growing_Array_Header*)*array) - 1;
for (u32 i = 0; i < header->valid_count; i++) {
void *next = (u8*)*array + i*header->block_size_in_bytes;
if (next == p) {
return i;
}
}
return -1;
}
s32
growing_array_find_index_from_left_by_value(void **array, void *p) {
Growing_Array_Header *header = ((Growing_Array_Header*)*array) - 1;
for (u32 i = 0; i < header->valid_count; i++) {
void *next = (u8*)*array + i*header->block_size_in_bytes;
if (bytes_match(next, p, header->block_size_in_bytes)) {
return i;
}
}
return -1;
}
bool
growing_array_ordered_remove_by_pointer(void **array, void *p) {
Growing_Array_Header *header = ((Growing_Array_Header*)*array) - 1;
s32 i = growing_array_find_index_from_left_by_pointer(array, p);
if (i < 0) return false;
growing_array_ordered_remove_by_index(array, i);
return true;
}
bool
growing_array_unordered_remove_by_pointer(void **array, void *p) {
Growing_Array_Header *header = ((Growing_Array_Header*)*array) - 1;
s32 i = growing_array_find_index_from_left_by_pointer(array, p);
if (i < 0) return false;
growing_array_unordered_remove_by_index(array, i);
return true;
}
bool
growing_array_ordered_remove_one_by_value(void **array, void *p) {
Growing_Array_Header *header = ((Growing_Array_Header*)*array) - 1;
s32 i = growing_array_find_index_from_left_by_value(array, p);
if (i < 0) return false;
growing_array_ordered_remove_by_index(array, i);
return true;
}
bool
growing_array_unordered_remove_one_by_value(void **array, void *p) {
Growing_Array_Header *header = ((Growing_Array_Header*)*array) - 1;
s32 i = growing_array_find_index_from_left_by_value(array, p);
if (i < 0) return false;
growing_array_unordered_remove_by_index(array, i);
return true;
}
// #Incomplete
// s32 growing_array_ordered_remove_one_by_value(void **array, void *p)
// s32 growing_array_unordered_remove_one_by_value(void **array, void *p)
u32
growing_array_get_valid_count(void *array) {
Growing_Array_Header *header = ((Growing_Array_Header*)array) - 1;
return header->valid_count;
}
u32
growing_array_get_allocated_count(void *array) {
Growing_Array_Header *header = ((Growing_Array_Header*)array) - 1;
return header->allocated_count;
}