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