diff options
Diffstat (limited to 'ext/gd/libgd/gd_io_dp.c')
-rw-r--r-- | ext/gd/libgd/gd_io_dp.c | 419 |
1 files changed, 419 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 0000000000..d28dfb01a4 --- /dev/null +++ b/ext/gd/libgd/gd_io_dp.c @@ -0,0 +1,419 @@ + +/* + * 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; + } +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); + +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) +{ + dpIOCtx *ctx; + dynamicPtr *dp; + + ctx = (dpIOCtx *) gdMalloc (sizeof (dpIOCtx)); + if (ctx == NULL) + { + return NULL; + } + + dp = newDynamic (initialSize, data); + if (!dp) + { + gdFree (ctx); + return NULL; + }; + + 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.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) + { + 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); + + /* clean up the data block and return it */ + if (dp->data != NULL) + { + gdFree (dp->data); + dp->data = NULL; + } + + 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) + { + if (!gdReallocDynamic (dp, dp->realSize * 2)) + { + dp->dataGood = FALSE; + return FALSE; + } + } + + /* 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) +{ + dynamicPtr *dp; + dp = (dynamicPtr *) gdMalloc (sizeof (dynamicPtr)); + if (dp == NULL) + { + return NULL; + } + + if (!allocDynamic (dp, initialSize, data)) + return NULL; + + dp->pos = 0; + + 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; + } + + if (dp->data != NULL) + { + dp->realSize = initialSize; + dp->dataGood = TRUE; + dp->pos = 0; + return TRUE; + } + else + { + dp->realSize = 0; + return FALSE; + } +} + +/* 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) + { + if (!gdReallocDynamic (dp, bytesNeeded * 2)) + { + dp->dataGood = FALSE; + return FALSE; + } + } + + /* 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); + if (!newPtr) + { + dp->dataGood = FALSE; + return FALSE; + } + + /* 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) +{ + return gdReallocDynamic (dp, dp->logicalSize); +} |