diff src/dmgrowbuf.c @ 1454:fff3b58d031c

Add a growable buffer implementation.
author Matti Hamalainen <ccr@tnsp.org>
date Thu, 10 May 2018 18:33:57 +0300
parents
children a957b318fbe2
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/dmgrowbuf.c	Thu May 10 18:33:57 2018 +0300
@@ -0,0 +1,160 @@
+/*
+ * DMLib
+ * -- Growable buffer implementation
+ * Programmed and designed by Matti 'ccr' Hamalainen
+ * (C) Copyright 2018 Tecnic Software productions (TNSP)
+ */
+#include "dmgrowbuf.h"
+
+
+int dmGrowBufInit(DMGrowBuf *buf, const size_t initial, const size_t mingrow)
+{
+    if (buf == NULL)
+        return DMERR_NULLPTR;
+
+    buf->len  = 0;
+    buf->size = initial;
+    buf->mingrow = mingrow;
+    buf->allocated = FALSE;
+
+    if ((buf->data = dmMalloc(initial)) == NULL)
+        return DMERR_MALLOC;
+
+    return DMERR_OK;
+}
+
+
+int dmGrowBufAlloc(DMGrowBuf **pbuf, const size_t initial, const size_t mingrow)
+{
+    int res;
+
+    if ((*pbuf = dmMalloc0(sizeof(DMGrowBuf))) == NULL)
+        return DMERR_MALLOC;
+
+    if ((res = dmGrowBufInit(*pbuf, initial, mingrow)) != DMERR_OK)
+    {
+        dmGrowBufFree(*pbuf);
+        return res;
+    }
+
+    (*pbuf)->allocated = TRUE;
+    return res;
+}
+
+
+void dmGrowBufFree(DMGrowBuf *buf)
+{
+    if (buf != NULL)
+    {
+        dmFreeR(&buf->data);
+        if (buf->allocated)
+            dmFree(buf);
+    }
+}
+
+
+BOOL dmGrowBufGrow(DMGrowBuf *buf, const size_t amount)
+{
+    if (buf->data == NULL || buf->len + amount > buf->size)
+    {
+        buf->size += amount + (buf->mingrow > 0 ? buf->mingrow : 1024);
+        if ((buf->data = dmRealloc(buf->data, buf->size)) == NULL)
+            return FALSE;
+    }
+
+    return TRUE;
+}
+
+
+int dmGrowBufResize(DMGrowBuf *buf)
+{
+    if (buf == NULL)
+        return DMERR_NULLPTR;
+
+    buf->size = buf->len;
+    if (buf->len == 0)
+        return DMERR_OK;
+
+    if ((buf->data = dmRealloc(buf->data, buf->len)) == NULL)
+        return DMERR_MALLOC;
+
+    return DMERR_OK;
+}
+
+
+BOOL dmGrowBufPutU8(DMGrowBuf *buf, const Uint8 value)
+{
+    if (!dmGrowBufGrow(buf, sizeof(Uint8)))
+        return FALSE;
+
+    buf->data[buf->len++] = value;
+
+    return TRUE;
+}
+
+
+BOOL dmGrowBufPutStr(DMGrowBuf *buf, const void *str, const size_t len)
+{
+    if (str == NULL)
+        return FALSE;
+
+    if (!dmGrowBufGrow(buf, len + 1))
+        return FALSE;
+
+    memcpy(buf->data + buf->len, str, len + 1);
+    buf->len += len;
+
+    return TRUE;
+}
+
+
+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;
+}
+
+
+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;
+}
+
+
+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;
+}
+
+
+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;
+}