changeset 2437:f7d54ac51880

Fix and improvements to dmres MemIO subsystem.
author Matti Hamalainen <ccr@tnsp.org>
date Tue, 25 Feb 2020 07:26:40 +0200
parents b7f622d39efc
children 0b18f597351a
files src/dmengine.c src/dmres.c src/dmres.h
diffstat 3 files changed, 103 insertions(+), 65 deletions(-) [+]
line wrap: on
line diff
--- a/src/dmengine.c	Mon Feb 24 16:12:16 2020 +0200
+++ b/src/dmengine.c	Tue Feb 25 07:26:40 2020 +0200
@@ -209,7 +209,7 @@
     OggVorbis_File vf;
 
     dmMsg(2, "vorbisfile '%s', %" DM_PRIu_SIZE_T " bytes resource loading\n",
-        res->filename, res->rawSize);
+        res->filename, res->memSize);
 
     if (ov_open_callbacks(res, &vf, NULL, 0, vorbisFileCBS) < 0)
         return DMERR_FOPEN;
--- a/src/dmres.c	Mon Feb 24 16:12:16 2020 +0200
+++ b/src/dmres.c	Tue Feb 25 07:26:40 2020 +0200
@@ -49,7 +49,7 @@
 
     node->lib = lib;
     node->filename = dm_strdup(filename);
-    node->rawSize = size;
+    node->memAlloc = node->memSize = size;
     node->flags = flags;
 
     return node;
@@ -75,8 +75,8 @@
 {
     if ((node->flags & DMF_UNALLOCATED) == 0)
     {
-        dmFree(node->rawData);
-        node->rawData = NULL;
+        dmFree(node->memData);
+        node->memData = NULL;
         node->flags &= ~DMF_LOADED_RAW;
     }
 }
@@ -231,8 +231,8 @@
     off_t savePos, fileSize;
 
     // Check if the size is cached
-    if (fh->rawSize != 0)
-        return fh->rawSize;
+    if (fh->memSize != 0)
+        return fh->memSize;
 
     // Get file size
     if ((savePos = dm_stdio_ftell(fh)) < 0)
@@ -247,7 +247,7 @@
     if (dm_stdio_fseek(fh, savePos, SEEK_SET) != 0)
         return -1;
 
-    fh->rawSize = fileSize;
+    fh->memSize = fileSize;
     return fileSize;
 }
 
@@ -298,11 +298,13 @@
 
     dm_stdio_fsize(handle);
 
-    handle->rawData = dmMalloc(handle->rawSize);
-    if (handle->rawData == NULL)
+    handle->memData = dmMalloc(handle->memSize);
+    if (handle->memData == NULL)
         return DMERR_MALLOC;
 
-    if (dm_stdio_fread(handle->rawData, sizeof(Uint8), handle->rawSize, handle) != handle->rawSize)
+    handle->memAlloc = handle->memSize;
+
+    if (dm_stdio_fread(handle->memData, sizeof(Uint8), handle->memSize, handle) != handle->memSize)
         return DMERR_FREAD;
 
     return DMERR_OK;
@@ -383,8 +385,8 @@
 
     // Initialize decompression
     memset(&zstr, 0, sizeof(zstr));
-    zstr.next_out = handle->rawData;
-    zstr.avail_out = handle->rawSize;
+    zstr.next_out = handle->memData;
+    zstr.avail_out = handle->memSize;
     cdataLeft = node->length;
 
     if ((zret = inflateInit(&zstr)) != Z_OK)
@@ -446,8 +448,8 @@
 
     ctx.inBuffer     = ctx.inBufferStart = inBuf;
     ctx.inBufferEnd  = inBuf + node->length;
-    ctx.outBuffer    = ctx.outBufferStart = handle->rawData;
-    ctx.outBufferEnd = handle->rawData + node->size;
+    ctx.outBuffer    = ctx.outBufferStart = handle->memData;
+    ctx.outBufferEnd = handle->memData + node->size;
     ctx.expandable   = FALSE;
 
     // Attempt decompression
@@ -457,8 +459,8 @@
     if ((ret = dmZLibInflate(&ctx)) != DMERR_OK)
         goto out;
 
-    handle->rawData = ctx.outBufferStart;
-    handle->rawSize = ctx.outBuffer - ctx.outBufferStart;
+    handle->memData = ctx.outBufferStart;
+    handle->memSize = ctx.outBuffer - ctx.outBufferStart;
 
 out:
     dmZLibCloseInflate(&ctx);
