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();