#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include "gd.h"
#include "gdhelpers.h"
#define TRUE 1
#define FALSE 0
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;
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 *);
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.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;
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);
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 (pos > dp->logicalSize)
{
dp->logicalSize = pos;
};
dp->pos = pos;
return TRUE;
}
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;
}
}
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;
}
}
static int
appendDynamic (dynamicPtr * dp, const void *src, int size)
{
int bytesNeeded;
char *tmp;
if (!dp->dataGood)
return FALSE;
bytesNeeded = dp->pos + size;
if (bytesNeeded > dp->realSize)
{
if (!gdReallocDynamic (dp, bytesNeeded * 2))
{
dp->dataGood = FALSE;
return FALSE;
}
}
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;
}
static int
gdReallocDynamic (dynamicPtr * dp, int required)
{
void *newPtr;
if ((newPtr = gdRealloc (dp->data, required)))
{
dp->realSize = required;
dp->data = newPtr;
return TRUE;
}
newPtr = gdMalloc (required);
if (!newPtr)
{
dp->dataGood = FALSE;
return FALSE;
}
memcpy (newPtr, dp->data, dp->logicalSize);
gdFree (dp->data);
dp->data = newPtr;
dp->realSize = required;
return TRUE;
}
static int
trimDynamic (dynamicPtr * dp)
{
return gdReallocDynamic (dp, dp->logicalSize);
}