Annotation of embedaddon/php/ext/gd/libgd/gd_io_dp.c, revision 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>