188 lines
5.6 KiB
C
188 lines
5.6 KiB
C
#include <shadow-tag.h>
|
|
#include <context.h>
|
|
#include <librr/memory.h>
|
|
#include <librr/strutil.h>
|
|
#include <stdlib.h>
|
|
|
|
void mt_init_shadow_tag_pool_allocation(MtShadowTagPool *pool, usz_t capacity)
|
|
{
|
|
usz_t slot_index = 0;
|
|
while(slot_index < capacity)
|
|
{
|
|
pool->allocation[slot_index].pool = pool;
|
|
pool->allocation[slot_index].next = &pool->allocation[slot_index+1];
|
|
++slot_index;
|
|
}
|
|
pool->allocation[capacity - 1].next = NULL;
|
|
}
|
|
|
|
void mt_init_shadow_tag_pool(MtShadowTagPool *pool, usz_t capacity)
|
|
{
|
|
pool->capacity = capacity;
|
|
pool->allocation = calloc(sizeof(MtShadowTag), capacity);
|
|
pool->first_free = pool->allocation;
|
|
pool->continuation = NULL;
|
|
mt_init_shadow_tag_pool_allocation(pool, capacity);
|
|
}
|
|
|
|
MtShadowTagPool * mt_new_shadow_tag_pool(usz_t capacity)
|
|
{
|
|
MtShadowTagPool *pool = malloc(sizeof(MtShadowTagPool));
|
|
mt_init_shadow_tag_pool(pool, capacity * 2);
|
|
return pool;
|
|
}
|
|
|
|
void mt_free_shadow_tag_pool(MtShadowTagPool *pool)
|
|
{
|
|
if(pool->continuation != NULL)
|
|
mt_free_shadow_tag_pool(pool->continuation);
|
|
free(pool->allocation);
|
|
free(pool);
|
|
}
|
|
|
|
MtShadowTag * mt_alloc_shadow_tag_in_pool(MtShadowTagPool *pool)
|
|
{
|
|
if(pool->first_free == NULL)
|
|
{
|
|
if(pool->continuation == NULL)
|
|
pool->continuation = mt_new_shadow_tag_pool(pool->capacity * 2);
|
|
return mt_alloc_shadow_tag_in_pool(pool->continuation);
|
|
}
|
|
MtShadowTag *allocated_tag = pool->first_free;
|
|
pool->first_free = allocated_tag->next;
|
|
|
|
// Reset the tag's old data
|
|
rr_memset(allocated_tag, sizeof(MtShadowTag), 0x00);
|
|
allocated_tag->pool = pool;
|
|
|
|
return allocated_tag;
|
|
}
|
|
|
|
MtShadowTag * mt_alloc_shadow_tag(void *context_ptr)
|
|
{
|
|
MtContext *context = context_ptr;
|
|
return mt_alloc_shadow_tag_in_pool(&context->shadow_tag_system.root_pool);
|
|
}
|
|
|
|
MtShadowTag * mt_alloc_shadow_tag_before(MtShadowTag *chain_start)
|
|
{
|
|
MtShadowTag *tag = mt_alloc_shadow_tag_in_pool(chain_start->pool);
|
|
tag->next = chain_start;
|
|
return tag;
|
|
}
|
|
|
|
void mt_free_shadow_tag_chain(MtShadowTag *tag)
|
|
{
|
|
MtShadowTagPool *pool = tag->pool;
|
|
MtShadowTag *last_tag = tag;
|
|
while(last_tag->next != NULL)
|
|
{
|
|
last_tag = last_tag->next;
|
|
}
|
|
last_tag->next = pool->first_free;
|
|
pool->first_free = tag;
|
|
}
|
|
|
|
|
|
|
|
void mt_init_shadow_tag_name_arena(MtShadowTagNameArena *arena, usz_t size)
|
|
{
|
|
arena->usage = 0;
|
|
arena->capacity = size;
|
|
arena->allocation = malloc(size);
|
|
arena->continuation = NULL;
|
|
}
|
|
|
|
MtShadowTagNameArena * mt_new_shadow_tag_name_arena(usz_t size)
|
|
{
|
|
MtShadowTagNameArena *arena = malloc(sizeof(MtShadowTagNameArena));
|
|
mt_init_shadow_tag_name_arena(arena, size);
|
|
return arena;
|
|
}
|
|
|
|
void mt_free_shadow_tag_name_arena(MtShadowTagNameArena *arena)
|
|
{
|
|
if(arena->continuation != NULL)
|
|
mt_free_shadow_tag_name_arena(arena->continuation);
|
|
free(arena->allocation);
|
|
free(arena);
|
|
}
|
|
|
|
void mt_init_shadow_tag_name_registry(MtShadowTagNameRegistry *name_registry)
|
|
{
|
|
name_registry->root_arena = mt_new_shadow_tag_name_arena(4096);
|
|
name_registry->id_counter = 1;
|
|
name_registry->num_names = 0;
|
|
name_registry->names_capacity = 256;
|
|
name_registry->names = calloc(sizeof(MtShadowTagName), name_registry->names_capacity);
|
|
}
|
|
|
|
void mt_cleanup_shadow_tag_name_registry(MtShadowTagNameRegistry *name_registry)
|
|
{
|
|
mt_free_shadow_tag_name_arena(name_registry->root_arena);
|
|
free(name_registry->names);
|
|
}
|
|
|
|
void mt_init_shadow_tag_system(MtShadowTagSystem *tag_system)
|
|
{
|
|
mt_init_shadow_tag_name_registry(&tag_system->name_registry);
|
|
mt_init_shadow_tag_pool(&tag_system->root_pool, 8192);
|
|
}
|
|
|
|
void mt_cleanup_shadow_tag_system(MtShadowTagSystem *tag_system)
|
|
{
|
|
mt_free_shadow_tag_pool(&tag_system->root_pool);
|
|
mt_cleanup_shadow_tag_name_registry(&tag_system->name_registry);
|
|
}
|
|
|
|
|
|
|
|
char * mt_shadow_tag_name_arena_alloc(MtShadowTagNameArena *arena, usz_t num_bytes)
|
|
{
|
|
usz_t end_size = arena->usage + num_bytes;
|
|
if(end_size >= arena->capacity)
|
|
{
|
|
if(arena->continuation == NULL)
|
|
arena->continuation = mt_new_shadow_tag_name_arena(arena->capacity * 2);
|
|
return mt_shadow_tag_name_arena_alloc(arena->continuation, num_bytes);
|
|
}
|
|
char *allocation = arena->allocation + arena->usage;
|
|
arena->usage = end_size;
|
|
return allocation;
|
|
}
|
|
|
|
u32_t mt_force_create_new_tag_name_entry(MtShadowTagNameRegistry *name_registry, const char *tag_name)
|
|
{
|
|
if(name_registry->num_names >= name_registry->names_capacity)
|
|
{
|
|
name_registry->names_capacity *= 2;
|
|
name_registry->names = realloc(name_registry->names, sizeof(MtShadowTagName) * name_registry->names_capacity);
|
|
}
|
|
MtShadowTagName *name_entry = &name_registry->names[name_registry->num_names++];
|
|
|
|
usz_t len_tag_name = rr_measure_string(tag_name);
|
|
char *tag_name_copy = mt_shadow_tag_name_arena_alloc(name_registry->root_arena, len_tag_name+1);
|
|
rr_memcopy(tag_name_copy, tag_name, len_tag_name + 1);
|
|
|
|
name_entry->string_in_arena = tag_name_copy;
|
|
name_entry->identifier = name_registry->id_counter++;
|
|
|
|
return name_entry->identifier;
|
|
}
|
|
|
|
u32_t mt_tag_name_to_id(void *context_ptr, const char *tag_name)
|
|
{
|
|
MtContext *context = context_ptr;
|
|
MtShadowTagNameRegistry *name_registry = &context->shadow_tag_system.name_registry;
|
|
|
|
usz_t name_index = 0;
|
|
while(name_index < name_registry->num_names)
|
|
{
|
|
if(rr_strings_equal(name_registry->names[name_index].string_in_arena, tag_name))
|
|
return name_registry->names[name_index].identifier;
|
|
++name_index;
|
|
}
|
|
return mt_force_create_new_tag_name_entry(name_registry, tag_name);
|
|
}
|
|
|