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-2018 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 && block && 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 )
     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 && block && 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 );
    145 
    146       block = memory->alloc( memory, new_count * item_size );
    147       if ( block == NULL )
    148         error = FT_THROW( Out_Of_Memory );
    149     }
    150     else
    151     {
    152       FT_Pointer  block2;
    153       FT_Long     cur_size = cur_count * item_size;
    154       FT_Long     new_size = new_count * item_size;
    155 
    156 
    157       block2 = memory->realloc( memory, cur_size, new_size, block );
    158       if ( !block2 )
    159         error = FT_THROW( Out_Of_Memory );
    160       else
    161         block = block2;
    162     }
    163 
    164     *p_error = error;
    165     return block;
    166   }
    167 
    168 
    169   FT_BASE_DEF( void )
    170   ft_mem_free( FT_Memory   memory,
    171                const void *P )
    172   {
    173     if ( P )
    174       memory->free( memory, (void*)P );
    175   }
    176 
    177 
    178   FT_BASE_DEF( FT_Pointer )
    179   ft_mem_dup( FT_Memory    memory,
    180               const void*  address,
    181               FT_ULong     size,
    182               FT_Error    *p_error )
    183   {
    184     FT_Error    error;
    185     FT_Pointer  p = ft_mem_qalloc( memory, (FT_Long)size, &error );
    186 
    187 
    188     if ( !error && address && size > 0 )
    189       ft_memcpy( p, address, size );
    190 
    191     *p_error = error;
    192     return p;
    193   }
    194 
    195 
    196   FT_BASE_DEF( FT_Pointer )
    197   ft_mem_strdup( FT_Memory    memory,
    198                  const char*  str,
    199                  FT_Error    *p_error )
    200   {
    201     FT_ULong  len = str ? (FT_ULong)ft_strlen( str ) + 1
    202                         : 0;
    203 
    204 
    205     return ft_mem_dup( memory, str, len, p_error );
    206   }
    207 
    208 
    209   FT_BASE_DEF( FT_Int )
    210   ft_mem_strcpyn( char*        dst,
    211                   const char*  src,
    212                   FT_ULong     size )
    213   {
    214     while ( size > 1 && *src != 0 )
    215     {
    216       *dst++ = *src++;
    217       size--;
    218     }
    219 
    220     *dst = 0;  /* always zero-terminate */
    221 
    222     return *src != 0;
    223   }
    224 
    225 
    226   /*************************************************************************/
    227   /*************************************************************************/
    228   /*************************************************************************/
    229   /*****                                                               *****/
    230   /*****                                                               *****/
    231   /*****            D O U B L Y   L I N K E D   L I S T S              *****/
    232   /*****                                                               *****/
    233   /*****                                                               *****/
    234   /*************************************************************************/
    235   /*************************************************************************/
    236   /*************************************************************************/
    237 
    238 #undef  FT_COMPONENT
    239 #define FT_COMPONENT  trace_list
    240 
    241   /* documentation is in ftlist.h */
    242 
    243   FT_EXPORT_DEF( FT_ListNode )
    244   FT_List_Find( FT_List  list,
    245                 void*    data )
    246   {
    247     FT_ListNode  cur;
    248 
    249 
    250     if ( !list )
    251       return NULL;
    252 
    253     cur = list->head;
    254     while ( cur )
    255     {
    256       if ( cur->data == data )
    257         return cur;
    258 
    259       cur = cur->next;
    260     }
    261 
    262     return NULL;
    263   }
    264 
    265 
    266   /* documentation is in ftlist.h */
    267 
    268   FT_EXPORT_DEF( void )
    269   FT_List_Add( FT_List      list,
    270                FT_ListNode  node )
    271   {
    272     FT_ListNode  before;
    273 
    274 
    275     if ( !list || !node )
    276       return;
    277 
    278     before = list->tail;
    279 
    280     node->next = NULL;
    281     node->prev = before;
    282 
    283     if ( before )
    284       before->next = node;
    285     else
    286       list->head = node;
    287 
    288     list->tail = node;
    289   }
    290 
    291 
    292   /* documentation is in ftlist.h */
    293 
    294   FT_EXPORT_DEF( void )
    295   FT_List_Insert( FT_List      list,
    296                   FT_ListNode  node )
    297   {
    298     FT_ListNode  after;
    299 
    300 
    301     if ( !list || !node )
    302       return;
    303 
    304     after = list->head;
    305 
    306     node->next = after;
    307     node->prev = NULL;
    308 
    309     if ( !after )
    310       list->tail = node;
    311     else
    312       after->prev = node;
    313 
    314     list->head = node;
    315   }
    316 
    317 
    318   /* documentation is in ftlist.h */
    319 
    320   FT_EXPORT_DEF( void )
    321   FT_List_Remove( FT_List      list,
    322                   FT_ListNode  node )
    323   {
    324     FT_ListNode  before, after;
    325 
    326 
    327     if ( !list || !node )
    328       return;
    329 
    330     before = node->prev;
    331     after  = node->next;
    332 
    333     if ( before )
    334       before->next = after;
    335     else
    336       list->head = after;
    337 
    338     if ( after )
    339       after->prev = before;
    340     else
    341       list->tail = before;
    342   }
    343 
    344 
    345   /* documentation is in ftlist.h */
    346 
    347   FT_EXPORT_DEF( void )
    348   FT_List_Up( FT_List      list,
    349               FT_ListNode  node )
    350   {
    351     FT_ListNode  before, after;
    352 
    353 
    354     if ( !list || !node )
    355       return;
    356 
    357     before = node->prev;
    358     after  = node->next;
    359 
    360     /* check whether we are already on top of the list */
    361     if ( !before )
    362       return;
    363 
    364     before->next = after;
    365 
    366     if ( after )
    367       after->prev = before;
    368     else
    369       list->tail = before;
    370 
    371     node->prev       = NULL;
    372     node->next       = list->head;
    373     list->head->prev = node;
    374     list->head       = node;
    375   }
    376 
    377 
    378   /* documentation is in ftlist.h */
    379 
    380   FT_EXPORT_DEF( FT_Error )
    381   FT_List_Iterate( FT_List           list,
    382                    FT_List_Iterator  iterator,
    383                    void*             user )
    384   {
    385     FT_ListNode  cur;
    386     FT_Error     error = FT_Err_Ok;
    387 
    388 
    389     if ( !list || !iterator )
    390       return FT_THROW( Invalid_Argument );
    391 
    392     cur = list->head;
    393 
    394     while ( cur )
    395     {
    396       FT_ListNode  next = cur->next;
    397 
    398 
    399       error = iterator( cur, user );
    400       if ( error )
    401         break;
    402 
    403       cur = next;
    404     }
    405 
    406     return error;
    407   }
    408 
    409 
    410   /* documentation is in ftlist.h */
    411 
    412   FT_EXPORT_DEF( void )
    413   FT_List_Finalize( FT_List             list,
    414                     FT_List_Destructor  destroy,
    415                     FT_Memory           memory,
    416                     void*               user )
    417   {
    418     FT_ListNode  cur;
    419 
    420 
    421     if ( !list || !memory )
    422       return;
    423 
    424     cur = list->head;
    425     while ( cur )
    426     {
    427       FT_ListNode  next = cur->next;
    428       void*        data = cur->data;
    429 
    430 
    431       if ( destroy )
    432         destroy( memory, data, user );
    433 
    434       FT_FREE( cur );
    435       cur = next;
    436     }
    437 
    438     list->head = NULL;
    439     list->tail = NULL;
    440   }
    441 
    442 
    443 /* END */
    444