#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Log.h" #include #include #include "OSSupport/IsThread.h" #if defined(ANDROID_NDK) #include #include "ToJava.h" #endif cLog* cLog::s_Log = NULL; cLog::cLog(const AString & a_FileName ) : m_File(NULL), m_LastStringSize(0) { s_Log = this; // create logs directory cFile::CreateFolder(FILE_IO_PREFIX + AString("logs")); OpenLog((FILE_IO_PREFIX + AString("logs/") + a_FileName).c_str() ); } cLog::~cLog() { CloseLog(); s_Log = NULL; } cLog* cLog::GetInstance() { if (s_Log != NULL) { return s_Log; } new cLog("log.txt"); return s_Log; } void cLog::CloseLog() { if( m_File ) fclose (m_File); m_File = 0; } void cLog::OpenLog( const char* a_FileName ) { if(m_File) fclose (m_File); #ifdef _MSC_VER fopen_s( &m_File, a_FileName, "a+" ); #else m_File = fopen(a_FileName, "a+" ); #endif } void cLog::ClearLog() { #ifdef _MSC_VER if( fopen_s( &m_File, "log.txt", "w" ) == 0) fclose (m_File); #else m_File = fopen("log.txt", "w" ); if( m_File ) fclose (m_File); #endif m_File = 0; } bool cLog::LogReplaceLine(const char * a_Format, va_list argList) { AString Message; AppendVPrintf(Message, a_Format, argList); time_t rawtime; time(&rawtime); struct tm* timeinfo; #ifdef _MSC_VER struct tm timeinforeal; timeinfo = &timeinforeal; localtime_s(timeinfo, &rawtime); #else timeinfo = localtime(&rawtime); #endif AString Line; #ifdef _DEBUG Printf(Line, "[%04x|%02d:%02d:%02d] %s", cIsThread::GetCurrentID(), timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec, Message.c_str()); #else Printf(Line, "[%02d:%02d:%02d] %s", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec, Message.c_str()); #endif if (m_File) { fprintf(m_File, "%s\n", Line.c_str()); fflush(m_File); } // Print to console: #if defined(ANDROID_NDK) //__android_log_vprint(ANDROID_LOG_ERROR,"MCServer", a_Format, argList); __android_log_print(ANDROID_LOG_ERROR, "MCServer", "%s", Line.c_str()); //CallJavaFunction_Void_String(g_JavaThread, "AddToLog", Line ); #else #ifdef _WIN32 size_t LineLength = Line.length(); if (m_LastStringSize == 0) m_LastStringSize = LineLength; // Initialise m_LastStringSize HANDLE Output = GetStdHandle(STD_OUTPUT_HANDLE); CONSOLE_SCREEN_BUFFER_INFO csbi; GetConsoleScreenBufferInfo(Output, &csbi); if ((size_t)((csbi.srWindow.Right - csbi.srWindow.Left) + 1) < LineLength) { printf("\n%s", Line.c_str()); // We are at line to be replaced, but since we can't, add a new line return false; } if (LineLength < m_LastStringSize) // If last printed line was longer than current, clear this line { for (size_t X = 0; X != m_LastStringSize + 1; ++X) { fputs(" ", stdout); } } #else // _WIN32 struct ttysize ts; #ifdef TIOCGSIZE ioctl(STDIN_FILENO, TIOCGSIZE, &ts); if (ts.ts_cols < LineLength) { return false; } #elif defined(TIOCGWINSZ) ioctl(STDIN_FILENO, TIOCGWINSZ, &ts); if (ts.ts_cols < LineLength) { return false; } #else /* TIOCGSIZE */ return false; #endif fputs("\033[K", stdout); // Clear current line #endif printf("\r%s", Line.c_str()); #ifdef __linux fputs("\033[1B", stdout); // Move down one line #endif // __linux m_LastStringSize = LineLength; #endif // ANDROID_NDK #if defined (_WIN32) && defined(_DEBUG) // In a Windows Debug build, output the log to debug console as well: OutputDebugStringA((Line + "\n").c_str()); #endif // _WIN32 return true; } void cLog::Log(const char * a_Format, va_list argList) { AString Message; AppendVPrintf(Message, a_Format, argList); time_t rawtime; time ( &rawtime ); struct tm* timeinfo; #ifdef _MSC_VER struct tm timeinforeal; timeinfo = &timeinforeal; localtime_s(timeinfo, &rawtime ); #else timeinfo = localtime( &rawtime ); #endif AString Line; #ifdef _DEBUG Printf(Line, "[%04x|%02d:%02d:%02d] %s", cIsThread::GetCurrentID(), timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec, Message.c_str()); #else Printf(Line, "[%02d:%02d:%02d] %s", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec, Message.c_str()); #endif if (m_File) { fprintf(m_File, "%s\n", Line.c_str()); fflush(m_File); } // Print to console: #if defined(ANDROID_NDK) //__android_log_vprint(ANDROID_LOG_ERROR,"MCServer", a_Format, argList); __android_log_print(ANDROID_LOG_ERROR, "MCServer", "%s", Line.c_str() ); //CallJavaFunction_Void_String(g_JavaThread, "AddToLog", Line ); #else printf("%s", Line.c_str()); #endif #if defined (_WIN32) && defined(_DEBUG) // In a Windows Debug build, output the log to debug console as well: OutputDebugStringA((Line + "\n").c_str()); #endif // _WIN32 } void cLog::Log(const char * a_Format, ...) { va_list argList; va_start(argList, a_Format); Log(a_Format, argList); va_end(argList); } void cLog::SimpleLog(const char * a_String) { Log("%s", a_String); }