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 <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_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 167 FT_BASE_DEF( void ) 168 ft_mem_free( FT_Memory memory, 169 const void *P ) 170 { 171 if ( P ) 172 memory->free( memory, (void*)P ); 173 } 174 175 176 FT_BASE_DEF( FT_Pointer ) 177 ft_mem_dup( FT_Memory memory, 178 const void* address, 179 FT_ULong size, 180 FT_Error *p_error ) 181 { 182 FT_Error error; 183 FT_Pointer p = ft_mem_qalloc( memory, size, &error ); 184 185 186 if ( !error && address ) 187 ft_memcpy( p, address, size ); 188 189 *p_error = error; 190 return p; 191 } 192 193 194 FT_BASE_DEF( FT_Pointer ) 195 ft_mem_strdup( FT_Memory memory, 196 const char* str, 197 FT_Error *p_error ) 198 { 199 FT_ULong len = str ? (FT_ULong)ft_strlen( str ) + 1 200 : 0; 201 202 203 return ft_mem_dup( memory, str, len, p_error ); 204 } 205 206 207 FT_BASE_DEF( FT_Int ) 208 ft_mem_strcpyn( char* dst, 209 const char* src, 210 FT_ULong size ) 211 { 212 while ( size > 1 && *src != 0 ) 213 { 214 *dst++ = *src++; 215 size--; 216 } 217 218 *dst = 0; /* always zero-terminate */ 219 220 return *src != 0; 221 } 222 223 224 /*************************************************************************/ 225 /*************************************************************************/ 226 /*************************************************************************/ 227 /***** *****/ 228 /***** *****/ 229 /***** D O U B L Y L I N K E D L I S T S *****/ 230 /***** *****/ 231 /***** *****/ 232 /*************************************************************************/ 233 /*************************************************************************/ 234 /*************************************************************************/ 235 236 #undef FT_COMPONENT 237 #define FT_COMPONENT trace_list 238 239 /* documentation is in ftlist.h */ 240 241 FT_EXPORT_DEF( FT_ListNode ) 242 FT_List_Find( FT_List list, 243 void* data ) 244 { 245 FT_ListNode cur; 246 247 248 cur = list->head; 249 while ( cur ) 250 { 251 if ( cur->data == data ) 252 return cur; 253 254 cur = cur->next; 255 } 256 257 return (FT_ListNode)0; 258 } 259 260 261 /* documentation is in ftlist.h */ 262 263 FT_EXPORT_DEF( void ) 264 FT_List_Add( FT_List list, 265 FT_ListNode node ) 266 { 267 FT_ListNode before = list->tail; 268 269 270 node->next = 0; 271 node->prev = before; 272 273 if ( before ) 274 before->next = node; 275 else 276 list->head = node; 277 278 list->tail = node; 279 } 280 281 282 /* documentation is in ftlist.h */ 283 284 FT_EXPORT_DEF( void ) 285 FT_List_Insert( FT_List list, 286 FT_ListNode node ) 287 { 288 FT_ListNode after = list->head; 289 290 291 node->next = after; 292 node->prev = 0; 293 294 if ( !after ) 295 list->tail = node; 296 else 297 after->prev = node; 298 299 list->head = node; 300 } 301 302 303 /* documentation is in ftlist.h */ 304 305 FT_EXPORT_DEF( void ) 306 FT_List_Remove( FT_List list, 307 FT_ListNode node ) 308 { 309 FT_ListNode before, after; 310 311 312 before = node->prev; 313 after = node->next; 314 315 if ( before ) 316 before->next = after; 317 else 318 list->head = after; 319 320 if ( after ) 321 after->prev = before; 322 else 323 list->tail = before; 324 } 325 326 327 /* documentation is in ftlist.h */ 328 329 FT_EXPORT_DEF( void ) 330 FT_List_Up( FT_List list, 331 FT_ListNode node ) 332 { 333 FT_ListNode before, after; 334 335 336 before = node->prev; 337 after = node->next; 338 339 /* check whether we are already on top of the list */ 340 if ( !before ) 341 return; 342 343 before->next = after; 344 345 if ( after ) 346 after->prev = before; 347 else 348 list->tail = before; 349 350 node->prev = 0; 351 node->next = list->head; 352 list->head->prev = node; 353 list->head = node; 354 } 355 356 357 /* documentation is in ftlist.h */ 358 359 FT_EXPORT_DEF( FT_Error ) 360 FT_List_Iterate( FT_List list, 361 FT_List_Iterator iterator, 362 void* user ) 363 { 364 FT_ListNode cur = list->head; 365 FT_Error error = FT_Err_Ok; 366 367 368 while ( cur ) 369 { 370 FT_ListNode next = cur->next; 371 372 373 error = iterator( cur, user ); 374 if ( error ) 375 break; 376 377 cur = next; 378 } 379 380 return error; 381 } 382 383 384 /* documentation is in ftlist.h */ 385 386 FT_EXPORT_DEF( void ) 387 FT_List_Finalize( FT_List list, 388 FT_List_Destructor destroy, 389 FT_Memory memory, 390 void* user ) 391 { 392 FT_ListNode cur; 393 394 395 cur = list->head; 396 while ( cur ) 397 { 398 FT_ListNode next = cur->next; 399 void* data = cur->data; 400 401 402 if ( destroy ) 403 destroy( memory, data, user ); 404 405 FT_FREE( cur ); 406 cur = next; 407 } 408 409 list->head = 0; 410 list->tail = 0; 411 } 412 413 414 FT_BASE_DEF( FT_UInt32 ) 415 ft_highpow2( FT_UInt32 value ) 416 { 417 FT_UInt32 value2; 418 419 420 /* 421 * We simply clear the lowest bit in each iteration. When 422 * we reach 0, we know that the previous value was our result. 423 */ 424 for ( ;; ) 425 { 426 value2 = value & (value - 1); /* clear lowest bit */ 427 if ( value2 == 0 ) 428 break; 429 430 value = value2; 431 } 432 return value; 433 } 434 435 436 /* END */ 437