pngmem.c 13.3 KB
Newer Older
1

2
/* pngmem.c - stub functions for memory allocation
3
 *
4
 * libpng 1.0.5 - October 5, 1999
5 6 7
 * For conditions of distribution and use, see copyright notice in png.h
 * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
 * Copyright (c) 1996, 1997 Andreas Dilger
8
 * Copyright (c) 1998, 1999 Glenn Randers-Pehrson
9
 *
10
 * This file provides a location for all memory allocation.  Users who
11 12 13 14
 * need special memory handling are expected to supply replacement
 * functions for png_malloc() and png_free(), and to use
 * png_create_read_struct_2() and png_create_write_struct_2() to
 * identify the replacement functions.
15
 */
16 17 18 19

#define PNG_INTERNAL
#include "png.h"

20 21 22 23
/* Borland DOS special memory handler */
#if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__)
/* if you change this, be sure to change the one in png.h also */

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
27
png_create_struct(int type)
28
{
29 30 31 32 33 34 35 36 37
#ifdef PNG_USER_MEM_SUPPORTED
   return (png_create_struct_2(type, NULL));
}

/* Alternate version of png_create_struct, for use with user-defined malloc. */
png_voidp
png_create_struct_2(int type, png_malloc_ptr malloc_fn)
{
#endif /* PNG_USER_MEM_SUPPORTED */
38
   png_size_t size;
39 40 41 42 43 44 45
   png_voidp struct_ptr;

   if (type == PNG_STRUCT_INFO)
     size = sizeof(png_info);
   else if (type == PNG_STRUCT_PNG)
     size = sizeof(png_struct);
   else
46
     return ((png_voidp)NULL);
47

48 49 50 51 52 53 54 55
#ifdef PNG_USER_MEM_SUPPORTED
   if(malloc_fn != NULL)
   {
      if ((struct_ptr = (*(malloc_fn))(NULL, size)) != NULL)
         png_memset(struct_ptr, 0, size);
         return (struct_ptr);
   }
#endif /* PNG_USER_MEM_SUPPORTED */
56 57 58 59 60 61 62 63 64 65 66 67
   if ((struct_ptr = (png_voidp)farmalloc(size)) != NULL)
   {
      png_memset(struct_ptr, 0, size);
   }
   return (struct_ptr);
}


/* Free memory allocated by a png_create_struct() call */
void
png_destroy_struct(png_voidp struct_ptr)
{
68 69 70 71 72 73 74 75 76
#ifdef PNG_USER_MEM_SUPPORTED
   png_destroy_struct_2(struct_ptr, (png_free_ptr)NULL);
}

/* Free memory allocated by a png_create_struct() call */
void
png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn)
{
#endif
77
   if (struct_ptr != NULL)
78
   {
79 80 81 82 83 84
#ifdef PNG_USER_MEM_SUPPORTED
      if(free_fn != NULL)
      {
         png_struct dummy_struct;
         png_structp png_ptr = &dummy_struct;
         (*(free_fn))(png_ptr, struct_ptr);
85
         struct_ptr = NULL;
86 87 88
         return;
      }
#endif /* PNG_USER_MEM_SUPPORTED */
89
      farfree (struct_ptr);
90
      struct_ptr = NULL;
91
   }
92 93
}

94
/* Allocate memory.  For reasonable files, size should never exceed
95 96 97 98 99 100
 * 64K.  However, zlib may allocate more then 64K if you don't tell
 * it not to.  See zconf.h and png.h for more information. zlib does
 * need to allocate exactly 64K, so whatever you call here must
 * have the ability to do that.
 *
 * 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 103 104 105 106 107 108 109 110 111 112
 * memory stuff).  zlib doesn't like this at all, so we have to
 * detect and deal with it.  This code should not be needed in
 * Windows or OS/2 modes, and only in 16 bit mode.  This code has
 * been updated by Alexander Lehmann for version 0.89 to waste less
 * memory.
 *
 * Note that we can't use png_size_t for the "size" declaration,
 * since on some systems a png_size_t is a 16-bit quantity, and as a
 * result, we would be truncating potentially larger memory requests
 * (which should cause a fatal error) and introducing major problems.
 */
113
png_voidp
114
png_malloc(png_structp png_ptr, png_uint_32 size)
115
{
116
#ifndef PNG_USER_MEM_SUPPORTED
117
   png_voidp ret;
118
#endif
119
   if (png_ptr == NULL || size == 0)
120
      return ((png_voidp)NULL);
121

122 123 124 125 126 127 128 129 130 131 132
#ifdef PNG_USER_MEM_SUPPORTED
   if(png_ptr->malloc_fn != NULL)
       return ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, size));
   else
       return png_malloc_default(png_ptr, size);
}

