Back to index

tetex-bin  3.0
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 #ifdef HAVE_CONFIG_H
00020 #include "config.h"
00021 #endif
00022 
00023 #include <math.h>
00024 #include <string.h>
00025 #include <stdlib.h>
00026 #include "gd.h"
00027 #include "gdhelpers.h"
00028 
00029 #define TRUE 1
00030 #define FALSE 0
00031 
00032 /* this is used for creating images in main memory */
00033 typedef struct dpStruct
00034 {
00035   void *data;
00036   int logicalSize;
00037   int realSize;
00038   int dataGood;
00039   int pos;
00040   int freeOK;
00041 }
00042 dynamicPtr;
00043 
00044 typedef struct dpIOCtx
00045 {
00046   gdIOCtx ctx;
00047   dynamicPtr *dp;
00048 }
00049 dpIOCtx;
00050 
00051 typedef struct dpIOCtx *dpIOCtxPtr;
00052 
00053 
00054 /* these functions operate on in-memory dynamic pointers */
00055 static int allocDynamic (dynamicPtr * dp, int initialSize, void *data);
00056 static int appendDynamic (dynamicPtr * dp, const void *src, int size);
00057 static int gdReallocDynamic (dynamicPtr * dp, int required);
00058 static int trimDynamic (dynamicPtr * dp);
00059 static void gdFreeDynamicCtx (struct gdIOCtx *ctx);
00060 static dynamicPtr *newDynamic (int initialSize, void *data, int freeOKFlag);
00061 
00062 static int dynamicPutbuf (struct gdIOCtx *, const void *, int);
00063 static void dynamicPutchar (struct gdIOCtx *, int a);
00064 
00065 static int dynamicGetbuf (gdIOCtxPtr ctx, void *buf, int len);
00066 static int dynamicGetchar (gdIOCtxPtr ctx);
00067 
00068 static int dynamicSeek (struct gdIOCtx *, const int);
00069 static long dynamicTell (struct gdIOCtx *);
00070 
00071 /* return data as a dynamic pointer */
00072 BGD_DECLARE(gdIOCtx *) gdNewDynamicCtx (int initialSize, void *data)
00073 {
00074   /* 2.0.23: Phil Moore: 'return' keyword was missing! */
00075   return gdNewDynamicCtxEx (initialSize, data, 1);
00076 }
00077 
00078 BGD_DECLARE(gdIOCtx *) gdNewDynamicCtxEx (int initialSize, void *data, int freeOKFlag)
00079 {
00080   dpIOCtx *ctx;
00081   dynamicPtr *dp;
00082 
00083   ctx = (dpIOCtx *) gdMalloc (sizeof (dpIOCtx));
00084   if (ctx == NULL)
00085     {
00086       return NULL;
00087     }
00088 
00089   dp = newDynamic (initialSize, data, freeOKFlag);
00090   if (!dp)
00091     {
00092       gdFree (ctx);
00093       return NULL;
00094     };
00095 
00096   ctx->dp = dp;
00097 
00098   ctx->ctx.getC = dynamicGetchar;
00099   ctx->ctx.putC = dynamicPutchar;
00100 
00101   ctx->ctx.getBuf = dynamicGetbuf;
00102   ctx->ctx.putBuf = dynamicPutbuf;
00103 
00104   ctx->ctx.seek = dynamicSeek;
00105   ctx->ctx.tell = dynamicTell;
00106 
00107   ctx->ctx.gd_free = gdFreeDynamicCtx;
00108 
00109   return (gdIOCtx *) ctx;
00110 }
00111 
00112 BGD_DECLARE(void *) gdDPExtractData (struct gdIOCtx *ctx, int *size)
00113 {
00114   dynamicPtr *dp;
00115   dpIOCtx *dctx;
00116   void *data;
00117 
00118   dctx = (dpIOCtx *) ctx;
00119   dp = dctx->dp;
00120 
00121   /* clean up the data block and return it */
00122   if (dp->dataGood)
00123     {
00124       trimDynamic (dp);
00125       *size = dp->logicalSize;
00126       data = dp->data;
00127     }
00128   else
00129     {
00130       *size = 0;
00131       data = NULL;
00132       /* 2.0.21: never free memory we don't own */
00133       if ((dp->data != NULL) && (dp->freeOK))
00134        {
00135          gdFree (dp->data);
00136        }
00137     }
00138 
00139   dp->data = NULL;
00140   dp->realSize = 0;
00141   dp->logicalSize = 0;
00142 
00143   return data;
00144 }
00145 
00146 static void
00147 gdFreeDynamicCtx (struct gdIOCtx *ctx)
00148 {
00149   dynamicPtr *dp;
00150   dpIOCtx *dctx;
00151 
00152   dctx = (dpIOCtx *) ctx;
00153   dp = dctx->dp;
00154 
00155   gdFree (ctx);
00156 
00157   /* clean up the data block and return it */
00158   /* 2.0.21: never free memory we don't own */
00159   if ((dp->data != NULL) && (dp->freeOK))
00160     {
00161       gdFree (dp->data);
00162       dp->data = NULL;
00163     }
00164 
00165   dp->realSize = 0;
00166   dp->logicalSize = 0;
00167 
00168   gdFree (dp);
00169 
00170 }
00171 
00172 static long
00173 dynamicTell (struct gdIOCtx *ctx)
00174 {
00175   dpIOCtx *dctx;
00176 
00177   dctx = (dpIOCtx *) ctx;
00178   return (dctx->dp->pos);
00179 }
00180 
00181 static int
00182 dynamicSeek (struct gdIOCtx *ctx, const int pos)
00183 {
00184   int bytesNeeded;
00185   dynamicPtr *dp;
00186   dpIOCtx *dctx;
00187 
00188   dctx = (dpIOCtx *) ctx;
00189   dp = dctx->dp;
00190 
00191   if (!dp->dataGood)
00192     return FALSE;
00193 
00194   bytesNeeded = pos;
00195   if (bytesNeeded > dp->realSize)
00196     {
00197       /* 2.0.21 */
00198       if (!dp->freeOK)
00199        {
00200          return FALSE;
00201        }
00202       if (overflow2(dp->realSize, 2)) {
00203         return FALSE;
00204       }
00205       if (!gdReallocDynamic (dp, dp->realSize * 2))
00206        {
00207          dp->dataGood = FALSE;
00208          return FALSE;
00209        }
00210     }
00211 
00212   /* if we get here, we can be sure that we have enough bytes
00213      to copy safely */
00214 
00215   /* Extend the logical size if we seek beyond EOF. */
00216   if (pos > dp->logicalSize)
00217     {
00218       dp->logicalSize = pos;
00219     };
00220 
00221   dp->pos = pos;
00222 
00223   return TRUE;
00224 }
00225 
00226 /* return data as a dynamic pointer */
00227 static dynamicPtr *
00228 newDynamic (int initialSize, void *data, int freeOKFlag)
00229 {
00230   dynamicPtr *dp;
00231   dp = (dynamicPtr *) gdMalloc (sizeof (dynamicPtr));
00232   if (dp == NULL)
00233     {
00234       return NULL;
00235     }
00236 
00237   if (!allocDynamic (dp, initialSize, data))
00238     return NULL;
00239 
00240   dp->pos = 0;
00241   dp->freeOK = freeOKFlag;
00242   return dp;
00243 }
00244 
00245 static int
00246 dynamicPutbuf (struct gdIOCtx *ctx, const void *buf, int size)
00247 {
00248   dpIOCtx *dctx;
00249   dctx = (dpIOCtx *) ctx;
00250 
00251   appendDynamic (dctx->dp, buf, size);
00252 
00253   if (dctx->dp->dataGood)
00254     {
00255       return size;
00256     }
00257   else
00258     {
00259       return -1;
00260     };
00261 
00262 }
00263 
00264 static void
00265 dynamicPutchar (struct gdIOCtx *ctx, int a)
00266 {
00267   unsigned char b;
00268   dpIOCtxPtr dctx;
00269 
00270   b = a;
00271   dctx = (dpIOCtxPtr) ctx;
00272 
00273   appendDynamic (dctx->dp, &b, 1);
00274 }
00275 
00276 static int
00277 dynamicGetbuf (gdIOCtxPtr ctx, void *buf, int len)
00278 {
00279   int rlen, remain;
00280   dpIOCtxPtr dctx;
00281   dynamicPtr *dp;
00282 
00283   dctx = (dpIOCtxPtr) ctx;
00284   dp = dctx->dp;
00285 
00286   remain = dp->logicalSize - dp->pos;
00287   if (remain >= len)
00288     {
00289       rlen = len;
00290     }
00291   else
00292     {
00293       if (remain == 0)
00294        {
00295          return EOF;
00296        }
00297       rlen = remain;
00298     }
00299 
00300   memcpy (buf, (void *) ((char *) dp->data + dp->pos), rlen);
00301   dp->pos += rlen;
00302 
00303   return rlen;
00304 }
00305 
00306 static int
00307 dynamicGetchar (gdIOCtxPtr ctx)
00308 {
00309   unsigned char b;
00310   int rv;
00311 
00312   rv = dynamicGetbuf (ctx, &b, 1);
00313 
00314   if (rv != 1)
00315     {
00316       return EOF;
00317     }
00318   else
00319     {
00320       return b;                    /* (b & 0xff); */
00321     }
00322 }
00323 
00324 /* *********************************************************************
00325 
00326  * InitDynamic - Return a dynamically resizable void*
00327  *
00328  * *********************************************************************
00329  */
00330 static int
00331 allocDynamic (dynamicPtr * dp, int initialSize, void *data)
00332 {
00333 
00334   if (data == NULL)
00335     {
00336       dp->logicalSize = 0;
00337       dp->dataGood = FALSE;
00338       dp->data = gdMalloc (initialSize);
00339     }
00340   else
00341     {
00342       dp->logicalSize = initialSize;
00343       dp->dataGood = TRUE;
00344       dp->data = data;
00345     }
00346 
00347   if (dp->data != NULL)
00348     {
00349       dp->realSize = initialSize;
00350       dp->dataGood = TRUE;
00351       dp->pos = 0;
00352       return TRUE;
00353     }
00354   else
00355     {
00356       dp->realSize = 0;
00357       return FALSE;
00358     }
00359 }
00360 
00361 /* append bytes to the end of a dynamic pointer */
00362 static int
00363 appendDynamic (dynamicPtr * dp, const void *src, int size)
00364 {
00365   int bytesNeeded;
00366   char *tmp;
00367 
00368   if (!dp->dataGood)
00369     return FALSE;
00370 
00371 /*  bytesNeeded = dp->logicalSize + size; */
00372   bytesNeeded = dp->pos + size;
00373 
00374   if (bytesNeeded > dp->realSize)
00375     {
00376       /* 2.0.21 */
00377       if (!dp->freeOK)
00378        {
00379          return FALSE;
00380        }
00381       if (overflow2(dp->realSize, 2)) {
00382         return FALSE;
00383       }
00384       if (!gdReallocDynamic (dp, bytesNeeded * 2))
00385        {
00386          dp->dataGood = FALSE;
00387          return FALSE;
00388        }
00389     }
00390 
00391   /* if we get here, we can be sure that we have enough bytes
00392      to copy safely */
00393   /*printf("Mem OK Size: %d, Pos: %d\n", dp->realSize, dp->pos); */
00394 
00395   tmp = (char *) dp->data;
00396   memcpy ((void *) (tmp + (dp->pos)), src, size);
00397   dp->pos += size;
00398 
00399   if (dp->pos > dp->logicalSize)
00400     {
00401       dp->logicalSize = dp->pos;
00402     };
00403 
00404   return TRUE;
00405 }
00406 
00407 /* grow (or shrink) dynamic pointer */
00408 static int
00409 gdReallocDynamic (dynamicPtr * dp, int required)
00410 {
00411   void *newPtr;
00412 
00413   /* First try gdRealloc().  If that doesn't work, make a new
00414      memory block and copy. */
00415   if ((newPtr = gdRealloc (dp->data, required)))
00416     {
00417       dp->realSize = required;
00418       dp->data = newPtr;
00419       return TRUE;
00420     }
00421 
00422   /* create a new pointer */
00423   newPtr = gdMalloc (required);
00424   if (!newPtr)
00425     {
00426       dp->dataGood = FALSE;
00427       return FALSE;
00428     }
00429 
00430   /* copy the old data into it */
00431   memcpy (newPtr, dp->data, dp->logicalSize);
00432   gdFree (dp->data);
00433   dp->data = newPtr;
00434 
00435   dp->realSize = required;
00436   return TRUE;
00437 }
00438 
00439 /* trim pointer so that its real and logical sizes match */
00440 static int
00441 trimDynamic (dynamicPtr * dp)
00442 {
00443   /* 2.0.21: we don't reallocate memory we don't own */
00444   if (!dp->freeOK)
00445     {
00446       return TRUE;
00447     }
00448   return gdReallocDynamic (dp, dp->logicalSize);
00449 }