changeset 1697:1036b0dcccb5

Refactor DMGrowBuf so that there can be buffers that grow "backwards". This also removes some support functions like the buffer state push/pop.
author Matti Hamalainen <ccr@tnsp.org>
date Tue, 05 Jun 2018 12:55:17 +0300
parents cf0fddd4bf52
children a51c2eaae9b8
files src/dmgrowbuf.c src/dmgrowbuf.h tools/lib64fmts.c tools/lib64gfx.c
diffstat 4 files changed, 170 insertions(+), 132 deletions(-) [+]
line wrap: on
line diff
--- a/src/dmgrowbuf.c	Tue Jun 05 11:36:55 2018 +0300
+++ b/src/dmgrowbuf.c	Tue Jun 05 12:55:17 2018 +0300
@@ -45,7 +45,7 @@
     buf->allocated = FALSE;
 
     // Allocate the data
-    if ((buf->adata = buf->data = dmMalloc0(initial)) == NULL)
+    if ((buf->data = dmMalloc0(initial)) == NULL)
         return DMERR_MALLOC;
 
     return DMERR_OK;
@@ -85,13 +85,11 @@
     if (buf != NULL)
     {
         DM_DBG(
-            "      buf->adata      = %p\n"
             "      buf->data       = %p\n"
             "      buf->allocated  = %s\n",
-            buf->adata, buf->data, buf->allocated ? "YES" : "NO"); 
+            buf->data, buf->allocated ? "YES" : "NO");
 
-        dmFreeR(&buf->adata);
-        buf->data = NULL;
+        dmFreeR(&buf->data);
 
         if (buf->allocated)
             dmFree(buf);
@@ -99,68 +97,38 @@
 }
 
 
