# HG changeset patch # User Matti Hamalainen # Date 1582608400 -7200 # Node ID f7d54ac5188062f8da4593850084c91f4f460b14 # Parent b7f622d39efc730bc0b5d083a722b3319740b864 Fix and improvements to dmres MemIO subsystem. diff -r b7f622d39efc -r f7d54ac51880 src/dmengine.c --- 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; diff -r b7f622d39efc -r f7d54ac51880 src/dmres.c --- 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); } diff -r b7f622d39efc -r f7d54ac51880 src/dmres.h --- 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;