source: trunk/third/libpng/pngmem.c @ 18166

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