/// Reallocate a block of memory for FreeType.
///
/// @param[in] pMemory      Handle to the source memory manager.
/// @param[in] currentSize  Current block size, in bytes.
/// @param[in] newSize      New block size, in bytes.
/// @param[in] pBlock       Block to reallocate.
///
/// @return  Pointer to the reallocated block of memory, or null if reallocation failed.
///
/// @see FreeTypeAllocate(), FreeTypeFree()
static void* FreeTypeReallocate( FT_Memory /*pMemory*/, long currentSize, long newSize, void* pBlock )
{
    DefaultAllocator allocator;

    // We cannot call Reallocate() if either the old or new size requires SIMD alignment (see FreeTypeAllocate() for
    // more information about why we need to align some allocations), so call Free()/Allocate()/AllocateAligned()
    // instead as appropriate.
    if( newSize < HELIUM_SIMD_SIZE )
    {
        if( currentSize < HELIUM_SIMD_SIZE )
        {
            // Our allocators allow for null pointers to be passed to their reallocate functions, so we do not need to
            // validate the block parameter.
            pBlock = allocator.ReallocateAligned( pBlock, HELIUM_SIMD_ALIGNMENT, newSize );
        }
        else
        {
            void* pOldBlock = pBlock;

            // Our allocators treat a realloc() with a size of zero as a free, so simulate that functionality here.
            pBlock = NULL;
            if( newSize )
            {
                pBlock = allocator.AllocateAligned( HELIUM_SIMD_ALIGNMENT, newSize );
                if( pBlock )
                {
                    HELIUM_ASSERT( newSize < currentSize );
                    MemoryCopy( pBlock, pOldBlock, newSize );
                }
            }

            allocator.FreeAligned( pOldBlock );
        }
    }
    else
    {
        void* pOldBlock = pBlock;

        // Note that newSize >= HELIUM_SIMD_SIZE, so we don't need to check for non-zero sizes here.
        pBlock = allocator.AllocateAligned( HELIUM_SIMD_ALIGNMENT, newSize );
        if( pBlock )
        {
            MemoryCopy( pBlock, pOldBlock, Min( currentSize, newSize ) );
        }

        allocator.FreeAligned( pOldBlock );
    }

    return pBlock;
}