misc/libfreetype/src/base/ftutil.c
changeset 9372 915436ff64ab
parent 9371 f3840de881bd
child 9373 b769a8e38cbd
equal deleted inserted replaced
9371:f3840de881bd 9372:915436ff64ab
     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 */