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

PWSTR HelpersRT::IntToStr($M,int value) $null_on_failure $needs_free
{
   return FormatAlloc($,$m, L"%d", value );
}

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

PWSTR HelpersRT::DuplicateSZ($AM,PCWSTR source) $null_on_failure $needs_free
{
   return DuplicateSZ($ci,$ci, source );
}

PWSTR HelpersRT::DuplicateStr($AM,PCWSTR source,int length) $null_on_failure $needs_free
{
   return DuplicateStr($ci,$ci, source, length );
}

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

PWSTR HelpersRT::ToUnicodeSZ($AM,PCSTR ansiStr) $null_on_failure $needs_free
{
   return ToUnicodeSZ($ci,$ci, ansiStr );
}

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

PWSTR HelpersRT::FormatAlloc($AM,PCWSTR messageFmt, ... ) $null_on_failure $needs_free
{
   $$VERIFY_POINTER_ARG( messageFmt );
   va_list argList;
   PWSTR rslt = FormatAllocVA($ci, $VA_COMPLEMENT( messageFmt, argList ) );
   va_end( argList );
   return rslt;
}
PWSTR HelpersRT::FormatAllocVA($AM,PCWSTR messageFmt,va_list argList) $null_on_failure $needs_free
{
   return FormatAllocVA($ci,$ci, messageFmt, argList );
}

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

PWSTR HelpersRT::DuplicateSZ($A,$M,PCWSTR source) $null_on_failure $needs_free
{
   $$VERIFY_POINTER_ARG( source );
   SIZE_T size = (SIZE_T)( $SZ::Length($ci, source ) + 1 ) * $CHAR_SIZE;
   auto target = (PWSTR)Allocate($,$m, size );
   if ( target )
      ::CopyMemory( target, source, size );
   return target;
}

PWSTR HelpersRT::DuplicateStr($A,$M,PCWSTR source,int length) $null_on_failure $needs_free
{
   $$VERIFY_POINTER_ARG( source );
   $$VERIFY_NOT_NEGATIVE_VALUE_ARG( length );
   SIZE_T size = (SIZE_T)( $SZ::VerifyLength($ci, (SIZE_T)length ) + 1 ) * $CHAR_SIZE;
   auto target = (PWSTR)Allocate($,$m, size );
   if ( target )
   {
      ::CopyMemory( target, source, size - $CHAR_SIZE );
      target[ length ] = L'\0';
   }
   return target;
}

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

PWSTR HelpersRT::ToUnicodeSZ($A,$M,PCSTR ansiStr) $null_on_failure $needs_free
{
   int capacity = ::MultiByteToWideChar( CP_ACP, 0, ansiStr, -1, NULL, 0 );
   if ( capacity <= 0 || ++capacity > STRSAFE_MAX_CCH )
      return nullptr;
   PWSTR pBuffer = (PWSTR)Allocate($,$m, capacity * $CHAR_SIZE );
   if ( !pBuffer ) return nullptr;
   int cch = ::MultiByteToWideChar( CP_ACP, 0, ansiStr, -1, pBuffer, capacity );
   DWORD dwError = ::GetLastError();
   if ( cch > 0 && cch < capacity )
   {
      PWSTR pBuffer_2 = (PWSTR)ReAllocate($,$m, pBuffer, cch * $CHAR_SIZE );
      if ( pBuffer_2 ) return pBuffer_2;
   }
   return $memory::Free( pBuffer );
}

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

PWSTR HelpersRT::FormatAlloc($A,$M,PCWSTR messageFmt, ... ) $null_on_failure $needs_free
{
   $$VERIFY_POINTER_ARG( messageFmt );
   va_list argList;
   PWSTR rslt = FormatAllocVA($ci,$m, $VA_COMPLEMENT( messageFmt, argList ) );
   va_end( argList );
   return rslt;
}
PWSTR HelpersRT::FormatAllocVA($A,$M,PCWSTR messageFmt,va_list argList) $null_on_failure $needs_free
{
   $$VERIFY_POINTER_ARG( messageFmt );
   $$VERIFY_POINTER_ARG( argList );
   SIZE_T capacity = 128;
   PWSTR pBuffer = (PWSTR)Allocate($,$m, capacity * $CHAR_SIZE );
   if ( !pBuffer )
      return nullptr;
   HRESULT hres; PWSTR pBuffer_2;
   while (FAILED( hres = ::StringCchVPrintf(pBuffer, capacity, messageFmt, argList )))
   {
      if ( hres != STRSAFE_E_INSUFFICIENT_BUFFER || capacity >= STRSAFE_MAX_CCH ||
           !( pBuffer_2 = (PWSTR)ReAllocate($,$m, pBuffer,
              ( capacity = $arith::Min<SIZE_T>( capacity * 2, STRSAFE_MAX_CCH ) )*$CHAR_SIZE )))
         goto FAILURE;
      pBuffer = pBuffer_2;
   }
   capacity = $SZ::Length($, pBuffer ) + 1;
   if ( pBuffer_2 = (PWSTR)ReAllocate($,$m, pBuffer, capacity * $CHAR_SIZE ) )
      return pBuffer_2;
FAILURE:
   return $memory::Free( pBuffer );
}

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