XFA: merge patch from CL 817753002
[pdfium.git] / core / src / fxge / fx_freetype / fxft2.5.01 / src / base / ftutil.c
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 */