(root)/
freetype-2.13.2/
src/
base/
ftutil.c
       1  /****************************************************************************
       2   *
       3   * ftutil.c
       4   *
       5   *   FreeType utility file for memory and list management (body).
       6   *
       7   * Copyright (C) 2002-2023 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 */