pngmem.c 9.5 KB
Newer Older
G
Guy Schalnat 已提交
1
/* pngmem.c - stub functions for memory allocation
2
 *
3
 * libpng 0.99c
4 5 6
 * 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
7
 * Copyright (c) 1998, Glenn Randers-Pehrson
8
 * February 7, 1998
9 10 11 12 13
 *
 * This file provides a location for all memory allocation.  Users which
 * need special memory handling are expected to modify the code in this file
 * to meet their needs.  See the instructions at each function.
 */
G
Guy Schalnat 已提交
14 15 16 17

#define PNG_INTERNAL
#include "png.h"

18 19 20 21 22 23 24 25 26 27
/* The following "hides" PNG_MALLOC and PNG_FREE thus allowing the pngtest
   application to put a wrapper on top of them. */
#ifdef PNGTEST_MEMORY_DEBUG
   #define PNG_MALLOC png_debug_malloc
   #define PNG_FREE   png_debug_free
#else
   #define PNG_MALLOC png_malloc
   #define PNG_FREE   png_free
#endif

G
Guy Schalnat 已提交
28 29 30 31
/* 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 */

G
Guy Schalnat 已提交
32
/* Allocate memory for a png_struct.  The malloc and memset can be replaced
A
Andreas Dilger 已提交
33
   by a single call to calloc() if this is thought to improve performance. */
G
Guy Schalnat 已提交
34
png_voidp
A
Andreas Dilger 已提交
35
png_create_struct(int type)
G
Guy Schalnat 已提交
36
{
A
Andreas Dilger 已提交
37
   png_size_t size;
G
Guy Schalnat 已提交
38 39 40 41 42 43 44
   png_voidp struct_ptr;

   if (type == PNG_STRUCT_INFO)
     size = sizeof(png_info);
   else if (type == PNG_STRUCT_PNG)
     size = sizeof(png_struct);
   else
45
     return ((png_voidp)NULL);
G
Guy Schalnat 已提交
46 47 48 49 50 51 52 53 54 55 56 57 58 59

   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)
{
A
Andreas Dilger 已提交
60
   if (struct_ptr != NULL)
61
   {
G
Guy Schalnat 已提交
62
      farfree (struct_ptr);
63 64
      struct_ptr = NULL;
   }
G
Guy Schalnat 已提交
65 66
}

G
Guy Schalnat 已提交
67
/* Allocate memory.  For reasonable files, size should never exceed
A
Andreas Dilger 已提交
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
 * 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.
 * It gives you a segment with an offset of 8 (perhaps to store it's
 * 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.
 */
