Home | History | Annotate | Line # | Download | only in internal
      1 /****************************************************************************
      2  *
      3  * ftmemory.h
      4  *
      5  *   The FreeType memory management macros (specification).
      6  *
      7  * Copyright (C) 1996-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 #ifndef FTMEMORY_H_
     20 #define FTMEMORY_H_
     21 
     22 
     23 #include <ft2build.h>
     24 #include FT_CONFIG_CONFIG_H
     25 #include <freetype/fttypes.h>
     26 
     27 #include "compiler-macros.h"
     28 
     29 FT_BEGIN_HEADER
     30 
     31 
     32   /**************************************************************************
     33    *
     34    * @macro:
     35    *   FT_SET_ERROR
     36    *
     37    * @description:
     38    *   This macro is used to set an implicit 'error' variable to a given
     39    *   expression's value (usually a function call), and convert it to a
     40    *   boolean which is set whenever the value is != 0.
     41    */
     42 #undef  FT_SET_ERROR
     43 #define FT_SET_ERROR( expression ) \
     44           ( ( error = (expression) ) != 0 )
     45 
     46 
     47 
     48   /*************************************************************************/
     49   /*************************************************************************/
     50   /*************************************************************************/
     51   /****                                                                 ****/
     52   /****                                                                 ****/
     53   /****                           M E M O R Y                           ****/
     54   /****                                                                 ****/
     55   /****                                                                 ****/
     56   /*************************************************************************/
     57   /*************************************************************************/
     58   /*************************************************************************/
     59 
     60 
     61   /* The calculation `NULL + n' is undefined in C.  Even if the resulting */
     62   /* pointer doesn't get dereferenced, this causes warnings with          */
     63   /* sanitizers.                                                          */
     64   /*                                                                      */
     65   /* We thus provide a macro that should be used if `base' can be NULL.   */
     66 #define FT_OFFSET( base, count )  ( (base) ? (base) + (count) : NULL )
     67 
     68 
     69   /*
     70    * C++ refuses to handle statements like p = (void*)anything, with `p' a
     71    * typed pointer.  Since we don't have a `typeof' operator in standard C++,
     72    * we have to use a template to emulate it.
     73    */
     74 
     75 #ifdef __cplusplus
     76 
     77 extern "C++"
     78 {
     79   template <typename T> inline T*
     80   cplusplus_typeof(        T*,
     81                     void  *v )
     82   {
     83     return static_cast <T*> ( v );
     84   }
     85 }
     86 
     87 #define FT_ASSIGNP( p, val )  (p) = cplusplus_typeof( (p), (val) )
     88 
     89 #else
     90 
     91 #define FT_ASSIGNP( p, val )  (p) = (val)
     92 
     93 #endif
     94 
     95 
     96 
     97 #ifdef FT_DEBUG_MEMORY
     98 
     99   FT_BASE( const char* )  _ft_debug_file;
    100   FT_BASE( long )         _ft_debug_lineno;
    101 
    102 #define FT_DEBUG_INNER( exp )  ( _ft_debug_file   = __FILE__, \
    103                                  _ft_debug_lineno = __LINE__, \
    104                                  (exp) )
    105 
    106 #define FT_ASSIGNP_INNER( p, exp )  ( _ft_debug_file   = __FILE__, \
    107                                       _ft_debug_lineno = __LINE__, \
    108                                       FT_ASSIGNP( p, exp ) )
    109 
    110 #else /* !FT_DEBUG_MEMORY */
    111 
    112 #define FT_DEBUG_INNER( exp )       (exp)
    113 #define FT_ASSIGNP_INNER( p, exp )  FT_ASSIGNP( p, exp )
    114 
    115 #endif /* !FT_DEBUG_MEMORY */
    116 
    117 
    118   /*
    119    * The allocation functions return a pointer, and the error code is written
    120    * to through the `p_error' parameter.
    121    */
    122 
    123   /* The `q' variants of the functions below (`q' for `quick') don't fill */
    124   /* the allocated or reallocated memory with zero bytes.                 */
    125 
    126   FT_BASE( FT_Pointer )
    127   ft_mem_alloc( FT_Memory  memory,
    128                 FT_Long    size,
    129                 FT_Error  *p_error );
    130 
    131   FT_BASE( FT_Pointer )
    132   ft_mem_qalloc( FT_Memory  memory,
    133                  FT_Long    size,
    134                  FT_Error  *p_error );
    135 
    136   FT_BASE( FT_Pointer )
    137   ft_mem_realloc( FT_Memory  memory,
    138                   FT_Long    item_size,
    139                   FT_Long    cur_count,
    140                   FT_Long    new_count,
    141                   void*      block,
    142                   FT_Error  *p_error );
    143 
    144   FT_BASE( FT_Pointer )
    145   ft_mem_qrealloc( FT_Memory  memory,
    146                    FT_Long    item_size,
    147                    FT_Long    cur_count,
    148                    FT_Long    new_count,
    149                    void*      block,
    150                    FT_Error  *p_error );
    151 
    152   FT_BASE( void )
    153   ft_mem_free( FT_Memory    memory,
    154                const void*  P );
    155 
    156 
    157   /* The `Q' variants of the macros below (`Q' for `quick') don't fill */
    158   /* the allocated or reallocated memory with zero bytes.              */
    159 
    160 #define FT_MEM_ALLOC( ptr, size )                               \
    161           FT_ASSIGNP_INNER( ptr, ft_mem_alloc( memory,          \
    162                                                (FT_Long)(size), \
    163                                                &error ) )
    164 
    165 #define FT_MEM_FREE( ptr )                                  \
    166           FT_BEGIN_STMNT                                    \
    167             FT_DEBUG_INNER( ft_mem_free( memory, (ptr) ) ); \
    168             (ptr) = NULL;                                   \
    169           FT_END_STMNT
    170 
    171 #define FT_MEM_NEW( ptr )                        \
    172           FT_MEM_ALLOC( ptr, sizeof ( *(ptr) ) )
    173 
    174 #define FT_MEM_REALLOC( ptr, cursz, newsz )                        \
    175           FT_ASSIGNP_INNER( ptr, ft_mem_realloc( memory,           \
    176                                                  1,                \
    177                                                  (FT_Long)(cursz), \
    178                                                  (FT_Long)(newsz), \
    179                                                  (ptr),            \
    180                                                  &error ) )
    181 
    182 #define FT_MEM_QALLOC( ptr, size )                               \
    183           FT_ASSIGNP_INNER( ptr, ft_mem_qalloc( memory,          \
    184                                                 (FT_Long)(size), \
    185                                                 &error ) )
    186 
    187 #define FT_MEM_QNEW( ptr )                        \
    188           FT_MEM_QALLOC( ptr, sizeof ( *(ptr) ) )
    189 
    190 #define FT_MEM_QREALLOC( ptr, cursz, newsz )                        \
    191           FT_ASSIGNP_INNER( ptr, ft_mem_qrealloc( memory,           \
    192                                                   1,                \
    193                                                   (FT_Long)(cursz), \
    194                                                   (FT_Long)(newsz), \
    195                                                   (ptr),            \
    196                                                   &error ) )
    197 
    198 #define FT_MEM_ALLOC_MULT( ptr, count, item_size )                     \
    199           FT_ASSIGNP_INNER( ptr, ft_mem_realloc( memory,               \
    200                                                  (FT_Long)(item_size), \
    201                                                  0,                    \
    202                                                  (FT_Long)(count),     \
    203                                                  NULL,                 \
    204                                                  &error ) )
    205 
    206 #define FT_MEM_REALLOC_MULT( ptr, oldcnt, newcnt, itmsz )           \
    207           FT_ASSIGNP_INNER( ptr, ft_mem_realloc( memory,            \
    208                                                  (FT_Long)(itmsz),  \
    209                                                  (FT_Long)(oldcnt), \
    210                                                  (FT_Long)(newcnt), \
    211                                                  (ptr),             \
    212                                                  &error ) )
    213 
    214 #define FT_MEM_QALLOC_MULT( ptr, count, item_size )                     \
    215           FT_ASSIGNP_INNER( ptr, ft_mem_qrealloc( memory,               \
    216                                                   (FT_Long)(item_size), \
    217                                                   0,                    \
    218                                                   (FT_Long)(count),     \
    219                                                   NULL,                 \
    220                                                   &error ) )
    221 
    222 #define FT_MEM_QREALLOC_MULT( ptr, oldcnt, newcnt, itmsz )           \
    223           FT_ASSIGNP_INNER( ptr, ft_mem_qrealloc( memory,            \
    224                                                   (FT_Long)(itmsz),  \
    225                                                   (FT_Long)(oldcnt), \
    226                                                   (FT_Long)(newcnt), \
    227                                                   (ptr),             \
    228                                                   &error ) )
    229 
    230 
    231 #define FT_MEM_SET_ERROR( cond )  ( (cond), error != 0 )
    232 
    233 
    234 #define FT_MEM_SET( dest, byte, count )               \
    235           ft_memset( dest, byte, (FT_Offset)(count) )
    236 
    237 #define FT_MEM_COPY( dest, source, count )              \
    238           ft_memcpy( dest, source, (FT_Offset)(count) )
    239 
    240 #define FT_MEM_MOVE( dest, source, count )               \
    241           ft_memmove( dest, source, (FT_Offset)(count) )
    242 
    243 
    244 #define FT_MEM_ZERO( dest, count )  FT_MEM_SET( dest, 0, count )
    245 
    246 #define FT_ZERO( p )                FT_MEM_ZERO( p, sizeof ( *(p) ) )
    247 
    248 
    249 #define FT_ARRAY_ZERO( dest, count )                             \
    250           FT_MEM_ZERO( dest,                                     \
    251                        (FT_Offset)(count) * sizeof ( *(dest) ) )
    252 
    253 #define FT_ARRAY_COPY( dest, source, count )                     \
    254           FT_MEM_COPY( dest,                                     \
    255                        source,                                   \
    256                        (FT_Offset)(count) * sizeof ( *(dest) ) )
    257 
    258 #define FT_ARRAY_MOVE( dest, source, count )                     \
    259           FT_MEM_MOVE( dest,                                     \
    260                        source,                                   \
    261                        (FT_Offset)(count) * sizeof ( *(dest) ) )
    262 
    263 
    264   /*
    265    * Return the maximum number of addressable elements in an array.  We limit
    266    * ourselves to INT_MAX, rather than UINT_MAX, to avoid any problems.
    267    */
    268 #define FT_ARRAY_MAX( ptr )           ( FT_INT_MAX / sizeof ( *(ptr) ) )
    269 
    270 #define FT_ARRAY_CHECK( ptr, count )  ( (count) <= FT_ARRAY_MAX( ptr ) )
    271 
    272 
    273   /**************************************************************************
    274    *
    275    * The following functions macros expect that their pointer argument is
    276    * _typed_ in order to automatically compute array element sizes.
    277    */
    278 
    279 #define FT_MEM_NEW_ARRAY( ptr, count )                              \
    280           FT_ASSIGNP_INNER( ptr, ft_mem_realloc( memory,            \
    281                                                  sizeof ( *(ptr) ), \
    282                                                  0,                 \
    283                                                  (FT_Long)(count),  \
    284                                                  NULL,              \
    285                                                  &error ) )
    286 
    287 #define FT_MEM_RENEW_ARRAY( ptr, cursz, newsz )                     \
    288           FT_ASSIGNP_INNER( ptr, ft_mem_realloc( memory,            \
    289                                                  sizeof ( *(ptr) ), \
    290                                                  (FT_Long)(cursz),  \
    291                                                  (FT_Long)(newsz),  \
    292                                                  (ptr),             \
    293                                                  &error ) )
    294 
    295 #define FT_MEM_QNEW_ARRAY( ptr, count )                              \
    296           FT_ASSIGNP_INNER( ptr, ft_mem_qrealloc( memory,            \
    297                                                   sizeof ( *(ptr) ), \
    298                                                   0,                 \
    299                                                   (FT_Long)(count),  \
    300                                                   NULL,              \
    301                                                   &error ) )
    302 
    303 #define FT_MEM_QRENEW_ARRAY( ptr, cursz, newsz )                     \
    304           FT_ASSIGNP_INNER( ptr, ft_mem_qrealloc( memory,            \
    305                                                   sizeof ( *(ptr) ), \
    306                                                   (FT_Long)(cursz),  \
    307                                                   (FT_Long)(newsz),  \
    308                                                   (ptr),             \
    309                                                   &error ) )
    310 
    311 #define FT_ALLOC( ptr, size )                           \
    312           FT_MEM_SET_ERROR( FT_MEM_ALLOC( ptr, size ) )
    313 
    314 #define FT_REALLOC( ptr, cursz, newsz )                           \
    315           FT_MEM_SET_ERROR( FT_MEM_REALLOC( ptr, cursz, newsz ) )
    316 
    317 #define FT_ALLOC_MULT( ptr, count, item_size )                           \
    318           FT_MEM_SET_ERROR( FT_MEM_ALLOC_MULT( ptr, count, item_size ) )
    319 
    320 #define FT_REALLOC_MULT( ptr, oldcnt, newcnt, itmsz )              \
    321           FT_MEM_SET_ERROR( FT_MEM_REALLOC_MULT( ptr, oldcnt,      \
    322                                                  newcnt, itmsz ) )
    323 
    324 #define FT_QALLOC( ptr, size )                           \
    325           FT_MEM_SET_ERROR( FT_MEM_QALLOC( ptr, size ) )
    326 
    327 #define FT_QREALLOC( ptr, cursz, newsz )                           \
    328           FT_MEM_SET_ERROR( FT_MEM_QREALLOC( ptr, cursz, newsz ) )
    329 
    330 #define FT_QALLOC_MULT( ptr, count, item_size )                           \
    331           FT_MEM_SET_ERROR( FT_MEM_QALLOC_MULT( ptr, count, item_size ) )
    332 
    333 #define FT_QREALLOC_MULT( ptr, oldcnt, newcnt, itmsz )              \
    334           FT_MEM_SET_ERROR( FT_MEM_QREALLOC_MULT( ptr, oldcnt,      \
    335                                                   newcnt, itmsz ) )
    336 
    337 #define FT_FREE( ptr )  FT_MEM_FREE( ptr )
    338 
    339 #define FT_NEW( ptr )  FT_MEM_SET_ERROR( FT_MEM_NEW( ptr ) )
    340 
    341 #define FT_NEW_ARRAY( ptr, count )                           \
    342           FT_MEM_SET_ERROR( FT_MEM_NEW_ARRAY( ptr, count ) )
    343 
    344 #define FT_RENEW_ARRAY( ptr, curcnt, newcnt )                           \
    345           FT_MEM_SET_ERROR( FT_MEM_RENEW_ARRAY( ptr, curcnt, newcnt ) )
    346 
    347 #define FT_QNEW( ptr )                           \
    348           FT_MEM_SET_ERROR( FT_MEM_QNEW( ptr ) )
    349 
    350 #define FT_QNEW_ARRAY( ptr, count )                          \
    351           FT_MEM_SET_ERROR( FT_MEM_NEW_ARRAY( ptr, count ) )
    352 
    353 #define FT_QRENEW_ARRAY( ptr, curcnt, newcnt )                          \
    354           FT_MEM_SET_ERROR( FT_MEM_RENEW_ARRAY( ptr, curcnt, newcnt ) )
    355 
    356 
    357   FT_BASE( FT_Pointer )
    358   ft_mem_strdup( FT_Memory    memory,
    359                  const char*  str,
    360                  FT_Error    *p_error );
    361 
    362   FT_BASE( FT_Pointer )
    363   ft_mem_dup( FT_Memory    memory,
    364               const void*  address,
    365               FT_ULong     size,
    366               FT_Error    *p_error );
    367 
    368 
    369 #define FT_MEM_STRDUP( dst, str )                                            \
    370           (dst) = (char*)ft_mem_strdup( memory, (const char*)(str), &error )
    371 
    372 #define FT_STRDUP( dst, str )                           \
    373           FT_MEM_SET_ERROR( FT_MEM_STRDUP( dst, str ) )
    374 
    375 #define FT_MEM_DUP( dst, address, size )                                    \
    376           (dst) = ft_mem_dup( memory, (address), (FT_ULong)(size), &error )
    377 
    378 #define FT_DUP( dst, address, size )                           \
    379           FT_MEM_SET_ERROR( FT_MEM_DUP( dst, address, size ) )
    380 
    381 
    382   /* Return >= 1 if a truncation occurs.            */
    383   /* Return 0 if the source string fits the buffer. */
    384   /* This is *not* the same as strlcpy().           */
    385   FT_BASE( FT_Int )
    386   ft_mem_strcpyn( char*        dst,
    387                   const char*  src,
    388                   FT_ULong     size );
    389 
    390 #define FT_STRCPYN( dst, src, size )                                         \
    391           ft_mem_strcpyn( (char*)dst, (const char*)(src), (FT_ULong)(size) )
    392 
    393 
    394 FT_END_HEADER
    395 
    396 #endif /* FTMEMORY_H_ */
    397 
    398 
    399 /* END */
    400