// RuntimeForStatic base library | C+- (SysRoutine) | Author: Sergei Y.Kitáev
#pragma once
#include "include_restrictions.h"
namespace RuntimeForStatic {
//==================================================================================================

template<typename T>static T* $memory::Clear($A, T* pElement ) $ret_target
{
   $VERIFY_POINTER_ARG( pElement );
   return (T*)$Memory::Clear($ci, pElement, sizeof(T) );
}
template<typename T>static T* $memory::Clear($A, T* pElements, int count $positive ) $ret_target
{
   $VERIFY_POINTER_ARG( pElements );
   return (T*)$Memory::Clear($ci, pElements, sizeof(T)*count );
}

template<typename T>static T* $memory::ClearIfNotNull( T* pElement $optional ) $ret_target
{
   return pElement ? Clear($, pElement ) : nullptr;
}
template<typename T>static T* $memory::ClearIfNotNull( T* pElements $optional,
                                                       int count $positive ) $ret_target
{
   return pElement ? Clear($, pElements, count ) : nullptr;
}

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

template<typename T>static T* $memory::Copy($A, const T* pSourceElement,
                                                T* pTargetElement ) $ret_target
{
   $VERIFY_POINTER_ARG( pSourceElement );
   $VERIFY_POINTER_ARG( pTargetElement );
   return (T*)$Memory::Copy($ci, pSourceElement, pTargetElement, sizeof(T) );
}
template<typename T>static T* $memory::Copy($A, const T* pSourceElements,
                                                T* pTargetElements,
                                                int count $positive ) $ret_target
{
   $VERIFY_POINTER_ARG( pSourceElements );
   $VERIFY_POINTER_ARG( pTargetElements );
   $$VERIFY_POSITIVE_VALUE_ARG( count );
   return (T*)$Memory::Copy($ci, pSourceElements, pTargetElements, sizeof(T)*count );
}

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

template<typename T>static T* $memory::Allocate($M) $fatal_error_on_failure
{
   return (T*)$Memory::Allocate($, sizeof(T) );
}
template<typename T>static T* $memory::Allocate($AM, int count $positive ) $fatal_error_on_failure
{
   return $memory::Allocate<T>($ci,$ci, count );
}

template<typename T>static T* $memory::CleanAlloc($M) $fatal_error_on_failure
{
   return (T*)$Memory::CleanAlloc($, sizeof(T) );
}
template<typename T>static T* $memory::CleanAlloc($AM, int count $positive ) $fatal_error_on_failure
{
   return $memory::CleanAlloc<T>($ci,$ci, count );
}

template<typename T>static T* $memory::ReAllocate($AM, T* pElements,
                                                       int newCount $positive )
                                                       $fatal_error_on_failure
{
   return $memory::ReAllocate<T>($ci,$ci, pElements, newCount );
}

template<typename T>static T* $memory::Allocate($A,$M, int count $positive ) $fatal_error_on_failure
{
   $$VERIFY_POSITIVE_VALUE_ARG( count );
   return (T*)$Memory::Allocate($,$m, sizeof(T), count );
}
template<typename T>static T* $memory::CleanAlloc($A,$M, int count $positive )
                                                         $fatal_error_on_failure
{
   return Clear($, Allocate($ci,$m, count ) );
}
template<typename T>static T* $memory::ReAllocate($A,$M, T* pElements, int newCount $positive )
                                                         $fatal_error_on_failure
{
   $VERIFY_POINTER_ARG( pElements );
   $$VERIFY_POSITIVE_VALUE_ARG( newCount );
   return (T*)$Memory::ReAllocate($,$m, pElements, sizeof(T)*newCount );
}

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

template<typename T>static T* $memory::Free( T*& pElements $optional ) $ret_null
{
   if ( pElements )
   {
      $Memory::Free( pElements );
      pElements = nullptr;
   }
   return nullptr;
}
template<typename T>static T* Free( const std::initializer_list<T*&>& listOfPointers $optionals )
                                    $ret_null
{
   for (auto ptr: listOfPointers)
   {
      $Memory::Free( ptr );
      ptr = nullptr;
   }
   return nullptr;
}

template<typename T>static T* $memory::FreeByPtr( T* volatile* ppElements $optional ) $ret_null
{
   $$VERIFY_POINTER_ARG( ppElements );
   return $Memory::Free($, (PVOID volatile*)ppElements );
}
template<typename T>static T* $memory::FreeByPointers( const std::initializer_list<T* volatile*>&
                                                       listOfPtrPointers $optionals ) $ret_null
{
   for (auto ppElements: listOfPtrPointers)
   {
      $$VERIFY_POINTER_ARG( ppElements );
      $Memory::Free($, (PVOID volatile*)ppElements );
   }
   return nullptr;
}

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

template<typename T>static T* $memory::AllocateNS($M) $null_on_failure $last_error
{
   return (T*)$Memory::AllocateNS($,$m, sizeof(T) );
}
template<typename T>static T* $memory::AllocateNS($AM, int count $positive ) $null_on_failure
                                                                             $last_error
{
   return $memory::AllocateNS<T>($ci,$ci, count );
}

template<typename T>static T* $memory::CleanAllocNS($M) $null_on_failure $last_error
{
   T* pointer = AllocateNS<T>($m);
   return pointer ? Clear($, pointer ) : nullptr;
}
template<typename T>static T* $memory::CleanAllocNS($AM, int count $positive ) $null_on_failure
                                                                               $last_error
{
   return $memory::CleanAllocNS<T>($ci,$ci, count );
}

template<typename T>static T* $memory::ReAllocateNS($AM, T* pElements,
                                                         int newCount $positive) $null_on_failure
                                                                                 $last_error
{
   return $memory::ReAllocateNS<T>($ci,$ci, pElements, newCount );
}

template<typename T>static T* $memory::AllocateNS($A,$M, int count $positive ) $null_on_failure
                                                                               $last_error
{
   $$VERIFY_POSITIVE_VALUE_ARG( count );
   return (T*)$Memory::AllocateNS($ci,$m, sizeof(T), count );
}
template<typename T>static T* $memory::CleanAllocNS($A,$M, int count $positive ) $null_on_failure
                                                                                 $last_error
{
   T* pointer = AllocateNS($ci,$m, count );
   return pointer ? Clear($, pointer, count ) : nullptr;
}
template<typename T>static T* $memory::ReAllocateNS($A,$M, T* pElements, int newCount $positive )
                                                           $null_on_failure $last_error
{
   $$VERIFY_POSITIVE_VALUE_ARG( newCount );
   return (T*)$Memory::ReAllocateNS($ci,$m, pElements, sizeof(T), newCount );
}

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

template<typename T>static T* $memory::TwiceEnlarge($AM, T* pElements ) $fatal_error_on_failure
{
   return TwiceEnlarge($ci,$ci, pElements );
}
template<typename T>static T* $memory::TwiceEnlargeNS($AM, T* pElements ) $null_on_failure
                                                                          $last_error
{
   return TwiceEnlargeNS($ci,$ci, pElements );
}

template<typename T>static T* $memory::TwiceEnlarge($A,$M, T* pElements ) $fatal_error_on_failure
{
   $VERIFY_POINTER_ARG( pElements );
   return (T*)$Memory::TwiceEnlarge($ci,$m, pElements );
}
template<typename T>static T* $memory::TwiceEnlargeNS($A,$M, T* pElements ) $null_on_failure
                                                                            $last_error
{
   $VERIFY_POINTER_ARG( pElements );
   return (T*)$Memory::TwiceEnlargeNS($ci,$m, pElements );
}

//==================================================================================================
} // RuntimeForStatic