png_voidp
png_malloc_default(png_structp png_ptr, png_uint_32 size)
{
   png_voidp ret;
133
#endif /* PNG_USER_MEM_SUPPORTED */
134

135
#ifdef PNG_MAX_MALLOC_64K
136 137
   if (size > (png_uint_32)65536L)
      png_error(png_ptr, "Cannot Allocate > 64K");
138 139
#endif

140
   if (size == (png_uint_32)65536L)
141
   {
142
      if (png_ptr->offset_table == NULL)
143 144 145
      {
         /* try to see if we need to do any of this fancy stuff */
         ret = farmalloc(size);
146
         if (ret == NULL || ((png_size_t)ret & 0xffff))
147 148 149 150 151
         {
            int num_blocks;
            png_uint_32 total_size;
            png_bytep table;
            int i;
152 153
            png_byte huge * hptr;

154
            if (ret != NULL)
155
            {
156
               farfree(ret);
157 158
               ret = NULL;
            }
159

160 161 162
            if(png_ptr->zlib_window_bits > 14)
               num_blocks = (int)(1 << (png_ptr->zlib_window_bits - 14));
            else
163 164 165 166 167 168
               num_blocks = 1;
            if (png_ptr->zlib_mem_level >= 7)
               num_blocks += (int)(1 << (png_ptr->zlib_mem_level - 7));
            else
               num_blocks++;

169
            total_size = ((png_uint_32)65536L) * (png_uint_32)num_blocks+16;
170 171 172

            table = farmalloc(total_size);

173
            if (table == NULL)
174
            {
175
               png_error(png_ptr, "Out Of Memory."); /* Note "O" and "M" */
176 177
            }

178
            if ((png_size_t)table & 0xfff0)
179
            {
180
               png_error(png_ptr, "Farmalloc didn't return normalized pointer");
181 182
            }

183
            png_ptr->offset_table = table;
184 185
            png_ptr->offset_table_ptr = farmalloc(num_blocks *
               sizeof (png_bytep));
186

187
            if (png_ptr->offset_table_ptr == NULL)
188
            {
189
               png_error(png_ptr, "Out Of memory.");
190 191 192
            }

            hptr = (png_byte huge *)table;
193
            if ((png_size_t)hptr & 0xf)
194
            {
195
               hptr = (png_byte huge *)((long)(hptr) & 0xfffffff0L);
196
               hptr = hptr + 16L;  /* "hptr += 16L" fails on Turbo C++ 3.0 */
197 198 199 200
            }
            for (i = 0; i < num_blocks; i++)
            {
               png_ptr->offset_table_ptr[i] = (png_bytep)hptr;
201
               hptr = hptr + (png_uint_32)65536L;  /* "+=" fails on TC++3.0 */
202 203 204 205 206 207
            }

            png_ptr->offset_table_number = num_blocks;
            png_ptr->offset_table_count = 0;
            png_ptr->offset_table_count_free = 0;
         }
208
      }
209

210
      if (png_ptr->offset_table_count >= png_ptr->offset_table_number)
211
         png_error(png_ptr, "Out of Memory.");
212

213
      ret = png_ptr->offset_table_ptr[png_ptr->offset_table_count++];
214 215 216
   }
   else
      ret = farmalloc(size);
217

218 219
   if (ret == NULL)
   {
220
      png_error(png_ptr, "Out of memory."); /* Note "o" and "m" */
221
   }
222

223
   return (ret);
224 225
}

226
/* free a pointer allocated by png_malloc().  In the default
227 228
   configuration, png_ptr is not used, but is passed in case it
   is needed.  If ptr is NULL, return without taking any action. */
229
void
230
png_free(png_structp png_ptr, png_voidp ptr)
231
{
232
   if (png_ptr == NULL || ptr == NULL)
233 234
      return;

235 236 237 238
#ifdef PNG_USER_MEM_SUPPORTED
   if (png_ptr->free_fn != NULL)
   {
      (*(png_ptr->free_fn))(png_ptr, ptr);
239
      ptr = NULL;
240 241 242 243 244 245 246 247 248
      return;
   }
   else png_free_default(png_ptr, ptr);
}

