#include "assets.h" #include "debug.h" #include "list.h" #include #include #include static List _assets; static asset_id _next_id = 0; static size_t file_length(FILE* fp) { long start = ftell(fp); fseek(fp, 0, SEEK_END); long r = ftell(fp); fseek(fp, start, SEEK_SET); return (size_t)r; } static void read_file(FILE* fp, char* out_buffer, size_t out_size) { long start = ftell(fp); fread(out_buffer, 1, out_size, fp); fseek(fp, start, SEEK_SET); } void assets_init() { LOG_INFO("assets_init"); _assets = list_from_type(Asset); _next_id = 1; } // clear all assets without shrinking the assets array. static void _empty_assets() { list_foreach(Asset*, asset, &_assets) { asset->drop->drop(asset->data); } list_empty(&_assets); } void assets_clean() { _empty_assets(); } void assets_reset() { _empty_assets(); } asset_id store_asset(Asset asset) { list_reserve(&_assets, _assets.len + 1); size_t index = list_add(&_assets, &asset); Asset* new_asset = list_at_as(Asset, &_assets, index); asset_id id = _next_id++; new_asset->tc->set_id(new_asset->data, id); asset_id actual_id = new_asset->tc->get_id(new_asset->data); ASSERT_RETURN(actual_id == id,actual_id, "ID stored in asset not the same as the expected id"); return actual_id; } static Asset* _internal_get_by_id(asset_id id) { ASSERT_RETURN_WARN(id != 0, NULL, "Cannot get element with id 0"); list_foreach(Asset*, asset, &_assets) { if(asset->tc->get_id(asset->data) == id) { return asset; } } RETURN_WARNING(NULL, "Failed to find requested asset with id %zu", id); } void* get_asset(asset_id id) { Asset* found = _internal_get_by_id(id); ASSERT_RETURN(found != NULL, NULL, "Failed to find asset with id %zu.", id); return found->data; } asset_id get_asset_id(void* asset) { list_foreach(Asset*, asset, &_assets) { if(asset->data == asset) { return asset->tc->get_id(asset->data); } } RETURN_WARNING(0, "Failed to find asset referencing %p", asset); } void free_asset(asset_id id) { Asset* found = NULL; size_t found_index = _assets.len; for(size_t i = 0; i < _assets.len; ++i) { found = list_at_as(Asset, &_assets, i); if(found->tc->get_id(found->data) == id) { found_index = i; break; } } ASSERT_RETURN(found != NULL,, "Attempt to free nonexistent asset."); found->drop->drop(found->data); list_erase(&_assets, found_index); } cJSON* load_json_from_file(const char* filename) { FILE* fp = fopen(filename, "r"); ASSERT_RETURN(fp != NULL, NULL, "Failed to open file %s.", filename); size_t len = file_length(fp); char* buffer = malloc(len + 1); ASSERT_RETURN(buffer != NULL, NULL, "Failed to allocate buffer for json string."); read_file(fp, buffer, len); cJSON* out = cJSON_Parse(buffer); free(buffer); ASSERT_RETURN(out != NULL, NULL, "Failed to parse json from file %s.", filename); return out; } size_t json_array_len(cJSON* json) { ASSERT_RETURN(cJSON_IsArray(json), 0, "Tried to get the length of a non-array json element."); size_t len = 0; cJSON* itr; cJSON_ArrayForEach(itr, json) { ++len; } return len; }