4coder/code/custom/4coder_string_pool.cpp

129 lines
3.5 KiB
C++
Raw Permalink Normal View History

function void
string_pool_init(String_Pool* pool)
{
pool->free_first.next = &pool->free_last;
pool->free_last.prev = &pool->free_first;
}
function String_Pool_Free_List*
free_string_inner(String_Pool* pool, String_Const_u8 str)
{
String_Pool_Free_List* free_at = (String_Pool_Free_List*)str.str;
free_at->next = 0; free_at->prev = 0;
free_at->size = str.size;
String_Pool_Free_List* prev = 0;
for (String_Pool_Free_List* at = pool->free_first.next; at != &pool->free_last; at = prev->next)
{
u8* addr = (u8*)at;
if (addr < (u8*)free_at) prev = at;
else break;
}
if (prev)
{
String_Pool_Free_List* next = prev->next;
prev->next = free_at;
free_at->prev = prev;
free_at->next = next;
next->prev = free_at;
b8 should_merge = (u8*)prev + prev->size == (u8*)free_at;
if (should_merge) free_at = prev;
}
else
{
String_Pool_Free_List* prev = &pool->free_first;
String_Pool_Free_List* next = pool->free_first.next;
prev->next = free_at;
free_at->prev = prev;
free_at->next = next;
next->prev = free_at;
}
while ((u8*)free_at + free_at->size == (u8*)free_at->next)
{
String_Pool_Free_List* next = free_at->next;
free_at->size += next->size;
next->next->prev = free_at;
free_at->next = next->next;
}
return free_at;
}
function String_Pool_Free_List*
string_pool_push_buffer(String_Pool* pool, int size_provided, Arena* backing_arena)
{
u64 next_buffer_size = pool->last_buffer_size * 2;
if (next_buffer_size == 0) next_buffer_size = KB(4);
String_Const_u8 buffer_data = string_const_u8_push(backing_arena, next_buffer_size);
pool->last_buffer_size = next_buffer_size;
String_Pool_Buffer* buffer = (String_Pool_Buffer*)buffer_data.str;
buffer_data.str += sizeof(String_Pool_Buffer);
buffer_data.size -= sizeof(String_Pool_Buffer);
buffer->data = buffer_data;
buffer->next = pool->buffers;
pool->buffers = buffer;
return free_string_inner(pool, buffer_data);
}
function String_Const_u8
alloc_string(String_Pool* pool, int size_provided, Arena* backing_arena)
{
int size = ((size_provided + STRING_POOL_ALLOC_SIZE - 1) / STRING_POOL_ALLOC_SIZE) * STRING_POOL_ALLOC_SIZE;
String_Pool_Free_List* free_at = pool->free_first.next;
while (free_at != &pool->free_last && free_at->size < size) free_at = free_at->next;
if (free_at == &pool->free_last || free_at->size < size)
{
free_at = string_pool_push_buffer(pool, size, backing_arena);
}
Assert(free_at->size >= size);
String_Const_u8 result;
result.str = (u8*)free_at;
result.size = size;
String_Pool_Free_List* prev = free_at->prev;
String_Pool_Free_List* next = free_at->next;
if (free_at->size - size > 0)
{
u8* new_free_at_ptr = (u8*)free_at;
String_Pool_Free_List* new_free_at = (String_Pool_Free_List*)(new_free_at_ptr + size);
new_free_at->size = free_at->size - size;
prev->next = new_free_at;
new_free_at->prev = prev;
new_free_at->next = next;
next->prev = new_free_at;
}
else
{
prev->next = next;
next->prev = prev;
}
block_zero(result.str, result.size);
return result;
}
function String_Const_u8
alloc_string_copy(String_Pool* pool, String_Const_u8 src, Arena* backing_arena)
{
String_Const_u8 dst = alloc_string(pool, src.size+1, backing_arena);
dst.size = src.size;
block_copy_dynamic_array(dst.str, src.str, src.size);
dst.str[src.size] = 0;
return dst;
}
function void
free_string(String_Pool* pool, String_Const_u8 str)
{
free_string_inner(pool, str);
}