1 /***************************************************************************/ 2 /* */ 3 /* ftutil.c */ 4 /* */ 5 /* FreeType utility file for memory and list management (body). */ 6 /* */ 7 /* Copyright 2002, 2004, 2005, 2006, 2007 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 <ft2build.h> 20 #include FT_INTERNAL_DEBUG_H 21 #include FT_INTERNAL_MEMORY_H 22 #include FT_INTERNAL_OBJECTS_H 23 #include FT_LIST_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_Err_Out_Of_Memory; 79 } 80 else if ( size < 0 ) 81 { 82 /* may help catch/prevent security issues */ 83 error = FT_Err_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 block = ft_mem_qrealloc( memory, item_size, 102 cur_count, new_count, block, &error ); 103 if ( !error && new_count > cur_count ) 104 FT_MEM_ZERO( (char*)block + cur_count * item_size, 105 ( new_count - cur_count ) * item_size ); 106 107 *p_error = error; 108 return block; 109 } 110 111 112 FT_BASE_DEF( FT_Pointer ) 113 ft_mem_qrealloc( FT_Memory memory, 114 FT_Long item_size, 115 FT_Long cur_count, 116 FT_Long new_count, 117 void* block, 118 FT_Error *p_error ) 119 { 120 FT_Error error = FT_Err_Ok; 121 122 123 /* Note that we now accept `item_size == 0' as a valid parameter, in 124 * order to cover very weird cases where an ALLOC_MULT macro would be 125 * called. 126 */ 127 if ( cur_count < 0 || new_count < 0 || item_size < 0 ) 128 { 129 /* may help catch/prevent nasty security issues */ 130 error = FT_Err_Invalid_Argument; 131 } 132 else if ( new_count == 0 || item_size == 0 ) 133 { 134 ft_mem_free( memory, block ); 135 block = NULL; 136 } 137 else if ( new_count > FT_INT_MAX/item_size ) 138 { 139 error = FT_Err_Array_Too_Large; 140 } 141 else if ( cur_count == 0 ) 142 { 143 FT_ASSERT( block == NULL ); 144 145 block = ft_mem_alloc( memory, new_count*item_size, &error ); 146 } 147 else 148 { 149 FT_Pointer block2; 150 FT_Long cur_size = cur_count*item_size; 151 FT_Long new_size = new_count*item_size; 152 153 154 block2 = memory->realloc( memory, cur_size, new_size, block ); 155 if ( block2 == NULL ) 156 error = FT_Err_Out_Of_Memory; 157 else 158 block = block2; 159 } 160 161 *p_error = error; 162 return block; 163 } 164 165 166 FT_BASE_DEF( void ) 167 ft_mem_free( FT_Memory memory, 168 const void *P ) 169 { 170 if ( P ) 171 memory->free( memory, (void*)P ); 172 } 173 174 175 FT_BASE_DEF( FT_Pointer ) 176 ft_mem_dup( FT_Memory memory, 177 const void* address, 178 FT_ULong size, 179 FT_Error *p_error ) 180 { 181 FT_Error error; 182 FT_Pointer p = ft_mem_qalloc( memory, size, &error ); 183 184 185 if ( !error && address ) 186 ft_memcpy( p, address, size ); 187 188 *p_error = error; 189 return p; 190 } 191 192 193 FT_BASE_DEF( FT_Pointer ) 194 ft_mem_strdup( FT_Memory memory, 195 const char* str, 196 FT_Error *p_error ) 197 { 198 FT_ULong len = str ? (FT_ULong)ft_strlen( str ) + 1 199 : 0; 200 201 202 return ft_mem_dup( memory, str, len, p_error ); 203 } 204 205 206 FT_BASE_DEF( FT_Int ) 207 ft_mem_strcpyn( char* dst, 208 const char* src, 209 FT_ULong size ) 210 { 211 while ( size > 1 && *src != 0 ) 212 { 213 *dst++ = *src++; 214 size--; 215 } 216 217 *dst = 0; /* always zero-terminate */ 218 219 return *src != 0; 220 } 221 222 223 /*************************************************************************/ 224 /*************************************************************************/ 225 /*************************************************************************/ 226 /***** *****/ 227 /***** *****/ 228 /***** D O U B L Y L I N K E D L I S T S *****/ 229 /***** *****/ 230 /***** *****/ 231 /*************************************************************************/ 232 /*************************************************************************/ 233 /*************************************************************************/ 234 235 #undef FT_COMPONENT 236 #define FT_COMPONENT trace_list 237 238 /* documentation is in ftlist.h */ 239 240 FT_EXPORT_DEF( FT_ListNode ) 241 FT_List_Find( FT_List list, 242 void* data ) 243 { 244 FT_ListNode cur; 245 246 247 cur = list->head; 248 while ( cur ) 249 { 250 if ( cur->data == data ) 251 return cur; 252 253 cur = cur->next; 254 } 255 256 return (FT_ListNode)0; 257 } 258 259 260 /* documentation is in ftlist.h */ 261 262 FT_EXPORT_DEF( void ) 263 FT_List_Add( FT_List list, 264 FT_ListNode node ) 265 { 266 FT_ListNode before = list->tail; 267 268 269 node->next = 0; 270 node->prev = before; 271 272 if ( before ) 273 before->next = node; 274 else 275 list->head = node; 276 277 list->tail = node; 278 } 279 280 281 /* documentation is in ftlist.h */ 282 283 FT_EXPORT_DEF( void ) 284 FT_List_Insert( FT_List list, 285 FT_ListNode node ) 286 { 287 FT_ListNode after = list->head; 288 289 290 node->next = after; 291 node->prev = 0; 292 293 if ( !after ) 294 list->tail = node; 295 else 296 after->prev = node; 297 298 list->head = node; 299 } 300 301 302 /* documentation is in ftlist.h */ 303 304 FT_EXPORT_DEF( void ) 305 FT_List_Remove( FT_List list, 306 FT_ListNode node ) 307 { 308 FT_ListNode before, after; 309 310 311 before = node->prev; 312 after = node->next; 313 314 if ( before ) 315 before->next = after; 316 else 317 list->head = after; 318 319 if ( after ) 320 after->prev = before; 321 else 322 list->tail = before; 323 } 324 325 326 /* documentation is in ftlist.h */ 327 328 FT_EXPORT_DEF( void ) 329 FT_List_Up( FT_List list, 330 FT_ListNode node ) 331 { 332 FT_ListNode before, after; 333 334 335 before = node->prev; 336 after = node->next; 337 338 /* check whether we are already on top of the list */ 339 if ( !before ) 340 return; 341 342 before->next = after; 343 344 if ( after ) 345 after->prev = before; 346 else 347 list->tail = before; 348 349 node->prev = 0; 350 node->next = list->head; 351 list->head->prev = node; 352 list->head = node; 353 } 354 355 356 /* documentation is in ftlist.h */ 357 358 FT_EXPORT_DEF( FT_Error ) 359 FT_List_Iterate( FT_List list, 360 FT_List_Iterator iterator, 361 void* user ) 362 { 363 FT_ListNode cur = list->head; 364 FT_Error error = FT_Err_Ok; 365 366 367 while ( cur ) 368 { 369 FT_ListNode next = cur->next; 370 371 372 error = iterator( cur, user ); 373 if ( error ) 374 break; 375 376 cur = next; 377 } 378 379 return error; 380 } 381 382 383 /* documentation is in ftlist.h */ 384 385 FT_EXPORT_DEF( void ) 386 FT_List_Finalize( FT_List list, 387 FT_List_Destructor destroy, 388 FT_Memory memory, 389 void* user ) 390 { 391 FT_ListNode cur; 392 393 394 cur = list->head; 395 while ( cur ) 396 { 397 FT_ListNode next = cur->next; 398 void* data = cur->data; 399 400 401 if ( destroy ) 402 destroy( memory, data, user ); 403 404 FT_FREE( cur ); 405 cur = next; 406 } 407 408 list->head = 0; 409 list->tail = 0; 410 } 411 412 413 FT_BASE_DEF( FT_UInt32 ) 414 ft_highpow2( FT_UInt32 value ) 415 { 416 FT_UInt32 value2; 417 418 419 /* 420 * We simply clear the lowest bit in each iteration. When 421 * we reach 0, we know that the previous value was our result. 422 */ 423 for ( ;; ) 424 { 425 value2 = value & (value - 1); /* clear lowest bit */ 426 if ( value2 == 0 ) 427 break; 428 429 value = value2; 430 } 431 return value; 432 } 433 434 435 #ifdef FT_CONFIG_OPTION_OLD_INTERNALS 436 437 FT_BASE_DEF( FT_Error ) 438 FT_Alloc( FT_Memory memory, 439 FT_Long size, 440 void* *P ) 441 { 442 FT_Error error; 443 444 445 (void)FT_ALLOC( *P, size ); 446 return error; 447 } 448 449 450 FT_BASE_DEF( FT_Error ) 451 FT_QAlloc( FT_Memory memory, 452 FT_Long size, 453 void* *p ) 454 { 455 FT_Error error; 456 457 458 (void)FT_QALLOC( *p, size ); 459 return error; 460 } 461 462 463 FT_BASE_DEF( FT_Error ) 464 FT_Realloc( FT_Memory memory, 465 FT_Long current, 466 FT_Long size, 467 void* *P ) 468 { 469 FT_Error error; 470 471 472 (void)FT_REALLOC( *P, current, size ); 473 return error; 474 } 475 476 477 FT_BASE_DEF( FT_Error ) 478 FT_QRealloc( FT_Memory memory, 479 FT_Long current, 480 FT_Long size, 481 void* *p ) 482 { 483 FT_Error error; 484 485 486 (void)FT_QREALLOC( *p, current, size ); 487 return error; 488 } 489 490 491 FT_BASE_DEF( void ) 492 FT_Free( FT_Memory memory, 493 void* *P ) 494 { 495 if ( *P ) 496 FT_MEM_FREE( *P ); 497 } 498 499 #endif /* FT_CONFIG_OPTION_OLD_INTERNALS */ 500 501 /* END */ 502