5
* Implements the dynamic pointer interface.
7
* Based on GD.pm code by Lincoln Stein for interfacing to libgd.
8
* Added support for reading as well as support for 'tell' and 'seek'.
10
* As will all I/O modules, most functions are for local use only (called
11
* via function pointers in the I/O context).
13
* gdDPExtractData is the exception to this: it will return the pointer to
14
* the internal data, and reset the internal storage.
16
* Written/Modified 1999, Philip Warner.
24
#include "gdhelpers.h"
29
/* this is used for creating images in main memory */
30
typedef struct dpStruct
40
typedef struct dpIOCtx
47
typedef struct dpIOCtx *dpIOCtxPtr;
50
/* these functions operate on in-memory dynamic pointers */
51
static int allocDynamic (dynamicPtr * dp, int initialSize, void *data);
52
static int appendDynamic (dynamicPtr * dp, const void *src, int size);
53
static int gdReallocDynamic (dynamicPtr * dp, int required);
54
static int trimDynamic (dynamicPtr * dp);
55
static void gdFreeDynamicCtx (struct gdIOCtx *ctx);
56
static dynamicPtr *newDynamic (int initialSize, void *data);
58
static int dynamicPutbuf (struct gdIOCtx *, const void *, int);
59
static void dynamicPutchar (struct gdIOCtx *, int a);
61
static int dynamicGetbuf (gdIOCtxPtr ctx, void *buf, int len);
62
static int dynamicGetchar (gdIOCtxPtr ctx);
64
static int dynamicSeek (struct gdIOCtx *, const int);
65
static long dynamicTell (struct gdIOCtx *);
67
/* return data as a dynamic pointer */
69
gdNewDynamicCtx (int initialSize, void *data)
74
ctx = (dpIOCtx *) gdMalloc (sizeof (dpIOCtx));
80
dp = newDynamic (initialSize, data);
89
ctx->ctx.getC = dynamicGetchar;
90
ctx->ctx.putC = dynamicPutchar;
92
ctx->ctx.getBuf = dynamicGetbuf;
93
ctx->ctx.putBuf = dynamicPutbuf;
95
ctx->ctx.seek = dynamicSeek;
96
ctx->ctx.tell = dynamicTell;
98
ctx->ctx.free = gdFreeDynamicCtx;
100
return (gdIOCtx *) ctx;
104
gdDPExtractData (struct gdIOCtx *ctx, int *size)
110
dctx = (dpIOCtx *) ctx;
113
/* clean up the data block and return it */
117
*size = dp->logicalSize;
124
if (dp->data != NULL)
139
gdFreeDynamicCtx (struct gdIOCtx *ctx)
144
dctx = (dpIOCtx *) ctx;
149
/* clean up the data block and return it */
150
if (dp->data != NULL)
164
dynamicTell (struct gdIOCtx *ctx)
168
dctx = (dpIOCtx *) ctx;
169
return (dctx->dp->pos);
173
dynamicSeek (struct gdIOCtx *ctx, const int pos)
179
dctx = (dpIOCtx *) ctx;
186
if (bytesNeeded > dp->realSize)
188
if (!gdReallocDynamic (dp, dp->realSize * 2))
190
dp->dataGood = FALSE;
195
/* if we get here, we can be sure that we have enough bytes
198
/* Extend the logical size if we seek beyond EOF. */
199
if (pos > dp->logicalSize)
201
dp->logicalSize = pos;
209
/* return data as a dynamic pointer */
211
newDynamic (int initialSize, void *data)
214
dp = (dynamicPtr *) gdMalloc (sizeof (dynamicPtr));
220
if (!allocDynamic (dp, initialSize, data))
229
dynamicPutbuf (struct gdIOCtx *ctx, const void *buf, int size)
232
dctx = (dpIOCtx *) ctx;
234
appendDynamic (dctx->dp, buf, size);
236
if (dctx->dp->dataGood)
248
dynamicPutchar (struct gdIOCtx *ctx, int a)
254
dctx = (dpIOCtxPtr) ctx;
256
appendDynamic (dctx->dp, &b, 1);
260
dynamicGetbuf (gdIOCtxPtr ctx, void *buf, int len)
266
dctx = (dpIOCtxPtr) ctx;
269
remain = dp->logicalSize - dp->pos;
283
memcpy (buf, (void *) ((char *) dp->data + dp->pos), rlen);
290
dynamicGetchar (gdIOCtxPtr ctx)
295
rv = dynamicGetbuf (ctx, &b, 1);
303
return b; /* (b & 0xff); */
307
/* *********************************************************************
309
* InitDynamic - Return a dynamically resizable void*
311
* *********************************************************************
314
allocDynamic (dynamicPtr * dp, int initialSize, void *data)
320
dp->dataGood = FALSE;
321
dp->data = gdMalloc (initialSize);
325
dp->logicalSize = initialSize;
330
if (dp->data != NULL)
332
dp->realSize = initialSize;
344
/* append bytes to the end of a dynamic pointer */
346
appendDynamic (dynamicPtr * dp, const void *src, int size)
354
/* bytesNeeded = dp->logicalSize + size; */
355
bytesNeeded = dp->pos + size;
357
if (bytesNeeded > dp->realSize)
359
if (!gdReallocDynamic (dp, bytesNeeded * 2))
361
dp->dataGood = FALSE;
366
/* if we get here, we can be sure that we have enough bytes
368
/*printf("Mem OK Size: %d, Pos: %d\n", dp->realSize, dp->pos); */
370
tmp = (char *) dp->data;
371
memcpy ((void *) (tmp + (dp->pos)), src, size);
374
if (dp->pos > dp->logicalSize)
376
dp->logicalSize = dp->pos;
382
/* grow (or shrink) dynamic pointer */
384
gdReallocDynamic (dynamicPtr * dp, int required)
388
/* First try gdRealloc(). If that doesn't work, make a new
389
memory block and copy. */
390
if ((newPtr = gdRealloc (dp->data, required)))
392
dp->realSize = required;
397
/* create a new pointer */
398
newPtr = gdMalloc (required);
401
dp->dataGood = FALSE;
405
/* copy the old data into it */
406
memcpy (newPtr, dp->data, dp->logicalSize);
410
dp->realSize = required;
414
/* trim pointer so that its real and logical sizes match */
416
trimDynamic (dynamicPtr * dp)
418
return gdReallocDynamic (dp, dp->logicalSize);