@@ -495,7 +497,7 @@
     }
 
     // Allocate memory for the node
-    if ((handle->rawData = dmMalloc(node->size)) == NULL)
+    if ((handle->memData = dmMalloc(node->size)) == NULL)
     {
         ret = dmErrorDBG(DMERR_MALLOC,
             "Failed to allocate node data for '%s' (%d bytes).\n",
@@ -509,12 +511,12 @@
         if ((ret = dm_pack_decompress(handle, node)) != DMERR_OK)
             goto out;
 
-        if (handle->rawSize != node->size)
+        if (handle->memSize != node->size)
         {
             ret = dmErrorDBG(DMERR_COMPRESSION,
                 "Decompressed data size for '%s' does not match size "
                 "stored in PACK entry (%" DM_PRIu_SIZE_T " <> %d).\n",
-                handle->filename, handle->rawSize, node->size);
+                handle->filename, handle->memSize, node->size);
         }
     }
     else
@@ -526,7 +528,7 @@
                 handle->filename, node->size, node->length);
             goto out;
         }
-        if (fread(handle->rawData, sizeof(Uint8), node->size, handle->lib->packFile->file) != node->size)
+        if (fread(handle->memData, sizeof(Uint8), node->size, handle->lib->packFile->file) != node->size)
         {
             ret = dmErrorDBG(DMERR_FREAD,
                 "Error reading raw node data '%s', %d bytes.\n",
@@ -563,20 +565,56 @@
 #endif
 
 
-static int dm_mem_freset(DMResource *fh)
+static BOOL dm_mem_realloc(DMResource *ctx, const size_t newSize)
 {
-    fh->rawOffset = 0;
+    size_t grow;
+
+    if (ctx->maxSize > 0 && newSize > ctx->maxSize)
+    {
+        ctx->error = DMERR_BOUNDS;
+        return FALSE;
+    }
+
+    if (newSize < ctx->memAlloc)
+        return TRUE;
+
+    grow = (ctx->minAlloc > 0) ? ctx->minAlloc : 8 * 1024;
+    if (newSize - ctx->memAlloc > grow)
+        grow += newSize - ctx->memAlloc;
+
+    if (ctx->maxSize > 0 && ctx->memAlloc + grow >= ctx->maxSize)
+    {
+        ctx->error = DMERR_BOUNDS;
+        return FALSE;
+    }
+
+    ctx->memAlloc += grow;
+    if ((ctx->memData = dmRealloc(ctx->memData, ctx->memAlloc)) == NULL)
+    {
+        ctx->error = DMERR_MALLOC;
+        return FALSE;
+    }
+
+    ctx->memSize = newSize;
+
+    return TRUE;
+}
+
+
+static int dm_mem_freset(DMResource *ctx)
+{
+    ctx->memOffset = 0;
     return DMERR_OK;
 }
 
 
-static int dm_mem_ferror(DMResource *fh)
+static int dm_mem_ferror(DMResource *ctx)
 {
-    return fh->error;
+    return ctx->error;
 }
 
 
-static int dm_mem_fseek(DMResource *fh, const off_t offset, const int whence)
+static int dm_mem_fseek(DMResource *ctx, const off_t offset, const int whence)
 {
     off_t newPos;
 
@@ -588,11 +626,11 @@
             break;
 
         case SEEK_CUR:
-            newPos = fh->rawOffset + offset;
+            newPos = ctx->memOffset + offset;
             break;
 
         case SEEK_END:
-            newPos = fh->rawSize + offset;
+            newPos = ctx->memSize + offset;
             break;
 
         default:
@@ -600,93 +638,90 @@
     }
 
     // Set the new position
-    fh->rawOffset = newPos;
+    ctx->memOffset = newPos;
 
     // Check the new position
-    if (newPos < 0 && (size_t) newPos >= fh->rawSize)
+    if (newPos < 0)
         return -1;
 
+    //if (!dm_mem_realloc(ctx, newPos))
+    //    return -1;
+
     return 0;
 }
 
 
-static off_t dm_mem_fsize(DMResource *fh)
+static off_t dm_mem_fsize(DMResource *ctx)
 {
-    return fh->rawSize;
+    return ctx->memSize;
 }
 
 
-static off_t dm_mem_ftell(DMResource *fh)
+static off_t dm_mem_ftell(DMResource *ctx)
 {
-    return fh->rawOffset;
+    return ctx->memOffset;
 }
 
 
-static BOOL dm_mem_feof(DMResource *fh)
+static BOOL dm_mem_feof(DMResource *ctx)
 {
-    // Check for EOF
-    if ((size_t) fh->rawOffset <= fh->rawSize)
-        return FALSE;
-    else
-        return TRUE;
+    return ((size_t) ctx->memOffset) >= ctx->memSize;
 }
 
 
-static int dm_mem_fgetc(DMResource *fh)
+static int dm_mem_fgetc(DMResource *ctx)
 {
     // Check for EOF
-    if ((size_t) fh->rawOffset < fh->rawSize)
-        return fh->rawData[fh->rawOffset++];
+    if ((size_t) ctx->memOffset < ctx->memSize)
+        return ctx->memData[ctx->memOffset++];
     else
         return EOF;
 }
 
 
-static size_t dm_mem_fread(void *buf, size_t size, size_t nmemb, DMResource *fh)
+static size_t dm_mem_fread(void *buf, size_t size, size_t nmemb, DMResource *ctx)
 {
-    size_t length = (size * nmemb);
+    size_t length = size * nmemb;
 
     // Check if we can read the whole chunk
-    if (((size_t) fh->rawOffset + length) >= fh->rawSize)
+    if (((size_t) ctx->memOffset + length) >= ctx->memSize)
     {
-        nmemb = (fh->rawSize - fh->rawOffset) / size;
+        nmemb = (ctx->memSize - ctx->memOffset) / size;
         length = size * nmemb;
     }
 
-    memcpy(buf, fh->rawData + fh->rawOffset, length);
-    fh->rawOffset += length;
+    memcpy(buf, ctx->memData + ctx->memOffset, length);
+    ctx->memOffset += length;
     return nmemb;
 }
 
 
-static int dm_mem_fputc(int ch, DMResource *fh)
+static int dm_mem_fputc(int ch, DMResource *ctx)
 {
     // Check for EOF
-    if ((size_t) fh->rawOffset < fh->rawSize)
-    {
-        fh->rawData[fh->rawOffset++] = ch;
-        return ch;
-    }
-    else
+    if (!dm_mem_realloc(ctx, ctx->memOffset + 1))
         return EOF;
+    
+    ctx->memData[ctx->memOffset++] = ch;
+    return ch;
 }
 
 
-static size_t dm_mem_fwrite(const void *buf, size_t size, size_t nmemb, DMResource *fh)
+static size_t dm_mem_fwrite(const void *buf, size_t size, size_t nmemb, DMResource *ctx)
 {
-    size_t length = (size * nmemb);
+    size_t length = size * nmemb;
 
     // Check if we can write the whole chunk
-    if (((size_t) fh->rawOffset + length) >= fh->rawSize)
+    if (!dm_mem_realloc(ctx, ctx->memOffset + length))
     {
-        nmemb = (fh->rawSize - fh->rawOffset) / size;
+        nmemb = (ctx->memSize - ctx->memOffset) / size;
         length = size * nmemb;
     }
 
     if (length > 0)
     {
-        memcpy(fh->rawData + fh->rawOffset, buf, length);
-        fh->rawOffset += length;
+        memcpy(ctx->memData + ctx->memOffset, buf, length);
+        ctx->memOffset += length;
     }
     return nmemb;
 }
@@ -849,7 +884,7 @@
             return DMERR_MALLOC;
 
         handle->fops    = &dfMemIOFileOps;
-        handle->rawData = buf;
+        handle->memData = buf;
         dmResourceInsert(lib, handle);
     }
 
--- a/src/dmres.h	Mon Feb 24 16:12:16 2020 +0200
+++ b/src/dmres.h	Tue Feb 25 07:26:40 2020 +0200
@@ -65,9 +65,12 @@
     char   *filename;
 
     // Raw data (or mem data)
-    size_t rawSize;            // Size of data
-    off_t  rawOffset;          // Current offset in data
-    Uint8 *rawData;            // Pointer to data
+    size_t maxSize;            // Maximum size (0 = no limit)
+    size_t memSize;            // Size of data
+    size_t memAlloc;           // Amount allocated
+    size_t minAlloc;           // Minimum allocation increase (0 = default)
+    off_t  memOffset;          // Current offset in data
+    Uint8  *memData;           // Pointer to data
 
     // Decoded resource data
     void   *resData;