G
Guy Schalnat 已提交
86
png_voidp
87
PNG_MALLOC(png_structp png_ptr, png_uint_32 size)
G
Guy Schalnat 已提交
88
{
G
Guy Schalnat 已提交
89
   png_voidp ret;
A
Andreas Dilger 已提交
90
   if (png_ptr == NULL || size == 0)
91
      return ((png_voidp)NULL);
G
Guy Schalnat 已提交
92 93

#ifdef PNG_MAX_MALLOC_64K
G
Guy Schalnat 已提交
94 95
   if (size > (png_uint_32)65536L)
      png_error(png_ptr, "Cannot Allocate > 64K");
G
Guy Schalnat 已提交
96 97
#endif

98
   if (size == (png_uint_32)65536L)
G
Guy Schalnat 已提交
99
   {
A
Andreas Dilger 已提交
100
      if (png_ptr->offset_table == NULL)
G
Guy Schalnat 已提交
101 102 103
      {
         /* try to see if we need to do any of this fancy stuff */
         ret = farmalloc(size);
A
Andreas Dilger 已提交
104
         if (ret == NULL || ((png_size_t)ret & 0xffff))
G
Guy Schalnat 已提交
105 106 107 108 109
         {
            int num_blocks;
            png_uint_32 total_size;
            png_bytep table;
            int i;
G
Guy Schalnat 已提交
110 111
            png_byte huge * hptr;

A
Andreas Dilger 已提交
112
            if (ret != NULL)
113
            {
G
Guy Schalnat 已提交
114
               farfree(ret);
115 116
               ret = NULL;
            }
G
Guy Schalnat 已提交
117 118 119 120 121 122 123 124 125

            num_blocks = (int)(1 << (png_ptr->zlib_window_bits - 14));
            if (num_blocks < 1)
               num_blocks = 1;
            if (png_ptr->zlib_mem_level >= 7)
               num_blocks += (int)(1 << (png_ptr->zlib_mem_level - 7));
            else
               num_blocks++;

G
Guy Schalnat 已提交
126
            total_size = ((png_uint_32)65536L) * (png_uint_32)num_blocks+16;
G
Guy Schalnat 已提交
127 128 129

            table = farmalloc(total_size);

A
Andreas Dilger 已提交
130
            if (table == NULL)
G
Guy Schalnat 已提交
131
            {
132
               png_error(png_ptr, "Out Of Memory."); /* Note "O" and "M" */
G
Guy Schalnat 已提交
133 134
            }

A
Andreas Dilger 已提交
135
            if ((png_size_t)table & 0xfff0)
G
Guy Schalnat 已提交
136
            {
G
Guy Schalnat 已提交
137
               png_error(png_ptr, "Farmalloc didn't return normalized pointer");
G
Guy Schalnat 已提交
138 139
            }

G
Guy Schalnat 已提交
140
            png_ptr->offset_table = table;
A
Andreas Dilger 已提交
141 142
            png_ptr->offset_table_ptr = farmalloc(num_blocks *
               sizeof (png_bytep));
G
Guy Schalnat 已提交
143

A
Andreas Dilger 已提交
144
            if (png_ptr->offset_table_ptr == NULL)
G
Guy Schalnat 已提交
145
            {
146
               png_error(png_ptr, "Out Of memory.");
G
Guy Schalnat 已提交
147 148 149
            }

            hptr = (png_byte huge *)table;
A
Andreas Dilger 已提交
150
            if ((png_size_t)hptr & 0xf)
G
Guy Schalnat 已提交
151
            {
G
Guy Schalnat 已提交
152 153
               hptr = (png_byte huge *)((long)(hptr) & 0xfffffff0L);
               hptr += 16L;
G
Guy Schalnat 已提交
154 155 156 157
            }
            for (i = 0; i < num_blocks; i++)
            {
               png_ptr->offset_table_ptr[i] = (png_bytep)hptr;
158
               hptr += (png_uint_32)65536L;
G
Guy Schalnat 已提交
159 160 161 162 163 164
            }

            png_ptr->offset_table_number = num_blocks;
            png_ptr->offset_table_count = 0;
            png_ptr->offset_table_count_free = 0;
         }
G
Guy Schalnat 已提交
165
      }
G
Guy Schalnat 已提交
166

G
Guy Schalnat 已提交
167
      if (png_ptr->offset_table_count >= png_ptr->offset_table_number)
168
         png_error(png_ptr, "Out of Memory.");
G
Guy Schalnat 已提交
169

G
Guy Schalnat 已提交
170
      ret = png_ptr->offset_table_ptr[png_ptr->offset_table_count++];
G
Guy Schalnat 已提交
171 172 173
   }
   else
      ret = farmalloc(size);
G
Guy Schalnat 已提交
174

G
Guy Schalnat 已提交
175 176
   if (ret == NULL)
   {
177
      png_error(png_ptr, "Out of memory."); /* Note "o" and "m" */
G
Guy Schalnat 已提交
178
   }
G
Guy Schalnat 已提交
179

180
   return (ret);
G
Guy Schalnat 已提交
181 182
}

183
/* free a pointer allocated by PNG_MALLOC().  In the default
A
Andreas Dilger 已提交
184 185
   configuration, png_ptr is not used, but is passed in case it
   is needed.  If ptr is NULL, return without taking any action. */
