Mercurial > hg > dmlib
diff dmres.c @ 26:2f463a59d732
Implement rudimentary resource system.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Sat, 29 Sep 2012 05:29:38 +0300 |
parents | e0fc7863d024 |
children | 21c14afbf63d |
line wrap: on
line diff
--- a/dmres.c Fri Sep 28 15:45:50 2012 +0300 +++ b/dmres.c Sat Sep 29 05:29:38 2012 +0300 @@ -48,6 +48,14 @@ { if (res != NULL) { + if (res->rdata != NULL && + res->rops != NULL && + res->rops->free != NULL) + { + res->rops->free(res); + res->rdata = NULL; + } + dmFree(res->filename); dmFree(res->data); dmFree(res); @@ -479,6 +487,28 @@ /* FS file handling functions. These functions call the actual * functions depending on where the file is located. */ +static void dmf_init_fops(DMResource *handle) +{ + // Check fops + if (handle->fops == NULL) + { +#ifdef DMRES_PACKFS + if (dfResFlags & DRF_USE_PACK) + handle->fops = &dfPackFileOps; +#ifdef DMRES_STDIO + else + handle->fops = &dfStdioFileOps; +#else + handle->fops = &dfPackFileOps; +#endif + +#else + handle->fops = &dfStdioFileOps; +#endif + } +} + + DMResource *dmf_open(const char *filename) { int ret; @@ -501,26 +531,10 @@ #endif } - // Check fops - if (handle->fops == NULL) - { -#ifdef DMRES_PACKFS - if (dfResFlags & DRF_USE_PACK) - handle->fops = &dfPackFileOps; -#ifdef DMRES_STDIO - else - handle->fops = &dfStdioFileOps; -#else - handle->fops = &dfPackFileOps; -#endif - -#else - handle->fops = &dfStdioFileOps; -#endif - } + dmf_init_fops(handle); // Check if the data is preloaded - if (handle->flags & DMF_LOADED) + if (handle->flags & DMF_LOADED_RAW) { dmres_ref(handle); return handle; @@ -528,7 +542,8 @@ // Check if we want to preload .. ret = DMERR_INIT_FAIL; - if ((handle->flags & DMF_PRELOAD) && + if (((handle->flags & DMF_PRELOAD_RAW) || (dfResFlags & DRF_PRELOAD_ALL)) && + (handle->flags & DMF_LOADED_RAW) == 0 && handle->fops->preload != NULL) ret = handle->fops->preload(handle); else @@ -539,11 +554,20 @@ if (handle->fops->preload != NULL) ret = handle->fops->preload(handle); } + + if (((handle->flags & DMF_PRELOAD_RES) || (dfResFlags & DRF_PRELOAD_RES)) && + (handle->flags & DMF_LOADED_RES) == 0 && + handle->rops != NULL && + handle->rops->load != NULL) + ret = handle->rops->load(handle); + if (ret == DMERR_OK) + { + dmres_ref(handle); return handle; + } - dmres_ref(handle); return NULL; } @@ -556,7 +580,7 @@ if ((handle = dmres_find(filename)) == NULL) { // Hmm.. does not exist? Fall back to a stdio file - handle = dmres_new(filename, DMF_LOADED, len); + handle = dmres_new(filename, DMF_LOADED_RAW, len); if (handle == NULL) return NULL; @@ -752,7 +776,7 @@ /* Resources subsystem initialization and shutdown routines */ -int dmres_init(const char *filename, const char *path, int flags) +int dmres_init(const char *filename, const char *path, int flags, int (*classifier)(DMResource *)) { // Check if we are already initialized if (dfResInitialized) @@ -810,6 +834,17 @@ return DMERR_INIT_FAIL; } + // Okay, classify resources + if (dfResources != NULL && classifier != NULL) + { + DMResource *node; + for (node = dfResources; node != NULL; node = node->next) + { + int ret = classifier(node); + if (ret != DMERR_OK) + return DMERR_INIT_FAIL; + } + } // Initialization complete dfResInitialized = TRUE; @@ -857,54 +892,90 @@ } -BOOL dmres_preload(int *loaded, int *total) +int dmres_preload(BOOL start, int *loaded, int *total) { static DMResource *dfPreload = NULL; + int ret = DMERR_OK; DMRES_LOCK(); - if (dfPreload == NULL) + // Initialize preloading + if (dfPreload == NULL || start) { DMResource *node; + dfPreload = dfResources; *loaded = 0; *total = 0; + + // Calculate total number of resources to be preloaded for (node = dfResources; node != NULL; node = node->next) { - if (node->flags & DMF_PRELOAD) + if ((dfResFlags & (DRF_PRELOAD_ALL | DRF_PRELOAD_RES)) || + (node->flags & (DMF_PRELOAD_RAW | DMF_PRELOAD_RES))) (*total)++; } } - + else if (dfPreload != NULL) { - if ((dfPreload->flags & DMF_PRELOAD) && (dfPreload->flags & DMF_LOADED) == 0) + // Check if the raw resource wants to be preloaded + if (((dfPreload->flags & DMF_PRELOAD_RAW) || (dfResFlags & DRF_PRELOAD_ALL)) && + (dfPreload->flags & DMF_LOADED_RAW) == 0) { - (*loaded)++; + dmf_init_fops(dfPreload); + if (dfPreload->fops->preload != NULL) + { + ret = dfPreload->fops->preload(dfPreload); + if (ret == DMERR_OK) + { + dfPreload->flags |= DMF_LOADED_RAW; + (*loaded)++; + } + else + goto error; + } + } + + // Preload actual resource, if requested + if (((dfPreload->flags & DMF_PRELOAD_RES) || (dfResFlags & DRF_PRELOAD_RES)) && + (dfPreload->flags & DMF_LOADED_RES) == 0 && + dfPreload->rops != NULL && + dfPreload->rops->load != NULL) + { + dmf_init_fops(dfPreload); + ret = dfPreload->rops->load(dfPreload); + if (ret != DMERR_OK) + goto error; + + dfPreload->flags |= DMF_LOADED_RES; } dfPreload = dfPreload->next; } DMRES_UNLOCK(); - - return (*total) == (*loaded); + return (dfPreload == NULL) ? DMERR_OK : DMERR_PROGRESS; + +error: + DMRES_UNLOCK(); + return ret; } void dmres_prune(int agems, int flags) { - DMResource *node, *next; + DMResource *node; int currtime = time(NULL); DMRES_LOCK(); - node = dfResources; - while (node != NULL) + for (node = dfResources; node != NULL; node = node->next) { - next = node->next; // Check if node has refcount of 0 and is // not marked as persistent resource - if (node->refcount == 0 && (node->flags & DMF_PERSIST) == 0) + if (node->refcount == 0 && + (node->flags & DMF_PERSIST) == 0 && + (node->flags & (DMF_LOADED_RES | DMF_LOADED_RAW))) { // Check if we match either one of atime or mtime if (((flags & DMPRUNE_ATIME) && @@ -912,10 +983,24 @@ ((flags & DMPRUNE_MTIME) && currtime - node->mtime >= agems)) { - dmres_delete(node); + // Check if resource data is loaded + if (node->rdata != NULL && + node->rops != NULL && + node->rops->free != NULL) + { + node->rops->free(node); + node->flags &= !DMF_LOADED_RES; + } + + // Check if raw data is loaded + if (node->flags & DMF_LOADED_RAW) + { + dmFree(node->data); + node->data = NULL; + node->flags &= !DMF_LOADED_RAW; + } } } - node = next; } DMRES_UNLOCK();