summaryrefslogtreecommitdiff
path: root/ext/gd/libgd/gd_io_dp.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/gd/libgd/gd_io_dp.c')
-rw-r--r--ext/gd/libgd/gd_io_dp.c360
1 files changed, 360 insertions, 0 deletions
diff --git a/ext/gd/libgd/gd_io_dp.c b/ext/gd/libgd/gd_io_dp.c
new file mode 100644
index 0000000..bfeb4cb
--- /dev/null
+++ b/ext/gd/libgd/gd_io_dp.c
@@ -0,0 +1,360 @@
+/*
+ * io_dp.c
+ *
+ * Implements the dynamic pointer interface.
+ *
+ * Based on GD.pm code by Lincoln Stein for interfacing to libgd.
+ * Added support for reading as well as support for 'tell' and 'seek'.
+ *
+ * As will all I/O modules, most functions are for local use only (called
+ * via function pointers in the I/O context).
+ *
+ * gdDPExtractData is the exception to this: it will return the pointer to
+ * the internal data, and reset the internal storage.
+ *
+ * Written/Modified 1999, Philip Warner.
+ *
+ */
+
+#include <math.h>
+#include <string.h>
+#include <stdlib.h>
+#include "gd.h"
+#include "gdhelpers.h"
+
+#define TRUE 1
+#define FALSE 0
+
+/* this is used for creating images in main memory */
+typedef struct dpStruct
+{
+ void *data;
+ int logicalSize;
+ int realSize;
+ int dataGood;
+ int pos;
+ int freeOK;
+} dynamicPtr;
+
+typedef struct dpIOCtx
+{
+ gdIOCtx ctx;
+ dynamicPtr *dp;
+} dpIOCtx;
+
+typedef struct dpIOCtx *dpIOCtxPtr;
+
+/* these functions operate on in-memory dynamic pointers */
+static int allocDynamic (dynamicPtr * dp, int initialSize, void *data);
+static int appendDynamic (dynamicPtr * dp, const void *src, int size);
+static int gdReallocDynamic (dynamicPtr * dp, int required);
+static int trimDynamic (dynamicPtr * dp);
+static void gdFreeDynamicCtx (struct gdIOCtx *ctx);
+static dynamicPtr *newDynamic (int initialSize, void *data, int freeOKFlag);
+
+static int dynamicPutbuf (struct gdIOCtx *, const void *, int);
+static void dynamicPutchar (struct gdIOCtx *, int a);
+
+static int dynamicGetbuf (gdIOCtxPtr ctx, void *buf, int len);
+static int dynamicGetchar (gdIOCtxPtr ctx);
+
+static int dynamicSeek (struct gdIOCtx *, const int);
+static long dynamicTell (struct gdIOCtx *);
+
+/* return data as a dynamic pointer */
+gdIOCtx * gdNewDynamicCtx (int initialSize, void *data)
+{
+ return gdNewDynamicCtxEx(initialSize, data, 1);
+}
+
+gdIOCtx * gdNewDynamicCtxEx (int initialSize, void *data, int freeOKFlag)
+{
+ dpIOCtx *ctx;
+ dynamicPtr *dp;
+
+ ctx = (dpIOCtx *) gdMalloc (sizeof (dpIOCtx));
+
+ dp = newDynamic(initialSize, data, freeOKFlag);
+
+ ctx->dp = dp;
+
+ ctx->ctx.getC = dynamicGetchar;
+ ctx->ctx.putC = dynamicPutchar;
+
+ ctx->ctx.getBuf = dynamicGetbuf;
+ ctx->ctx.putBuf = dynamicPutbuf;
+
+ ctx->ctx.seek = dynamicSeek;
+ ctx->ctx.tell = dynamicTell;
+
+ ctx->ctx.gd_free = gdFreeDynamicCtx;
+
+ return (gdIOCtx *) ctx;
+}
+
+void * gdDPExtractData (struct gdIOCtx *ctx, int *size)
+{
+ dynamicPtr *dp;
+ dpIOCtx *dctx;
+ void *data;
+
+ dctx = (dpIOCtx *) ctx;
+ dp = dctx->dp;
+
+ /* clean up the data block and return it */
+ if (dp->dataGood) {
+ trimDynamic (dp);
+ *size = dp->logicalSize;
+ data = dp->data;
+ } else {
+ *size = 0;
+ data = NULL;
+ if (dp->data != NULL && dp->freeOK) {
+ gdFree(dp->data);
+ }
+ }
+
+ dp->data = NULL;
+ dp->realSize = 0;
+ dp->logicalSize = 0;
+
+ return data;
+}
+
+static void gdFreeDynamicCtx (struct gdIOCtx *ctx)
+{
+ dynamicPtr *dp;
+ dpIOCtx *dctx;
+
+ dctx = (dpIOCtx *) ctx;
+ dp = dctx->dp;
+
+ gdFree(ctx);
+
+ dp->realSize = 0;
+ dp->logicalSize = 0;
+
+ gdFree(dp);
+}
+
+static long dynamicTell (struct gdIOCtx *ctx)
+{
+ dpIOCtx *dctx;
+
+ dctx = (dpIOCtx *) ctx;
+
+ return (dctx->dp->pos);
+}
+
+static int dynamicSeek (struct gdIOCtx *ctx, const int pos)
+{
+ int bytesNeeded;
+ dynamicPtr *dp;
+ dpIOCtx *dctx;
+
+ dctx = (dpIOCtx *) ctx;
+ dp = dctx->dp;
+
+ if (!dp->dataGood) {
+ return FALSE;
+ }
+
+ bytesNeeded = pos;
+ if (bytesNeeded > dp->realSize) {
+ /* 2.0.21 */
+ if (!dp->freeOK) {
+ return FALSE;
+ }
+ gdReallocDynamic (dp, dp->realSize * 2);
+ }
+
+ /* if we get here, we can be sure that we have enough bytes to copy safely */
+
+ /* Extend the logical size if we seek beyond EOF. */
+ if (pos > dp->logicalSize) {
+ dp->logicalSize = pos;
+ }
+
+ dp->pos = pos;
+
+ return TRUE;
+}
+
+/* return data as a dynamic pointer */
+static dynamicPtr * newDynamic (int initialSize, void *data, int freeOKFlag)
+{
+ dynamicPtr *dp;
+ dp = (dynamicPtr *) gdMalloc (sizeof (dynamicPtr));
+
+ allocDynamic (dp, initialSize, data);
+
+ dp->pos = 0;
+ dp->freeOK = freeOKFlag;
+
+ return dp;
+}
+
+static int
+dynamicPutbuf (struct gdIOCtx *ctx, const void *buf, int size)
+{
+ dpIOCtx *dctx;
+ dctx = (dpIOCtx *) ctx;
+
+ appendDynamic (dctx->dp, buf, size);
+
+ if (dctx->dp->dataGood)
+ {
+ return size;
+ }
+ else
+ {
+ return -1;
+ };
+
+}
+
+static void dynamicPutchar (struct gdIOCtx *ctx, int a)
+{
+ unsigned char b;
+ dpIOCtxPtr dctx;
+
+ b = a;
+ dctx = (dpIOCtxPtr) ctx;
+
+ appendDynamic(dctx->dp, &b, 1);
+}
+
+static int dynamicGetbuf (gdIOCtxPtr ctx, void *buf, int len)
+{
+ int rlen, remain;
+ dpIOCtxPtr dctx;
+ dynamicPtr *dp;
+
+ dctx = (dpIOCtxPtr) ctx;
+ dp = dctx->dp;
+
+ remain = dp->logicalSize - dp->pos;
+ if (remain >= len) {
+ rlen = len;
+ } else {
+ if (remain == 0) {
+ return EOF;
+ }
+ rlen = remain;
+ }
+
+ memcpy(buf, (void *) ((char *) dp->data + dp->pos), rlen);
+ dp->pos += rlen;
+
+ return rlen;
+}
+
+static int dynamicGetchar (gdIOCtxPtr ctx)
+{
+ unsigned char b;
+ int rv;
+
+ rv = dynamicGetbuf (ctx, &b, 1);
+ if (rv != 1) {
+ return EOF;
+ } else {
+ return b; /* (b & 0xff); */
+ }
+}
+
+/* *********************************************************************
+
+ * InitDynamic - Return a dynamically resizable void*
+ *
+ * *********************************************************************
+ */
+static int
+allocDynamic (dynamicPtr * dp, int initialSize, void *data)
+{
+
+ if (data == NULL) {
+ dp->logicalSize = 0;
+ dp->dataGood = FALSE;
+ dp->data = gdMalloc(initialSize);
+ } else {
+ dp->logicalSize = initialSize;
+ dp->dataGood = TRUE;
+ dp->data = data;
+ }
+
+ dp->realSize = initialSize;
+ dp->dataGood = TRUE;
+ dp->pos = 0;
+
+ return TRUE;
+}
+
+/* append bytes to the end of a dynamic pointer */
+static int appendDynamic (dynamicPtr * dp, const void *src, int size)
+{
+ int bytesNeeded;
+ char *tmp;
+
+ if (!dp->dataGood) {
+ return FALSE;
+ }
+
+ /* bytesNeeded = dp->logicalSize + size; */
+ bytesNeeded = dp->pos + size;
+
+ if (bytesNeeded > dp->realSize) {
+ /* 2.0.21 */
+ if (!dp->freeOK) {
+ return FALSE;
+ }
+ gdReallocDynamic(dp, bytesNeeded * 2);
+ }
+
+ /* if we get here, we can be sure that we have enough bytes to copy safely */
+ /*printf("Mem OK Size: %d, Pos: %d\n", dp->realSize, dp->pos); */
+
+ tmp = (char *) dp->data;
+ memcpy((void *) (tmp + (dp->pos)), src, size);
+ dp->pos += size;
+
+ if (dp->pos > dp->logicalSize) {
+ dp->logicalSize = dp->pos;
+ }
+
+ return TRUE;
+}
+
+/* grow (or shrink) dynamic pointer */
+static int gdReallocDynamic (dynamicPtr * dp, int required)
+{
+ void *newPtr;
+
+ /* First try gdRealloc(). If that doesn't work, make a new memory block and copy. */
+ if ((newPtr = gdRealloc(dp->data, required))) {
+ dp->realSize = required;
+ dp->data = newPtr;
+ return TRUE;
+ }
+
+ /* create a new pointer */
+ newPtr = gdMalloc(required);
+
+ /* copy the old data into it */
+ memcpy(newPtr, dp->data, dp->logicalSize);
+ gdFree(dp->data);
+ dp->data = newPtr;
+
+ dp->realSize = required;
+
+ return TRUE;
+}
+
+/* trim pointer so that its real and logical sizes match */
+static int trimDynamic (dynamicPtr * dp)
+{
+ /* 2.0.21: we don't reallocate memory we don't own */
+ if (!dp->freeOK) {
+ return FALSE;
+ }
+ return gdReallocDynamic(dp, dp->logicalSize);
+}