| OLD | NEW |
| (Empty) |
| 1 /***************************************************************************/ | |
| 2 /* */ | |
| 3 /* ftutil.c */ | |
| 4 /* */ | |
| 5 /* FreeType utility file for memory and list management (body). */ | |
| 6 /* */ | |
| 7 /* Copyright 2002, 2004-2007, 2013 by */ | |
| 8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */ | |
| 9 /* */ | |
| 10 /* This file is part of the FreeType project, and may only be used, */ | |
| 11 /* modified, and distributed under the terms of the FreeType project */ | |
| 12 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ | |
| 13 /* this file you indicate that you have read the license and */ | |
| 14 /* understand and accept it fully. */ | |
| 15 /* */ | |
| 16 /***************************************************************************/ | |
| 17 | |
| 18 | |
| 19 #include "../../include/ft2build.h" | |
| 20 #include "../../include/freetype/internal/ftdebug.h" | |
| 21 #include "../../include/freetype/internal/ftmemory.h" | |
| 22 #include "../../include/freetype/internal/ftobjs.h" | |
| 23 #include "../../include/freetype/ftlist.h" | |
| 24 | |
| 25 | |
| 26 /*************************************************************************/ | |
| 27 /* */ | |
| 28 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ | |
| 29 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ | |
| 30 /* messages during execution. */ | |
| 31 /* */ | |
| 32 #undef FT_COMPONENT | |
| 33 #define FT_COMPONENT trace_memory | |
| 34 | |
| 35 | |
| 36 /*************************************************************************/ | |
| 37 /*************************************************************************/ | |
| 38 /*************************************************************************/ | |
| 39 /***** *****/ | |
| 40 /***** *****/ | |
| 41 /***** M E M O R Y M A N A G E M E N T *****/ | |
| 42 /***** *****/ | |
| 43 /***** *****/ | |
| 44 /*************************************************************************/ | |
| 45 /*************************************************************************/ | |
| 46 /*************************************************************************/ | |
| 47 | |
| 48 | |
| 49 FT_BASE_DEF( FT_Pointer ) | |
| 50 ft_mem_alloc( FT_Memory memory, | |
| 51 FT_Long size, | |
| 52 FT_Error *p_error ) | |
| 53 { | |
| 54 FT_Error error; | |
| 55 FT_Pointer block = ft_mem_qalloc( memory, size, &error ); | |
| 56 | |
| 57 if ( !error && size > 0 ) | |
| 58 FT_MEM_ZERO( block, size ); | |
| 59 | |
| 60 *p_error = error; | |
| 61 return block; | |
| 62 } | |
| 63 | |
| 64 | |
| 65 FT_BASE_DEF( FT_Pointer ) | |
| 66 ft_mem_qalloc( FT_Memory memory, | |
| 67 FT_Long size, | |
| 68 FT_Error *p_error ) | |
| 69 { | |
| 70 FT_Error error = FT_Err_Ok; | |
| 71 FT_Pointer block = NULL; | |
| 72 | |
| 73 | |
| 74 if ( size > 0 ) | |
| 75 { | |
| 76 block = memory->alloc( memory, size ); | |
| 77 if ( block == NULL ) | |
| 78 error = FT_THROW( Out_Of_Memory ); | |
| 79 } | |
| 80 else if ( size < 0 ) | |
| 81 { | |
| 82 /* may help catch/prevent security issues */ | |
| 83 error = FT_THROW( Invalid_Argument ); | |
| 84 } | |
| 85 | |
| 86 *p_error = error; | |
| 87 return block; | |
| 88 } | |
| 89 | |
| 90 | |
| 91 FT_BASE_DEF( FT_Pointer ) | |
| 92 ft_mem_realloc( FT_Memory memory, | |
| 93 FT_Long item_size, | |
| 94 FT_Long cur_count, | |
| 95 FT_Long new_count, | |
| 96 void* block, | |
| 97 FT_Error *p_error ) | |
| 98 { | |
| 99 FT_Error error = FT_Err_Ok; | |
| 100 | |
| 101 | |
| 102 block = ft_mem_qrealloc( memory, item_size, | |
| 103 cur_count, new_count, block, &error ); | |
| 104 if ( !error && new_count > cur_count ) | |
| 105 FT_MEM_ZERO( (char*)block + cur_count * item_size, | |
| 106 ( new_count - cur_count ) * item_size ); | |
| 107 | |
| 108 *p_error = error; | |
| 109 return block; | |
| 110 } | |
| 111 | |
| 112 | |
| 113 FT_BASE_DEF( FT_Pointer ) | |
| 114 ft_mem_qrealloc( FT_Memory memory, | |
| 115 FT_Long item_size, | |
| 116 FT_Long cur_count, | |
| 117 FT_Long new_count, | |
| 118 void* block, | |
| 119 FT_Error *p_error ) | |
| 120 { | |
| 121 FT_Error error = FT_Err_Ok; | |
| 122 | |
| 123 | |
| 124 /* Note that we now accept `item_size == 0' as a valid parameter, in | |
| 125 * order to cover very weird cases where an ALLOC_MULT macro would be | |
| 126 * called. | |
| 127 */ | |
| 128 if ( cur_count < 0 || new_count < 0 || item_size < 0 ) | |
| 129 { | |
| 130 /* may help catch/prevent nasty security issues */ | |
| 131 error = FT_THROW( Invalid_Argument ); | |
| 132 } | |
| 133 else if ( new_count == 0 || item_size == 0 ) | |
| 134 { | |
| 135 ft_mem_free( memory, block ); | |
| 136 block = NULL; | |
| 137 } | |
| 138 else if ( new_count > FT_INT_MAX/item_size ) | |
| 139 { | |
| 140 error = FT_THROW( Array_Too_Large ); | |
| 141 } | |
| 142 else if ( cur_count == 0 ) | |
| 143 { | |
| 144 FT_ASSERT( block == NULL ); | |
| 145 | |
| 146 block = ft_mem_alloc( memory, new_count*item_size, &error ); | |
| 147 } | |
| 148 else | |
| 149 { | |
| 150 FT_Pointer block2; | |
| 151 FT_Long cur_size = cur_count*item_size; | |
| 152 FT_Long new_size = new_count*item_size; | |
| 153 | |
| 154 | |
| 155 block2 = memory->realloc( memory, cur_size, new_size, block ); | |
| 156 if ( block2 == NULL ) | |
| 157 error = FT_THROW( Out_Of_Memory ); | |
| 158 else | |
| 159 block = block2; | |
| 160 } | |
| 161 | |
| 162 *p_error = error; | |
| 163 return block; | |
| 164 } | |
| 165 | |
| 166 #ifdef _XYQ_MEM_DEBUG /** XYQ 2006-10-12 */ | |
| 167 FT_BASE_DEF( FT_Pointer ) | |
| 168 ft_mem_allocdebug( FT_Memory memory, | |
| 169 FT_Long size, const char* file, int line, | |
| 170 FT_Error *p_error ) | |
| 171 { | |
| 172 FT_Error error; | |
| 173 FT_Pointer block = ft_mem_qallocdebug( memory, size, file, line, &error ); | |
| 174 | |
| 175 if ( !error && size > 0 ) | |
| 176 FT_MEM_ZERO( block, size ); | |
| 177 | |
| 178 *p_error = error; | |
| 179 return block; | |
| 180 } | |
| 181 | |
| 182 | |
| 183 FT_BASE_DEF( FT_Pointer ) | |
| 184 ft_mem_qallocdebug( FT_Memory memory, | |
| 185 FT_Long size, const char* file, int line, | |
| 186 FT_Error *p_error ) | |
| 187 { | |
| 188 FT_Error error = FT_Err_Ok; | |
| 189 FT_Pointer block = NULL; | |
| 190 | |
| 191 | |
| 192 if ( size > 0 ) | |
| 193 { | |
| 194 block = memory->allocdebug( memory, size, file, line ); | |
| 195 if ( block == NULL ) | |
| 196 error = FT_Err_Out_Of_Memory; | |
| 197 } | |
| 198 else if ( size < 0 ) | |
| 199 { | |
| 200 /* may help catch/prevent security issues */ | |
| 201 error = FT_Err_Invalid_Argument; | |
| 202 } | |
| 203 | |
| 204 *p_error = error; | |
| 205 return block; | |
| 206 } | |
| 207 | |
| 208 | |
| 209 FT_BASE_DEF( FT_Pointer ) | |
| 210 ft_mem_reallocdebug( FT_Memory memory, | |
| 211 FT_Long item_size, | |
| 212 FT_Long cur_count, | |
| 213 FT_Long new_count, | |
| 214 void* block, const char* file, int line, | |
| 215 FT_Error *p_error ) | |
| 216 { | |
| 217 FT_Error error = FT_Err_Ok; | |
| 218 | |
| 219 block = ft_mem_qreallocdebug( memory, item_size, | |
| 220 cur_count, new_count, block, file, line, &error ); | |
| 221 if ( !error && new_count > cur_count ) | |
| 222 FT_MEM_ZERO( (char*)block + cur_count * item_size, | |
| 223 ( new_count - cur_count ) * item_size ); | |
| 224 | |
| 225 *p_error = error; | |
| 226 return block; | |
| 227 } | |
| 228 | |
| 229 | |
| 230 FT_BASE_DEF( FT_Pointer ) | |
| 231 ft_mem_qreallocdebug( FT_Memory memory, | |
| 232 FT_Long item_size, | |
| 233 FT_Long cur_count, | |
| 234 FT_Long new_count, | |
| 235 void* block, const char* file, int line, | |
| 236 FT_Error *p_error ) | |
| 237 { | |
| 238 FT_Error error = FT_Err_Ok; | |
| 239 | |
| 240 | |
| 241 if ( cur_count < 0 || new_count < 0 || item_size <= 0 ) | |
| 242 { | |
| 243 /* may help catch/prevent nasty security issues */ | |
| 244 error = FT_Err_Invalid_Argument; | |
| 245 } | |
| 246 else if ( new_count == 0 ) | |
| 247 { | |
| 248 ft_mem_free( memory, block ); | |
| 249 block = NULL; | |
| 250 } | |
| 251 else if ( new_count > FT_INT_MAX/item_size ) | |
| 252 { | |
| 253 error = FT_Err_Array_Too_Large; | |
| 254 } | |
| 255 else if ( cur_count == 0 ) | |
| 256 { | |
| 257 FT_ASSERT( block == NULL ); | |
| 258 | |
| 259 block = ft_mem_allocdebug( memory, new_count*item_size, file, line, &error
); | |
| 260 } | |
| 261 else | |
| 262 { | |
| 263 FT_Pointer block2; | |
| 264 FT_Long cur_size = cur_count*item_size; | |
| 265 FT_Long new_size = new_count*item_size; | |
| 266 | |
| 267 | |
| 268 block2 = memory->realloc( memory, cur_size, new_size, block ); | |
| 269 if ( block2 == NULL ) | |
| 270 error = FT_Err_Out_Of_Memory; | |
| 271 else | |
| 272 block = block2; | |
| 273 } | |
| 274 | |
| 275 *p_error = error; | |
| 276 return block; | |
| 277 } | |
| 278 #endif | |
| 279 FT_BASE_DEF( void ) | |
| 280 ft_mem_free( FT_Memory memory, | |
| 281 const void *P ) | |
| 282 { | |
| 283 if ( P ) | |
| 284 memory->free( memory, (void*)P ); | |
| 285 } | |
| 286 | |
| 287 | |
| 288 FT_BASE_DEF( FT_Pointer ) | |
| 289 ft_mem_dup( FT_Memory memory, | |
| 290 const void* address, | |
| 291 FT_ULong size, | |
| 292 FT_Error *p_error ) | |
| 293 { | |
| 294 FT_Error error; | |
| 295 FT_Pointer p = ft_mem_qalloc( memory, size, &error ); | |
| 296 | |
| 297 | |
| 298 if ( !error && address ) | |
| 299 ft_memcpy( p, address, size ); | |
| 300 | |
| 301 *p_error = error; | |
| 302 return p; | |
| 303 } | |
| 304 | |
| 305 | |
| 306 FT_BASE_DEF( FT_Pointer ) | |
| 307 ft_mem_strdup( FT_Memory memory, | |
| 308 const char* str, | |
| 309 FT_Error *p_error ) | |
| 310 { | |
| 311 FT_ULong len = str ? (FT_ULong)ft_strlen( str ) + 1 | |
| 312 : 0; | |
| 313 | |
| 314 | |
| 315 return ft_mem_dup( memory, str, len, p_error ); | |
| 316 } | |
| 317 | |
| 318 | |
| 319 FT_BASE_DEF( FT_Int ) | |
| 320 ft_mem_strcpyn( char* dst, | |
| 321 const char* src, | |
| 322 FT_ULong size ) | |
| 323 { | |
| 324 while ( size > 1 && *src != 0 ) | |
| 325 { | |
| 326 *dst++ = *src++; | |
| 327 size--; | |
| 328 } | |
| 329 | |
| 330 *dst = 0; /* always zero-terminate */ | |
| 331 | |
| 332 return *src != 0; | |
| 333 } | |
| 334 | |
| 335 | |
| 336 /*************************************************************************/ | |
| 337 /*************************************************************************/ | |
| 338 /*************************************************************************/ | |
| 339 /***** *****/ | |
| 340 /***** *****/ | |
| 341 /***** D O U B L Y L I N K E D L I S T S *****/ | |
| 342 /***** *****/ | |
| 343 /***** *****/ | |
| 344 /*************************************************************************/ | |
| 345 /*************************************************************************/ | |
| 346 /*************************************************************************/ | |
| 347 | |
| 348 #undef FT_COMPONENT | |
| 349 #define FT_COMPONENT trace_list | |
| 350 | |
| 351 /* documentation is in ftlist.h */ | |
| 352 | |
| 353 FT_EXPORT_DEF( FT_ListNode ) | |
| 354 FT_List_Find( FT_List list, | |
| 355 void* data ) | |
| 356 { | |
| 357 FT_ListNode cur; | |
| 358 | |
| 359 | |
| 360 cur = list->head; | |
| 361 while ( cur ) | |
| 362 { | |
| 363 if ( cur->data == data ) | |
| 364 return cur; | |
| 365 | |
| 366 cur = cur->next; | |
| 367 } | |
| 368 | |
| 369 return (FT_ListNode)0; | |
| 370 } | |
| 371 | |
| 372 | |
| 373 /* documentation is in ftlist.h */ | |
| 374 | |
| 375 FT_EXPORT_DEF( void ) | |
| 376 FT_List_Add( FT_List list, | |
| 377 FT_ListNode node ) | |
| 378 { | |
| 379 FT_ListNode before = list->tail; | |
| 380 | |
| 381 | |
| 382 node->next = 0; | |
| 383 node->prev = before; | |
| 384 | |
| 385 if ( before ) | |
| 386 before->next = node; | |
| 387 else | |
| 388 list->head = node; | |
| 389 | |
| 390 list->tail = node; | |
| 391 } | |
| 392 | |
| 393 | |
| 394 /* documentation is in ftlist.h */ | |
| 395 | |
| 396 FT_EXPORT_DEF( void ) | |
| 397 FT_List_Insert( FT_List list, | |
| 398 FT_ListNode node ) | |
| 399 { | |
| 400 FT_ListNode after = list->head; | |
| 401 | |
| 402 | |
| 403 node->next = after; | |
| 404 node->prev = 0; | |
| 405 | |
| 406 if ( !after ) | |
| 407 list->tail = node; | |
| 408 else | |
| 409 after->prev = node; | |
| 410 | |
| 411 list->head = node; | |
| 412 } | |
| 413 | |
| 414 | |
| 415 /* documentation is in ftlist.h */ | |
| 416 | |
| 417 FT_EXPORT_DEF( void ) | |
| 418 FT_List_Remove( FT_List list, | |
| 419 FT_ListNode node ) | |
| 420 { | |
| 421 FT_ListNode before, after; | |
| 422 | |
| 423 | |
| 424 before = node->prev; | |
| 425 after = node->next; | |
| 426 | |
| 427 if ( before ) | |
| 428 before->next = after; | |
| 429 else | |
| 430 list->head = after; | |
| 431 | |
| 432 if ( after ) | |
| 433 after->prev = before; | |
| 434 else | |
| 435 list->tail = before; | |
| 436 } | |
| 437 | |
| 438 | |
| 439 /* documentation is in ftlist.h */ | |
| 440 | |
| 441 FT_EXPORT_DEF( void ) | |
| 442 FT_List_Up( FT_List list, | |
| 443 FT_ListNode node ) | |
| 444 { | |
| 445 FT_ListNode before, after; | |
| 446 | |
| 447 | |
| 448 before = node->prev; | |
| 449 after = node->next; | |
| 450 | |
| 451 /* check whether we are already on top of the list */ | |
| 452 if ( !before ) | |
| 453 return; | |
| 454 | |
| 455 before->next = after; | |
| 456 | |
| 457 if ( after ) | |
| 458 after->prev = before; | |
| 459 else | |
| 460 list->tail = before; | |
| 461 | |
| 462 node->prev = 0; | |
| 463 node->next = list->head; | |
| 464 list->head->prev = node; | |
| 465 list->head = node; | |
| 466 } | |
| 467 | |
| 468 | |
| 469 /* documentation is in ftlist.h */ | |
| 470 | |
| 471 FT_EXPORT_DEF( FT_Error ) | |
| 472 FT_List_Iterate( FT_List list, | |
| 473 FT_List_Iterator iterator, | |
| 474 void* user ) | |
| 475 { | |
| 476 FT_ListNode cur = list->head; | |
| 477 FT_Error error = FT_Err_Ok; | |
| 478 | |
| 479 | |
| 480 while ( cur ) | |
| 481 { | |
| 482 FT_ListNode next = cur->next; | |
| 483 | |
| 484 | |
| 485 error = iterator( cur, user ); | |
| 486 if ( error ) | |
| 487 break; | |
| 488 | |
| 489 cur = next; | |
| 490 } | |
| 491 | |
| 492 return error; | |
| 493 } | |
| 494 | |
| 495 | |
| 496 /* documentation is in ftlist.h */ | |
| 497 | |
| 498 FT_EXPORT_DEF( void ) | |
| 499 FT_List_Finalize( FT_List list, | |
| 500 FT_List_Destructor destroy, | |
| 501 FT_Memory memory, | |
| 502 void* user ) | |
| 503 { | |
| 504 FT_ListNode cur; | |
| 505 | |
| 506 | |
| 507 cur = list->head; | |
| 508 while ( cur ) | |
| 509 { | |
| 510 FT_ListNode next = cur->next; | |
| 511 void* data = cur->data; | |
| 512 | |
| 513 | |
| 514 if ( destroy ) | |
| 515 destroy( memory, data, user ); | |
| 516 | |
| 517 FT_FREE( cur ); | |
| 518 cur = next; | |
| 519 } | |
| 520 | |
| 521 list->head = 0; | |
| 522 list->tail = 0; | |
| 523 } | |
| 524 | |
| 525 | |
| 526 FT_BASE_DEF( FT_UInt32 ) | |
| 527 ft_highpow2( FT_UInt32 value ) | |
| 528 { | |
| 529 FT_UInt32 value2; | |
| 530 | |
| 531 | |
| 532 /* | |
| 533 * We simply clear the lowest bit in each iteration. When | |
| 534 * we reach 0, we know that the previous value was our result. | |
| 535 */ | |
| 536 for ( ;; ) | |
| 537 { | |
| 538 value2 = value & (value - 1); /* clear lowest bit */ | |
| 539 if ( value2 == 0 ) | |
| 540 break; | |
| 541 | |
| 542 value = value2; | |
| 543 } | |
| 544 return value; | |
| 545 } | |
| 546 | |
| 547 | |
| 548 /* END */ | |
| OLD | NEW |