Mercurial > hg > dmlib
view src/dmgrowbuf.c @ 2343:94a653883a32
Change Uint8 pointer in getPixel functions to DMC64ScanLine pointer in
preparation for future changes related to sprites on scanlines.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Wed, 25 Sep 2019 12:11:35 +0300 |
parents | b5abfff07ca9 |
children | c801995cbb13 |
line wrap: on
line source
/* * DMLib * -- Growable buffer implementation * Programmed and designed by Matti 'ccr' Hamalainen * (C) Copyright 2018-2019 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; dmMemset(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->backwards = FALSE; buf->is_const = FALSE; // Allocate the data if ((buf->data = dmMalloc0(initial)) == NULL) return DMERR_MALLOC; return DMERR_OK; } void dmGrowBufFree(DMGrowBuf *buf) { DM_DBG("dmGrowBufFree(%p)\n", buf); if (buf != NULL) { DM_DBG( " buf->data = %p\n" " buf->is_const = %s\n", buf->data, buf->is_const ? "YES" : "NO"); if (buf->is_const) return; dmFree(buf->data); dmMemset(buf, 0, sizeof(DMGrowBuf)); } } DMGrowBuf * dmGrowBufCopy(DMGrowBuf *dst, const DMGrowBuf *src, const size_t enlarge) { if (dst == NULL) return NULL; DM_DBG("dmGrowBufCopy(dst=%p, src=%p, enlarge=%" DM_PRIu_SIZE_T "):\n" " data=%p, size=%" DM_PRIu_SIZE_T ", len=%" DM_PRIu_SIZE_T ", offs=%" DM_PRIu_SIZE_T "\n", dst, src, enlarge, src->data, src->size, src->len, src->offs); // Copy the struct here memcpy(dst, src, sizeof(DMGrowBuf)); dst->size += enlarge; // Allocate new memory for the data if ((dst->data = dmMalloc(dst->size)) == NULL) { // If that fails, clear the struct dmMemset(dst, 0, sizeof(DMGrowBuf)); return NULL; } // Copy data memcpy(dst->data, src->data, src->size); if (enlarge > 0) dmMemset(dst->data + src->size, 0, enlarge); // And reset some struct information dst->is_const = FALSE; return dst; } 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 * dmGrowBufConstCreateFrom(DMGrowBuf *dst, Uint8 *data, const size_t len) { if (dmGrowBufInit(dst) != DMERR_OK) return NULL; DM_DBG("dmGrowBufConstCreateFrom(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; } DMGrowBuf * dmGrowBufConstCopyOffs(DMGrowBuf *dst, const DMGrowBuf *src, const size_t offs) { return dmGrowBufConstCreateFrom(dst, src->data + offs, src->len - offs); } DMGrowBuf * dmGrowBufConstCopyOffsSize(DMGrowBuf *dst, const DMGrowBuf *src, const size_t offs, const size_t len) { if (src->len < offs + len) return NULL; return dmGrowBufConstCreateFrom(dst, src->data + offs, len); } DMGrowBuf * dmGrowBufCopyOffs(DMGrowBuf *dst, const DMGrowBuf *src, const size_t offs, const size_t enlarge) { DMGrowBuf tmp; return dmGrowBufCopy(dst, dmGrowBufConstCreateFrom(&tmp, src->data + offs, src->len - offs), enlarge); } DMGrowBuf * dmGrowBufCopyOffsSize(DMGrowBuf *dst, const DMGrowBuf *src, const size_t offs, const size_t len, const size_t enlarge) { DMGrowBuf tmp; if (src->len < offs + len) return NULL; return dmGrowBufCopy(dst, dmGrowBufConstCreateFrom(&tmp, src->data + offs, len), enlarge); } 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; DM_DBG(" clrsize=%" DM_PRIu_SIZE_T "\n", clrsize); if (buf->backwards) { memmove(buf->data + clrsize, buf->data, buf->size); buf->offs += clrsize; } // Check if we need to clear the newly allocated area? if (clear) { if (buf->backwards) dmMemset(buf->data, 0, clrsize); else dmMemset(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)) { DM_DBG("dmGrowBufGrow(%p, amount=%" DM_PRIu_SIZE_T "): grow=%" DM_PRIu_SIZE_T "\n", buf, amount, grow); 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; } if (nsize > buf->len) buf->len = nsize; return TRUE; } 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) { for (size_t n = 0; n < len; n++) buf->data[--buf->offs] = data[len - n]; } 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; } return TRUE; } BOOL dmGrowBufPutU8(DMGrowBuf *buf, const Uint8 value) { if (!dmGrowBufGrow(buf, sizeof(Uint8))) return FALSE; if (buf->backwards) buf->data[--buf->offs] = value; else buf->data[buf->offs++] = value; 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) { if (buf->offs > 0) *value = buf->data[--buf->offs]; else return FALSE; } else { if (buf->offs < buf->len) *value = buf->data[buf->offs++]; else return FALSE; } return TRUE; }