blob: 6ae1469ebafa6c4dafaede20a77464fc7059b170 [file] [log] [blame]
Guy Schalnat0d580581995-07-20 02:43:20 -05001
2/* pngstub.c - stub functions for i/o and memory allocation
3
4 libpng 1.0 beta 1 - version 0.71
5 For conditions of distribution and use, see copyright notice in png.h
6 Copyright (c) 1995 Guy Eric Schalnat, Group 42, Inc.
7 June 26, 1995
8
9 This file provides a location for all input/output, memory location,
10 and error handling. Users which need special handling in these areas
11 are expected to modify the code in this file to meet their needs. See
12 the instructions at each function. */
13
14#define PNG_INTERNAL
15#include "png.h"
16
17/* Write the data to whatever output you are using. The default
18 routine writes to a file pointer. If you need to write to something
19 else, this is the place to do it. We suggest saving the old code
20 for future use, possibly in a #define. Note that this routine sometimes
21 gets called with very small lengths, so you should implement some kind
22 of simple buffering if you are using unbuffered writes. This should
23 never be asked to write more then 64K on a 16 bit machine. The cast
24 to png_size_t is there for insurance, but if you are having problems
25 with it, you can take it out. Just be sure to cast length to whatever
26 fwrite needs in that spot if you don't have a function prototype for
27 it. */
28void
29png_write_data(png_struct *png_ptr, png_byte *data, png_uint_32 length)
30{
31 png_uint_32 check;
32
33 check = fwrite(data, 1, (png_size_t)length, png_ptr->fp);
34 if (check != length)
35 {
36 png_error(png_ptr, "Write Error");
37 }
38}
39
40/* Read the data from whatever input you are using. The default
41 routine reads from a file pointer. If you need to read from something
42 else, this is the place to do it. We suggest saving the old code
43 for future use. Note that this routine sometimes gets called with
44 very small lengths, so you should implement some kind of simple
45 buffering if you are using unbuffered reads. This should
46 never be asked to read more then 64K on a 16 bit machine. The cast
47 to png_size_t is there for insurance, but if you are having problems
48 with it, you can take it out. Just be sure to cast length to whatever
49 fread needs in that spot if you don't have a function prototype for
50 it. */
51void
52png_read_data(png_struct *png_ptr, png_byte *data, png_uint_32 length)
53{
54 png_uint_32 check;
55
56 check = fread(data, 1, (size_t)length, png_ptr->fp);
57 if (check != length)
58 {
59 png_error(png_ptr, "Read Error");
60 }
61}
62
63/* Initialize the input/output for the png file. If you change
64 the read and write routines, you will probably need to change
65 this routine (or write your own). If you change the parameters
66 of this routine, remember to change png.h also. */
67void
68png_init_io(png_struct *png_ptr, FILE *fp)
69{
70 png_ptr->fp = fp;
71}
72
73/* Allocate memory. For reasonable files, size should never exceed
74 64K. However, zlib may allocate more then 64K if you don't tell
75 it not to. See zconf.h and png.h for more information. zlib does
76 need to allocate exactly 64K, so whatever you call here must
77 have the ability to do that. */
78
79/* Borland compilers have this habit of not giving you 64K chunks
80 that start on the segment in DOS mode. This has not been observed
81 in Windows, and of course it doesn't matter in 32 bit mode, as there
82 are no segments. Now libpng doesn't need that much memory normally,
83 but zlib does, so we have to normalize it, if necessary. It would be
84 better if zlib worked in less then 64K, but it doesn't, so we
85 have to deal with it. Truely, we are misusing farmalloc here,
86 as it is designed for use with huge pointers, which don't care
87 about segments. So we allocate a large amount of memory, and
88 divvy off segments when needed.
89 */
90#ifdef __TURBOC__
91#ifndef __WIN32__
92
93/* NUM_SEG is the number of segments allocated at once */
94#define NUM_SEG 4
95typedef struct borland_seg_struct
96{
97 void *mem_ptr;
98 void *seg_ptr[NUM_SEG];
99 int seg_used[NUM_SEG];
100 int num_used;
101} borland_seg;
102
103borland_seg *save_array;
104int num_save_array;
105int max_save_array;
106
107#endif
108#endif
109
110void *
111png_large_malloc(png_struct *png_ptr, png_uint_32 size)
112{
113 void *ret;
114
115#ifdef PNG_MAX_MALLOC_64K
116 if (size > (png_uint_32)65536L)
117 png_error(png_ptr, "Cannot Allocate > 64K");
118#endif
119
120#ifdef __TURBOC__
121# ifdef __WIN32__
122 ret = farmalloc(size);
123# else
124
125 if (size == 65536L)
126 {
127 unsigned long offset;
128 if (!save_array)
129 {
130 ret = farmalloc(size);
131 offset = (unsigned long)(ret);
132 offset &= 0xffffL;
133 }
134 else
135 {
136 ret = (void *)0;
137 }
138 if (save_array || offset)
139 {
140 int i, j;
141
142 if (ret)
143 farfree(ret);
144 ret = (void *)0;
145
146 if (!save_array)
147 {
148 unsigned long offset;
149 png_byte huge *ptr;
150 int i;
151
152 num_save_array = 1;
153 save_array = malloc(num_save_array * sizeof (borland_seg));
154 if (!save_array)
155 png_error(png_ptr, "Out of Memory");
156 save_array->mem_ptr = farmalloc(
157 (unsigned long)(NUM_SEG) * 65536L + 65528L);
158 if (!save_array->mem_ptr)
159 png_error(png_ptr, "Out of Memory");
160 offset = (unsigned long)(ret);
161 offset &= 0xffffL;
162 ptr = save_array->mem_ptr;
163 if (offset)
164 ptr += 65536L - offset;
165 for (i = 0; i < NUM_SEG; i++, ptr += 65536L)
166 {
167 save_array->seg_ptr[i] = ptr;
168 save_array->seg_used[i] = 0;
169 }
170 save_array->num_used = 0;
171 }
172
173 for (i = 0; i < num_save_array; i++)
174 {
175 for (j = 0; j < NUM_SEG; j++)
176 {
177 if (!save_array[i].seg_used[j])
178 {
179 ret = save_array[i].seg_ptr[j];
180 save_array[i].seg_used[j] = 1;
181 save_array[i].num_used++;
182 break;
183 }
184 }
185 if (ret)
186 break;
187 }
188
189 if (!ret)
190 {
191 unsigned long offset;
192 png_byte huge *ptr;
193
194 save_array = realloc(save_array,
195 (num_save_array + 1) * sizeof (borland_seg));
196 if (!save_array)
197 png_error(png_ptr, "Out of Memory");
198 save_array[num_save_array].mem_ptr = farmalloc(
199 (unsigned long)(NUM_SEG) * 65536L + 65528L);
200 if (!save_array[num_save_array].mem_ptr)
201 png_error(png_ptr, "Out of Memory");
202 offset = (unsigned long)(ret);
203 offset &= 0xffffL;
204 ptr = save_array[num_save_array].mem_ptr;
205 if (offset)
206 ptr += 65536L - offset;
207 for (i = 0; i < NUM_SEG; i++, ptr += 65536L)
208 {
209 save_array[num_save_array].seg_ptr[i] = ptr;
210 save_array[num_save_array].seg_used[i] = 0;
211 }
212 ret = save_array[num_save_array].seg_ptr[0];
213 save_array[num_save_array].seg_used[0] = 1;
214 save_array[num_save_array].num_used = 1;
215 num_save_array++;
216 }
217 }
218 }
219 else
220 {
221 ret = farmalloc(size);
222 }
223
224# endif /* __WIN32__ */
225#else /* __TURBOC__ */
226# ifdef _MSC_VER
227 ret = halloc(size, 1);
228# else
229 /* everybody else, so normal malloc should do it. */
230 ret = malloc(size);
231# endif
232#endif
233
234 if (!ret)
235 {
236 png_error(png_ptr, "Out of Memory");
237 }
238
239 return ret;
240}
241
242/* free a pointer allocated by png_large_malloc(). In the default
243 configuration, png_ptr is not used, but is passed in case it
244 is needed. If ptr is NULL, return without taking any action. */
245void
246png_large_free(png_struct *png_ptr, void *ptr)
247{
248 if (!png_ptr)
249 return;
250
251 if (ptr != (void *)0)
252 {
253#ifdef __TURBOC__
254# ifndef __WIN32__
255 int i, j;
256
257 for (i = 0; i < num_save_array; i++)
258 {
259 for (j = 0; j < NUM_SEG; j++)
260 {
261 if (ptr == save_array[i].seg_ptr[j])
262 {
263printf("freeing pointer: i, j: %d, %d\n", i, j);
264 save_array[i].seg_used[j] = 0;
265 ptr = 0;
266 save_array[i].num_used--;
267 if (!save_array[i].num_used)
268 {
269 int k;
270printf("freeing array: %d\n", i);
271 num_save_array--;
272 farfree(save_array[i].mem_ptr);
273 for (k = i; k < num_save_array; k++)
274 save_array[k] = save_array[k + 1];
275 if (!num_save_array)
276 {
277 free(save_array);
278 save_array = 0;
279 }
280 }
281 break;
282 }
283 }
284 if (!ptr)
285 break;
286 }
287
288# endif
289 if (ptr)
290 farfree(ptr);
291#else
292# ifdef _MSC_VER
293 hfree(ptr);
294# else
295 free(ptr);
296# endif
297#endif
298 }
299}
300
301/* Allocate memory. This is called for smallish blocks only It
302 should not get anywhere near 64K. */
303void *
304png_malloc(png_struct *png_ptr, png_uint_32 size)
305{
306 void *ret;
307
308 if (!png_ptr)
309 return ((void *)0);
310
311#ifdef PNG_MAX_MALLOC_64K
312 if (size > (png_uint_32)65536L)
313 png_error(png_ptr, "Cannot Allocate > 64K");
314#endif
315
316 ret = malloc((png_size_t)size);
317
318 if (!ret)
319 {
320 png_error(png_ptr, "Out of Memory");
321 }
322
323 return ret;
324}
325
326/* Reallocate memory. This will not get near 64K on a
327 even marginally reasonable file. */
328void *
329png_realloc(png_struct *png_ptr, void *ptr, png_uint_32 size)
330{
331 void *ret;
332
333 if (!png_ptr)
334 return ((void *)0);
335
336#ifdef PNG_MAX_MALLOC_64K
337 if (size > (png_uint_32)65536L)
338 png_error(png_ptr, "Cannot Allocate > 64K");
339#endif
340
341 ret = realloc(ptr, (png_size_t)size);
342
343 if (!ret)
344 {
345 png_error(png_ptr, "Out of Memory");
346 }
347
348 return ret;
349}
350
351/* free a pointer allocated by png_malloc(). In the default
352 configuration, png_ptr is not used, but is passed incase it
353 is needed. If ptr is NULL, return without taking any action. */
354void
355png_free(png_struct *png_ptr, void *ptr)
356{
357 if (!png_ptr)
358 return;
359
360 if (ptr != (void *)0)
361 free(ptr);
362}
363
364/* This function is called whenever there is an error. Replace with
365 however you wish to handle the error. Note that this function
366 MUST NOT return, or the program will crash */
367void
368png_error(png_struct *png_ptr, char *message)
369{
370 fprintf(stderr, "libpng error: %s\n", message);
371
372 longjmp(png_ptr->jmpbuf, 1);
373}
374
375/* This function is called when there is a warning, but the library
376 thinks it can continue anyway. You don't have to do anything here
377 if you don't want to. In the default configuration, png_ptr is
378 not used, but it is passed in case it may be useful. */
379void
380png_warning(png_struct *png_ptr, char *message)
381{
382 if (!png_ptr)
383 return;
384
385 fprintf(stderr, "libpng warning: %s\n", message);
386}
387