# HG changeset patch # User Matti Hamalainen # Date 1582604108 -7200 # Node ID fb4093ad1f7bdb6edf9ec542efe81cb5cfbc4965 # Parent dfabc7eef3dd134d26ccc79b990bb3cb33031c01 Add MemIO ioctx functionality. diff -r dfabc7eef3dd -r fb4093ad1f7b th_ioctx.c --- a/th_ioctx.c Tue Feb 25 05:16:42 2020 +0200 +++ b/th_ioctx.c Tue Feb 25 06:15:08 2020 +0200 @@ -274,9 +274,9 @@ return ctx->fops->fputs(ptr, ctx); const char *p = ptr; - int retv = 0; - while (*p && (retv = ctx->fops->fputc(*p, ctx)) != EOF) p++; - return retv; + int rval = 0; + while (*p && (rval = ctx->fops->fputc(*p, ctx)) != EOF) p++; + return rval; } @@ -296,12 +296,12 @@ int thfprintf(th_ioctx *ctx, const char *fmt, ...) { - int retv; + int rval; va_list ap; va_start(ap, fmt); - retv = thvfprintf(ctx, fmt, ap); + rval = thvfprintf(ctx, fmt, ap); va_end(ap); - return retv; + return rval; } @@ -526,3 +526,189 @@ th_stdio_fputs, th_stdio_vfprintf, }; + + +static BOOL th_mem_realloc(th_ioctx *ctx, const size_t newSize) +{ + size_t grow; + + if (ctx->maxSize > 0 && newSize > ctx->maxSize) + { + ctx->status = THERR_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->status = THERR_BOUNDS; + return FALSE; + } + + ctx->memAlloc += grow; + if ((ctx->memData = th_realloc(ctx->memData, ctx->memAlloc)) == NULL) + { + ctx->status = THERR_MALLOC; + return FALSE; + } + + 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", + + NULL, + NULL, + + 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 +}; diff -r dfabc7eef3dd -r fb4093ad1f7b th_ioctx.h --- a/th_ioctx.h Tue Feb 25 05:16:42 2020 +0200 +++ b/th_ioctx.h Tue Feb 25 06:15:08 2020 +0200 @@ -42,6 +42,15 @@ int status; ///< Status size_t line; ///< Line number + // Mem 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_t *memData; ///< Pointer to data + + // Message functions void (*error)(struct th_ioctx *ctx, const int err, const char *msg); void (*msg)(struct th_ioctx *ctx, const int level, const char *msg); @@ -77,7 +86,7 @@ // // Some basic iops // -extern const th_ioctx_ops th_stdio_io_ops; +extern const th_ioctx_ops th_stdio_io_ops, th_mem_io_ops;