//\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
//
// CommonHelpers satellite library | Author: Sergei Y.Kitáev
//
// TYPIFIED MEMORY OPERATIONS (TEMPLATE IMPLEMENTATION):
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#pragma once
#ifndef HTEMPLATES_IMPL_H
   #error "This header file is designed to be included only from 'HTemplates.Impl.h'."
#endif
namespace CommonHelpers {
//==================================================================================================

template<typename T>static int HTMemory::ElementSize()
{
   return sizeof(T);
}

template<typename T>static int HTMemory::CountToSize(int count)
{
   return HCheckedInt::Multiply( ElementSize<T>(), count );
}

//==================================================================================================

template<typename T>static T* HTMemory::Clear($OUT T* pDestinationElement)
{
   return Clear( pDestinationElement, 1 );
}

template<typename T>static T* HTMemory::Clear($OUT T* pDestinationElements,$NULLABLE<int> count)
{
   return (T*)HUnsafeMemory::Clear( pDestinationElements,
      count.HasValue ? CountToSize<T>( count.Value ) :
         GetAllocatedCapacity( pDestinationElements ) );
}

//--------------------------------------------------------------------------------------------------

template<typename T>static T* HTMemory::Copy( $IN const T* pcSourceElements,
                                              $OUT T* pDestinationElements,
                                              int count )
{
   return (T*)HUnsafeMemory::Copy(
      ($PVOID)pcSourceElements, pDestinationElements, CountToSize<T>( count ) );
}

//==================================================================================================

template<typename T>static T* HTMemory::Allocate()
{
   return Allocate<T>( 1 );
}

template<typename T>static T* HTMemory::Allocate(int capacity)
{
   return (T*)HUnsafeMemory::Allocate( CountToSize<T>( capacity ) );
}

template<typename T>static T* HTMemory::ReAllocate($IN T* pAllocatedBuffer,int newCapacity)
{
   return (T*)HUnsafeMemory::ReAllocate( pAllocatedBuffer, CountToSize( newCapacity ) );
}

template<typename T>static T* HTMemory::ReAllocate($IN T* %pAllocatedBuffer,int newCapacity)
{
   return (T*)HUnsafeMemory::ReAllocate( %pAllocatedBuffer, CountToSize( newCapacity ) );
}

template<typename T>static T* HTMemory::Duplicate($IN const T* pcAllocatedBuffer)
{
   return (T*)HUnsafeMemory::Duplicate( pcAllocatedBuffer );
}

//--------------------------------------------------------------------------------------------------

template<typename T>static int HTMemory::GetAllocatedCapacity(const T* pcAllocatedBuffer)
{
   return HCheckedInt::Divide(
      HUnsafeMemory::GetAllocatedSize( ($PVOID)pcAllocatedBuffer ),
      ElementSize<T>() );
}

//--------------------------------------------------------------------------------------------------

template<typename T>static bool HTMemory::Free($OPT T* pAllocatedBuffer)
{
   return HUnsafeMemory::Free( pAllocatedBuffer );
}

template<typename T>static bool HTMemory::Free($OPT T* volatile* ppAllocatedBuffer)
{
   return HUnsafeMemory::Free( ppAllocatedBuffer );
}

//==================================================================================================
} // CommonHelpers
