Mercurial > hg > dmlib
view src/dmgrowbuf.c @ 1702:94329f678841
Explicitly initialize some DMGrowBuf fields for clarity, though they are already cleared previously by memset().
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Tue, 05 Jun 2018 18:27:16 +0300 |
parents | 31a1f710e342 |
children | fcc568e03bed |
line wrap: on
line source
/* * DMLib * -- Growable buffer implementation * Programmed and designed by Matti 'ccr' Hamalainen * (C) Copyright 2018 Tecnic Software productions (TNSP) */ #include "dmgrowbuf.h" //#define DM_GROWBUF_DEBUG 1 #ifdef DM_GROWBUF_DEBUG # define DM_DBG(...) do { fprintf(stderr, __VA_ARGS__); } while (0) #else # define DM_DBG(...) do { } while (0) #endif int dmGrowBufInit(DMGrowBuf *buf) { DM_DBG("dmGrowBufInit(%p)\n", buf); if (buf == NULL) return DMERR_NULLPTR; memset(buf, 0, sizeof(DMGrowBuf)); return DMERR_OK; } int dmGrowBufAlloc(DMGrowBuf *buf, const size_t initial, const size_t mingrow) { int res; DM_DBG("dmGrowBufAlloc(%p, %" DM_PRIu_SIZE_T ", %" DM_PRIu_SIZE_T ")\n", buf, initial, mingrow); if ((res = dmGrowBufInit(buf)) != DMERR_OK) return res; buf->len = 0; buf->offs = 0; buf->size = initial; buf->mingrow = mingrow; buf->allocated = FALSE; buf->backwards = FALSE; buf->is_const = FALSE; // Allocate the data if ((buf->data = dmMalloc0(initial)) == NULL) return DMERR_MALLOC; return DMERR_OK; } int dmGrowBufNew(DMGrowBuf **pbuf, const size_t initial, const size_t mingrow) { int res; if (pbuf == NULL) return DMERR_NULLPTR; DM_DBG("dmGrowBufNew(%p, %" DM_PRIu_SIZE_T ", %" DM_PRIu_SIZE_T ")\n", pbuf, initial, mingrow); if ((*pbuf = dmMalloc0(sizeof(DMGrowBuf))) == NULL) return DMERR_MALLOC; if ((res = dmGrowBufAlloc(*pbuf, initial, mingrow)) != DMERR_OK) { // The "allocated" flag has not yet been set dmGrowBufFree(*pbuf); // .. thus free the allocated struct here dmFreeR(pbuf); return res; } (*pbuf)->allocated = TRUE; return res; } void dmGrowBufFree(DMGrowBuf *buf) { DM_DBG("dmGrowBufFree(%p)\n", buf); if (buf != NULL) { DM_DBG( " buf->data = %p\n" " buf->allocated = %s\n" " buf->is_const = %s\n", buf->data, buf->allocated ? "YES" : "NO", buf->is_const ? "YES" : "NO"); if (buf->is_const) return; dmFreeR(&buf->data); if (buf->allocated) dmFree(buf); } } DMGrowBuf * dmGrowBufConstCopy(DMGrowBuf *dst, const DMGrowBuf *src) { if (dst == NULL) return NULL; DM_DBG("dmGrowBufConstCopy(dst=%p, src=%p):\n" " data=%p, size=%" DM_PRIu_SIZE_T ", len=%" DM_PRIu_SIZE_T ", offs=%" DM_PRIu_SIZE_T "\n", dst, src, src->data, src->size, src->len, src->offs); memcpy(dst, src, sizeof(DMGrowBuf)); dst->is_const = TRUE; return dst; } DMGrowBuf * dmGrowBufCreateFrom(DMGrowBuf *dst, Uint8 *data, size_t len) { if (dmGrowBufInit(dst) != DMERR_OK) return NULL; DM_DBG("dmGrowBufCreateFrom(dst=%p, data=%p, len=%" DM_PRIu_SIZE_T ")\n", dst, data, len); dst->data = data; dst->len = dst->size = len; dst->is_const = TRUE; return dst; } static BOOL dmGrowBufRealloc(DMGrowBuf *buf, const size_t nsize, const BOOL clear) { DM_DBG("dmGrowBufRealloc(%p):\n" " size=%" DM_PRIu_SIZE_T ", nsize=%" DM_PRIu_SIZE_T ", offs=%" DM_PRIu_SIZE_T "\n", buf, buf->size, nsize, buf->offs); if (buf->is_const) return FALSE; // 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) { if (buf->backwards) memset(buf->data, 0, clrsize); else memset(buf->data + buf->size, 0, clrsize); } buf->size = nsize; return TRUE; } // // Grow the buffer by "amount" bytes, but at least by buf->mingrow, // if there is not enough space for at least that amount compared to // current buffer "len". // BOOL dmGrowBufGrow(DMGrowBuf *buf, const size_t amount) { size_t grow = (amount > buf->mingrow) ? amount : buf->mingrow; if (buf->is_const) return FALSE; if (buf->data == NULL || (buf->backwards && amount >= buf->offs) || (!buf->backwards && buf->offs + amount >= buf->size)) { if (!dmGrowBufRealloc(buf, buf->size + grow, TRUE)) return FALSE; } buf->len += amount; return TRUE; } // // Grow the buffer if "nsize" is larger than the current buffer size. // Buffer is enlarged to nsize + mingrow. // BOOL dmGrowBufCheckGrow(DMGrowBuf *buf, const size_t nsize) { if (buf->is_const) return FALSE; if (buf->data == NULL || nsize > buf->size) { 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; } BOOL dmGrowBufPutU8(DMGrowBuf *buf, const Uint8 value) { if (!dmGrowBufGrow(buf, sizeof(Uint8))) return FALSE; buf->data[buf->offs] = value; if (buf->backwards) buf->offs--; else buf->offs++; dmGrowBufUpdate(buf); return TRUE; } BOOL dmGrowBufPutU16BE(DMGrowBuf *buf, const Uint16 val) { 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 (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 (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 (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); } } BOOL dmGrowBufGetU8(DMGrowBuf *buf, Uint8 *value) { if (buf->backwards && buf->offs > 0) { *value = buf->data[buf->offs]; buf->offs--; return TRUE; } else if (!buf->backwards && buf->offs < buf->len) { *value = buf->data[buf->offs]; buf->offs++; return TRUE; } return FALSE; }