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, 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 )
     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_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 )
     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 )
    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 )
    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 )
    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 )
    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 )
    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 )
    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 )
    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 )
    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 )
    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 )
    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 )
    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 )
    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 )
    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 )
    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 )
    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 )
    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 )
    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 )
    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