Annotation of embedaddon/php/ext/gd/libgd/gd_io_dp.c, revision 1.1.1.1
1.1 misho 1: /*
2: * io_dp.c
3: *
4: * Implements the dynamic pointer interface.
5: *
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'.
8: *
9: * As will all I/O modules, most functions are for local use only (called
10: * via function pointers in the I/O context).
11: *
12: * gdDPExtractData is the exception to this: it will return the pointer to
13: * the internal data, and reset the internal storage.
14: *
15: * Written/Modified 1999, Philip Warner.
16: *
17: */
18:
19: #include <math.h>
20: #include <string.h>
21: #include <stdlib.h>
22: #include "gd.h"
23: #include "gdhelpers.h"
24:
25: #define TRUE 1
26: #define FALSE 0
27:
28: /* this is used for creating images in main memory */
29: typedef struct dpStruct
30: {
31: void *data;
32: int logicalSize;
33: int realSize;
34: int dataGood;
35: int pos;
36: int freeOK;
37: } dynamicPtr;
38:
39: typedef struct dpIOCtx
40: {
41: gdIOCtx ctx;
42: dynamicPtr *dp;
43: } dpIOCtx;
44:
45: typedef struct dpIOCtx *dpIOCtxPtr;
46:
47: /* these functions operate on in-memory dynamic pointers */
48: static int allocDynamic (dynamicPtr * dp, int initialSize, void *data);
49: static int appendDynamic (dynamicPtr * dp, const void *src, int size);
50: static int gdReallocDynamic (dynamicPtr * dp, int required);
51: static int trimDynamic (dynamicPtr * dp);
52: static void gdFreeDynamicCtx (struct gdIOCtx *ctx);
53: static dynamicPtr *newDynamic (int initialSize, void *data, int freeOKFlag);
54:
55: static int dynamicPutbuf (struct gdIOCtx *, const void *, int);
56: static void dynamicPutchar (struct gdIOCtx *, int a);
57:
58: static int dynamicGetbuf (gdIOCtxPtr ctx, void *buf, int len);
59: static int dynamicGetchar (gdIOCtxPtr ctx);
60:
61: static int dynamicSeek (struct gdIOCtx *, const int);
62: static long dynamicTell (struct gdIOCtx *);
63:
64: /* return data as a dynamic pointer */
65: gdIOCtx * gdNewDynamicCtx (int initialSize, void *data)
66: {
67: return gdNewDynamicCtxEx(initialSize, data, 1);
68: }
69:
70: gdIOCtx * gdNewDynamicCtxEx (int initialSize, void *data, int freeOKFlag)
71: {
72: dpIOCtx *ctx;
73: dynamicPtr *dp;
74:
75: ctx = (dpIOCtx *) gdMalloc (sizeof (dpIOCtx));
76:
77: dp = newDynamic(initialSize, data, freeOKFlag);
78:
79: ctx->dp = dp;
80:
81: ctx->ctx.getC = dynamicGetchar;
82: ctx->ctx.putC = dynamicPutchar;
83:
84: ctx->ctx.getBuf = dynamicGetbuf;
85: ctx->ctx.putBuf = dynamicPutbuf;
86:
87: ctx->ctx.seek = dynamicSeek;
88: ctx->ctx.tell = dynamicTell;
89:
90: ctx->ctx.gd_free = gdFreeDynamicCtx;
91:
92: return (gdIOCtx *) ctx;
93: }
94:
95: void * gdDPExtractData (struct gdIOCtx *ctx, int *size)
96: {
97: dynamicPtr *dp;
98: dpIOCtx *dctx;
99: void *data;
100:
101: dctx = (dpIOCtx *) ctx;
102: dp = dctx->dp;
103:
104: /* clean up the data block and return it */
105: if (dp->dataGood) {
106: trimDynamic (dp);
107: *size = dp->logicalSize;
108: data = dp->data;
109: } else {
110: *size = 0;
111: data = NULL;
112: if (dp->data != NULL && dp->freeOK) {
113: gdFree(dp->data);
114: }
115: }
116:
117: dp->data = NULL;
118: dp->realSize = 0;
119: dp->logicalSize = 0;
120:
121: return data;
122: }
123:
124: static void gdFreeDynamicCtx (struct gdIOCtx *ctx)
125: {
126: dynamicPtr *dp;
127: dpIOCtx *dctx;
128:
129: dctx = (dpIOCtx *) ctx;
130: dp = dctx->dp;
131:
132: gdFree(ctx);
133:
134: dp->realSize = 0;
135: dp->logicalSize = 0;
136:
137: gdFree(dp);
138: }
139:
140: static long dynamicTell (struct gdIOCtx *ctx)
141: {
142: dpIOCtx *dctx;
143:
144: dctx = (dpIOCtx *) ctx;
145:
146: return (dctx->dp->pos);
147: }
148:
149: static int dynamicSeek (struct gdIOCtx *ctx, const int pos)
150: {
151: int bytesNeeded;
152: dynamicPtr *dp;
153: dpIOCtx *dctx;
154:
155: dctx = (dpIOCtx *) ctx;
156: dp = dctx->dp;
157:
158: if (!dp->dataGood) {
159: return FALSE;
160: }
161:
162: bytesNeeded = pos;
163: if (bytesNeeded > dp->realSize) {
164: /* 2.0.21 */
165: if (!dp->freeOK) {
166: return FALSE;
167: }
168: gdReallocDynamic (dp, dp->realSize * 2);
169: }
170:
171: /* if we get here, we can be sure that we have enough bytes to copy safely */
172:
173: /* Extend the logical size if we seek beyond EOF. */
174: if (pos > dp->logicalSize) {
175: dp->logicalSize = pos;
176: }
177:
178: dp->pos = pos;
179:
180: return TRUE;
181: }
182:
183: /* return data as a dynamic pointer */
184: static dynamicPtr * newDynamic (int initialSize, void *data, int freeOKFlag)
185: {
186: dynamicPtr *dp;
187: dp = (dynamicPtr *) gdMalloc (sizeof (dynamicPtr));
188:
189: allocDynamic (dp, initialSize, data);
190:
191: dp->pos = 0;
192: dp->freeOK = freeOKFlag;
193:
194: return dp;
195: }
196:
197: static int
198: dynamicPutbuf (struct gdIOCtx *ctx, const void *buf, int size)
199: {
200: dpIOCtx *dctx;
201: dctx = (dpIOCtx *) ctx;
202:
203: appendDynamic (dctx->dp, buf, size);
204:
205: if (dctx->dp->dataGood)
206: {
207: return size;
208: }
209: else
210: {
211: return -1;
212: };
213:
214: }
215:
216: static void dynamicPutchar (struct gdIOCtx *ctx, int a)
217: {
218: unsigned char b;
219: dpIOCtxPtr dctx;
220:
221: b = a;
222: dctx = (dpIOCtxPtr) ctx;
223:
224: appendDynamic(dctx->dp, &b, 1);
225: }
226:
227: static int dynamicGetbuf (gdIOCtxPtr ctx, void *buf, int len)
228: {
229: int rlen, remain;
230: dpIOCtxPtr dctx;
231: dynamicPtr *dp;
232:
233: dctx = (dpIOCtxPtr) ctx;
234: dp = dctx->dp;
235:
236: remain = dp->logicalSize - dp->pos;
237: if (remain >= len) {
238: rlen = len;
239: } else {
240: if (remain == 0) {
241: return EOF;
242: }
243: rlen = remain;
244: }
245:
246: memcpy(buf, (void *) ((char *) dp->data + dp->pos), rlen);
247: dp->pos += rlen;
248:
249: return rlen;
250: }
251:
252: static int dynamicGetchar (gdIOCtxPtr ctx)
253: {
254: unsigned char b;
255: int rv;
256:
257: rv = dynamicGetbuf (ctx, &b, 1);
258: if (rv != 1) {
259: return EOF;
260: } else {
261: return b; /* (b & 0xff); */
262: }
263: }
264:
265: /* *********************************************************************
266:
267: * InitDynamic - Return a dynamically resizable void*
268: *
269: * *********************************************************************
270: */
271: static int
272: allocDynamic (dynamicPtr * dp, int initialSize, void *data)
273: {
274:
275: if (data == NULL) {
276: dp->logicalSize = 0;
277: dp->dataGood = FALSE;
278: dp->data = gdMalloc(initialSize);
279: } else {
280: dp->logicalSize = initialSize;
281: dp->dataGood = TRUE;
282: dp->data = data;
283: }
284:
285: dp->realSize = initialSize;
286: dp->dataGood = TRUE;
287: dp->pos = 0;
288:
289: return TRUE;
290: }
291:
292: /* append bytes to the end of a dynamic pointer */
293: static int appendDynamic (dynamicPtr * dp, const void *src, int size)
294: {
295: int bytesNeeded;
296: char *tmp;
297:
298: if (!dp->dataGood) {
299: return FALSE;
300: }
301:
302: /* bytesNeeded = dp->logicalSize + size; */
303: bytesNeeded = dp->pos + size;
304:
305: if (bytesNeeded > dp->realSize) {
306: /* 2.0.21 */
307: if (!dp->freeOK) {
308: return FALSE;
309: }
310: gdReallocDynamic(dp, bytesNeeded * 2);
311: }
312:
313: /* if we get here, we can be sure that we have enough bytes to copy safely */
314: /*printf("Mem OK Size: %d, Pos: %d\n", dp->realSize, dp->pos); */
315:
316: tmp = (char *) dp->data;
317: memcpy((void *) (tmp + (dp->pos)), src, size);
318: dp->pos += size;
319:
320: if (dp->pos > dp->logicalSize) {
321: dp->logicalSize = dp->pos;
322: }
323:
324: return TRUE;
325: }
326:
327: /* grow (or shrink) dynamic pointer */
328: static int gdReallocDynamic (dynamicPtr * dp, int required)
329: {
330: void *newPtr;
331:
332: /* First try gdRealloc(). If that doesn't work, make a new memory block and copy. */
333: if ((newPtr = gdRealloc(dp->data, required))) {
334: dp->realSize = required;
335: dp->data = newPtr;
336: return TRUE;
337: }
338:
339: /* create a new pointer */
340: newPtr = gdMalloc(required);
341:
342: /* copy the old data into it */
343: memcpy(newPtr, dp->data, dp->logicalSize);
344: gdFree(dp->data);
345: dp->data = newPtr;
346:
347: dp->realSize = required;
348:
349: return TRUE;
350: }
351:
352: /* trim pointer so that its real and logical sizes match */
353: static int trimDynamic (dynamicPtr * dp)
354: {
355: /* 2.0.21: we don't reallocate memory we don't own */
356: if (!dp->freeOK) {
357: return FALSE;
358: }
359: return gdReallocDynamic(dp, dp->logicalSize);
360: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>