changeset 675:fb4093ad1f7b

Add MemIO ioctx functionality.
author Matti Hamalainen <ccr@tnsp.org>
date Tue, 25 Feb 2020 06:15:08 +0200
parents dfabc7eef3dd
children f3649df3d9a7
files th_ioctx.c th_ioctx.h
diffstat 2 files changed, 202 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- 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
+};
--- 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;