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