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

$Status HelpersRT::Trace()
{
   return TraceEx($, $TraceMessageType_Neutral );
}
$Status HelpersRT::Trace($A,PCWSTR message)
{
   return TraceEx($ci, $TraceMessageType_Neutral, message );
}
$Status HelpersRT::TraceFmt($A,PCWSTR messageFmt, ... )
{
   $$VERIFY_POINTER_ARG( messageFmt );
   va_list argList;
   auto status = TraceVA($ci, $VA_COMPLEMENT( messageFmt, argList ) );
   va_end( argList );
   return status;
}
$Status HelpersRT::TraceVA($A,PCWSTR messageFmt,va_list argList)
{
   return TraceExVA($ci, $TraceMessageType_Neutral, messageFmt, argList );
}

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

$Status HelpersRT::TraceInformation()
{
   return TraceEx($, $TraceMessageType_Information );
}
$Status HelpersRT::TraceInformation($A,PCWSTR message)
{
   return TraceEx($ci, $TraceMessageType_Information, message );
}
$Status HelpersRT::TraceInformationFmt($A,PCWSTR messageFmt, ... )
{
   $$VERIFY_POINTER_ARG( messageFmt );
   va_list argList;
   auto status = TraceInformationVA($ci, $VA_COMPLEMENT( messageFmt, argList ) );
   va_end( argList );
   return status;
}
$Status HelpersRT::TraceInformationVA($A,PCWSTR messageFmt,va_list argList)
{
   return TraceExVA($ci, $TraceMessageType_Information, messageFmt, argList );
}

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

$Status HelpersRT::TraceWarning()
{
   return TraceEx($, $TraceMessageType_Warning );
}
$Status HelpersRT::TraceWarning($A,PCWSTR message)
{
   return TraceEx($ci, $TraceMessageType_Warning, message );
}
$Status HelpersRT::TraceWarningFmt($A,PCWSTR messageFmt, ... )
{
   $$VERIFY_POINTER_ARG( messageFmt );
   va_list argList;
   auto status = TraceWarningVA($ci, $VA_COMPLEMENT( messageFmt, argList ) );
   va_end( argList );
   return status;
}
$Status HelpersRT::TraceWarningVA($A,PCWSTR messageFmt,va_list argList)
{
   return TraceExVA($ci, $TraceMessageType_Warning, messageFmt, argList );
}

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

$Status HelpersRT::TraceError()
{
   return TraceEx($, $TraceMessageType_Error );
}
$Status HelpersRT::TraceError($A,PCWSTR message)
{
   return TraceEx($ci, $TraceMessageType_Error, message );
}
$Status HelpersRT::TraceErrorFmt($A,PCWSTR messageFmt, ... )
{
   $$VERIFY_POINTER_ARG( messageFmt );
   va_list argList;
   auto status = TraceErrorVA($ci, $VA_COMPLEMENT( messageFmt, argList ) );
   va_end( argList );
   return status;
}
$Status HelpersRT::TraceErrorVA($A,PCWSTR messageFmt,va_list argList)
{
   return TraceExVA($ci, $TraceMessageType_Error, messageFmt, argList );
}

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

$Status HelpersRT::TraceOperation($A,PCWSTR message)
{
   return TraceExFmt($ci, _OperationTraceMessageType_, L"* %s ...", message );
}
$Status HelpersRT::TraceOperationFmt($A,PCWSTR messageFmt, ... )
{
   $$VERIFY_POINTER_ARG( messageFmt );
   va_list argList;
   auto status = TraceOperationVA($ci, $VA_COMPLEMENT( messageFmt, argList ) );
   va_end( argList );
   return status;
}
$Status HelpersRT::TraceOperationVA($A,PCWSTR messageFmt,va_list argList)
{
   PWSTR pMessage = HelpersRT::FormatAllocVA($ci, messageFmt, argList );
   if ( !pMessage ) return TraceError_FormatMessage;
   auto status = TraceOperation($ci, pMessage );
   $Memory::Free( pMessage );
   return status;
}

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

$Status HelpersRT::TraceInFunction($A,PCWSTR funcNameOrSignature)
{
   $$VERIFY_POINTER_ARG( funcNameOrSignature );
   return TraceExFmt($, _InOutFunctionTraceMessageType_,
      L"=== In [%s] function: ===",
      funcNameOrSignature );
}
$Status HelpersRT::TraceOutOfFunction($A,PCWSTR funcNameOrSignature)
{
   $$VERIFY_POINTER_ARG( funcNameOrSignature );
   return TraceExFmt($, _InOutFunctionTraceMessageType_,
      L"=== Out of [%s] function. ===",
      funcNameOrSignature );
}

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

$Status HelpersRT::TraceEx($A,$TraceMessageType messageType)
{
   return TraceEx($ci, messageType, L"" );
}
$Status HelpersRT::TraceEx($A,$TraceMessageType messageType,PCWSTR message)
{
   bool isActiveType = messageType != $TraceMessageType_None;
#ifdef NDEBUG
   if ( !isActiveType )
      return 0;
#endif // NDEBUG
   WCHAR signSZ[2];
   signSZ[0] = $TraceHelpers::MessageSign($ci, messageType );
   signSZ[1] = L'\0';
   $$VERIFY_POINTER_ARG( message );
   PWSTR pExeName = nullptr;
   PCWSTR moduleName = $RT::GetMainModuleName();
   if ( !moduleName && !(moduleName = $RT::GetModuleName()) )
      moduleName = $subst::NullSubst<PCWSTR>(
         pExeName = HelpersRT::GetExeName($),
         L"???" );
   PWSTR pMessage = HelpersRT::FormatAlloc($ci, L"%s %s >> %s", moduleName, signSZ, message );
   $AUTO_FREE_2( pExeName, pMessage );
   if ( !pMessage )
      return TraceError_FormatMessage;
   if ( isActiveType )
      ::OutputDebugString( pMessage );
   return 0; // SUCCESS
}
$Status HelpersRT::TraceExFmt($A,$TraceMessageType messageType,PCWSTR messageFmt, ... )
{
   $$VERIFY_POINTER_ARG( messageFmt );
   va_list argList;
   auto status = TraceExVA($ci, messageType, $VA_COMPLEMENT( messageFmt, argList ) );
   va_end( argList );
   return status;
}
$Status HelpersRT::TraceExVA($A,$TraceMessageType messageType,PCWSTR messageFmt,va_list argList)
{
   PWSTR pMessage = HelpersRT::FormatAllocVA($ci, messageFmt, argList );
   if ( !pMessage ) return TraceError_FormatMessage;
   auto status = TraceEx($ci, messageType, pMessage );
   $Memory::Free( pMessage );
   return status;
}

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

PCWSTR HelpersRT::TraceErrorToMessage($Status status) $not_null $static_pointer
{
   if ( !status )
      return $TEXT(
         L"No trace error.",
         L"Нет ошибки трассировки." );
   switch ( status )
   {
   case TraceError_FormatMessage: return $TEXT(
      L"Can not format message for trace output.",
      L"Не удаётся отформатировать строку для трэйс-вывода." );
   case TraceError_ExeName: return $TEXT(
      L"Can not obtain exe-name for trace output.",
      L"Не удаётся получить имя EXE для трэйс-вывода." );
   default: return $TEXT(
      L"Unknown trace error.",
      L"Неизвестная ошибка трассировки." );
   }
}

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