4
* Implements the dynamic pointer interface.
6
* Based on GD.pm code by Lincoln Stein for interfacing to libgd.
7
* Added support for reading as well as support for 'tell' and 'seek'.
9
* As will all I/O modules, most functions are for local use only (called
10
* via function pointers in the I/O context).
12
* gdDPExtractData is the exception to this: it will return the pointer to
13
* the internal data, and reset the internal storage.
15
* Written/Modified 1999, Philip Warner.
27
/* this is used for creating images in main memory*/
28
typedef struct dpStruct {
36
typedef struct dpIOCtx {
41
typedef struct dpIOCtx *dpIOCtxPtr;
44
/* these functions operate on in-memory dynamic pointers */
45
static int allocDynamic (dynamicPtr* dp,int initialSize, void *data);
46
static int appendDynamic (dynamicPtr* dp, const void* src, int size);
47
static int reallocDynamic (dynamicPtr* dp, int required);
48
static int trimDynamic (dynamicPtr* dp);
49
static void freeDynamicCtx(struct gdIOCtx* ctx);
50
static dynamicPtr* newDynamic(int initialSize, void *data);
52
static int dynamicPutbuf( struct gdIOCtx*, const void *, int );
53
static void dynamicPutchar( struct gdIOCtx*, int a );
55
static int dynamicGetbuf( gdIOCtxPtr ctx, void *buf, int len);
56
static int dynamicGetchar( gdIOCtxPtr ctx );
58
static int dynamicSeek(struct gdIOCtx*, const int);
59
static long dynamicTell(struct gdIOCtx*);
61
/* return data as a dynamic pointer */
62
gdIOCtx* gdNewDynamicCtx (int initialSize, void *data) {
66
ctx = (dpIOCtx*) malloc(sizeof(dpIOCtx));
71
dp = newDynamic(initialSize, data);
79
ctx->ctx.getC = dynamicGetchar;
80
ctx->ctx.putC = dynamicPutchar;
82
ctx->ctx.getBuf = dynamicGetbuf;
83
ctx->ctx.putBuf = dynamicPutbuf;
85
ctx->ctx.seek = dynamicSeek;
86
ctx->ctx.tell = dynamicTell;
88
ctx->ctx.free = freeDynamicCtx;
93
void* gdDPExtractData(struct gdIOCtx* ctx, int *size)
99
dctx = (dpIOCtx*) ctx;
102
/* clean up the data block and return it */
105
*size = dp->logicalSize;
110
if (dp->data != NULL) {
123
void freeDynamicCtx(struct gdIOCtx* ctx)
128
dctx = (dpIOCtx*) ctx;
133
/* clean up the data block and return it */
134
if (dp->data != NULL) {
146
static long dynamicTell(struct gdIOCtx* ctx)
150
dctx = (dpIOCtx*) ctx;
151
return (dctx->dp->pos);
154
static int dynamicSeek(struct gdIOCtx* ctx, const int pos)
160
dctx = (dpIOCtx*) ctx;
163
if (!dp->dataGood) return FALSE;
166
if (bytesNeeded > dp->realSize) {
167
if (!reallocDynamic(dp,dp->realSize*2)) {
168
dp->dataGood = FALSE;
173
/* if we get here, we can be sure that we have enough bytes
176
/* Extend the logical size if we seek beyond EOF. */
177
if (pos > dp->logicalSize) {
178
dp->logicalSize = pos;
186
/* return data as a dynamic pointer */
187
static dynamicPtr* newDynamic (int initialSize, void *data) {
189
dp = (dynamicPtr*) malloc(sizeof(dynamicPtr));
194
if (!allocDynamic(dp,initialSize, data))
203
dynamicPutbuf( struct gdIOCtx* ctx, const void *buf, int size )
206
dctx = (dpIOCtx*) ctx;
208
appendDynamic(dctx->dp,buf,size);
210
if (dctx->dp->dataGood) {
219
dynamicPutchar( struct gdIOCtx* ctx, int a )
225
dctx = (dpIOCtxPtr) ctx;
227
appendDynamic(dctx->dp,&b,1);
231
dynamicGetbuf( gdIOCtxPtr ctx, void *buf, int len)
237
dctx = (dpIOCtxPtr) ctx;
240
remain = dp->logicalSize - dp->pos;
250
memcpy(buf, (void*)((char*)dp->data + dp->pos), rlen);
257
dynamicGetchar( gdIOCtxPtr ctx )
262
rv = dynamicGetbuf(ctx, &b, 1);
267
return b ;/* (b & 0xff); */
271
/* *********************************************************************
273
* InitDynamic - Return a dynamically resizable void*
275
* *********************************************************************
278
allocDynamic (dynamicPtr* dp,int initialSize, void *data) {
282
dp->dataGood = FALSE;
283
dp->data = malloc(initialSize);
285
dp->logicalSize = initialSize;
290
if (dp->data !=NULL) {
291
dp->realSize = initialSize;
301
/* append bytes to the end of a dynamic pointer */
303
appendDynamic (dynamicPtr* dp, const void* src, int size) {
307
if (!dp->dataGood) return FALSE;
309
/* bytesNeeded = dp->logicalSize + size; */
310
bytesNeeded = dp->pos + size;
312
if (bytesNeeded > dp->realSize) {
313
if (!reallocDynamic(dp,bytesNeeded*2)) {
314
dp->dataGood = FALSE;
319
/* if we get here, we can be sure that we have enough bytes
321
/*printf("Mem OK Size: %d, Pos: %d\n", dp->realSize, dp->pos); */
323
tmp = (char*)dp->data;
324
memcpy((void*)(tmp+(dp->pos)),src,size);
327
if (dp->pos > dp->logicalSize) {
328
dp->logicalSize = dp->pos;
334
/* grow (or shrink) dynamic pointer */
336
reallocDynamic (dynamicPtr* dp, int required) {
339
/* First try realloc(). If that doesn't work, make a new
340
memory block and copy. */
341
if ( (newPtr = realloc(dp->data,required)) ) {
342
dp->realSize = required;
347
/* create a new pointer */
348
newPtr = malloc(required);
350
dp->dataGood = FALSE;
354
/* copy the old data into it */
355
memcpy(newPtr,dp->data,dp->logicalSize);
359
dp->realSize = required;
363
/* trim pointer so that its real and logical sizes match */
365
trimDynamic (dynamicPtr* dp) {
366
return reallocDynamic(dp,dp->logicalSize);