-void dmGrowBufPush(DMGrowBuf *buf)
-{
-    if (buf != NULL && buf->adata != NULL)
-    {
-        DM_DBG("dmGrowBufPush(%p): size=%" DM_PRIu_SIZE_T "\n"
-            "    nstack=%d [offs=%" DM_PRIu_SIZE_T ", len=%" DM_PRIu_SIZE_T "]\n",
-            buf, buf->size, buf->nstack, buf->offs, buf->len);
-
-        buf->stack[buf->nstack].offs = buf->offs;
-        buf->stack[buf->nstack].len = buf->len;
-        buf->nstack++;
-
-        buf->offs = buf->len;
-        buf->data = buf->adata + buf->offs;
-        buf->len  = 0;
-
-        DM_DBG(
-            "    nstack=%d [offs=%" DM_PRIu_SIZE_T ", len=%" DM_PRIu_SIZE_T "]\n",
-            buf->nstack, buf->offs, buf->len);
-    }
-    else
-        DM_DBG("dmGrowBufPush(%p)\n", buf);
-}
-
-
-void dmGrowBufPop(DMGrowBuf *buf)
-{
-    if (buf != NULL && buf->adata != NULL && buf->nstack > 0)
-    {
-        DM_DBG("dmGrowBufPop(%p): size=%" DM_PRIu_SIZE_T "\n"
-            "    nstack=%d [offs=%" DM_PRIu_SIZE_T ", len=%" DM_PRIu_SIZE_T "]\n",
-            buf, buf->size, buf->nstack, buf->offs, buf->len);
-
-        buf->nstack--;
-        buf->offs  = buf->stack[buf->nstack].offs;
-        buf->len  += buf->stack[buf->nstack].len;
-
-        buf->data = buf->adata + buf->offs;
-
-        DM_DBG(
-            "    nstack=%d [offs=%" DM_PRIu_SIZE_T ", len=%" DM_PRIu_SIZE_T "]\n",
-            buf->nstack, buf->offs, buf->len);
-
-    }
-    else
-        DM_DBG("dmGrowBufPop(%p)\n", buf);
-}
-
-
 static BOOL dmGrowBufRealloc(DMGrowBuf *buf, const size_t nsize, const BOOL clear)
 {
-    DM_DBG("dmGrowBufRealloc(%p): size=%" DM_PRIu_SIZE_T "\n"
-        "    nstack=%d [offs=%" DM_PRIu_SIZE_T ", len=%" DM_PRIu_SIZE_T "]\n",
-        buf, buf->size, buf->nstack, buf->offs, buf->len);
+    DM_DBG("dmGrowBufRealloc(%p):\n"
+        "    size=%" DM_PRIu_SIZE_T ", nsize=" DM_PRIu_SIZE_T
+        ", nstack=%d, offs=%" DM_PRIu_SIZE_T "\n",
+        buf, buf->size, nsize, buf->nstack, buf->offs);
 
-    if ((buf->adata = dmRealloc(buf->adata, nsize)) == NULL)
+    // Can't be smaller than current size!
+    if (nsize < buf->size)
+        return FALSE;
+
+    if ((buf->data = dmRealloc(buf->data, nsize)) == NULL)
         return FALSE;
 
+    // For buffers growing backwards, we must move the
+    // current data to the end of the buffer ..
+    size_t clrsize = nsize - buf->size;
+    if (buf->backwards)
+    {
+        memmove(buf->data + clrsize, buf->data, clrsize);
+        buf->offs += clrsize;
+    }
+
+    // Check if we need to clear the newly allocated area?
     if (clear)
-        memset(buf->adata + buf->size, 0, nsize - buf->size);
+    {
+        if (buf->backwards)
+            memset(buf->data, 0, clrsize);
+        else
+            memset(buf->data + buf->size, 0, clrsize);
+    }
 
-    buf->data = buf->adata + buf->offs;
     buf->size = nsize;
 
     return TRUE;
@@ -174,13 +142,17 @@
 //
 BOOL dmGrowBufGrow(DMGrowBuf *buf, const size_t amount)
 {
-    if (buf->adata == NULL || buf->offs + buf->len + amount >= buf->size)
+    size_t grow = (amount > buf->mingrow) ? amount : buf->mingrow;
+
+    if (buf->data == NULL ||
+        (buf->backwards && amount >= buf->offs) ||
+        (!buf->backwards && buf->offs + amount >= buf->size))
     {
-        size_t grow = (amount > buf->mingrow) ? amount : buf->mingrow;
-        if (!dmGrowBufRealloc(buf, buf->offs + buf->len + grow, TRUE))
+        if (!dmGrowBufRealloc(buf, buf->size + grow, TRUE))
             return FALSE;
     }
 
+    buf->len += amount;
     return TRUE;
 }
 
@@ -191,12 +163,56 @@
 //
 BOOL dmGrowBufCheckGrow(DMGrowBuf *buf, const size_t nsize)
 {
-    if (buf->adata == NULL || buf->offs + nsize > buf->size)
+    if (buf->data == NULL || nsize > buf->size)
     {
-        if (!dmGrowBufRealloc(buf, buf->offs + nsize + buf->mingrow, TRUE))
+        if (!dmGrowBufRealloc(buf, nsize + buf->mingrow, TRUE))
             return FALSE;
     }
 
+    buf->len = nsize;
+    return TRUE;
+}
+
+
+static void dmGrowBufUpdate(DMGrowBuf *buf)
+{
+    if (buf->offs < buf->min_offs)
+        buf->min_offs = buf->offs;
+
+    if (buf->offs > buf->max_offs)
+        buf->max_offs = buf->offs;
+}
+
+
+BOOL dmGrowBufPut(DMGrowBuf *buf, const Uint8 *data, const size_t len)
+{
+    if (data == NULL)
+        return FALSE;
+
+    if (!dmGrowBufGrow(buf, len))
+        return FALSE;
+
+    if (buf->backwards)
+    {
+        if (buf->literal)
+        {
+            buf->offs -= len;
+            memcpy(buf->data + buf->offs, data, len);
+        }
+        else
+        {
+            for (size_t n = 0; n < len; n++)
+                buf->data[buf->offs--] = data[n];
+        }
+    }
+    else
+    {
+        memcpy(buf->data + buf->offs, data, len);
+        buf->offs += len;
+    }
+
+    dmGrowBufUpdate(buf);
+
     return TRUE;
 }
 
@@ -206,22 +222,13 @@
     if (!dmGrowBufGrow(buf, sizeof(Uint8)))
         return FALSE;
 
-    buf->data[buf->len++] = value;
-
-    return TRUE;
-}
-
+    buf->data[buf->offs] = value;
+    if (buf->backwards)
+        buf->offs--;
+    else
+        buf->offs++;
 
-BOOL dmGrowBufPut(DMGrowBuf *buf, const void *str, const size_t len)
-{
-    if (str == NULL)
-        return FALSE;
-
-    if (!dmGrowBufGrow(buf, len))
-        return FALSE;
-
-    memcpy(buf->data + buf->len, str, len);
-    buf->len += len;
+    dmGrowBufUpdate(buf);
 
     return TRUE;
 }