G
Guy Schalnat 已提交
186
void
187
PNG_FREE(png_structp png_ptr, png_voidp ptr)
G
Guy Schalnat 已提交
188
{
A
Andreas Dilger 已提交
189
   if (png_ptr == NULL || ptr == NULL)
G
Guy Schalnat 已提交
190 191
      return;

A
Andreas Dilger 已提交
192
   if (png_ptr->offset_table != NULL)
G
Guy Schalnat 已提交
193
   {
A
Andreas Dilger 已提交
194
      int i;
G
Guy Schalnat 已提交
195

A
Andreas Dilger 已提交
196 197 198
      for (i = 0; i < png_ptr->offset_table_count; i++)
      {
         if (ptr == png_ptr->offset_table_ptr[i])
G
Guy Schalnat 已提交
199
         {
A
Andreas Dilger 已提交
200 201 202
            ptr = NULL;
            png_ptr->offset_table_count_free++;
            break;
G
Guy Schalnat 已提交
203
         }
G
Guy Schalnat 已提交
204
      }
A
Andreas Dilger 已提交
205 206 207 208 209 210 211
      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;
      }
G
Guy Schalnat 已提交
212
   }
A
Andreas Dilger 已提交
213 214

   if (ptr != NULL)
215
   {
A
Andreas Dilger 已提交
216
      farfree(ptr);
217 218
      ptr = NULL;
   }
G
Guy Schalnat 已提交
219 220 221 222
}

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

G
Guy Schalnat 已提交
223
/* Allocate memory for a png_struct or a png_info.  The malloc and
A
Andreas Dilger 已提交
224 225
   memset can be replaced by a single call to calloc() if this is thought
   to improve performance noticably.*/
