From 5e494bac1bec3072602a7cd4d6f6cba1b5fbc32c Mon Sep 17 00:00:00 2001 From: Sara Date: Sun, 24 Sep 2023 23:39:39 +0200 Subject: [PATCH] added asset manager --- src/assets.c | 100 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/assets.h | 28 +++++++++++++++ 2 files changed, 128 insertions(+) create mode 100644 src/assets.c create mode 100644 src/assets.h diff --git a/src/assets.c b/src/assets.c new file mode 100644 index 0000000..1663acb --- /dev/null +++ b/src/assets.c @@ -0,0 +1,100 @@ +#include "assets.h" +#include +#include + +typedef +struct AssetData { + void* asset; + asset_id id; + AssetDestructor destructor; +} AssetData; + +static AssetData* _assets = NULL; +static size_t _assets_len = 0; +static size_t _assets_cap = 0; +static asset_id _next_id = 0; + +static +void _resize_if_needed(size_t requested_len) { + if(requested_len < _assets_cap) { + return; // not needed. + } + + size_t new_cap = _assets_cap ? _assets_cap : 8; + while(new_cap < requested_len) { + new_cap *= 2; + } + AssetData* new_assets = realloc(_assets, new_cap * sizeof(AssetData)); + if(new_assets != NULL) { + _assets = new_assets; + _assets_cap = new_cap; + } +} + +void assets_init() { + _assets = malloc(_assets_cap * sizeof(AssetData)); + _next_id = 1; +} + +asset_id store_asset(void* asset, AssetDestructor destructor) { + _resize_if_needed(_assets_len + 1); + AssetData* data = _assets + _assets_len; + + data->asset = asset; + data->destructor = destructor; + data->id = _next_id; + + ++_next_id; + ++_assets_len; + + return data->id; +} + +static +AssetData* _internal_get_by_id(asset_id id) { + if(id == 0) { + return NULL; + } + + for(size_t i = 0; i < _assets_len; ++i) { + if(_assets[i].id == id) { + return _assets + i; + } + } + + return NULL; +} + +void* get_asset(asset_id id) { + AssetData* found = _internal_get_by_id(id); + if(found != NULL) { + return found->asset; + } + + return NULL; +} + +asset_id get_asset_id(void* asset) { + for(size_t i = 0; i < _assets_len; ++i) { + if(_assets[i].asset == asset) { + return _assets[i].id; + } + } + + return 0; +} + +void free_asset(asset_id id) { + AssetData* found = _internal_get_by_id(id); + + if(found == NULL) { + return; + } + + found->destructor(found->asset); + + AssetData* next = found + 1; + size_t dif = next - (_assets + _assets_len); + memmove(found, next, dif); +} + diff --git a/src/assets.h b/src/assets.h new file mode 100644 index 0000000..3d3708f --- /dev/null +++ b/src/assets.h @@ -0,0 +1,28 @@ +#ifndef _fencer_assets_h +#define _fencer_assets_h + +#include + +typedef void(*AssetDestructor)(void*); + +typedef uintptr_t asset_id; + +// Prepare asset management. +// Other asset management functions are invalid until assets_init is called. +void assets_init(); +// Clean up and shut down assets management. +void assets_clean(); +// Clear all assets and reset to initial state. +void assets_reset(); +// Submit an object to be managed as an asset. If the destructor is NULL, free will be used. +// Returns zero if asset could not be stored. +asset_id store_asset(void* asset, AssetDestructor destructor); +// Get an asset already submitted to the asset manager. +// Returns 0 if asset does not exist. +void* get_asset(asset_id id); +// Get an asset id, returns 0 if no such asset exists. +asset_id get_asset_id(void* asset); +// Free an asset managed by the asset manager using it's destructor, or free(..) if NULL. +void free_asset(asset_id id); + +#endif // !_fencer_assets_h