void
png_free_default(png_structp png_ptr, png_voidp ptr)
{
#endif /* PNG_USER_MEM_SUPPORTED */
249

250
   if (png_ptr->offset_table != NULL)
251
   {
252
      int i;
253

254 255 256
      for (i = 0; i < png_ptr->offset_table_count; i++)
      {
         if (ptr == png_ptr->offset_table_ptr[i])
257
         {
258 259 260
            ptr = NULL;
            png_ptr->offset_table_count_free++;
            break;
261
         }
262
      }
263 264 265 266 267 268 269
      if (png_ptr->offset_table_count_free == png_ptr->offset_table_count)
      {
         farfree(png_ptr->offset_table);
         farfree(png_ptr->offset_table_ptr);
         png_ptr->offset_table = NULL;
         png_ptr->offset_table_ptr = NULL;
      }
270
   }
271 272

   if (ptr != NULL)
273
   {
274
      farfree(ptr);
275
      ptr = NULL;
276
   }
277 278 279 280
}

#else /* Not the Borland DOS special memory handler */

281
/* Allocate memory for a png_struct or a png_info.  The malloc and
282 283
   memset can be replaced by a single call to calloc() if this is thought
   to improve performance noticably.*/
284
png_voidp
285
png_create_struct(int type)
286
{
287 288 289 290 291 292 293 294 295 296 297
#ifdef PNG_USER_MEM_SUPPORTED
   return (png_create_struct_2(type, NULL));
}

/* Allocate memory for a png_struct or a png_info.  The malloc and
   memset can be replaced by a single call to calloc() if this is thought
   to improve performance noticably.*/
png_voidp
png_create_struct_2(int type, png_malloc_ptr malloc_fn)
{
#endif /* PNG_USER_MEM_SUPPORTED */
298
   png_size_t size;
299 300 301
   png_voidp struct_ptr;

   if (type == PNG_STRUCT_INFO)
302
      size = sizeof(png_info);
303
   else if (type == PNG_STRUCT_PNG)
304
      size = sizeof(png_struct);
305
   else
306
      return ((png_voidp)NULL);
307

308 309 310 311 312 313 314 315 316
#ifdef PNG_USER_MEM_SUPPORTED
   if(malloc_fn != NULL)
   {
      if ((struct_ptr = (*(malloc_fn))(NULL, size)) != NULL)
         png_memset(struct_ptr, 0, size);
      return (struct_ptr);
   }
#endif /* PNG_USER_MEM_SUPPORTED */

317 318 319 320
#if defined(__TURBOC__) && !defined(__FLAT__)
   if ((struct_ptr = (png_voidp)farmalloc(size)) != NULL)
#else
# if defined(_MSC_VER) && defined(MAXSEG_64K)
321
   if ((struct_ptr = (png_voidp)halloc(size,1)) != NULL)
322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337
# else
   if ((struct_ptr = (png_voidp)malloc(size)) != NULL)
# endif
#endif
   {
      png_memset(struct_ptr, 0, size);
   }

   return (struct_ptr);
}


/* Free memory allocated by a png_create_struct() call */
void
png_destroy_struct(png_voidp struct_ptr)
{
338 339 340 341 342 343 344 345 346
#ifdef PNG_USER_MEM_SUPPORTED
   png_destroy_struct_2(struct_ptr, (png_free_ptr)NULL);
}

/* Free memory allocated by a png_create_struct() call */
void
png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn)
{
#endif /* PNG_USER_MEM_SUPPORTED */
347
   if (struct_ptr != NULL)
348
   {
349 350 351 352 353 354
#ifdef PNG_USER_MEM_SUPPORTED
      if(free_fn != NULL)
      {
         png_struct dummy_struct;
         png_structp png_ptr = &dummy_struct;
         (*(free_fn))(png_ptr, struct_ptr);
355
         struct_ptr = NULL;
356 357 358
         return;
      }
#endif /* PNG_USER_MEM_SUPPORTED */
359 360
#if defined(__TURBOC__) && !defined(__FLAT__)
      farfree(struct_ptr);
361
      struct_ptr = NULL;
362 363 364
#else
# if defined(_MSC_VER) && defined(MAXSEG_64K)
      hfree(struct_ptr);
365
      struct_ptr = NULL;
366 367
# else
      free(struct_ptr);
368
      struct_ptr = NULL;
369 370
# endif
#endif
371
   }
372 373 374
}


375
/* Allocate memory.  For reasonable files, size should never exceed
376
   64K.  However, zlib may allocate more then 64K if you don't tell
377
   it not to.  See zconf.h and png.h for more information.  zlib does
378 379
   need to allocate exactly 64K, so whatever you call here must
   have the ability to do that. */