G
Guy Schalnat 已提交
226
png_voidp
A
Andreas Dilger 已提交
227
png_create_struct(int type)
G
Guy Schalnat 已提交
228
{
A
Andreas Dilger 已提交
229
   png_size_t size;
G
Guy Schalnat 已提交
230 231 232
   png_voidp struct_ptr;

   if (type == PNG_STRUCT_INFO)
A
Andreas Dilger 已提交
233
      size = sizeof(png_info);
G
Guy Schalnat 已提交
234
   else if (type == PNG_STRUCT_PNG)
A
Andreas Dilger 已提交
235
      size = sizeof(png_struct);
G
Guy Schalnat 已提交
236
   else
237
      return ((png_voidp)NULL);
G
Guy Schalnat 已提交
238 239 240 241 242

#if defined(__TURBOC__) && !defined(__FLAT__)
   if ((struct_ptr = (png_voidp)farmalloc(size)) != NULL)
#else
# if defined(_MSC_VER) && defined(MAXSEG_64K)
G
Guy Schalnat 已提交
243
   if ((struct_ptr = (png_voidp)halloc(size,1)) != NULL)
G
Guy Schalnat 已提交
244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259
# 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)
{
A
Andreas Dilger 已提交
260
   if (struct_ptr != NULL)
261
   {
G
Guy Schalnat 已提交
262 263 264 265 266 267 268 269 270
#if defined(__TURBOC__) && !defined(__FLAT__)
      farfree(struct_ptr);
#else
# if defined(_MSC_VER) && defined(MAXSEG_64K)
      hfree(struct_ptr);
# else
      free(struct_ptr);
# endif
#endif
271
   }
G
Guy Schalnat 已提交
272 273 274
}


G
Guy Schalnat 已提交
275
/* Allocate memory.  For reasonable files, size should never exceed
G
Guy Schalnat 已提交
276
   64K.  However, zlib may allocate more then 64K if you don't tell
A
Andreas Dilger 已提交
277
   it not to.  See zconf.h and png.h for more information.  zlib does
G
Guy Schalnat 已提交
278 279
   need to allocate exactly 64K, so whatever you call here must
   have the ability to do that. */
G
Guy Schalnat 已提交
280 281

png_voidp
282
PNG_MALLOC(png_structp png_ptr, png_uint_32 size)
G
Guy Schalnat 已提交
283
{
G
Guy Schalnat 已提交
284
   png_voidp ret;
285 286
   png_size_t length;

A
Andreas Dilger 已提交
287
   if (png_ptr == NULL || size == 0)
288
      return ((png_voidp)NULL);
G
Guy Schalnat 已提交
289 290

#ifdef PNG_MAX_MALLOC_64K
291
   if (png_size > (png_uint_32)65536L)
G
Guy Schalnat 已提交
292
      png_error(png_ptr, "Cannot Allocate > 64K");
G
Guy Schalnat 已提交
293 294
#endif

295 296 297 298
   length = (png_size_t)size;
   if ((png_uint_32)length != size)
      png_error(png_ptr, "Cannot Allocate > size_t");

G
Guy Schalnat 已提交
299
#if defined(__TURBOC__) && !defined(__FLAT__)
300
   ret = farmalloc(length);
G
Guy Schalnat 已提交
301
#else
G
Guy Schalnat 已提交
302
# if defined(_MSC_VER) && defined(MAXSEG_64K)
303
   ret = halloc(length, 1);
G
Guy Schalnat 已提交
304
# else
305
   ret = malloc(length);
G
Guy Schalnat 已提交
306
# endif
G
Guy Schalnat 已提交
307 308
#endif

G
Guy Schalnat 已提交
309
   if (ret == NULL)
G
Guy Schalnat 已提交
310
   {
G
Guy Schalnat 已提交
311
      png_error(png_ptr, "Out of Memory");
G
Guy Schalnat 已提交
312 313
   }

314
   return (ret);
G
Guy Schalnat 已提交
315 316
}

317
/* Free a pointer allocated by PNG_MALLOC().  In the default
G
Guy Schalnat 已提交
318 319 320
  configuration, png_ptr is not used, but is passed in case it
  is needed.  If ptr is NULL, return without taking any action. */
void
321
PNG_FREE(png_structp png_ptr, png_voidp ptr)
G
Guy Schalnat 已提交
322
{
A
Andreas Dilger 已提交
323
   if (png_ptr == NULL || ptr == NULL)
G
Guy Schalnat 已提交
324
      return;
G
Guy Schalnat 已提交
325

G
Guy Schalnat 已提交
326
#if defined(__TURBOC__) && !defined(__FLAT__)
A
Andreas Dilger 已提交
327
   farfree(ptr);
G
Guy Schalnat 已提交
328
#else
G
Guy Schalnat 已提交
329
# if defined(_MSC_VER) && defined(MAXSEG_64K)
A
Andreas Dilger 已提交
330
   hfree(ptr);
G
Guy Schalnat 已提交
331
# else
A
Andreas Dilger 已提交
332
   free(ptr);
G
Guy Schalnat 已提交
333
# endif
G
Guy Schalnat 已提交
334 335 336
#endif
}

G
Guy Schalnat 已提交
337
#endif /* Not Borland DOS special memory handler */
G
Guy Schalnat 已提交
338

339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367
void
png_buffered_memcpy (png_structp png_ptr, png_voidp s1, png_voidp s2,
   png_uint_32 length)
{
   png_size_t size;
   png_uint_32 i;
   for (i=0; i<length; i+=65530)
   {
      size = (png_size_t)(length - i);
      if (size > (png_size_t)65530L)
         size=(png_size_t)65530L;
      png_memcpy (s1, s2, size);
   }
}

void
png_buffered_memset (png_structp png_ptr, png_voidp s1, int value,
   png_uint_32 length)
{
   png_size_t size;
   png_uint_32 i;
   for (i=0; i<length; i+=65530)
   {
      size = length - i;
      if (size > 65530)
         size=65530;
      png_memset (s1, value, size);
   }
}