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