• 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-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 )
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_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 )
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 
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 )
ft_mem_qrealloc(FT_Memory memory,FT_Long item_size,FT_Long cur_count,FT_Long new_count,void * block,FT_Error * p_error)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 )
ft_mem_free(FT_Memory memory,const void * P)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 )
ft_mem_dup(FT_Memory memory,const void * address,FT_ULong size,FT_Error * p_error)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 )
ft_mem_strdup(FT_Memory memory,const char * str,FT_Error * p_error)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 )
ft_mem_strcpyn(char * dst,const char * src,FT_ULong size)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 )
FT_List_Find(FT_List list,void * data)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 )
FT_List_Add(FT_List list,FT_ListNode node)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 )
FT_List_Insert(FT_List list,FT_ListNode node)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 )
FT_List_Remove(FT_List list,FT_ListNode node)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 )
FT_List_Up(FT_List list,FT_ListNode node)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 )
FT_List_Iterate(FT_List list,FT_List_Iterator iterator,void * user)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 )
FT_List_Finalize(FT_List list,FT_List_Destructor destroy,FT_Memory memory,void * user)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 )
ft_highpow2(FT_UInt32 value)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