@@ -229,51 +236,75 @@
 
 BOOL dmGrowBufPutU16BE(DMGrowBuf *buf, const Uint16 val)
 {
-    if (!dmGrowBufGrow(buf, sizeof(Uint16)))
-        return FALSE;
-
-    buf->data[buf->len++] = (val >> 8) & 0xff;
-    buf->data[buf->len++] = val & 0xff;
-
-    return TRUE;
+    if (buf->literal && buf->backwards)
+    {
+        return
+            !dmGrowBufPutU8(buf, val & 0xff) ||
+            !dmGrowBufPutU8(buf, (val >> 8) & 0xff);
+    }
+    else
+    {
+        return
+            !dmGrowBufPutU8(buf, (val >> 8) & 0xff) ||
+            !dmGrowBufPutU8(buf, val & 0xff);
+    }
 }
 
 
 BOOL dmGrowBufPutU16LE(DMGrowBuf *buf, const Uint16 val)
 {
-    if (!dmGrowBufGrow(buf, sizeof(Uint16)))
-        return FALSE;
-
-    buf->data[buf->len++] = val & 0xff;
-    buf->data[buf->len++] = (val >> 8) & 0xff;
-
-    return TRUE;
+    if (buf->literal && buf->backwards)
+    {
+        return
+            !dmGrowBufPutU8(buf, (val >> 8) & 0xff) ||
+            !dmGrowBufPutU8(buf, val & 0xff);
+    }
+    else
+    {
+        return
+            !dmGrowBufPutU8(buf, val & 0xff) ||
+            !dmGrowBufPutU8(buf, (val >> 8) & 0xff);
+    }
 }
 
 
 BOOL dmGrowBufPutU32BE(DMGrowBuf *buf, const Uint32 val)
 {
-    if (!dmGrowBufGrow(buf, sizeof(Uint32)))
-        return FALSE;
-
-    buf->data[buf->len++] = (val >> 24) & 0xff;
-    buf->data[buf->len++] = (val >> 16) & 0xff;
-    buf->data[buf->len++] = (val >> 8) & 0xff;
-    buf->data[buf->len++] = val & 0xff;
-
-    return TRUE;
+    if (buf->literal && buf->backwards)
+    {
+        return
+            !dmGrowBufPutU8(buf, (val >> 24) & 0xff) ||
+            !dmGrowBufPutU8(buf, (val >> 16) & 0xff) ||
+            !dmGrowBufPutU8(buf, (val >> 8) & 0xff) ||
+            !dmGrowBufPutU8(buf, val & 0xff);
+    }
+    else
+    {
+        return
+            !dmGrowBufPutU8(buf, val & 0xff) ||
+            !dmGrowBufPutU8(buf, (val >> 8) & 0xff) ||
+            !dmGrowBufPutU8(buf, (val >> 16) & 0xff) ||
+            !dmGrowBufPutU8(buf, (val >> 24) & 0xff);
+    }
 }
 
 
 BOOL dmGrowBufPutU32LE(DMGrowBuf *buf, const Uint32 val)
 {
-    if (!dmGrowBufGrow(buf, sizeof(Uint32)))
-        return FALSE;
-
-    buf->data[buf->len++] = val & 0xff;
-    buf->data[buf->len++] = (val >> 8) & 0xff;
-    buf->data[buf->len++] = (val >> 16) & 0xff;
-    buf->data[buf->len++] = (val >> 24) & 0xff;
-
-    return TRUE;
+    if (buf->literal && buf->backwards)
+    {
+        return
+            !dmGrowBufPutU8(buf, val & 0xff) ||
+            !dmGrowBufPutU8(buf, (val >> 8) & 0xff) ||
+            !dmGrowBufPutU8(buf, (val >> 16) & 0xff) ||
+            !dmGrowBufPutU8(buf, (val >> 24) & 0xff);
+    }
+    else
+    {
+        return
+            !dmGrowBufPutU8(buf, (val >> 24) & 0xff) ||
+            !dmGrowBufPutU8(buf, (val >> 16) & 0xff) ||
+            !dmGrowBufPutU8(buf, (val >> 8) & 0xff) ||
+            !dmGrowBufPutU8(buf, val & 0xff);
+    }
 }
--- a/src/dmgrowbuf.h	Tue Jun 05 11:36:55 2018 +0300
+++ b/src/dmgrowbuf.h	Tue Jun 05 12:55:17 2018 +0300
@@ -16,12 +16,21 @@
 
 typedef struct
 {
-    Uint8 *data, *adata;
-    size_t len, size, mingrow, offs;
-    BOOL allocated;
+    Uint8
+        *data;      // Actually allocated data pointer
 
-    int nstack;
-    struct { size_t offs, len; } stack[32];
+    size_t
+        offs,       // Current offset
+        min_offs,
+        max_offs,
+        size,       // Actual allocated size
+        len,        // Size requested
+        mingrow;    // Minimum amount of bytes the allocation size grows by
+
+    BOOL
+        allocated,  // TRUE if this structure itself has been allocated and can be freed, FALSE if static
+        backwards,  // TRUE if the buffer grows backwards (e.g. "offs" moves backwards)
+        literal;    // TRUE if dmGrowBufPut*() functions stores data "literally" in backwards mode
 } DMGrowBuf;
 
 
@@ -30,15 +39,11 @@
 int    dmGrowBufNew(DMGrowBuf **pbuf, const size_t initial, const size_t mingrow);
 void   dmGrowBufFree(DMGrowBuf *buf);
 
