"Fossies" - the Fresh Open Source Software Archive

Member "libgd-2.3.3/src/gd_io_dp.c" (11 Sep 2021, 8163 Bytes) of package /linux/www/libgd-2.3.3.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

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