380 381

png_voidp
382
png_malloc(png_structp png_ptr, png_uint_32 size)
383
{
384
#ifndef PNG_USER_MEM_SUPPORTED
385
   png_voidp ret;
386
#endif
387
   if (png_ptr == NULL || size == 0)
388
      return ((png_voidp)NULL);
389

390 391 392 393 394 395 396 397 398 399 400 401
#ifdef PNG_USER_MEM_SUPPORTED
   if(png_ptr->malloc_fn != NULL)
       return ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, size));
   else
       return (png_malloc_default(png_ptr, size));
}
png_voidp
png_malloc_default(png_structp png_ptr, png_uint_32 size)
{
   png_voidp ret;
#endif /* PNG_USER_MEM_SUPPORTED */

402
#ifdef PNG_MAX_MALLOC_64K
403
   if (size > (png_uint_32)65536L)
404
      png_error(png_ptr, "Cannot Allocate > 64K");
405 406
#endif

407
#if defined(__TURBOC__) && !defined(__FLAT__)
408
   ret = farmalloc(size);
409
#else
410
# if defined(_MSC_VER) && defined(MAXSEG_64K)
411
   ret = halloc(size, 1);
412
# else
413
   ret = malloc((size_t)size);
414
# endif
415 416
#endif

417
   if (ret == NULL)
418
   {
419
      png_error(png_ptr, "Out of Memory");
420 421
   }

422
   return (ret);
423 424
}

425 426
/* Free a pointer allocated by png_malloc().  If ptr is NULL, return
   without taking any action. */
427
void
428
png_free(png_structp png_ptr, png_voidp ptr)
429
{
430
   if (png_ptr == NULL || ptr == NULL)
431
      return;
432

433 434 435 436
#ifdef PNG_USER_MEM_SUPPORTED
   if (png_ptr->free_fn != NULL)
   {
      (*(png_ptr->free_fn))(png_ptr, ptr);
437
      ptr = NULL;
438 439 440 441 442 443 444 445 446
      return;
   }
   else png_free_default(png_ptr, ptr);
}
void
png_free_default(png_structp png_ptr, png_voidp ptr)
{
#endif /* PNG_USER_MEM_SUPPORTED */

447
#if defined(__TURBOC__) && !defined(__FLAT__)
448
   farfree(ptr);
449
   ptr = NULL;
450
#else
451
# if defined(_MSC_VER) && defined(MAXSEG_64K)
452
   hfree(ptr);
453
   ptr = NULL;
454
# else
455
   free(ptr);
456
   ptr = NULL;
457
# endif
458 459 460
#endif
}

461
#endif /* Not Borland DOS special memory handler */
462

463 464
png_voidp
png_memcpy_check (png_structp png_ptr, png_voidp s1, png_voidp s2,
465 466 467
   png_uint_32 length)
{
   png_size_t size;
468 469 470 471

   size = (png_size_t)length;
   if ((png_uint_32)size != length)
      png_error(png_ptr,"Overflow in png_memcpy_check.");
472

473
   return(png_memcpy (s1, s2, size));
474 475
}

476 477
png_voidp
png_memset_check (png_structp png_ptr, png_voidp s1, int value,
478 479 480
   png_uint_32 length)
{
   png_size_t size;
481 482 483 484 485 486 487

   size = (png_size_t)length;
   if ((png_uint_32)size != length)
      png_error(png_ptr,"Overflow in png_memset_check.");

   return (png_memset (s1, value, size));

488
}
489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512

#ifdef PNG_USER_MEM_SUPPORTED
/* This function is called when the application wants to use another method
 * of allocating and freeing memory.
 */
void
png_set_mem_fn(png_structp png_ptr, png_voidp mem_ptr, png_malloc_ptr
  malloc_fn, png_free_ptr free_fn)
{
   png_ptr->mem_ptr = mem_ptr;
   png_ptr->malloc_fn = malloc_fn;
   png_ptr->free_fn = free_fn;
}

/* This function returns a pointer to the mem_ptr associated with the user
 * functions.  The application should free any memory associated with this
 * pointer before png_write_destroy and png_read_destroy are called.
 */
png_voidp
png_get_mem_ptr(png_structp png_ptr)
{
   return ((png_voidp)png_ptr->mem_ptr);
}
#endif /* PNG_USER_MEM_SUPPORTED */
反馈
建议
客服 返回
顶部