Guy Schalnat | 0d58058 | 1995-07-20 02:43:20 -0500 | [diff] [blame] | 1 | |
Guy Schalnat | 0f71645 | 1995-11-28 11:22:13 -0600 | [diff] [blame^] | 2 | /* pngmem.c - stub functions for memory allocation |
Guy Schalnat | 0d58058 | 1995-07-20 02:43:20 -0500 | [diff] [blame] | 3 | |
Guy Schalnat | 51f0eb4 | 1995-09-26 05:22:39 -0500 | [diff] [blame] | 4 | libpng 1.0 beta 2 - version 0.81 |
Guy Schalnat | 0d58058 | 1995-07-20 02:43:20 -0500 | [diff] [blame] | 5 | For conditions of distribution and use, see copyright notice in png.h |
| 6 | Copyright (c) 1995 Guy Eric Schalnat, Group 42, Inc. |
Guy Schalnat | 51f0eb4 | 1995-09-26 05:22:39 -0500 | [diff] [blame] | 7 | August 24, 1995 |
Guy Schalnat | 0d58058 | 1995-07-20 02:43:20 -0500 | [diff] [blame] | 8 | |
Guy Schalnat | 51f0eb4 | 1995-09-26 05:22:39 -0500 | [diff] [blame] | 9 | This file provides a location for all memory allocation. Users which |
| 10 | need special memory handling are expected to modify the code in this file |
| 11 | to meet their needs. See the instructions at each function. */ |
Guy Schalnat | 0d58058 | 1995-07-20 02:43:20 -0500 | [diff] [blame] | 12 | |
| 13 | #define PNG_INTERNAL |
| 14 | #include "png.h" |
| 15 | |
Guy Schalnat | 0d58058 | 1995-07-20 02:43:20 -0500 | [diff] [blame] | 16 | /* Allocate memory. For reasonable files, size should never exceed |
| 17 | 64K. However, zlib may allocate more then 64K if you don't tell |
| 18 | it not to. See zconf.h and png.h for more information. zlib does |
| 19 | need to allocate exactly 64K, so whatever you call here must |
| 20 | have the ability to do that. */ |
| 21 | |
| 22 | /* Borland compilers have this habit of not giving you 64K chunks |
| 23 | that start on the segment in DOS mode. This has not been observed |
| 24 | in Windows, and of course it doesn't matter in 32 bit mode, as there |
| 25 | are no segments. Now libpng doesn't need that much memory normally, |
| 26 | but zlib does, so we have to normalize it, if necessary. It would be |
| 27 | better if zlib worked in less then 64K, but it doesn't, so we |
| 28 | have to deal with it. Truely, we are misusing farmalloc here, |
| 29 | as it is designed for use with huge pointers, which don't care |
| 30 | about segments. So we allocate a large amount of memory, and |
| 31 | divvy off segments when needed. |
| 32 | */ |
| 33 | #ifdef __TURBOC__ |
| 34 | #ifndef __WIN32__ |
Guy Schalnat | 51f0eb4 | 1995-09-26 05:22:39 -0500 | [diff] [blame] | 35 | #ifndef __FLAT__ |
Guy Schalnat | 0d58058 | 1995-07-20 02:43:20 -0500 | [diff] [blame] | 36 | |
| 37 | /* NUM_SEG is the number of segments allocated at once */ |
| 38 | #define NUM_SEG 4 |
| 39 | typedef struct borland_seg_struct |
| 40 | { |
| 41 | void *mem_ptr; |
| 42 | void *seg_ptr[NUM_SEG]; |
| 43 | int seg_used[NUM_SEG]; |
| 44 | int num_used; |
| 45 | } borland_seg; |
| 46 | |
| 47 | borland_seg *save_array; |
| 48 | int num_save_array; |
| 49 | int max_save_array; |
| 50 | |
| 51 | #endif |
| 52 | #endif |
Guy Schalnat | 51f0eb4 | 1995-09-26 05:22:39 -0500 | [diff] [blame] | 53 | #endif |
Guy Schalnat | 0d58058 | 1995-07-20 02:43:20 -0500 | [diff] [blame] | 54 | |
Guy Schalnat | 51f0eb4 | 1995-09-26 05:22:39 -0500 | [diff] [blame] | 55 | voidpf |
| 56 | png_large_malloc(png_structf *png_ptr, png_uint_32 size) |
Guy Schalnat | 0d58058 | 1995-07-20 02:43:20 -0500 | [diff] [blame] | 57 | { |
Guy Schalnat | 51f0eb4 | 1995-09-26 05:22:39 -0500 | [diff] [blame] | 58 | voidpf ret; |
| 59 | if (!png_ptr || !size) |
| 60 | return ((void *)0); |
Guy Schalnat | 0d58058 | 1995-07-20 02:43:20 -0500 | [diff] [blame] | 61 | |
| 62 | #ifdef PNG_MAX_MALLOC_64K |
| 63 | if (size > (png_uint_32)65536L) |
Guy Schalnat | 0f71645 | 1995-11-28 11:22:13 -0600 | [diff] [blame^] | 64 | (*(png_ptr->error_fn))(png_ptr, "Cannot Allocate > 64K"); |
Guy Schalnat | 0d58058 | 1995-07-20 02:43:20 -0500 | [diff] [blame] | 65 | #endif |
| 66 | |
| 67 | #ifdef __TURBOC__ |
Guy Schalnat | 51f0eb4 | 1995-09-26 05:22:39 -0500 | [diff] [blame] | 68 | # if defined(__WIN32__) || defined(__FLAT__) |
| 69 | ret = malloc(size); |
Guy Schalnat | 0d58058 | 1995-07-20 02:43:20 -0500 | [diff] [blame] | 70 | # else |
| 71 | |
| 72 | if (size == 65536L) |
| 73 | { |
| 74 | unsigned long offset; |
| 75 | if (!save_array) |
| 76 | { |
| 77 | ret = farmalloc(size); |
| 78 | offset = (unsigned long)(ret); |
| 79 | offset &= 0xffffL; |
| 80 | } |
| 81 | else |
| 82 | { |
| 83 | ret = (void *)0; |
| 84 | } |
| 85 | if (save_array || offset) |
| 86 | { |
| 87 | int i, j; |
| 88 | |
| 89 | if (ret) |
| 90 | farfree(ret); |
| 91 | ret = (void *)0; |
| 92 | |
| 93 | if (!save_array) |
| 94 | { |
| 95 | unsigned long offset; |
| 96 | png_byte huge *ptr; |
| 97 | int i; |
| 98 | |
| 99 | num_save_array = 1; |
| 100 | save_array = malloc(num_save_array * sizeof (borland_seg)); |
| 101 | if (!save_array) |
Guy Schalnat | 0f71645 | 1995-11-28 11:22:13 -0600 | [diff] [blame^] | 102 | (*(png_ptr->error_fn))(png_ptr, "Out of Memory 1"); |
Guy Schalnat | 0d58058 | 1995-07-20 02:43:20 -0500 | [diff] [blame] | 103 | save_array->mem_ptr = farmalloc( |
Guy Schalnat | 51f0eb4 | 1995-09-26 05:22:39 -0500 | [diff] [blame] | 104 | (unsigned long)(NUM_SEG) * 65536L + 65532L); |
Guy Schalnat | 0d58058 | 1995-07-20 02:43:20 -0500 | [diff] [blame] | 105 | if (!save_array->mem_ptr) |
Guy Schalnat | 0f71645 | 1995-11-28 11:22:13 -0600 | [diff] [blame^] | 106 | (*(png_ptr->error_fn))(png_ptr, "Out of Memory 2"); |
Guy Schalnat | 0d58058 | 1995-07-20 02:43:20 -0500 | [diff] [blame] | 107 | offset = (unsigned long)(ret); |
| 108 | offset &= 0xffffL; |
| 109 | ptr = save_array->mem_ptr; |
| 110 | if (offset) |
| 111 | ptr += 65536L - offset; |
| 112 | for (i = 0; i < NUM_SEG; i++, ptr += 65536L) |
| 113 | { |
| 114 | save_array->seg_ptr[i] = ptr; |
| 115 | save_array->seg_used[i] = 0; |
| 116 | } |
| 117 | save_array->num_used = 0; |
| 118 | } |
| 119 | |
| 120 | for (i = 0; i < num_save_array; i++) |
| 121 | { |
| 122 | for (j = 0; j < NUM_SEG; j++) |
| 123 | { |
| 124 | if (!save_array[i].seg_used[j]) |
| 125 | { |
| 126 | ret = save_array[i].seg_ptr[j]; |
| 127 | save_array[i].seg_used[j] = 1; |
| 128 | save_array[i].num_used++; |
| 129 | break; |
| 130 | } |
| 131 | } |
| 132 | if (ret) |
| 133 | break; |
| 134 | } |
| 135 | |
| 136 | if (!ret) |
| 137 | { |
| 138 | unsigned long offset; |
| 139 | png_byte huge *ptr; |
| 140 | |
| 141 | save_array = realloc(save_array, |
| 142 | (num_save_array + 1) * sizeof (borland_seg)); |
| 143 | if (!save_array) |
Guy Schalnat | 0f71645 | 1995-11-28 11:22:13 -0600 | [diff] [blame^] | 144 | (*(png_ptr->error_fn))(png_ptr, "Out of Memory 3"); |
Guy Schalnat | 0d58058 | 1995-07-20 02:43:20 -0500 | [diff] [blame] | 145 | save_array[num_save_array].mem_ptr = farmalloc( |
Guy Schalnat | 51f0eb4 | 1995-09-26 05:22:39 -0500 | [diff] [blame] | 146 | (unsigned long)(NUM_SEG) * 65536L + 65532L); |
Guy Schalnat | 0d58058 | 1995-07-20 02:43:20 -0500 | [diff] [blame] | 147 | if (!save_array[num_save_array].mem_ptr) |
Guy Schalnat | 0f71645 | 1995-11-28 11:22:13 -0600 | [diff] [blame^] | 148 | (*(png_ptr->error_fn))(png_ptr, "Out of Memory 4"); |
Guy Schalnat | 0d58058 | 1995-07-20 02:43:20 -0500 | [diff] [blame] | 149 | offset = (unsigned long)(ret); |
| 150 | offset &= 0xffffL; |
| 151 | ptr = save_array[num_save_array].mem_ptr; |
| 152 | if (offset) |
| 153 | ptr += 65536L - offset; |
| 154 | for (i = 0; i < NUM_SEG; i++, ptr += 65536L) |
| 155 | { |
| 156 | save_array[num_save_array].seg_ptr[i] = ptr; |
| 157 | save_array[num_save_array].seg_used[i] = 0; |
| 158 | } |
| 159 | ret = save_array[num_save_array].seg_ptr[0]; |
| 160 | save_array[num_save_array].seg_used[0] = 1; |
| 161 | save_array[num_save_array].num_used = 1; |
| 162 | num_save_array++; |
| 163 | } |
| 164 | } |
| 165 | } |
| 166 | else |
| 167 | { |
| 168 | ret = farmalloc(size); |
| 169 | } |
| 170 | |
| 171 | # endif /* __WIN32__ */ |
| 172 | #else /* __TURBOC__ */ |
| 173 | # ifdef _MSC_VER |
| 174 | ret = halloc(size, 1); |
| 175 | # else |
| 176 | /* everybody else, so normal malloc should do it. */ |
| 177 | ret = malloc(size); |
| 178 | # endif |
| 179 | #endif |
| 180 | |
Guy Schalnat | 51f0eb4 | 1995-09-26 05:22:39 -0500 | [diff] [blame] | 181 | if (ret == NULL) |
Guy Schalnat | 0d58058 | 1995-07-20 02:43:20 -0500 | [diff] [blame] | 182 | { |
Guy Schalnat | 0f71645 | 1995-11-28 11:22:13 -0600 | [diff] [blame^] | 183 | (*(png_ptr->error_fn))(png_ptr, "Out of Memory"); |
Guy Schalnat | 0d58058 | 1995-07-20 02:43:20 -0500 | [diff] [blame] | 184 | } |
| 185 | |
| 186 | return ret; |
| 187 | } |
| 188 | |
| 189 | /* free a pointer allocated by png_large_malloc(). In the default |
| 190 | configuration, png_ptr is not used, but is passed in case it |
| 191 | is needed. If ptr is NULL, return without taking any action. */ |
| 192 | void |
Guy Schalnat | 51f0eb4 | 1995-09-26 05:22:39 -0500 | [diff] [blame] | 193 | png_large_free(png_structf *png_ptr, voidpf ptr) |
Guy Schalnat | 0d58058 | 1995-07-20 02:43:20 -0500 | [diff] [blame] | 194 | { |
| 195 | if (!png_ptr) |
| 196 | return; |
| 197 | |
| 198 | if (ptr != (void *)0) |
| 199 | { |
| 200 | #ifdef __TURBOC__ |
Guy Schalnat | 51f0eb4 | 1995-09-26 05:22:39 -0500 | [diff] [blame] | 201 | # if defined(__WIN32__) || defined(__FLAT__) |
| 202 | if (ptr) |
| 203 | free(ptr); |
| 204 | # else |
Guy Schalnat | 0d58058 | 1995-07-20 02:43:20 -0500 | [diff] [blame] | 205 | int i, j; |
| 206 | |
| 207 | for (i = 0; i < num_save_array; i++) |
| 208 | { |
| 209 | for (j = 0; j < NUM_SEG; j++) |
| 210 | { |
| 211 | if (ptr == save_array[i].seg_ptr[j]) |
| 212 | { |
Guy Schalnat | 0d58058 | 1995-07-20 02:43:20 -0500 | [diff] [blame] | 213 | save_array[i].seg_used[j] = 0; |
| 214 | ptr = 0; |
| 215 | save_array[i].num_used--; |
| 216 | if (!save_array[i].num_used) |
| 217 | { |
| 218 | int k; |
Guy Schalnat | 51f0eb4 | 1995-09-26 05:22:39 -0500 | [diff] [blame] | 219 | |
Guy Schalnat | 0d58058 | 1995-07-20 02:43:20 -0500 | [diff] [blame] | 220 | num_save_array--; |
| 221 | farfree(save_array[i].mem_ptr); |
| 222 | for (k = i; k < num_save_array; k++) |
| 223 | save_array[k] = save_array[k + 1]; |
| 224 | if (!num_save_array) |
| 225 | { |
| 226 | free(save_array); |
| 227 | save_array = 0; |
| 228 | } |
| 229 | } |
| 230 | break; |
| 231 | } |
| 232 | } |
| 233 | if (!ptr) |
| 234 | break; |
| 235 | } |
| 236 | |
Guy Schalnat | 0d58058 | 1995-07-20 02:43:20 -0500 | [diff] [blame] | 237 | if (ptr) |
| 238 | farfree(ptr); |
Guy Schalnat | 51f0eb4 | 1995-09-26 05:22:39 -0500 | [diff] [blame] | 239 | # endif |
Guy Schalnat | 0d58058 | 1995-07-20 02:43:20 -0500 | [diff] [blame] | 240 | #else |
| 241 | # ifdef _MSC_VER |
| 242 | hfree(ptr); |
| 243 | # else |
| 244 | free(ptr); |
| 245 | # endif |
| 246 | #endif |
| 247 | } |
| 248 | } |
| 249 | |
| 250 | /* Allocate memory. This is called for smallish blocks only It |
| 251 | should not get anywhere near 64K. */ |
| 252 | void * |
| 253 | png_malloc(png_struct *png_ptr, png_uint_32 size) |
| 254 | { |
| 255 | void *ret; |
| 256 | |
Guy Schalnat | 51f0eb4 | 1995-09-26 05:22:39 -0500 | [diff] [blame] | 257 | if (!png_ptr || !size) |
Guy Schalnat | 0d58058 | 1995-07-20 02:43:20 -0500 | [diff] [blame] | 258 | return ((void *)0); |
| 259 | |
| 260 | #ifdef PNG_MAX_MALLOC_64K |
| 261 | if (size > (png_uint_32)65536L) |
Guy Schalnat | 0f71645 | 1995-11-28 11:22:13 -0600 | [diff] [blame^] | 262 | (*(png_ptr->error_fn))(png_ptr, "Cannot Allocate > 64K"); |
Guy Schalnat | 0d58058 | 1995-07-20 02:43:20 -0500 | [diff] [blame] | 263 | #endif |
| 264 | |
| 265 | ret = malloc((png_size_t)size); |
| 266 | |
| 267 | if (!ret) |
| 268 | { |
Guy Schalnat | 0f71645 | 1995-11-28 11:22:13 -0600 | [diff] [blame^] | 269 | (*(png_ptr->error_fn))(png_ptr, "Out of Memory 6"); |
Guy Schalnat | 0d58058 | 1995-07-20 02:43:20 -0500 | [diff] [blame] | 270 | } |
| 271 | |
| 272 | return ret; |
| 273 | } |
| 274 | |
| 275 | /* Reallocate memory. This will not get near 64K on a |
| 276 | even marginally reasonable file. */ |
| 277 | void * |
Guy Schalnat | 51f0eb4 | 1995-09-26 05:22:39 -0500 | [diff] [blame] | 278 | png_realloc(png_struct *png_ptr, void *ptr, png_uint_32 size, |
| 279 | png_uint_32 old_size) |
Guy Schalnat | 0d58058 | 1995-07-20 02:43:20 -0500 | [diff] [blame] | 280 | { |
| 281 | void *ret; |
| 282 | |
Guy Schalnat | 51f0eb4 | 1995-09-26 05:22:39 -0500 | [diff] [blame] | 283 | if (!png_ptr || !old_size || !ptr || !size) |
Guy Schalnat | 0d58058 | 1995-07-20 02:43:20 -0500 | [diff] [blame] | 284 | return ((void *)0); |
| 285 | |
| 286 | #ifdef PNG_MAX_MALLOC_64K |
| 287 | if (size > (png_uint_32)65536L) |
Guy Schalnat | 0f71645 | 1995-11-28 11:22:13 -0600 | [diff] [blame^] | 288 | (*(png_ptr->error_fn))(png_ptr, "Cannot Allocate > 64K"); |
Guy Schalnat | 0d58058 | 1995-07-20 02:43:20 -0500 | [diff] [blame] | 289 | #endif |
| 290 | |
| 291 | ret = realloc(ptr, (png_size_t)size); |
| 292 | |
| 293 | if (!ret) |
| 294 | { |
Guy Schalnat | 0f71645 | 1995-11-28 11:22:13 -0600 | [diff] [blame^] | 295 | (*(png_ptr->error_fn))(png_ptr, "Out of Memory 7"); |
Guy Schalnat | 0d58058 | 1995-07-20 02:43:20 -0500 | [diff] [blame] | 296 | } |
| 297 | |
| 298 | return ret; |
| 299 | } |
| 300 | |
| 301 | /* free a pointer allocated by png_malloc(). In the default |
| 302 | configuration, png_ptr is not used, but is passed incase it |
| 303 | is needed. If ptr is NULL, return without taking any action. */ |
| 304 | void |
| 305 | png_free(png_struct *png_ptr, void *ptr) |
| 306 | { |
| 307 | if (!png_ptr) |
| 308 | return; |
| 309 | |
| 310 | if (ptr != (void *)0) |
| 311 | free(ptr); |
| 312 | } |
| 313 | |