Mercurial > hg > th-libs
view th_ioctx_mem.c @ 708:a34715d51ea4
Add support for deallocator function in th_cfg_free() for freeing the values.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Mon, 27 Apr 2020 00:44:15 +0300 |
parents | 0fc5ddaccc57 |
children | e73200c4584a |
line wrap: on
line source
/* * Simple I/O abstraction and context handling layer * Programmed and designed by Matti 'ccr' Hamalainen * (C) Copyright 2012-2020 Tecnic Software productions (TNSP) * * Please read file 'COPYING' for information on license and distribution. */ #include "th_ioctx.h" static int th_mem_fopen(th_ioctx *ctx) { if (ctx->mode == NULL) return THERR_NULLPTR; // Setup some things based on the mode string switch (ctx->mode[0]) { case 'a': // Append ctx->memWrite = TRUE; ctx->memOffset = ctx->memSize; break; case 'r': // Read or read-write ctx->memWrite = ctx->mode[1] == '+'; ctx->memOffset = 0; break; case 'w': // Write, so truncate size ctx->memOffset = 0; ctx->memSize = 0; ctx->memWrite = TRUE; break; default: return THERR_INVALID_ARGS; } return THERR_OK; } static void th_mem_fclose(th_ioctx *ctx) { if (ctx->memFree) th_free_r(&ctx->memData); } static BOOL th_mem_realloc(th_ioctx *ctx, const size_t newSize) { size_t grow; // Check write flag if (!ctx->memWrite) { ctx->status = THERR_FWRITE; return FALSE; } // Check against max size if (ctx->maxSize > 0 && newSize > ctx->maxSize) { ctx->status = THERR_BOUNDS; return FALSE; } // New size is smaller than old if (newSize < ctx->memAlloc) goto out; // Compute the allocation grow amount 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->status = THERR_BOUNDS; return FALSE; } // Grow the buffer ctx->memAlloc += grow; if ((ctx->memData = th_realloc(ctx->memData, ctx->memAlloc)) == NULL) { ctx->status = THERR_MALLOC; return FALSE; } out: ctx->memSize = newSize; return TRUE; } static int th_mem_freset(th_ioctx *ctx) { ctx->memOffset = 0; return THERR_OK; } static int th_mem_ferror(th_ioctx *ctx) { return ctx->status; } static int th_mem_fseek(th_ioctx *ctx, const off_t offset, const int whence) { off_t newPos; // Calculate the new position switch (whence) { case SEEK_SET: newPos = offset; break; case SEEK_CUR: newPos = ctx->memOffset + offset; break; case SEEK_END: newPos = ctx->memSize + offset; break; default: return -1; } // Set the new position ctx->memOffset = newPos; // Check the new position if (newPos < 0) return -1; //if (!th_mem_realloc(ctx, newPos)) // return -1; return 0; } static off_t th_mem_fsize(th_ioctx *ctx) { return ctx->memSize; } static off_t th_mem_ftell(th_ioctx *ctx) { return ctx->memOffset; } static BOOL th_mem_feof(th_ioctx *ctx) { return ((size_t) ctx->memOffset) >= ctx->memSize; } static int th_mem_fgetc(th_ioctx *ctx) { // Check for EOF if ((size_t) ctx->memOffset < ctx->memSize) return ctx->memData[ctx->memOffset++]; else return EOF; } static size_t th_mem_fread(void *buf, size_t size, size_t nmemb, th_ioctx *ctx) { size_t length = size * nmemb; // Check if we can read the whole chunk if (((size_t) ctx->memOffset + length) >= ctx->memSize) { nmemb = (ctx->memSize - ctx->memOffset) / size; length = size * nmemb; } memcpy(buf, ctx->memData + ctx->memOffset, length); ctx->memOffset += length; return nmemb; } static int th_mem_fputc(int ch, th_ioctx *ctx) { // Check for EOF if (!th_mem_realloc(ctx, ctx->memOffset + 1)) return EOF; ctx->memData[ctx->memOffset++] = ch; return ch; } static size_t th_mem_fwrite(const void *buf, size_t size, size_t nmemb, th_ioctx *ctx) { size_t length = size * nmemb; // Check if we can write the whole chunk if (!th_mem_realloc(ctx, ctx->memOffset + length)) { nmemb = (ctx->memSize - ctx->memOffset) / size; length = size * nmemb; } if (length > 0) { memcpy(ctx->memData + ctx->memOffset, buf, length); ctx->memOffset += length; } return nmemb; } const th_ioctx_ops th_mem_io_ops = { "MemIO", th_mem_fopen, th_mem_fclose, th_mem_freset, th_mem_ferror, th_mem_fseek, th_mem_fsize, th_mem_ftell, th_mem_feof, th_mem_fgetc, th_mem_fputc, th_mem_fread, th_mem_fwrite, NULL, NULL, NULL };