Back to index

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