home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / gd201.zip / gd-2.0.1 / gd_io_dp.c < prev    next >
C/C++ Source or Header  |  2001-04-03  |  8KB  |  420 lines

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