84ef17a0ddfc1609dbada47fc8cbf0cf71c5a256
[rrdtool.git] / libraries / libpng-1.0.9 / pngmem.c
1
2 /* pngmem.c - stub functions for memory allocation
3  *
4  * libpng 1.0.9 - January 31, 2001
5  * For conditions of distribution and use, see copyright notice in png.h
6  * Copyright (c) 1998-2001 Glenn Randers-Pehrson
7  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
8  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
9  *
10  * This file provides a location for all memory allocation.  Users who
11  * need special memory handling are expected to supply replacement
12  * functions for png_malloc() and png_free(), and to use
13  * png_create_read_struct_2() and png_create_write_struct_2() to
14  * identify the replacement functions.
15  */
16
17 #define PNG_INTERNAL
18 #include "png.h"
19
20 /* Borland DOS special memory handler */
21 #if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__)
22 /* if you change this, be sure to change the one in png.h also */
23
24 /* Allocate memory for a png_struct.  The malloc and memset can be replaced
25    by a single call to calloc() if this is thought to improve performance. */
26 png_voidp /* PRIVATE */
27 png_create_struct(int type)
28 {
29 #ifdef PNG_USER_MEM_SUPPORTED
30    return (png_create_struct_2(type, NULL));
31 }
32
33 /* Alternate version of png_create_struct, for use with user-defined malloc. */
34 png_voidp /* PRIVATE */
35 png_create_struct_2(int type, png_malloc_ptr malloc_fn)
36 {
37 #endif /* PNG_USER_MEM_SUPPORTED */
38    png_size_t size;
39    png_voidp struct_ptr;
40
41    if (type == PNG_STRUCT_INFO)
42      size = sizeof(png_info);
43    else if (type == PNG_STRUCT_PNG)
44      size = sizeof(png_struct);
45    else
46      return ((png_voidp)NULL);
47
48 #ifdef PNG_USER_MEM_SUPPORTED
49    if(malloc_fn != NULL)
50    {
51       if ((struct_ptr = (*(malloc_fn))(NULL, size)) != NULL)
52          png_memset(struct_ptr, 0, size);
53          return (struct_ptr);
54    }
55 #endif /* PNG_USER_MEM_SUPPORTED */
56    if ((struct_ptr = (png_voidp)farmalloc(size)) != NULL)
57    {
58       png_memset(struct_ptr, 0, size);
59    }
60    return (struct_ptr);
61 }
62
63
64 /* Free memory allocated by a png_create_struct() call */
65 void /* PRIVATE */
66 png_destroy_struct(png_voidp struct_ptr)
67 {
68 #ifdef PNG_USER_MEM_SUPPORTED
69    png_destroy_struct_2(struct_ptr, (png_free_ptr)NULL);
70 }
71
72 /* Free memory allocated by a png_create_struct() call */
73 void /* PRIVATE */
74 png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn)
75 {
76 #endif
77    if (struct_ptr != NULL)
78    {
79 #ifdef PNG_USER_MEM_SUPPORTED
80       if(free_fn != NULL)
81       {
82          png_struct dummy_struct;
83          png_structp png_ptr = &dummy_struct;
84          (*(free_fn))(png_ptr, struct_ptr);
85          return;
86       }
87 #endif /* PNG_USER_MEM_SUPPORTED */
88       farfree (struct_ptr);
89    }
90 }
91
92 /* Allocate memory.  For reasonable files, size should never exceed
93  * 64K.  However, zlib may allocate more then 64K if you don't tell
94  * it not to.  See zconf.h and png.h for more information. zlib does
95  * need to allocate exactly 64K, so whatever you call here must
96  * have the ability to do that.
97  *
98  * Borland seems to have a problem in DOS mode for exactly 64K.
99  * It gives you a segment with an offset of 8 (perhaps to store its
100  * memory stuff).  zlib doesn't like this at all, so we have to
101  * detect and deal with it.  This code should not be needed in
102  * Windows or OS/2 modes, and only in 16 bit mode.  This code has
103  * been updated by Alexander Lehmann for version 0.89 to waste less
104  * memory.
105  *
106  * Note that we can't use png_size_t for the "size" declaration,
107  * since on some systems a png_size_t is a 16-bit quantity, and as a
108  * result, we would be truncating potentially larger memory requests
109  * (which should cause a fatal error) and introducing major problems.
110  */
111 png_voidp PNGAPI
112 png_malloc(png_structp png_ptr, png_uint_32 size)
113 {
114 #ifndef PNG_USER_MEM_SUPPORTED
115    png_voidp ret;
116 #endif
117    if (png_ptr == NULL || size == 0)
118       return ((png_voidp)NULL);
119
120 #ifdef PNG_USER_MEM_SUPPORTED
121    if(png_ptr->malloc_fn != NULL)
122        return ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, size));
123    else
124        return png_malloc_default(png_ptr, size);
125 }
126
127 png_voidp PNGAPI
128 png_malloc_default(png_structp png_ptr, png_uint_32 size)
129 {
130    png_voidp ret;
131 #endif /* PNG_USER_MEM_SUPPORTED */
132
133 #ifdef PNG_MAX_MALLOC_64K
134    if (size > (png_uint_32)65536L)
135       png_error(png_ptr, "Cannot Allocate > 64K");
136 #endif
137
138    if (size == (png_uint_32)65536L)
139    {
140       if (png_ptr->offset_table == NULL)
141       {
142          /* try to see if we need to do any of this fancy stuff */
143          ret = farmalloc(size);
144          if (ret == NULL || ((png_size_t)ret & 0xffff))
145          {
146             int num_blocks;
147             png_uint_32 total_size;
148             png_bytep table;
149             int i;
150             png_byte huge * hptr;
151
152             if (ret != NULL)
153             {
154                farfree(ret);
155                ret = NULL;
156             }
157
158             if(png_ptr->zlib_window_bits > 14)
159                num_blocks = (int)(1 << (png_ptr->zlib_window_bits - 14));
160             else
161                num_blocks = 1;
162             if (png_ptr->zlib_mem_level >= 7)
163                num_blocks += (int)(1 << (png_ptr->zlib_mem_level - 7));
164             else
165                num_blocks++;
166
167             total_size = ((png_uint_32)65536L) * (png_uint_32)num_blocks+16;
168
169             table = farmalloc(total_size);
170
171             if (table == NULL)
172             {
173                png_error(png_ptr, "Out Of Memory."); /* Note "O" and "M" */
174             }
175
176             if ((png_size_t)table & 0xfff0)
177             {
178                png_error(png_ptr, "Farmalloc didn't return normalized pointer");
179             }
180
181             png_ptr->offset_table = table;
182             png_ptr->offset_table_ptr = farmalloc(num_blocks *
183                sizeof (png_bytep));
184
185             if (png_ptr->offset_table_ptr == NULL)
186             {
187                png_error(png_ptr, "Out Of memory.");
188             }
189
190             hptr = (png_byte huge *)table;
191             if ((png_size_t)hptr & 0xf)
192             {
193                hptr = (png_byte huge *)((long)(hptr) & 0xfffffff0L);
194                hptr = hptr + 16L;  /* "hptr += 16L" fails on Turbo C++ 3.0 */
195             }
196             for (i = 0; i < num_blocks; i++)
197             {
198                png_ptr->offset_table_ptr[i] = (png_bytep)hptr;
199                hptr = hptr + (png_uint_32)65536L;  /* "+=" fails on TC++3.0 */
200             }
201
202             png_ptr->offset_table_number = num_blocks;
203             png_ptr->offset_table_count = 0;
204             png_ptr->offset_table_count_free = 0;
205          }
206       }
207
208       if (png_ptr->offset_table_count >= png_ptr->offset_table_number)
209          png_error(png_ptr, "Out of Memory.");
210
211       ret = png_ptr->offset_table_ptr[png_ptr->offset_table_count++];
212    }
213    else
214       ret = farmalloc(size);
215
216    if (ret == NULL)
217    {
218       png_error(png_ptr, "Out of memory."); /* Note "o" and "m" */
219    }
220
221    return (ret);
222 }
223
224 /* free a pointer allocated by png_malloc().  In the default
225    configuration, png_ptr is not used, but is passed in case it
226    is needed.  If ptr is NULL, return without taking any action. */
227 void PNGAPI
228 png_free(png_structp png_ptr, png_voidp ptr)
229 {
230    if (png_ptr == NULL || ptr == NULL)
231       return;
232
233 #ifdef PNG_USER_MEM_SUPPORTED
234    if (png_ptr->free_fn != NULL)
235    {
236       (*(png_ptr->free_fn))(png_ptr, ptr);
237       return;
238    }
239    else png_free_default(png_ptr, ptr);
240 }
241
242 void PNGAPI
243 png_free_default(png_structp png_ptr, png_voidp ptr)
244 {
245 #endif /* PNG_USER_MEM_SUPPORTED */
246
247    if (png_ptr->offset_table != NULL)
248    {
249       int i;
250
251       for (i = 0; i < png_ptr->offset_table_count; i++)
252       {
253          if (ptr == png_ptr->offset_table_ptr[i])
254          {
255             ptr = NULL;
256             png_ptr->offset_table_count_free++;
257             break;
258          }
259       }
260       if (png_ptr->offset_table_count_free == png_ptr->offset_table_count)
261       {
262          farfree(png_ptr->offset_table);
263          farfree(png_ptr->offset_table_ptr);
264          png_ptr->offset_table = NULL;
265          png_ptr->offset_table_ptr = NULL;
266       }
267    }
268
269    if (ptr != NULL)
270    {
271       farfree(ptr);
272    }
273 }
274
275 #else /* Not the Borland DOS special memory handler */
276
277 /* Allocate memory for a png_struct or a png_info.  The malloc and
278    memset can be replaced by a single call to calloc() if this is thought
279    to improve performance noticably.*/
280 png_voidp /* PRIVATE */
281 png_create_struct(int type)
282 {
283 #ifdef PNG_USER_MEM_SUPPORTED
284    return (png_create_struct_2(type, NULL));
285 }
286
287 /* Allocate memory for a png_struct or a png_info.  The malloc and
288    memset can be replaced by a single call to calloc() if this is thought
289    to improve performance noticably.*/
290 png_voidp /* PRIVATE */
291 png_create_struct_2(int type, png_malloc_ptr malloc_fn)
292 {
293 #endif /* PNG_USER_MEM_SUPPORTED */
294    png_size_t size;
295    png_voidp struct_ptr;
296
297    if (type == PNG_STRUCT_INFO)
298       size = sizeof(png_info);
299    else if (type == PNG_STRUCT_PNG)
300       size = sizeof(png_struct);
301    else
302       return ((png_voidp)NULL);
303
304 #ifdef PNG_USER_MEM_SUPPORTED
305    if(malloc_fn != NULL)
306    {
307       if ((struct_ptr = (*(malloc_fn))(NULL, size)) != NULL)
308          png_memset(struct_ptr, 0, size);
309       return (struct_ptr);
310    }
311 #endif /* PNG_USER_MEM_SUPPORTED */
312
313 #if defined(__TURBOC__) && !defined(__FLAT__)
314    if ((struct_ptr = (png_voidp)farmalloc(size)) != NULL)
315 #else
316 # if defined(_MSC_VER) && defined(MAXSEG_64K)
317    if ((struct_ptr = (png_voidp)halloc(size,1)) != NULL)
318 # else
319    if ((struct_ptr = (png_voidp)malloc(size)) != NULL)
320 # endif
321 #endif
322    {
323       png_memset(struct_ptr, 0, size);
324    }
325
326    return (struct_ptr);
327 }
328
329
330 /* Free memory allocated by a png_create_struct() call */
331 void /* PRIVATE */
332 png_destroy_struct(png_voidp struct_ptr)
333 {
334 #ifdef PNG_USER_MEM_SUPPORTED
335    png_destroy_struct_2(struct_ptr, (png_free_ptr)NULL);
336 }
337
338 /* Free memory allocated by a png_create_struct() call */
339 void /* PRIVATE */
340 png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn)
341 {
342 #endif /* PNG_USER_MEM_SUPPORTED */
343    if (struct_ptr != NULL)
344    {
345 #ifdef PNG_USER_MEM_SUPPORTED
346       if(free_fn != NULL)
347       {
348          png_struct dummy_struct;
349          png_structp png_ptr = &dummy_struct;
350          (*(free_fn))(png_ptr, struct_ptr);
351          return;
352       }
353 #endif /* PNG_USER_MEM_SUPPORTED */
354 #if defined(__TURBOC__) && !defined(__FLAT__)
355       farfree(struct_ptr);
356 #else
357 # if defined(_MSC_VER) && defined(MAXSEG_64K)
358       hfree(struct_ptr);
359 # else
360       free(struct_ptr);
361 # endif
362 #endif
363    }
364 }
365
366
367 /* Allocate memory.  For reasonable files, size should never exceed
368    64K.  However, zlib may allocate more then 64K if you don't tell
369    it not to.  See zconf.h and png.h for more information.  zlib does
370    need to allocate exactly 64K, so whatever you call here must
371    have the ability to do that. */
372
373 png_voidp PNGAPI
374 png_malloc(png_structp png_ptr, png_uint_32 size)
375 {
376 #ifndef PNG_USER_MEM_SUPPORTED
377    png_voidp ret;
378 #endif
379    if (png_ptr == NULL || size == 0)
380       return ((png_voidp)NULL);
381
382 #ifdef PNG_USER_MEM_SUPPORTED
383    if(png_ptr->malloc_fn != NULL)
384        return ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, size));
385    else
386        return (png_malloc_default(png_ptr, size));
387 }
388 png_voidp /* PRIVATE */
389 png_malloc_default(png_structp png_ptr, png_uint_32 size)
390 {
391    png_voidp ret;
392 #endif /* PNG_USER_MEM_SUPPORTED */
393
394 #ifdef PNG_MAX_MALLOC_64K
395    if (size > (png_uint_32)65536L)
396       png_error(png_ptr, "Cannot Allocate > 64K");
397 #endif
398
399 #if defined(__TURBOC__) && !defined(__FLAT__)
400    ret = farmalloc(size);
401 #else
402 # if defined(_MSC_VER) && defined(MAXSEG_64K)
403    ret = halloc(size, 1);
404 # else
405    ret = malloc((size_t)size);
406 # endif
407 #endif
408
409    if (ret == NULL)
410    {
411       png_error(png_ptr, "Out of Memory");
412    }
413
414    return (ret);
415 }
416
417 /* Free a pointer allocated by png_malloc().  If ptr is NULL, return
418    without taking any action. */
419 void PNGAPI
420 png_free(png_structp png_ptr, png_voidp ptr)
421 {
422    if (png_ptr == NULL || ptr == NULL)
423       return;
424
425 #ifdef PNG_USER_MEM_SUPPORTED
426    if (png_ptr->free_fn != NULL)
427    {
428       (*(png_ptr->free_fn))(png_ptr, ptr);
429       return;
430    }
431    else png_free_default(png_ptr, ptr);
432 }
433 void /* PRIVATE */
434 png_free_default(png_structp png_ptr, png_voidp ptr)
435 {
436    if (png_ptr == NULL || ptr == NULL)
437       return;
438
439 #endif /* PNG_USER_MEM_SUPPORTED */
440
441 #if defined(__TURBOC__) && !defined(__FLAT__)
442    farfree(ptr);
443 #else
444 # if defined(_MSC_VER) && defined(MAXSEG_64K)
445    hfree(ptr);
446 # else
447    free(ptr);
448 # endif
449 #endif
450 }
451
452 #endif /* Not Borland DOS special memory handler */
453
454 png_voidp /* PRIVATE */
455 png_memcpy_check (png_structp png_ptr, png_voidp s1, png_voidp s2,
456    png_uint_32 length)
457 {
458    png_size_t size;
459
460    size = (png_size_t)length;
461    if ((png_uint_32)size != length)
462       png_error(png_ptr,"Overflow in png_memcpy_check.");
463
464    return(png_memcpy (s1, s2, size));
465 }
466
467 png_voidp /* PRIVATE */
468 png_memset_check (png_structp png_ptr, png_voidp s1, int value,
469    png_uint_32 length)
470 {
471    png_size_t size;
472
473    size = (png_size_t)length;
474    if ((png_uint_32)size != length)
475       png_error(png_ptr,"Overflow in png_memset_check.");
476
477    return (png_memset (s1, value, size));
478
479 }
480
481 #ifdef PNG_USER_MEM_SUPPORTED
482 /* This function is called when the application wants to use another method
483  * of allocating and freeing memory.
484  */
485 void PNGAPI
486 png_set_mem_fn(png_structp png_ptr, png_voidp mem_ptr, png_malloc_ptr
487   malloc_fn, png_free_ptr free_fn)
488 {
489    png_ptr->mem_ptr = mem_ptr;
490    png_ptr->malloc_fn = malloc_fn;
491    png_ptr->free_fn = free_fn;
492 }
493
494 /* This function returns a pointer to the mem_ptr associated with the user
495  * functions.  The application should free any memory associated with this
496  * pointer before png_write_destroy and png_read_destroy are called.
497  */
498 png_voidp PNGAPI
499 png_get_mem_ptr(png_structp png_ptr)
500 {
501    return ((png_voidp)png_ptr->mem_ptr);
502 }
503 #endif /* PNG_USER_MEM_SUPPORTED */