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 |