Home | History | Annotate | Line # | Download | only in base
      1 /****************************************************************************
      2  *
      3  * ftutil.c
      4  *
      5  *   FreeType utility file for memory and list management (body).
      6  *
      7  * Copyright (C) 2002-2020 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 <freetype/internal/ftdebug.h>
     20 #include <freetype/internal/ftmemory.h>
     21 #include <freetype/internal/ftobjs.h>
     22 #include <freetype/ftlist.h>
     23 
     24 
     25   /**************************************************************************
     26    *
     27    * The macro FT_COMPONENT is used in trace mode.  It is an implicit
     28    * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
     29    * messages during execution.
     30    */
     31 #undef  FT_COMPONENT
     32 #define FT_COMPONENT  memory
     33 
     34 
     35   /*************************************************************************/
     36   /*************************************************************************/
     37   /*************************************************************************/
     38   /*****                                                               *****/
     39   /*****                                                               *****/
     40   /*****               M E M O R Y   M A N A G E M E N T               *****/
     41   /*****                                                               *****/
     42   /*****                                                               *****/
     43   /*************************************************************************/
     44   /*************************************************************************/
     45   /*************************************************************************/
     46 
     47 
     48   FT_BASE_DEF( FT_Pointer )
     49   ft_mem_alloc( FT_Memory  memory,
     50                 FT_Long    size,
     51                 FT_Error  *p_error )
     52   {
     53     FT_Error    error;
     54     FT_Pointer  block = ft_mem_qalloc( memory, size, &error );
     55 
     56     if ( !error && block && size > 0 )
     57       FT_MEM_ZERO( block, size );
     58 
     59     *p_error = error;
     60     return block;
     61   }
     62 
     63 
     64   FT_BASE_DEF( FT_Pointer )
     65   ft_mem_qalloc( FT_Memory  memory,
     66                  FT_Long    size,
     67                  FT_Error  *p_error )
     68   {
     69     FT_Error    error = FT_Err_Ok;
     70     FT_Pointer  block = NULL;
     71 
     72 
     73     if ( size > 0 )
     74     {
     75       block = memory->alloc( memory, size );
     76       if ( !block )
     77         error = FT_THROW( Out_Of_Memory );
     78     }
     79     else if ( size < 0 )
     80     {
     81       /* may help catch/prevent security issues */
     82       error = FT_THROW( Invalid_Argument );
     83     }
     84 
     85     *p_error = error;
     86     return block;
     87   }
     88 
     89 
     90   FT_BASE_DEF( FT_Pointer )
     91   ft_mem_realloc( FT_Memory  memory,
     92                   FT_Long    item_size,
     93                   FT_Long    cur_count,
     94                   FT_Long    new_count,
     95                   void*      block,
     96                   FT_Error  *p_error )
     97   {
     98     FT_Error  error = FT_Err_Ok;
     99 
    100 
    101     block = ft_mem_qrealloc( memory, item_size,
    102                              cur_count, new_count, block, &error );
    103     if ( !error && block && 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_THROW( 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_THROW( Array_Too_Large );
    140     }
    141     else if ( cur_count == 0 )
    142     {
    143       FT_ASSERT( !block );
    144 
    145       block = memory->alloc( memory, new_count * item_size );
    146       if ( block == NULL )
    147         error = FT_THROW( Out_Of_Memory );
    148     }
    149     else
    150     {
    151       FT_Pointer  block2;
    152       FT_Long     cur_size = cur_count * item_size;
    153       FT_Long     new_size = new_count * item_size;
    154 
    155 
    156       block2 = memory->realloc( memory, cur_size, new_size, block );
    157       if ( !block2 )
    158         error = FT_THROW( Out_Of_Memory );
    159       else
    160         block = block2;
    161     }
    162 
    163     *p_error = error;
    164     return block;
    165   }
    166 
    167 
    168   FT_BASE_DEF( void )
    169   ft_mem_free( FT_Memory   memory,
    170                const void *P )
    171   {
    172     if ( P )
    173       memory->free( memory, (void*)P );
    174   }
    175 
    176 
    177   FT_BASE_DEF( FT_Pointer )
    178   ft_mem_dup( FT_Memory    memory,
    179               const void*  address,
    180               FT_ULong     size,
    181               FT_Error    *p_error )
    182   {
    183     FT_Error    error;
    184     FT_Pointer  p = ft_mem_qalloc( memory, (FT_Long)size, &error );
    185 
    186 
    187     if ( !error && address && size > 0 )
    188       ft_memcpy( p, address, size );
    189 
    190     *p_error = error;
    191     return p;
    192   }
    193 
    194 
    195   FT_BASE_DEF( FT_Pointer )
    196   ft_mem_strdup( FT_Memory    memory,
    197                  const char*  str,
    198                  FT_Error    *p_error )
    199   {
    200     FT_ULong  len = str ? (FT_ULong)ft_strlen( str ) + 1
    201                         : 0;
    202 
    203 
    204     return ft_mem_dup( memory, str, len, p_error );
    205   }
    206 
    207 
    208   FT_BASE_DEF( FT_Int )
    209   ft_mem_strcpyn( char*        dst,
    210                   const char*  src,
    211                   FT_ULong     size )
    212   {
    213     while ( size > 1 && *src != 0 )
    214     {
    215       *dst++ = *src++;
    216       size--;
    217     }
    218 
    219     *dst = 0;  /* always zero-terminate */
    220 
    221     return *src != 0;
    222   }
    223 
    224 
    225   /*************************************************************************/
    226   /*************************************************************************/
    227   /*************************************************************************/
    228   /*****                                                               *****/
    229   /*****                                                               *****/
    230   /*****            D O U B L Y   L I N K E D   L I S T S              *****/
    231   /*****                                                               *****/
    232   /*****                                                               *****/
    233   /*************************************************************************/
    234   /*************************************************************************/
    235   /*************************************************************************/
    236 
    237 #undef  FT_COMPONENT
    238 #define FT_COMPONENT  list
    239 
    240   /* documentation is in ftlist.h */
    241 
    242   FT_EXPORT_DEF( FT_ListNode )
    243   FT_List_Find( FT_List  list,
    244                 void*    data )
    245   {
    246     FT_ListNode  cur;
    247 
    248 
    249     if ( !list )
    250       return NULL;
    251 
    252     cur = list->head;
    253     while ( cur )
    254     {
    255       if ( cur->data == data )
    256         return cur;
    257 
    258       cur = cur->next;
    259     }
    260 
    261     return NULL;
    262   }
    263 
    264 
    265   /* documentation is in ftlist.h */
    266 
    267   FT_EXPORT_DEF( void )
    268   FT_List_Add( FT_List      list,
    269                FT_ListNode  node )
    270   {
    271     FT_ListNode  before;
    272 
    273 
    274     if ( !list || !node )
    275       return;
    276 
    277     before = list->tail;
    278 
    279     node->next = NULL;
    280     node->prev = before;
    281 
    282     if ( before )
    283       before->next = node;
    284     else
    285       list->head = node;
    286 
    287     list->tail = node;
    288   }
    289 
    290 
    291   /* documentation is in ftlist.h */
    292 
    293   FT_EXPORT_DEF( void )
    294   FT_List_Insert( FT_List      list,
    295                   FT_ListNode  node )
    296   {
    297     FT_ListNode  after;
    298 
    299 
    300     if ( !list || !node )
    301       return;
    302 
    303     after = list->head;
    304 
    305     node->next = after;
    306     node->prev = NULL;
    307 
    308     if ( !after )
    309       list->tail = node;
    310     else
    311       after->prev = node;
    312 
    313     list->head = node;
    314   }
    315 
    316 
    317   /* documentation is in ftlist.h */
    318 
    319   FT_EXPORT_DEF( void )
    320   FT_List_Remove( FT_List      list,
    321                   FT_ListNode  node )
    322   {
    323     FT_ListNode  before, after;
    324 
    325 
    326     if ( !list || !node )
    327       return;
    328 
    329     before = node->prev;
    330     after  = node->next;
    331 
    332     if ( before )
    333       before->next = after;
    334     else
    335       list->head = after;
    336 
    337     if ( after )
    338       after->prev = before;
    339     else
    340       list->tail = before;
    341   }
    342 
    343 
    344   /* documentation is in ftlist.h */
    345 
    346   FT_EXPORT_DEF( void )
    347   FT_List_Up( FT_List      list,
    348               FT_ListNode  node )
    349   {
    350     FT_ListNode  before, after;
    351 
    352 
    353     if ( !list || !node )
    354       return;
    355 
    356     before = node->prev;
    357     after  = node->next;
    358 
    359     /* check whether we are already on top of the list */
    360     if ( !before )
    361       return;
    362 
    363     before->next = after;
    364 
    365     if ( after )
    366       after->prev = before;
    367     else
    368       list->tail = before;
    369 
    370     node->prev       = NULL;
    371     node->next       = list->head;
    372     list->head->prev = node;
    373     list->head       = node;
    374   }
    375 
    376 
    377   /* documentation is in ftlist.h */
    378 
    379   FT_EXPORT_DEF( FT_Error )
    380   FT_List_Iterate( FT_List           list,
    381                    FT_List_Iterator  iterator,
    382                    void*             user )
    383   {
    384     FT_ListNode  cur;
    385     FT_Error     error = FT_Err_Ok;
    386 
    387 
    388     if ( !list || !iterator )
    389       return FT_THROW( Invalid_Argument );
    390 
    391     cur = list->head;
    392 
    393     while ( cur )
    394     {
    395       FT_ListNode  next = cur->next;
    396 
    397 
    398       error = iterator( cur, user );
    399       if ( error )
    400         break;
    401 
    402       cur = next;
    403     }
    404 
    405     return error;
    406   }
    407 
    408 
    409   /* documentation is in ftlist.h */
    410 
    411   FT_EXPORT_DEF( void )
    412   FT_List_Finalize( FT_List             list,
    413                     FT_List_Destructor  destroy,
    414                     FT_Memory           memory,
    415                     void*               user )
    416   {
    417     FT_ListNode  cur;
    418 
    419 
    420     if ( !list || !memory )
    421       return;
    422 
    423     cur = list->head;
    424     while ( cur )
    425     {
    426       FT_ListNode  next = cur->next;
    427       void*        data = cur->data;
    428 
    429 
    430       if ( destroy )
    431         destroy( memory, data, user );
    432 
    433       FT_FREE( cur );
    434       cur = next;
    435     }
    436 
    437     list->head = NULL;
    438     list->tail = NULL;
    439   }
    440 
    441 
    442 /* END */
    443