Back to index

php5  5.3.10
gd_io_dp.c
Go to the documentation of this file.
00001 /*
00002    * io_dp.c
00003    *
00004    * Implements the dynamic pointer interface.
00005    *
00006    * Based on GD.pm code by Lincoln Stein for interfacing to libgd.
00007    * Added support for reading as well as support for 'tell' and 'seek'.
00008    *
00009    * As will all I/O modules, most functions are for local use only (called
00010    * via function pointers in the I/O context).
00011    *
00012    * gdDPExtractData is the exception to this: it will return the pointer to
00013    * the internal data, and reset the internal storage.
00014    *
00015    * Written/Modified 1999, Philip Warner.
00016    *
00017  */
00018 
00019 #include <math.h>
00020 #include <string.h>
00021 #include <stdlib.h>
00022 #include "gd.h"
00023 #include "gdhelpers.h"
00024 
00025 #define TRUE 1
00026 #define FALSE 0
00027 
00028 /* this is used for creating images in main memory */
00029 typedef struct dpStruct
00030 {
00031        void *data;
00032        int logicalSize;
00033        int realSize;
00034        int dataGood;
00035        int pos;
00036        int freeOK;
00037 } dynamicPtr;
00038 
00039 typedef struct dpIOCtx
00040 {
00041        gdIOCtx ctx;
00042        dynamicPtr *dp;
00043 } dpIOCtx;
00044 
00045 typedef struct dpIOCtx *dpIOCtxPtr;
00046 
00047 /* these functions operate on in-memory dynamic pointers */
00048 static int allocDynamic (dynamicPtr * dp, int initialSize, void *data);
00049 static int appendDynamic (dynamicPtr * dp, const void *src, int size);
00050 static int gdReallocDynamic (dynamicPtr * dp, int required);
00051 static int trimDynamic (dynamicPtr * dp);
00052 static void gdFreeDynamicCtx (struct gdIOCtx *ctx);
00053 static dynamicPtr *newDynamic (int initialSize, void *data, int freeOKFlag);
00054 
00055 static int dynamicPutbuf (struct gdIOCtx *, const void *, int);
00056 static void dynamicPutchar (struct gdIOCtx *, int a);
00057 
00058 static int dynamicGetbuf (gdIOCtxPtr ctx, void *buf, int len);
00059 static int dynamicGetchar (gdIOCtxPtr ctx);
00060 
00061 static int dynamicSeek (struct gdIOCtx *, const int);
00062 static long dynamicTell (struct gdIOCtx *);
00063 
00064 /* return data as a dynamic pointer */
00065 gdIOCtx * gdNewDynamicCtx (int initialSize, void *data)
00066 {
00067        return gdNewDynamicCtxEx(initialSize, data, 1);
00068 }
00069 
00070 gdIOCtx * gdNewDynamicCtxEx (int initialSize, void *data, int freeOKFlag)
00071 {
00072        dpIOCtx *ctx;
00073        dynamicPtr *dp;
00074 
00075        ctx = (dpIOCtx *) gdMalloc (sizeof (dpIOCtx));
00076 
00077        dp = newDynamic(initialSize, data, freeOKFlag);
00078 
00079        ctx->dp = dp;
00080 
00081        ctx->ctx.getC = dynamicGetchar;
00082        ctx->ctx.putC = dynamicPutchar;
00083 
00084        ctx->ctx.getBuf = dynamicGetbuf;
00085        ctx->ctx.putBuf = dynamicPutbuf;
00086 
00087        ctx->ctx.seek = dynamicSeek;
00088        ctx->ctx.tell = dynamicTell;
00089 
00090        ctx->ctx.gd_free = gdFreeDynamicCtx;
00091 
00092        return (gdIOCtx *) ctx;
00093 }
00094 
00095 void * gdDPExtractData (struct gdIOCtx *ctx, int *size)
00096 {
00097        dynamicPtr *dp;
00098        dpIOCtx *dctx;
00099        void *data;
00100 
00101        dctx = (dpIOCtx *) ctx;
00102        dp = dctx->dp;
00103 
00104        /* clean up the data block and return it */
00105        if (dp->dataGood) {
00106               trimDynamic (dp);
00107               *size = dp->logicalSize;
00108               data = dp->data;
00109        } else {
00110               *size = 0;
00111               data = NULL;
00112               if (dp->data != NULL && dp->freeOK) {
00113                      gdFree(dp->data);
00114               }
00115        }
00116 
00117        dp->data = NULL;
00118        dp->realSize = 0;
00119        dp->logicalSize = 0;
00120 
00121        return data;
00122 }
00123 
00124 static void gdFreeDynamicCtx (struct gdIOCtx *ctx)
00125 {
00126        dynamicPtr *dp;
00127        dpIOCtx *dctx;
00128 
00129        dctx = (dpIOCtx *) ctx;
00130        dp = dctx->dp;
00131 
00132        gdFree(ctx);
00133 
00134        dp->realSize = 0;
00135        dp->logicalSize = 0;
00136 
00137        gdFree(dp);
00138 }
00139 
00140 static long dynamicTell (struct gdIOCtx *ctx)
00141 {
00142        dpIOCtx *dctx;
00143 
00144        dctx = (dpIOCtx *) ctx;
00145 
00146        return (dctx->dp->pos);
00147 }
00148 
00149 static int dynamicSeek (struct gdIOCtx *ctx, const int pos)
00150 {
00151        int bytesNeeded;
00152        dynamicPtr *dp;
00153        dpIOCtx *dctx;
00154 
00155        dctx = (dpIOCtx *) ctx;
00156        dp = dctx->dp;
00157 
00158        if (!dp->dataGood) {
00159               return FALSE;
00160        }
00161 
00162        bytesNeeded = pos;
00163        if (bytesNeeded > dp->realSize) {
00164               /* 2.0.21 */
00165               if (!dp->freeOK) {
00166                      return FALSE;
00167               }
00168               gdReallocDynamic (dp, dp->realSize * 2);
00169        }
00170 
00171        /* if we get here, we can be sure that we have enough bytes to copy safely */
00172 
00173        /* Extend the logical size if we seek beyond EOF. */
00174        if (pos > dp->logicalSize) {
00175               dp->logicalSize = pos;
00176        }
00177 
00178        dp->pos = pos;
00179 
00180        return TRUE;
00181 }
00182 
00183 /* return data as a dynamic pointer */
00184 static dynamicPtr * newDynamic (int initialSize, void *data, int freeOKFlag)
00185 {
00186        dynamicPtr *dp;
00187        dp = (dynamicPtr *) gdMalloc (sizeof (dynamicPtr));
00188 
00189        allocDynamic (dp, initialSize, data);
00190 
00191        dp->pos = 0;
00192        dp->freeOK = freeOKFlag;
00193 
00194        return dp;
00195 }
00196 
00197 static int
00198 dynamicPutbuf (struct gdIOCtx *ctx, const void *buf, int size)
00199 {
00200   dpIOCtx *dctx;
00201   dctx = (dpIOCtx *) ctx;
00202 
00203   appendDynamic (dctx->dp, buf, size);
00204 
00205   if (dctx->dp->dataGood)
00206     {
00207       return size;
00208     }
00209   else
00210     {
00211       return -1;
00212     };
00213 
00214 }
00215 
00216 static void dynamicPutchar (struct gdIOCtx *ctx, int a)
00217 {
00218        unsigned char b;
00219        dpIOCtxPtr dctx;
00220 
00221        b = a;
00222        dctx = (dpIOCtxPtr) ctx;
00223 
00224        appendDynamic(dctx->dp, &b, 1);
00225 }
00226 
00227 static int dynamicGetbuf (gdIOCtxPtr ctx, void *buf, int len)
00228 {
00229        int rlen, remain;
00230        dpIOCtxPtr dctx;
00231        dynamicPtr *dp;
00232 
00233        dctx = (dpIOCtxPtr) ctx;
00234        dp = dctx->dp;
00235 
00236        remain = dp->logicalSize - dp->pos;
00237        if (remain >= len) {
00238               rlen = len;
00239        } else {
00240               if (remain == 0) {
00241                      return EOF;
00242               }
00243               rlen = remain;
00244        }
00245 
00246        memcpy(buf, (void *) ((char *) dp->data + dp->pos), rlen);
00247        dp->pos += rlen;
00248 
00249        return rlen;
00250 }
00251 
00252 static int dynamicGetchar (gdIOCtxPtr ctx)
00253 {
00254        unsigned char b;
00255        int rv;
00256 
00257        rv = dynamicGetbuf (ctx, &b, 1);
00258        if (rv != 1) {
00259               return EOF;
00260        } else {
00261               return b;            /* (b & 0xff); */
00262        }
00263 }
00264 
00265 /* *********************************************************************
00266 
00267  * InitDynamic - Return a dynamically resizable void*
00268  *
00269  * *********************************************************************
00270  */
00271 static int
00272 allocDynamic (dynamicPtr * dp, int initialSize, void *data)
00273 {
00274 
00275        if (data == NULL) {
00276               dp->logicalSize = 0;
00277               dp->dataGood = FALSE;
00278               dp->data = gdMalloc(initialSize);
00279        } else {
00280               dp->logicalSize = initialSize;
00281               dp->dataGood = TRUE;
00282               dp->data = data;
00283        }
00284 
00285        dp->realSize = initialSize;
00286        dp->dataGood = TRUE;
00287        dp->pos = 0;
00288 
00289        return TRUE;
00290 }
00291 
00292 /* append bytes to the end of a dynamic pointer */
00293 static int appendDynamic (dynamicPtr * dp, const void *src, int size)
00294 {
00295        int bytesNeeded;
00296        char *tmp;
00297 
00298        if (!dp->dataGood) {
00299               return FALSE;
00300        }
00301 
00302        /*  bytesNeeded = dp->logicalSize + size; */
00303        bytesNeeded = dp->pos + size;
00304 
00305        if (bytesNeeded > dp->realSize) {
00306               /* 2.0.21 */
00307               if (!dp->freeOK) {
00308                      return FALSE;
00309               }
00310               gdReallocDynamic(dp, bytesNeeded * 2);
00311        }
00312 
00313        /* if we get here, we can be sure that we have enough bytes to copy safely */
00314        /*printf("Mem OK Size: %d, Pos: %d\n", dp->realSize, dp->pos); */
00315 
00316        tmp = (char *) dp->data;
00317        memcpy((void *) (tmp + (dp->pos)), src, size);
00318        dp->pos += size;
00319 
00320        if (dp->pos > dp->logicalSize) {
00321               dp->logicalSize = dp->pos;
00322        }
00323 
00324        return TRUE;
00325 }
00326 
00327 /* grow (or shrink) dynamic pointer */
00328 static int gdReallocDynamic (dynamicPtr * dp, int required)
00329 {
00330        void *newPtr;
00331 
00332        /* First try gdRealloc(). If that doesn't work, make a new memory block and copy. */
00333        if ((newPtr = gdRealloc(dp->data, required))) {
00334               dp->realSize = required;
00335               dp->data = newPtr;
00336               return TRUE;
00337        }
00338 
00339        /* create a new pointer */
00340        newPtr = gdMalloc(required);
00341 
00342        /* copy the old data into it */
00343        memcpy(newPtr, dp->data, dp->logicalSize);
00344        gdFree(dp->data);
00345        dp->data = newPtr;
00346 
00347        dp->realSize = required;
00348 
00349        return TRUE;
00350 }
00351 
00352 /* trim pointer so that its real and logical sizes match */
00353 static int trimDynamic (dynamicPtr * dp)
00354 {
00355        /* 2.0.21: we don't reallocate memory we don't own */
00356        if (!dp->freeOK) {
00357               return FALSE;
00358        }
00359        return gdReallocDynamic(dp, dp->logicalSize);
00360 }