-void   dmGrowBufPush(DMGrowBuf *buf);
-void   dmGrowBufPop(DMGrowBuf *buf);
-
 BOOL   dmGrowBufGrow(DMGrowBuf *buf, const size_t amount);
 BOOL   dmGrowBufCheckGrow(DMGrowBuf *buf, const size_t nsize);
 
+BOOL   dmGrowBufPut(DMGrowBuf *buf, const Uint8 *data, const size_t len);
 BOOL   dmGrowBufPutU8(DMGrowBuf *buf, const Uint8 value);
-BOOL   dmGrowBufPut(DMGrowBuf *buf, const void *str, const size_t len);
-
 BOOL   dmGrowBufPutU16BE(DMGrowBuf *buf, const Uint16 val);
 BOOL   dmGrowBufPutU16LE(DMGrowBuf *buf, const Uint16 val);
 BOOL   dmGrowBufPutU32BE(DMGrowBuf *buf, const Uint32 val);
--- a/tools/lib64fmts.c	Tue Jun 05 11:36:55 2018 +0300
+++ b/tools/lib64fmts.c	Tue Jun 05 12:55:17 2018 +0300
@@ -146,7 +146,7 @@
     dmGenericRLEAnalyze(tmp.data, tmp.len, &cfg);
 
     // Add the header bits
-    if (!dmGrowBufPut(buf, magicID, strlen(magicID)) ||
+    if (!dmGrowBufPut(buf, (Uint8 *) magicID, strlen(magicID)) ||
         !dmGrowBufPutU8(buf, cfg.rleMarkerB))
     {
         res = DMERR_MALLOC;
@@ -248,7 +248,7 @@
     dmGenericRLEAnalyze(tmp.data, tmp.len, &cfg);
 
     // Add the header bits
-    if (!dmGrowBufPut(buf, fmtBDP5MagicID, strlen(fmtBDP5MagicID)) ||
+    if (!dmGrowBufPut(buf, (Uint8 *) fmtBDP5MagicID, strlen(fmtBDP5MagicID)) ||
         !dmGrowBufPutU8(buf, cfg.rleMarkerB) ||
         !dmGrowBufPutU8(buf, cfg.rleMarkerW))
     {
@@ -612,7 +612,7 @@
 static int fmtEncodeFunPaint2Unpacked(DMGrowBuf *buf, const DMC64Image *img, const DMC64ImageFormat *fmt)
 {
     // Add the header bits
-    if (!dmGrowBufPut(buf, fmtFunPaint2MagicID, strlen(fmtFunPaint2MagicID)) ||
+    if (!dmGrowBufPut(buf, (Uint8 *) fmtFunPaint2MagicID, strlen(fmtFunPaint2MagicID)) ||
         !dmGrowBufPutU8(buf, 0))
         return DMERR_MALLOC;
 
@@ -639,7 +639,7 @@
     dmGenericRLEAnalyze(tmp.data, tmp.len, &cfg);
 
     // Add the header bits
-    if (!dmGrowBufPut(buf, fmtFunPaint2MagicID, strlen(fmtFunPaint2MagicID)) ||
+    if (!dmGrowBufPut(buf, (Uint8 *) fmtFunPaint2MagicID, strlen(fmtFunPaint2MagicID)) ||
         !dmGrowBufPutU8(buf, cfg.rleMarkerB))
     {
         res = DMERR_MALLOC;
--- a/tools/lib64gfx.c	Tue Jun 05 11:36:55 2018 +0300
+++ b/tools/lib64gfx.c	Tue Jun 05 12:55:17 2018 +0300
@@ -905,7 +905,12 @@
         goto err;
     }
 
-    dmGrowBufPush(buf);
+    if (buf->backwards)
+    {
+        dmError(DMERR_INVALID_DATA,
+            "Buffer specified for dmC64EncodeGenericBMP() is in backwards mode, which is not supported.\n");
+        goto err;
+    }
 
     // Perform encoding
     for (int i = 0; i < D64_MAX_ENCDEC_OPS; i++)
@@ -935,7 +940,7 @@
         }
 
         // Do we need to reallocate some more space?
-        chksize = op->offs + size;
+        chksize = buf->offs + op->offs + size;
         if (!dmGrowBufCheckGrow(buf, chksize))
         {
             res = dmError(DMERR_MALLOC,
@@ -948,8 +953,7 @@
             buf->len = chksize;
 
         // Perform operation
-        Uint8 *dst;
-        dst = buf->data + op->offs;
+        Uint8 *dst = buf->data + buf->offs + op->offs;
         switch (op->type)
         {
             case DO_COPY:
@@ -1060,8 +1064,6 @@
         }
     }
 
-    dmGrowBufPop(buf);
-
     res = DMERR_OK;
 
 err: