gd_io_dp.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363
  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 will 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. #include <math.h>
  19. #include <string.h>
  20. #include <stdlib.h>
  21. #include "gd.h"
  22. #include "gdhelpers.h"
  23. #define TRUE 1
  24. #define FALSE 0
  25. /* this is used for creating images in main memory */
  26. typedef struct dpStruct
  27. {
  28. void *data;
  29. int logicalSize;
  30. int realSize;
  31. int dataGood;
  32. int pos;
  33. int freeOK;
  34. } dynamicPtr;
  35. typedef struct dpIOCtx
  36. {
  37. gdIOCtx ctx;
  38. dynamicPtr *dp;
  39. } dpIOCtx;
  40. typedef struct dpIOCtx *dpIOCtxPtr;
  41. /* these functions operate on in-memory dynamic pointers */
  42. static int allocDynamic (dynamicPtr * dp, int initialSize, void *data);
  43. static int appendDynamic (dynamicPtr * dp, const void *src, int size);
  44. static int gdReallocDynamic (dynamicPtr * dp, int required);
  45. static int trimDynamic (dynamicPtr * dp);
  46. static void gdFreeDynamicCtx (struct gdIOCtx *ctx);
  47. static dynamicPtr *newDynamic (int initialSize, void *data, int freeOKFlag);
  48. static int dynamicPutbuf (struct gdIOCtx *, const void *, int);
  49. static void dynamicPutchar (struct gdIOCtx *, int a);
  50. static int dynamicGetbuf (gdIOCtxPtr ctx, void *buf, int len);
  51. static int dynamicGetchar (gdIOCtxPtr ctx);
  52. static int dynamicSeek (struct gdIOCtx *, const int);
  53. static long dynamicTell (struct gdIOCtx *);
  54. /* return data as a dynamic pointer */
  55. gdIOCtx * gdNewDynamicCtx (int initialSize, void *data)
  56. {
  57. return gdNewDynamicCtxEx(initialSize, data, 1);
  58. }
  59. gdIOCtx * gdNewDynamicCtxEx (int initialSize, void *data, int freeOKFlag)
  60. {
  61. dpIOCtx *ctx;
  62. dynamicPtr *dp;
  63. ctx = (dpIOCtx *) gdMalloc (sizeof (dpIOCtx));
  64. dp = newDynamic(initialSize, data, freeOKFlag);
  65. ctx->dp = dp;
  66. ctx->ctx.getC = dynamicGetchar;
  67. ctx->ctx.putC = dynamicPutchar;
  68. ctx->ctx.getBuf = dynamicGetbuf;
  69. ctx->ctx.putBuf = dynamicPutbuf;
  70. ctx->ctx.seek = dynamicSeek;
  71. ctx->ctx.tell = dynamicTell;
  72. ctx->ctx.gd_free = gdFreeDynamicCtx;
  73. return (gdIOCtx *) ctx;
  74. }
  75. void * gdDPExtractData (struct gdIOCtx *ctx, int *size)
  76. {
  77. dynamicPtr *dp;
  78. dpIOCtx *dctx;
  79. void *data;
  80. dctx = (dpIOCtx *) ctx;
  81. dp = dctx->dp;
  82. /* clean up the data block and return it */
  83. if (dp->dataGood) {
  84. trimDynamic (dp);
  85. *size = dp->logicalSize;
  86. data = dp->data;
  87. } else {
  88. *size = 0;
  89. data = NULL;
  90. if (dp->data != NULL && dp->freeOK) {
  91. gdFree(dp->data);
  92. }
  93. }
  94. dp->data = NULL;
  95. dp->realSize = 0;
  96. dp->logicalSize = 0;
  97. return data;
  98. }
  99. static void gdFreeDynamicCtx (struct gdIOCtx *ctx)
  100. {
  101. dynamicPtr *dp;
  102. dpIOCtx *dctx;
  103. dctx = (dpIOCtx *) ctx;
  104. dp = dctx->dp;
  105. gdFree(ctx);
  106. dp->realSize = 0;
  107. dp->logicalSize = 0;
  108. gdFree(dp);
  109. }
  110. static long dynamicTell (struct gdIOCtx *ctx)
  111. {
  112. dpIOCtx *dctx;
  113. dctx = (dpIOCtx *) ctx;
  114. return (dctx->dp->pos);
  115. }
  116. static int dynamicSeek (struct gdIOCtx *ctx, const int pos)
  117. {
  118. int bytesNeeded;
  119. dynamicPtr *dp;
  120. dpIOCtx *dctx;
  121. if (pos < 0) {
  122. return FALSE;
  123. }
  124. dctx = (dpIOCtx *) ctx;
  125. dp = dctx->dp;
  126. if (!dp->dataGood) {
  127. return FALSE;
  128. }
  129. bytesNeeded = pos;
  130. if (bytesNeeded > dp->realSize) {
  131. /* 2.0.21 */
  132. if (!dp->freeOK) {
  133. return FALSE;
  134. }
  135. gdReallocDynamic (dp, dp->realSize * 2);
  136. }
  137. /* if we get here, we can be sure that we have enough bytes to copy safely */
  138. /* Extend the logical size if we seek beyond EOF. */
  139. if (pos > dp->logicalSize) {
  140. dp->logicalSize = pos;
  141. }
  142. dp->pos = pos;
  143. return TRUE;
  144. }
  145. /* return data as a dynamic pointer */
  146. static dynamicPtr * newDynamic (int initialSize, void *data, int freeOKFlag)
  147. {
  148. dynamicPtr *dp;
  149. dp = (dynamicPtr *) gdMalloc (sizeof (dynamicPtr));
  150. allocDynamic (dp, initialSize, data);
  151. dp->pos = 0;
  152. dp->freeOK = freeOKFlag;
  153. return dp;
  154. }
  155. static int
  156. dynamicPutbuf (struct gdIOCtx *ctx, const void *buf, int size)
  157. {
  158. dpIOCtx *dctx;
  159. dctx = (dpIOCtx *) ctx;
  160. appendDynamic (dctx->dp, buf, size);
  161. if (dctx->dp->dataGood)
  162. {
  163. return size;
  164. }
  165. else
  166. {
  167. return -1;
  168. };
  169. }
  170. static void dynamicPutchar (struct gdIOCtx *ctx, int a)
  171. {
  172. unsigned char b;
  173. dpIOCtxPtr dctx;
  174. b = a;
  175. dctx = (dpIOCtxPtr) ctx;
  176. appendDynamic(dctx->dp, &b, 1);
  177. }
  178. static int dynamicGetbuf (gdIOCtxPtr ctx, void *buf, int len)
  179. {
  180. int rlen, remain;
  181. dpIOCtxPtr dctx;
  182. dynamicPtr *dp;
  183. dctx = (dpIOCtxPtr) ctx;
  184. dp = dctx->dp;
  185. remain = dp->logicalSize - dp->pos;
  186. if (remain >= len) {
  187. rlen = len;
  188. } else {
  189. if (remain <= 0) {
  190. return EOF;
  191. }
  192. rlen = remain;
  193. }
  194. memcpy(buf, (void *) ((char *) dp->data + dp->pos), rlen);
  195. dp->pos += rlen;
  196. return rlen;
  197. }
  198. static int dynamicGetchar (gdIOCtxPtr ctx)
  199. {
  200. unsigned char b;
  201. int rv;
  202. rv = dynamicGetbuf (ctx, &b, 1);
  203. if (rv != 1) {
  204. return EOF;
  205. } else {
  206. return b; /* (b & 0xff); */
  207. }
  208. }
  209. /* *********************************************************************
  210. * InitDynamic - Return a dynamically resizable void*
  211. *
  212. * *********************************************************************
  213. */
  214. static int
  215. allocDynamic (dynamicPtr * dp, int initialSize, void *data)
  216. {
  217. if (data == NULL) {
  218. dp->logicalSize = 0;
  219. dp->dataGood = FALSE;
  220. dp->data = gdMalloc(initialSize);
  221. } else {
  222. dp->logicalSize = initialSize;
  223. dp->dataGood = TRUE;
  224. dp->data = data;
  225. }
  226. dp->realSize = initialSize;
  227. dp->dataGood = TRUE;
  228. dp->pos = 0;
  229. return TRUE;
  230. }
  231. /* append bytes to the end of a dynamic pointer */
  232. static int appendDynamic (dynamicPtr * dp, const void *src, int size)
  233. {
  234. int bytesNeeded;
  235. char *tmp;
  236. if (!dp->dataGood) {
  237. return FALSE;
  238. }
  239. /* bytesNeeded = dp->logicalSize + size; */
  240. bytesNeeded = dp->pos + size;
  241. if (bytesNeeded > dp->realSize) {
  242. /* 2.0.21 */
  243. if (!dp->freeOK) {
  244. return FALSE;
  245. }
  246. gdReallocDynamic(dp, bytesNeeded * 2);
  247. }
  248. /* if we get here, we can be sure that we have enough bytes to copy safely */
  249. /*printf("Mem OK Size: %d, Pos: %d\n", dp->realSize, dp->pos); */
  250. tmp = (char *) dp->data;
  251. memcpy((void *) (tmp + (dp->pos)), src, size);
  252. dp->pos += size;
  253. if (dp->pos > dp->logicalSize) {
  254. dp->logicalSize = dp->pos;
  255. }
  256. return TRUE;
  257. }
  258. /* grow (or shrink) dynamic pointer */
  259. static int gdReallocDynamic (dynamicPtr * dp, int required)
  260. {
  261. void *newPtr;
  262. /* First try gdRealloc(). If that doesn't work, make a new memory block and copy. */
  263. if ((newPtr = gdRealloc(dp->data, required))) {
  264. dp->realSize = required;
  265. dp->data = newPtr;
  266. return TRUE;
  267. }
  268. /* create a new pointer */
  269. newPtr = gdMalloc(required);
  270. /* copy the old data into it */
  271. memcpy(newPtr, dp->data, dp->logicalSize);
  272. gdFree(dp->data);
  273. dp->data = newPtr;
  274. dp->realSize = required;
  275. return TRUE;
  276. }
  277. /* trim pointer so that its real and logical sizes match */
  278. static int trimDynamic (dynamicPtr * dp)
  279. {
  280. /* 2.0.21: we don't reallocate memory we don't own */
  281. if (!dp->freeOK) {
  282. return FALSE;
  283. }
  284. return gdReallocDynamic(dp, dp->logicalSize);
  285. }