Home | History | Annotate | Download | only in base
      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