# HG changeset patch # User Matti Hamalainen # Date 1348885778 -10800 # Node ID 2f463a59d732e131a919540b9cc979577b036b71 # Parent 372b68c0752a35b0efe471e57ce9ed29cd6f58d6 Implement rudimentary resource system. diff -r 372b68c0752a -r 2f463a59d732 dmlib.h --- a/dmlib.h Fri Sep 28 15:45:50 2012 +0300 +++ b/dmlib.h Sat Sep 29 05:29:38 2012 +0300 @@ -35,20 +35,22 @@ enum { // General error codes DMERR_OK = 0, + DMERR_PROGRESS, // Status OK, but operation in progress + DMERR_FOPEN, DMERR_FREAD, DMERR_FWRITE, DMERR_FSEEK, - DMERR_NOT_FOUND, + DMERR_NOT_FOUND, // Resource/data not found - DMERR_INVALID_DATA, - DMERR_MALLOC, - DMERR_ALREADY_INIT, - DMERR_INIT_FAIL, + DMERR_INVALID_DATA, // Some data was invalid + DMERR_MALLOC, // Memory allocation failure + DMERR_ALREADY_INIT, // Resource has already been initialized + DMERR_INIT_FAIL, // General initialization failure DMERR_INVALID_ARGS, - DMERR_NULLPTR, - DMERR_NOT_SUPPORTED, + DMERR_NULLPTR, // NULL pointer specified in critical argument + DMERR_NOT_SUPPORTED,// Operation not supported DMERR_OUT_OF_DATA, DMERR_EXTRA_DATA, DMERR_BOUNDS, diff -r 372b68c0752a -r 2f463a59d732 dmres.c --- 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(); diff -r 372b68c0752a -r 2f463a59d732 dmres.h --- a/dmres.h Fri Sep 28 15:45:50 2012 +0300 +++ b/dmres.h Sat Sep 29 05:29:38 2012 +0300 @@ -30,24 +30,30 @@ enum { DRF_USE_PACK = 0x0001, + DRF_PRELOAD_ALL = 0x0002, + DRF_PRELOAD_RES = 0x0004, }; enum { - DMF_PRELOAD = 0x0001, // Preload this resource - DMF_PERSIST = 0x0002, // Persist loaded resource (only freed at shutdown/explicit prune) - //DMF_STREAM = 0x0004, // This resource is streamed + DMF_PRELOAD_RAW = 0x0001, // Preload raw data + DMF_PRELOAD_RES = 0x0002, // Perform resource preloading (not + DMF_PERSIST = 0x0004, // Persist loaded resource (only freed at shutdown/explicit prune) + DMF_STREAM = 0x0008, // This resource is streamed (UNSUPPORTED FOR NOW) DMF_MASK = 0x0fff, - DMF_LOADED = 0x1000, // Resource has been loaded + DMF_LOADED_RAW = 0x1000, // Raw data has been loaded + DMF_LOADED_RES = 0x2000, // Resource has been loaded }; /* Typedefs and structures */ +struct DMResourceDataOps; struct DMResourceOps; +struct DMResource; -typedef struct _DMResource +typedef struct DMResource { // Timestamps (in seconds from time()) int mtime, // When resource was loaded @@ -64,12 +70,22 @@ int error; // Error code struct DMResourceOps *fops; // Pointer to file handling functions struct - struct _DMResource *next, *prev; + struct DMResource *next, *prev; + + void *rdata; + struct DMResourceDataOps *rops; FILE * fh; } DMResource; +typedef struct DMResourceDataOps +{ + int (*load)(DMResource *res); + void (*free)(DMResource *res); +} DMResourceDataOps; + + typedef struct DMResourceOps { int (*ferror)(DMResource *); @@ -88,11 +104,11 @@ /* Functions */ -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 *)); void dmres_close(void); void dmres_prune(int agems, int flags); -int dmres_preload(); +int dmres_preload(BOOL start, int *loaded, int *total); int dmres_load_resfile(const char *filename); int dmres_write_resfile(const char *filename);