xref: /plan9/sys/src/cmd/gs/libpng/pngmem.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
1*593dc095SDavid du Colombier 
27dd7cddfSDavid du Colombier /* pngmem.c - stub functions for memory allocation
37dd7cddfSDavid du Colombier  *
4*593dc095SDavid du Colombier  * libpng version 1.2.8 - December 3, 2004
57dd7cddfSDavid du Colombier  * For conditions of distribution and use, see copyright notice in png.h
6*593dc095SDavid du Colombier  * Copyright (c) 1998-2004 Glenn Randers-Pehrson
7*593dc095SDavid du Colombier  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
8*593dc095SDavid du Colombier  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
97dd7cddfSDavid du Colombier  *
10*593dc095SDavid du Colombier  * This file provides a location for all memory allocation.  Users who
11*593dc095SDavid du Colombier  * need special memory handling are expected to supply replacement
12*593dc095SDavid du Colombier  * functions for png_malloc() and png_free(), and to use
13*593dc095SDavid du Colombier  * png_create_read_struct_2() and png_create_write_struct_2() to
14*593dc095SDavid du Colombier  * identify the replacement functions.
157dd7cddfSDavid du Colombier  */
167dd7cddfSDavid du Colombier 
177dd7cddfSDavid du Colombier #define PNG_INTERNAL
187dd7cddfSDavid du Colombier #include "png.h"
197dd7cddfSDavid du Colombier 
207dd7cddfSDavid du Colombier /* Borland DOS special memory handler */
217dd7cddfSDavid du Colombier #if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__)
227dd7cddfSDavid du Colombier /* if you change this, be sure to change the one in png.h also */
237dd7cddfSDavid du Colombier 
247dd7cddfSDavid du Colombier /* Allocate memory for a png_struct.  The malloc and memset can be replaced
257dd7cddfSDavid du Colombier    by a single call to calloc() if this is thought to improve performance. */
26*593dc095SDavid du Colombier png_voidp /* PRIVATE */
png_create_struct(int type)277dd7cddfSDavid du Colombier png_create_struct(int type)
287dd7cddfSDavid du Colombier {
29*593dc095SDavid du Colombier #ifdef PNG_USER_MEM_SUPPORTED
30*593dc095SDavid du Colombier    return (png_create_struct_2(type, png_malloc_ptr_NULL, png_voidp_NULL));
31*593dc095SDavid du Colombier }
32*593dc095SDavid du Colombier 
33*593dc095SDavid du Colombier /* Alternate version of png_create_struct, for use with user-defined malloc. */
34*593dc095SDavid du Colombier png_voidp /* PRIVATE */
png_create_struct_2(int type,png_malloc_ptr malloc_fn,png_voidp mem_ptr)35*593dc095SDavid du Colombier png_create_struct_2(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr)
36*593dc095SDavid du Colombier {
37*593dc095SDavid du Colombier #endif /* PNG_USER_MEM_SUPPORTED */
387dd7cddfSDavid du Colombier    png_size_t size;
397dd7cddfSDavid du Colombier    png_voidp struct_ptr;
407dd7cddfSDavid du Colombier 
417dd7cddfSDavid du Colombier    if (type == PNG_STRUCT_INFO)
42*593dc095SDavid du Colombier      size = png_sizeof(png_info);
437dd7cddfSDavid du Colombier    else if (type == PNG_STRUCT_PNG)
44*593dc095SDavid du Colombier      size = png_sizeof(png_struct);
457dd7cddfSDavid du Colombier    else
46*593dc095SDavid du Colombier      return (png_get_copyright(NULL));
477dd7cddfSDavid du Colombier 
48*593dc095SDavid du Colombier #ifdef PNG_USER_MEM_SUPPORTED
49*593dc095SDavid du Colombier    if(malloc_fn != NULL)
507dd7cddfSDavid du Colombier    {
51*593dc095SDavid du Colombier       png_struct dummy_struct;
52*593dc095SDavid du Colombier       png_structp png_ptr = &dummy_struct;
53*593dc095SDavid du Colombier       png_ptr->mem_ptr=mem_ptr;
54*593dc095SDavid du Colombier       struct_ptr = (*(malloc_fn))(png_ptr, (png_uint_32)size);
55*593dc095SDavid du Colombier    }
56*593dc095SDavid du Colombier    else
57*593dc095SDavid du Colombier #endif /* PNG_USER_MEM_SUPPORTED */
58*593dc095SDavid du Colombier       struct_ptr = (png_voidp)farmalloc(size);
59*593dc095SDavid du Colombier    if (struct_ptr != NULL)
607dd7cddfSDavid du Colombier       png_memset(struct_ptr, 0, size);
61*593dc095SDavid du Colombier    return (struct_ptr);
627dd7cddfSDavid du Colombier }
637dd7cddfSDavid du Colombier 
647dd7cddfSDavid du Colombier /* Free memory allocated by a png_create_struct() call */
65*593dc095SDavid du Colombier void /* PRIVATE */
png_destroy_struct(png_voidp struct_ptr)667dd7cddfSDavid du Colombier png_destroy_struct(png_voidp struct_ptr)
677dd7cddfSDavid du Colombier {
68*593dc095SDavid du Colombier #ifdef PNG_USER_MEM_SUPPORTED
69*593dc095SDavid du Colombier    png_destroy_struct_2(struct_ptr, png_free_ptr_NULL, png_voidp_NULL);
70*593dc095SDavid du Colombier }
71*593dc095SDavid du Colombier 
72*593dc095SDavid du Colombier /* Free memory allocated by a png_create_struct() call */
73*593dc095SDavid du Colombier void /* PRIVATE */
png_destroy_struct_2(png_voidp struct_ptr,png_free_ptr free_fn,png_voidp mem_ptr)74*593dc095SDavid du Colombier png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn,
75*593dc095SDavid du Colombier     png_voidp mem_ptr)
76*593dc095SDavid du Colombier {
77*593dc095SDavid du Colombier #endif
787dd7cddfSDavid du Colombier    if (struct_ptr != NULL)
797dd7cddfSDavid du Colombier    {
80*593dc095SDavid du Colombier #ifdef PNG_USER_MEM_SUPPORTED
81*593dc095SDavid du Colombier       if(free_fn != NULL)
82*593dc095SDavid du Colombier       {
83*593dc095SDavid du Colombier          png_struct dummy_struct;
84*593dc095SDavid du Colombier          png_structp png_ptr = &dummy_struct;
85*593dc095SDavid du Colombier          png_ptr->mem_ptr=mem_ptr;
86*593dc095SDavid du Colombier          (*(free_fn))(png_ptr, struct_ptr);
87*593dc095SDavid du Colombier          return;
88*593dc095SDavid du Colombier       }
89*593dc095SDavid du Colombier #endif /* PNG_USER_MEM_SUPPORTED */
907dd7cddfSDavid du Colombier       farfree (struct_ptr);
917dd7cddfSDavid du Colombier    }
927dd7cddfSDavid du Colombier }
937dd7cddfSDavid du Colombier 
947dd7cddfSDavid du Colombier /* Allocate memory.  For reasonable files, size should never exceed
957dd7cddfSDavid du Colombier  * 64K.  However, zlib may allocate more then 64K if you don't tell
967dd7cddfSDavid du Colombier  * it not to.  See zconf.h and png.h for more information. zlib does
977dd7cddfSDavid du Colombier  * need to allocate exactly 64K, so whatever you call here must
987dd7cddfSDavid du Colombier  * have the ability to do that.
997dd7cddfSDavid du Colombier  *
1007dd7cddfSDavid du Colombier  * Borland seems to have a problem in DOS mode for exactly 64K.
101*593dc095SDavid du Colombier  * It gives you a segment with an offset of 8 (perhaps to store its
1027dd7cddfSDavid du Colombier  * memory stuff).  zlib doesn't like this at all, so we have to
1037dd7cddfSDavid du Colombier  * detect and deal with it.  This code should not be needed in
1047dd7cddfSDavid du Colombier  * Windows or OS/2 modes, and only in 16 bit mode.  This code has
1057dd7cddfSDavid du Colombier  * been updated by Alexander Lehmann for version 0.89 to waste less
1067dd7cddfSDavid du Colombier  * memory.
1077dd7cddfSDavid du Colombier  *
1087dd7cddfSDavid du Colombier  * Note that we can't use png_size_t for the "size" declaration,
1097dd7cddfSDavid du Colombier  * since on some systems a png_size_t is a 16-bit quantity, and as a
1107dd7cddfSDavid du Colombier  * result, we would be truncating potentially larger memory requests
1117dd7cddfSDavid du Colombier  * (which should cause a fatal error) and introducing major problems.
1127dd7cddfSDavid du Colombier  */
113*593dc095SDavid du Colombier 
114*593dc095SDavid du Colombier png_voidp PNGAPI
png_malloc(png_structp png_ptr,png_uint_32 size)115*593dc095SDavid du Colombier png_malloc(png_structp png_ptr, png_uint_32 size)
1167dd7cddfSDavid du Colombier {
1177dd7cddfSDavid du Colombier    png_voidp ret;
118*593dc095SDavid du Colombier 
1197dd7cddfSDavid du Colombier    if (png_ptr == NULL || size == 0)
120*593dc095SDavid du Colombier       return (NULL);
121*593dc095SDavid du Colombier 
122*593dc095SDavid du Colombier #ifdef PNG_USER_MEM_SUPPORTED
123*593dc095SDavid du Colombier    if(png_ptr->malloc_fn != NULL)
124*593dc095SDavid du Colombier        ret = ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, (png_size_t)size));
125*593dc095SDavid du Colombier    else
126*593dc095SDavid du Colombier        ret = (png_malloc_default(png_ptr, size));
127*593dc095SDavid du Colombier    if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
128*593dc095SDavid du Colombier        png_error(png_ptr, "Out of memory!");
129*593dc095SDavid du Colombier    return (ret);
130*593dc095SDavid du Colombier }
131*593dc095SDavid du Colombier 
132*593dc095SDavid du Colombier png_voidp PNGAPI
png_malloc_default(png_structp png_ptr,png_uint_32 size)133*593dc095SDavid du Colombier png_malloc_default(png_structp png_ptr, png_uint_32 size)
134*593dc095SDavid du Colombier {
135*593dc095SDavid du Colombier    png_voidp ret;
136*593dc095SDavid du Colombier #endif /* PNG_USER_MEM_SUPPORTED */
1377dd7cddfSDavid du Colombier 
1387dd7cddfSDavid du Colombier #ifdef PNG_MAX_MALLOC_64K
1397dd7cddfSDavid du Colombier    if (size > (png_uint_32)65536L)
140*593dc095SDavid du Colombier    {
141*593dc095SDavid du Colombier       png_warning(png_ptr, "Cannot Allocate > 64K");
142*593dc095SDavid du Colombier       ret = NULL;
143*593dc095SDavid du Colombier    }
144*593dc095SDavid du Colombier    else
1457dd7cddfSDavid du Colombier #endif
1467dd7cddfSDavid du Colombier 
147*593dc095SDavid du Colombier    if (size != (size_t)size)
148*593dc095SDavid du Colombier      ret = NULL;
149*593dc095SDavid du Colombier    else if (size == (png_uint_32)65536L)
1507dd7cddfSDavid du Colombier    {
1517dd7cddfSDavid du Colombier       if (png_ptr->offset_table == NULL)
1527dd7cddfSDavid du Colombier       {
1537dd7cddfSDavid du Colombier          /* try to see if we need to do any of this fancy stuff */
1547dd7cddfSDavid du Colombier          ret = farmalloc(size);
1557dd7cddfSDavid du Colombier          if (ret == NULL || ((png_size_t)ret & 0xffff))
1567dd7cddfSDavid du Colombier          {
1577dd7cddfSDavid du Colombier             int num_blocks;
1587dd7cddfSDavid du Colombier             png_uint_32 total_size;
1597dd7cddfSDavid du Colombier             png_bytep table;
1607dd7cddfSDavid du Colombier             int i;
1617dd7cddfSDavid du Colombier             png_byte huge * hptr;
1627dd7cddfSDavid du Colombier 
1637dd7cddfSDavid du Colombier             if (ret != NULL)
1647dd7cddfSDavid du Colombier             {
1657dd7cddfSDavid du Colombier                farfree(ret);
1667dd7cddfSDavid du Colombier                ret = NULL;
1677dd7cddfSDavid du Colombier             }
1687dd7cddfSDavid du Colombier 
169*593dc095SDavid du Colombier             if(png_ptr->zlib_window_bits > 14)
1707dd7cddfSDavid du Colombier                num_blocks = (int)(1 << (png_ptr->zlib_window_bits - 14));
171*593dc095SDavid du Colombier             else
1727dd7cddfSDavid du Colombier                num_blocks = 1;
1737dd7cddfSDavid du Colombier             if (png_ptr->zlib_mem_level >= 7)
1747dd7cddfSDavid du Colombier                num_blocks += (int)(1 << (png_ptr->zlib_mem_level - 7));
1757dd7cddfSDavid du Colombier             else
1767dd7cddfSDavid du Colombier                num_blocks++;
1777dd7cddfSDavid du Colombier 
1787dd7cddfSDavid du Colombier             total_size = ((png_uint_32)65536L) * (png_uint_32)num_blocks+16;
1797dd7cddfSDavid du Colombier 
1807dd7cddfSDavid du Colombier             table = farmalloc(total_size);
1817dd7cddfSDavid du Colombier 
1827dd7cddfSDavid du Colombier             if (table == NULL)
1837dd7cddfSDavid du Colombier             {
184*593dc095SDavid du Colombier #ifndef PNG_USER_MEM_SUPPORTED
185*593dc095SDavid du Colombier                if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
1867dd7cddfSDavid du Colombier                   png_error(png_ptr, "Out Of Memory."); /* Note "O" and "M" */
187*593dc095SDavid du Colombier                else
188*593dc095SDavid du Colombier                   png_warning(png_ptr, "Out Of Memory.");
189*593dc095SDavid du Colombier #endif
190*593dc095SDavid du Colombier                return (NULL);
1917dd7cddfSDavid du Colombier             }
1927dd7cddfSDavid du Colombier 
1937dd7cddfSDavid du Colombier             if ((png_size_t)table & 0xfff0)
1947dd7cddfSDavid du Colombier             {
195*593dc095SDavid du Colombier #ifndef PNG_USER_MEM_SUPPORTED
196*593dc095SDavid du Colombier                if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
197*593dc095SDavid du Colombier                   png_error(png_ptr,
198*593dc095SDavid du Colombier                     "Farmalloc didn't return normalized pointer");
199*593dc095SDavid du Colombier                else
200*593dc095SDavid du Colombier                   png_warning(png_ptr,
201*593dc095SDavid du Colombier                     "Farmalloc didn't return normalized pointer");
202*593dc095SDavid du Colombier #endif
203*593dc095SDavid du Colombier                return (NULL);
2047dd7cddfSDavid du Colombier             }
2057dd7cddfSDavid du Colombier 
2067dd7cddfSDavid du Colombier             png_ptr->offset_table = table;
2077dd7cddfSDavid du Colombier             png_ptr->offset_table_ptr = farmalloc(num_blocks *
208*593dc095SDavid du Colombier                png_sizeof (png_bytep));
2097dd7cddfSDavid du Colombier 
2107dd7cddfSDavid du Colombier             if (png_ptr->offset_table_ptr == NULL)
2117dd7cddfSDavid du Colombier             {
212*593dc095SDavid du Colombier #ifndef PNG_USER_MEM_SUPPORTED
213*593dc095SDavid du Colombier                if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
214*593dc095SDavid du Colombier                   png_error(png_ptr, "Out Of memory."); /* Note "O" and "M" */
215*593dc095SDavid du Colombier                else
216*593dc095SDavid du Colombier                   png_warning(png_ptr, "Out Of memory.");
217*593dc095SDavid du Colombier #endif
218*593dc095SDavid du Colombier                return (NULL);
2197dd7cddfSDavid du Colombier             }
2207dd7cddfSDavid du Colombier 
2217dd7cddfSDavid du Colombier             hptr = (png_byte huge *)table;
2227dd7cddfSDavid du Colombier             if ((png_size_t)hptr & 0xf)
2237dd7cddfSDavid du Colombier             {
2247dd7cddfSDavid du Colombier                hptr = (png_byte huge *)((long)(hptr) & 0xfffffff0L);
225*593dc095SDavid du Colombier                hptr = hptr + 16L;  /* "hptr += 16L" fails on Turbo C++ 3.0 */
2267dd7cddfSDavid du Colombier             }
2277dd7cddfSDavid du Colombier             for (i = 0; i < num_blocks; i++)
2287dd7cddfSDavid du Colombier             {
2297dd7cddfSDavid du Colombier                png_ptr->offset_table_ptr[i] = (png_bytep)hptr;
230*593dc095SDavid du Colombier                hptr = hptr + (png_uint_32)65536L;  /* "+=" fails on TC++3.0 */
2317dd7cddfSDavid du Colombier             }
2327dd7cddfSDavid du Colombier 
2337dd7cddfSDavid du Colombier             png_ptr->offset_table_number = num_blocks;
2347dd7cddfSDavid du Colombier             png_ptr->offset_table_count = 0;
2357dd7cddfSDavid du Colombier             png_ptr->offset_table_count_free = 0;
2367dd7cddfSDavid du Colombier          }
2377dd7cddfSDavid du Colombier       }
2387dd7cddfSDavid du Colombier 
2397dd7cddfSDavid du Colombier       if (png_ptr->offset_table_count >= png_ptr->offset_table_number)
240*593dc095SDavid du Colombier       {
241*593dc095SDavid du Colombier #ifndef PNG_USER_MEM_SUPPORTED
242*593dc095SDavid du Colombier          if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
243*593dc095SDavid du Colombier             png_error(png_ptr, "Out of Memory."); /* Note "o" and "M" */
244*593dc095SDavid du Colombier          else
245*593dc095SDavid du Colombier             png_warning(png_ptr, "Out of Memory.");
246*593dc095SDavid du Colombier #endif
247*593dc095SDavid du Colombier          return (NULL);
248*593dc095SDavid du Colombier       }
2497dd7cddfSDavid du Colombier 
2507dd7cddfSDavid du Colombier       ret = png_ptr->offset_table_ptr[png_ptr->offset_table_count++];
2517dd7cddfSDavid du Colombier    }
2527dd7cddfSDavid du Colombier    else
2537dd7cddfSDavid du Colombier       ret = farmalloc(size);
2547dd7cddfSDavid du Colombier 
255*593dc095SDavid du Colombier #ifndef PNG_USER_MEM_SUPPORTED
2567dd7cddfSDavid du Colombier    if (ret == NULL)
2577dd7cddfSDavid du Colombier    {
258*593dc095SDavid du Colombier       if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
2597dd7cddfSDavid du Colombier          png_error(png_ptr, "Out of memory."); /* Note "o" and "m" */
260*593dc095SDavid du Colombier       else
261*593dc095SDavid du Colombier          png_warning(png_ptr, "Out of memory."); /* Note "o" and "m" */
262*593dc095SDavid du Colombier    }
263*593dc095SDavid du Colombier #endif
264*593dc095SDavid du Colombier 
265*593dc095SDavid du Colombier    return (ret);
2667dd7cddfSDavid du Colombier }
2677dd7cddfSDavid du Colombier 
268*593dc095SDavid du Colombier /* free a pointer allocated by png_malloc().  In the default
2697dd7cddfSDavid du Colombier    configuration, png_ptr is not used, but is passed in case it
2707dd7cddfSDavid du Colombier    is needed.  If ptr is NULL, return without taking any action. */
271*593dc095SDavid du Colombier void PNGAPI
png_free(png_structp png_ptr,png_voidp ptr)272*593dc095SDavid du Colombier png_free(png_structp png_ptr, png_voidp ptr)
2737dd7cddfSDavid du Colombier {
2747dd7cddfSDavid du Colombier    if (png_ptr == NULL || ptr == NULL)
2757dd7cddfSDavid du Colombier       return;
2767dd7cddfSDavid du Colombier 
277*593dc095SDavid du Colombier #ifdef PNG_USER_MEM_SUPPORTED
278*593dc095SDavid du Colombier    if (png_ptr->free_fn != NULL)
279*593dc095SDavid du Colombier    {
280*593dc095SDavid du Colombier       (*(png_ptr->free_fn))(png_ptr, ptr);
281*593dc095SDavid du Colombier       return;
282*593dc095SDavid du Colombier    }
283*593dc095SDavid du Colombier    else png_free_default(png_ptr, ptr);
284*593dc095SDavid du Colombier }
285*593dc095SDavid du Colombier 
286*593dc095SDavid du Colombier void PNGAPI
png_free_default(png_structp png_ptr,png_voidp ptr)287*593dc095SDavid du Colombier png_free_default(png_structp png_ptr, png_voidp ptr)
288*593dc095SDavid du Colombier {
289*593dc095SDavid du Colombier #endif /* PNG_USER_MEM_SUPPORTED */
290*593dc095SDavid du Colombier 
2917dd7cddfSDavid du Colombier    if (png_ptr->offset_table != NULL)
2927dd7cddfSDavid du Colombier    {
2937dd7cddfSDavid du Colombier       int i;
2947dd7cddfSDavid du Colombier 
2957dd7cddfSDavid du Colombier       for (i = 0; i < png_ptr->offset_table_count; i++)
2967dd7cddfSDavid du Colombier       {
2977dd7cddfSDavid du Colombier          if (ptr == png_ptr->offset_table_ptr[i])
2987dd7cddfSDavid du Colombier          {
2997dd7cddfSDavid du Colombier             ptr = NULL;
3007dd7cddfSDavid du Colombier             png_ptr->offset_table_count_free++;
3017dd7cddfSDavid du Colombier             break;
3027dd7cddfSDavid du Colombier          }
3037dd7cddfSDavid du Colombier       }
3047dd7cddfSDavid du Colombier       if (png_ptr->offset_table_count_free == png_ptr->offset_table_count)
3057dd7cddfSDavid du Colombier       {
3067dd7cddfSDavid du Colombier          farfree(png_ptr->offset_table);
3077dd7cddfSDavid du Colombier          farfree(png_ptr->offset_table_ptr);
3087dd7cddfSDavid du Colombier          png_ptr->offset_table = NULL;
3097dd7cddfSDavid du Colombier          png_ptr->offset_table_ptr = NULL;
3107dd7cddfSDavid du Colombier       }
3117dd7cddfSDavid du Colombier    }
3127dd7cddfSDavid du Colombier 
3137dd7cddfSDavid du Colombier    if (ptr != NULL)
3147dd7cddfSDavid du Colombier    {
3157dd7cddfSDavid du Colombier       farfree(ptr);
3167dd7cddfSDavid du Colombier    }
3177dd7cddfSDavid du Colombier }
3187dd7cddfSDavid du Colombier 
3197dd7cddfSDavid du Colombier #else /* Not the Borland DOS special memory handler */
3207dd7cddfSDavid du Colombier 
3217dd7cddfSDavid du Colombier /* Allocate memory for a png_struct or a png_info.  The malloc and
3227dd7cddfSDavid du Colombier    memset can be replaced by a single call to calloc() if this is thought
3237dd7cddfSDavid du Colombier    to improve performance noticably. */
324*593dc095SDavid du Colombier png_voidp /* PRIVATE */
png_create_struct(int type)3257dd7cddfSDavid du Colombier png_create_struct(int type)
3267dd7cddfSDavid du Colombier {
327*593dc095SDavid du Colombier #ifdef PNG_USER_MEM_SUPPORTED
328*593dc095SDavid du Colombier    return (png_create_struct_2(type, png_malloc_ptr_NULL, png_voidp_NULL));
329*593dc095SDavid du Colombier }
330*593dc095SDavid du Colombier 
331*593dc095SDavid du Colombier /* Allocate memory for a png_struct or a png_info.  The malloc and
332*593dc095SDavid du Colombier    memset can be replaced by a single call to calloc() if this is thought
333*593dc095SDavid du Colombier    to improve performance noticably. */
334*593dc095SDavid du Colombier png_voidp /* PRIVATE */
png_create_struct_2(int type,png_malloc_ptr malloc_fn,png_voidp mem_ptr)335*593dc095SDavid du Colombier png_create_struct_2(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr)
336*593dc095SDavid du Colombier {
337*593dc095SDavid du Colombier #endif /* PNG_USER_MEM_SUPPORTED */
3387dd7cddfSDavid du Colombier    png_size_t size;
3397dd7cddfSDavid du Colombier    png_voidp struct_ptr;
3407dd7cddfSDavid du Colombier 
3417dd7cddfSDavid du Colombier    if (type == PNG_STRUCT_INFO)
342*593dc095SDavid du Colombier       size = png_sizeof(png_info);
3437dd7cddfSDavid du Colombier    else if (type == PNG_STRUCT_PNG)
344*593dc095SDavid du Colombier       size = png_sizeof(png_struct);
3457dd7cddfSDavid du Colombier    else
346*593dc095SDavid du Colombier       return (NULL);
347*593dc095SDavid du Colombier 
348*593dc095SDavid du Colombier #ifdef PNG_USER_MEM_SUPPORTED
349*593dc095SDavid du Colombier    if(malloc_fn != NULL)
350*593dc095SDavid du Colombier    {
351*593dc095SDavid du Colombier       png_struct dummy_struct;
352*593dc095SDavid du Colombier       png_structp png_ptr = &dummy_struct;
353*593dc095SDavid du Colombier       png_ptr->mem_ptr=mem_ptr;
354*593dc095SDavid du Colombier       struct_ptr = (*(malloc_fn))(png_ptr, size);
355*593dc095SDavid du Colombier       if (struct_ptr != NULL)
356*593dc095SDavid du Colombier          png_memset(struct_ptr, 0, size);
357*593dc095SDavid du Colombier       return (struct_ptr);
358*593dc095SDavid du Colombier    }
359*593dc095SDavid du Colombier #endif /* PNG_USER_MEM_SUPPORTED */
3607dd7cddfSDavid du Colombier 
3617dd7cddfSDavid du Colombier #if defined(__TURBOC__) && !defined(__FLAT__)
362*593dc095SDavid du Colombier    struct_ptr = (png_voidp)farmalloc(size);
3637dd7cddfSDavid du Colombier #else
3647dd7cddfSDavid du Colombier # if defined(_MSC_VER) && defined(MAXSEG_64K)
365*593dc095SDavid du Colombier    struct_ptr = (png_voidp)halloc(size,1);
3667dd7cddfSDavid du Colombier # else
367*593dc095SDavid du Colombier    struct_ptr = (png_voidp)malloc(size);
3687dd7cddfSDavid du Colombier # endif
3697dd7cddfSDavid du Colombier #endif
370*593dc095SDavid du Colombier    if (struct_ptr != NULL)
3717dd7cddfSDavid du Colombier       png_memset(struct_ptr, 0, size);
3727dd7cddfSDavid du Colombier 
373*593dc095SDavid du Colombier    return (struct_ptr);
3747dd7cddfSDavid du Colombier }
3757dd7cddfSDavid du Colombier 
3767dd7cddfSDavid du Colombier 
3777dd7cddfSDavid du Colombier /* Free memory allocated by a png_create_struct() call */
378*593dc095SDavid du Colombier void /* PRIVATE */
png_destroy_struct(png_voidp struct_ptr)3797dd7cddfSDavid du Colombier png_destroy_struct(png_voidp struct_ptr)
3807dd7cddfSDavid du Colombier {
381*593dc095SDavid du Colombier #ifdef PNG_USER_MEM_SUPPORTED
382*593dc095SDavid du Colombier    png_destroy_struct_2(struct_ptr, png_free_ptr_NULL, png_voidp_NULL);
383*593dc095SDavid du Colombier }
384*593dc095SDavid du Colombier 
385*593dc095SDavid du Colombier /* Free memory allocated by a png_create_struct() call */
386*593dc095SDavid du Colombier void /* PRIVATE */
png_destroy_struct_2(png_voidp struct_ptr,png_free_ptr free_fn,png_voidp mem_ptr)387*593dc095SDavid du Colombier png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn,
388*593dc095SDavid du Colombier     png_voidp mem_ptr)
389*593dc095SDavid du Colombier {
390*593dc095SDavid du Colombier #endif /* PNG_USER_MEM_SUPPORTED */
3917dd7cddfSDavid du Colombier    if (struct_ptr != NULL)
3927dd7cddfSDavid du Colombier    {
393*593dc095SDavid du Colombier #ifdef PNG_USER_MEM_SUPPORTED
394*593dc095SDavid du Colombier       if(free_fn != NULL)
395*593dc095SDavid du Colombier       {
396*593dc095SDavid du Colombier          png_struct dummy_struct;
397*593dc095SDavid du Colombier          png_structp png_ptr = &dummy_struct;
398*593dc095SDavid du Colombier          png_ptr->mem_ptr=mem_ptr;
399*593dc095SDavid du Colombier          (*(free_fn))(png_ptr, struct_ptr);
400*593dc095SDavid du Colombier          return;
401*593dc095SDavid du Colombier       }
402*593dc095SDavid du Colombier #endif /* PNG_USER_MEM_SUPPORTED */
4037dd7cddfSDavid du Colombier #if defined(__TURBOC__) && !defined(__FLAT__)
4047dd7cddfSDavid du Colombier       farfree(struct_ptr);
4057dd7cddfSDavid du Colombier #else
4067dd7cddfSDavid du Colombier # if defined(_MSC_VER) && defined(MAXSEG_64K)
4077dd7cddfSDavid du Colombier       hfree(struct_ptr);
4087dd7cddfSDavid du Colombier # else
4097dd7cddfSDavid du Colombier       free(struct_ptr);
4107dd7cddfSDavid du Colombier # endif
4117dd7cddfSDavid du Colombier #endif
4127dd7cddfSDavid du Colombier    }
4137dd7cddfSDavid du Colombier }
4147dd7cddfSDavid du Colombier 
4157dd7cddfSDavid du Colombier /* Allocate memory.  For reasonable files, size should never exceed
4167dd7cddfSDavid du Colombier    64K.  However, zlib may allocate more then 64K if you don't tell
4177dd7cddfSDavid du Colombier    it not to.  See zconf.h and png.h for more information.  zlib does
4187dd7cddfSDavid du Colombier    need to allocate exactly 64K, so whatever you call here must
4197dd7cddfSDavid du Colombier    have the ability to do that. */
4207dd7cddfSDavid du Colombier 
421*593dc095SDavid du Colombier png_voidp PNGAPI
png_malloc(png_structp png_ptr,png_uint_32 size)422*593dc095SDavid du Colombier png_malloc(png_structp png_ptr, png_uint_32 size)
4237dd7cddfSDavid du Colombier {
4247dd7cddfSDavid du Colombier    png_voidp ret;
4257dd7cddfSDavid du Colombier 
426*593dc095SDavid du Colombier #ifdef PNG_USER_MEM_SUPPORTED
427*593dc095SDavid du Colombier    if (png_ptr == NULL || size == 0)
428*593dc095SDavid du Colombier       return (NULL);
429*593dc095SDavid du Colombier 
430*593dc095SDavid du Colombier    if(png_ptr->malloc_fn != NULL)
431*593dc095SDavid du Colombier        ret = ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, (png_size_t)size));
432*593dc095SDavid du Colombier    else
433*593dc095SDavid du Colombier        ret = (png_malloc_default(png_ptr, size));
434*593dc095SDavid du Colombier    if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
435*593dc095SDavid du Colombier        png_error(png_ptr, "Out of Memory!");
436*593dc095SDavid du Colombier    return (ret);
437*593dc095SDavid du Colombier }
438*593dc095SDavid du Colombier 
439*593dc095SDavid du Colombier png_voidp PNGAPI
png_malloc_default(png_structp png_ptr,png_uint_32 size)440*593dc095SDavid du Colombier png_malloc_default(png_structp png_ptr, png_uint_32 size)
441*593dc095SDavid du Colombier {
442*593dc095SDavid du Colombier    png_voidp ret;
443*593dc095SDavid du Colombier #endif /* PNG_USER_MEM_SUPPORTED */
444*593dc095SDavid du Colombier 
445*593dc095SDavid du Colombier    if (png_ptr == NULL || size == 0)
446*593dc095SDavid du Colombier       return (NULL);
4477dd7cddfSDavid du Colombier 
4487dd7cddfSDavid du Colombier #ifdef PNG_MAX_MALLOC_64K
4497dd7cddfSDavid du Colombier    if (size > (png_uint_32)65536L)
450*593dc095SDavid du Colombier    {
451*593dc095SDavid du Colombier #ifndef PNG_USER_MEM_SUPPORTED
452*593dc095SDavid du Colombier       if(png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
4537dd7cddfSDavid du Colombier          png_error(png_ptr, "Cannot Allocate > 64K");
454*593dc095SDavid du Colombier       else
455*593dc095SDavid du Colombier #endif
456*593dc095SDavid du Colombier          return NULL;
457*593dc095SDavid du Colombier    }
4587dd7cddfSDavid du Colombier #endif
4597dd7cddfSDavid du Colombier 
460*593dc095SDavid du Colombier  /* Check for overflow */
4617dd7cddfSDavid du Colombier #if defined(__TURBOC__) && !defined(__FLAT__)
462*593dc095SDavid du Colombier  if (size != (unsigned long)size)
463*593dc095SDavid du Colombier    ret = NULL;
464*593dc095SDavid du Colombier  else
4657dd7cddfSDavid du Colombier    ret = farmalloc(size);
4667dd7cddfSDavid du Colombier #else
4677dd7cddfSDavid du Colombier # if defined(_MSC_VER) && defined(MAXSEG_64K)
468*593dc095SDavid du Colombier  if (size != (unsigned long)size)
469*593dc095SDavid du Colombier    ret = NULL;
470*593dc095SDavid du Colombier  else
4717dd7cddfSDavid du Colombier    ret = halloc(size, 1);
4727dd7cddfSDavid du Colombier # else
473*593dc095SDavid du Colombier  if (size != (size_t)size)
474*593dc095SDavid du Colombier    ret = NULL;
475*593dc095SDavid du Colombier  else
476*593dc095SDavid du Colombier    ret = malloc((size_t)size);
4777dd7cddfSDavid du Colombier # endif
4787dd7cddfSDavid du Colombier #endif
4797dd7cddfSDavid du Colombier 
480*593dc095SDavid du Colombier #ifndef PNG_USER_MEM_SUPPORTED
481*593dc095SDavid du Colombier    if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
4827dd7cddfSDavid du Colombier       png_error(png_ptr, "Out of Memory");
483*593dc095SDavid du Colombier #endif
484*593dc095SDavid du Colombier 
485*593dc095SDavid du Colombier    return (ret);
4867dd7cddfSDavid du Colombier }
4877dd7cddfSDavid du Colombier 
488*593dc095SDavid du Colombier /* Free a pointer allocated by png_malloc().  If ptr is NULL, return
489*593dc095SDavid du Colombier    without taking any action. */
490*593dc095SDavid du Colombier void PNGAPI
png_free(png_structp png_ptr,png_voidp ptr)491*593dc095SDavid du Colombier png_free(png_structp png_ptr, png_voidp ptr)
4927dd7cddfSDavid du Colombier {
4937dd7cddfSDavid du Colombier    if (png_ptr == NULL || ptr == NULL)
4947dd7cddfSDavid du Colombier       return;
4957dd7cddfSDavid du Colombier 
496*593dc095SDavid du Colombier #ifdef PNG_USER_MEM_SUPPORTED
497*593dc095SDavid du Colombier    if (png_ptr->free_fn != NULL)
498*593dc095SDavid du Colombier    {
499*593dc095SDavid du Colombier       (*(png_ptr->free_fn))(png_ptr, ptr);
500*593dc095SDavid du Colombier       return;
501*593dc095SDavid du Colombier    }
502*593dc095SDavid du Colombier    else png_free_default(png_ptr, ptr);
503*593dc095SDavid du Colombier }
504*593dc095SDavid du Colombier void PNGAPI
png_free_default(png_structp png_ptr,png_voidp ptr)505*593dc095SDavid du Colombier png_free_default(png_structp png_ptr, png_voidp ptr)
506*593dc095SDavid du Colombier {
507*593dc095SDavid du Colombier    if (png_ptr == NULL || ptr == NULL)
508*593dc095SDavid du Colombier       return;
509*593dc095SDavid du Colombier 
510*593dc095SDavid du Colombier #endif /* PNG_USER_MEM_SUPPORTED */
511*593dc095SDavid du Colombier 
5127dd7cddfSDavid du Colombier #if defined(__TURBOC__) && !defined(__FLAT__)
5137dd7cddfSDavid du Colombier    farfree(ptr);
5147dd7cddfSDavid du Colombier #else
5157dd7cddfSDavid du Colombier # if defined(_MSC_VER) && defined(MAXSEG_64K)
5167dd7cddfSDavid du Colombier    hfree(ptr);
5177dd7cddfSDavid du Colombier # else
5187dd7cddfSDavid du Colombier    free(ptr);
5197dd7cddfSDavid du Colombier # endif
5207dd7cddfSDavid du Colombier #endif
5217dd7cddfSDavid du Colombier }
5227dd7cddfSDavid du Colombier 
5237dd7cddfSDavid du Colombier #endif /* Not Borland DOS special memory handler */
5247dd7cddfSDavid du Colombier 
525*593dc095SDavid du Colombier #if defined(PNG_1_0_X)
526*593dc095SDavid du Colombier #  define png_malloc_warn png_malloc
527*593dc095SDavid du Colombier #else
528*593dc095SDavid du Colombier /* This function was added at libpng version 1.2.3.  The png_malloc_warn()
529*593dc095SDavid du Colombier  * function will set up png_malloc() to issue a png_warning and return NULL
530*593dc095SDavid du Colombier  * instead of issuing a png_error, if it fails to allocate the requested
531*593dc095SDavid du Colombier  * memory.
532*593dc095SDavid du Colombier  */
533*593dc095SDavid du Colombier png_voidp PNGAPI
png_malloc_warn(png_structp png_ptr,png_uint_32 size)534*593dc095SDavid du Colombier png_malloc_warn(png_structp png_ptr, png_uint_32 size)
535*593dc095SDavid du Colombier {
536*593dc095SDavid du Colombier    png_voidp ptr;
537*593dc095SDavid du Colombier    png_uint_32 save_flags=png_ptr->flags;
538*593dc095SDavid du Colombier 
539*593dc095SDavid du Colombier    png_ptr->flags|=PNG_FLAG_MALLOC_NULL_MEM_OK;
540*593dc095SDavid du Colombier    ptr = (png_voidp)png_malloc((png_structp)png_ptr, size);
541*593dc095SDavid du Colombier    png_ptr->flags=save_flags;
542*593dc095SDavid du Colombier    return(ptr);
543*593dc095SDavid du Colombier }
544*593dc095SDavid du Colombier #endif
545*593dc095SDavid du Colombier 
546*593dc095SDavid du Colombier png_voidp PNGAPI
png_memcpy_check(png_structp png_ptr,png_voidp s1,png_voidp s2,png_uint_32 length)547*593dc095SDavid du Colombier png_memcpy_check (png_structp png_ptr, png_voidp s1, png_voidp s2,
548*593dc095SDavid du Colombier    png_uint_32 length)
549*593dc095SDavid du Colombier {
550*593dc095SDavid du Colombier    png_size_t size;
551*593dc095SDavid du Colombier 
552*593dc095SDavid du Colombier    size = (png_size_t)length;
553*593dc095SDavid du Colombier    if ((png_uint_32)size != length)
554*593dc095SDavid du Colombier       png_error(png_ptr,"Overflow in png_memcpy_check.");
555*593dc095SDavid du Colombier 
556*593dc095SDavid du Colombier    return(png_memcpy (s1, s2, size));
557*593dc095SDavid du Colombier }
558*593dc095SDavid du Colombier 
559*593dc095SDavid du Colombier png_voidp PNGAPI
png_memset_check(png_structp png_ptr,png_voidp s1,int value,png_uint_32 length)560*593dc095SDavid du Colombier png_memset_check (png_structp png_ptr, png_voidp s1, int value,
561*593dc095SDavid du Colombier    png_uint_32 length)
562*593dc095SDavid du Colombier {
563*593dc095SDavid du Colombier    png_size_t size;
564*593dc095SDavid du Colombier 
565*593dc095SDavid du Colombier    size = (png_size_t)length;
566*593dc095SDavid du Colombier    if ((png_uint_32)size != length)
567*593dc095SDavid du Colombier       png_error(png_ptr,"Overflow in png_memset_check.");
568*593dc095SDavid du Colombier 
569*593dc095SDavid du Colombier    return (png_memset (s1, value, size));
570*593dc095SDavid du Colombier 
571*593dc095SDavid du Colombier }
572*593dc095SDavid du Colombier 
573*593dc095SDavid du Colombier #ifdef PNG_USER_MEM_SUPPORTED
574*593dc095SDavid du Colombier /* This function is called when the application wants to use another method
575*593dc095SDavid du Colombier  * of allocating and freeing memory.
576*593dc095SDavid du Colombier  */
577*593dc095SDavid du Colombier void PNGAPI
png_set_mem_fn(png_structp png_ptr,png_voidp mem_ptr,png_malloc_ptr malloc_fn,png_free_ptr free_fn)578*593dc095SDavid du Colombier png_set_mem_fn(png_structp png_ptr, png_voidp mem_ptr, png_malloc_ptr
579*593dc095SDavid du Colombier   malloc_fn, png_free_ptr free_fn)
580*593dc095SDavid du Colombier {
581*593dc095SDavid du Colombier    png_ptr->mem_ptr = mem_ptr;
582*593dc095SDavid du Colombier    png_ptr->malloc_fn = malloc_fn;
583*593dc095SDavid du Colombier    png_ptr->free_fn = free_fn;
584*593dc095SDavid du Colombier }
585*593dc095SDavid du Colombier 
586*593dc095SDavid du Colombier /* This function returns a pointer to the mem_ptr associated with the user
587*593dc095SDavid du Colombier  * functions.  The application should free any memory associated with this
588*593dc095SDavid du Colombier  * pointer before png_write_destroy and png_read_destroy are called.
589*593dc095SDavid du Colombier  */
590*593dc095SDavid du Colombier png_voidp PNGAPI
png_get_mem_ptr(png_structp png_ptr)591*593dc095SDavid du Colombier png_get_mem_ptr(png_structp png_ptr)
592*593dc095SDavid du Colombier {
593*593dc095SDavid du Colombier    return ((png_voidp)png_ptr->mem_ptr);
594*593dc095SDavid du Colombier }
595*593dc095SDavid du Colombier #endif /* PNG_USER_MEM_SUPPORTED */
596