• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 )
ft_mem_alloc(FT_Memory memory,FT_Long size,FT_Error * p_error)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 )
ft_mem_qalloc(FT_Memory memory,FT_Long size,FT_Error * p_error)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 )
ft_mem_realloc(FT_Memory memory,FT_Long item_size,FT_Long cur_count,FT_Long new_count,void * block,FT_Error * p_error)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 )
ft_mem_qrealloc(FT_Memory memory,FT_Long item_size,FT_Long cur_count,FT_Long new_count,void * block,FT_Error * p_error)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 )
ft_mem_free(FT_Memory memory,const void * P)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 )
ft_mem_dup(FT_Memory memory,const void * address,FT_ULong size,FT_Error * p_error)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 )
ft_mem_strdup(FT_Memory memory,const char * str,FT_Error * p_error)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 )
ft_mem_strcpyn(char * dst,const char * src,FT_ULong size)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 )
FT_List_Find(FT_List list,void * data)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 )
FT_List_Add(FT_List list,FT_ListNode node)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 )
FT_List_Insert(FT_List list,FT_ListNode node)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 )
FT_List_Remove(FT_List list,FT_ListNode node)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 )
FT_List_Up(FT_List list,FT_ListNode node)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 )
FT_List_Iterate(FT_List list,FT_List_Iterator iterator,void * user)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 )
FT_List_Finalize(FT_List list,FT_List_Destructor destroy,FT_Memory memory,void * user)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 )
ft_highpow2(FT_UInt32 value)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 )
FT_Alloc(FT_Memory memory,FT_Long size,void ** P)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 )
FT_QAlloc(FT_Memory memory,FT_Long size,void ** p)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 )
FT_Realloc(FT_Memory memory,FT_Long current,FT_Long size,void ** P)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 )
FT_QRealloc(FT_Memory memory,FT_Long current,FT_Long size,void ** p)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 )
FT_Free(FT_Memory memory,void ** P)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