nux-1.16.0
|
00001 /* 00002 * Copyright 2010 Inalogic® Inc. 00003 * 00004 * This program is free software: you can redistribute it and/or modify it 00005 * under the terms of the GNU Lesser General Public License, as 00006 * published by the Free Software Foundation; either version 2.1 or 3.0 00007 * of the License. 00008 * 00009 * This program is distributed in the hope that it will be useful, but 00010 * WITHOUT ANY WARRANTY; without even the implied warranties of 00011 * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR 00012 * PURPOSE. See the applicable version of the GNU Lesser General Public 00013 * License for more details. 00014 * 00015 * You should have received a copy of both the GNU Lesser General Public 00016 * License along with this program. If not, see <http://www.gnu.org/licenses/> 00017 * 00018 * Authored by: Jay Taoko <jaytaoko@inalogic.com> 00019 * 00020 */ 00021 00022 00023 #include "NuxCore.h" 00024 #include "Parsing.h" 00025 00026 namespace nux 00027 { 00028 00029 #if defined(NUX_DEBUG) 00030 00031 00034 static void CreateBackupCopy (const TCHAR *Filename) 00035 { 00036 if (GFileManager.FileSize (Filename) > 0) 00037 { 00038 // Create string with system time to create a unique filename. 00039 unsigned int Year, Month, Day, Hour, Min, Sec, MSec; 00040 GetLocalTime (Year, Month, Day, Hour, Min, Sec, MSec); 00041 NString Name, Extension; 00042 NString (Filename).SplitAtLastOccurenceOf (TEXT ("."), Name, Extension); 00043 NString BackupFilename; 00044 00045 if (Extension.Size() ) 00046 { 00047 BackupFilename = NString::Printf (TEXT ("%s-backup-%i.%02i.%02i-%02i.%02i.%02i.%s"), Name.GetTCharPtr(), Year, Month, Day, Hour, Min, Sec, Extension.GetTCharPtr() ); 00048 } 00049 else 00050 { 00051 BackupFilename = NString::Printf (TEXT ("%s-backup-%i.%02i.%02i-%02i.%02i.%02i"), Name.GetTCharPtr(), Year, Month, Day, Hour, Min, Sec); 00052 } 00053 00054 GFileManager.Copy (BackupFilename.GetTCharPtr(), Filename, true, true, NULL); 00055 } 00056 } 00057 #endif 00058 00059 NUX_IMPLEMENT_GLOBAL_OBJECT (NullOutput); 00060 NUX_IMPLEMENT_GLOBAL_OBJECT (LogOutputRedirector); 00061 NUX_IMPLEMENT_GLOBAL_OBJECT (LogFileOutput); 00062 NUX_IMPLEMENT_GLOBAL_OBJECT (VisualOutputConsole) 00063 NUX_IMPLEMENT_GLOBAL_OBJECT (PrintfOutputConsole) 00064 00065 LogOutputDevice::LogOutputDevice() 00066 : _object_destroyed (false) 00067 { 00068 _enabled = true; 00069 } 00070 00071 LogOutputDevice::~LogOutputDevice() 00072 { 00073 _object_destroyed = true; 00074 } 00075 00076 void LogOutputDevice::Shutdown() 00077 { 00078 _object_destroyed = true; 00079 } 00080 00081 void LogOutputDevice::Flush() 00082 { 00083 00084 } 00085 00086 void LogOutputDevice::Enable () 00087 { 00088 _enabled = true; 00089 } 00090 00091 void LogOutputDevice::Disable () 00092 { 00093 _enabled = false; 00094 } 00095 00096 00097 VARARG_BODY ( void /*FuncRet*/, LogOutputDevice::LogFunction/*FuncName*/, const TCHAR* /*FmtType*/, VARARG_EXTRA (int severity) /*ExtraDecl*/) 00098 { 00099 if (_object_destroyed) 00100 return; 00101 00102 t_int BufferSize = 1024; 00103 t_int NewBufferSize = 0; 00104 TCHAR *Buffer = NULL; 00105 t_int Result = -1; 00106 00107 while (Result == -1) 00108 { 00109 if (NewBufferSize) 00110 { 00111 TCHAR *temp = new TCHAR[NewBufferSize]; 00112 Memcpy (temp, Buffer, BufferSize); 00113 NUX_SAFE_DELETE_ARRAY (Buffer); 00114 Buffer = temp; 00115 BufferSize = NewBufferSize; 00116 } 00117 else 00118 { 00119 Buffer = new TCHAR[BufferSize]; 00120 } 00121 00122 GET_VARARGS_RESULT (Buffer, BufferSize, BufferSize - 1, Fmt, Result); 00123 00124 if (Result == -1) 00125 NewBufferSize = 2 * BufferSize; 00126 }; 00127 00128 Buffer[Result] = 0; 00129 00130 Serialize (Buffer, TEXT ("Nux"), severity); 00131 00132 NUX_SAFE_DELETE_ARRAY (Buffer); 00133 } 00134 00135 void LogFileOutput::Constructor() 00136 { 00137 m_LogSerializer = NULL; 00138 m_Opened = false; 00139 m_Closed = false; 00140 00141 #if defined(NUX_DEBUG) 00142 // The Editor requires a fully qualified directory to not end up putting the log in various directories. 00143 m_Filename = GetProgramDirectory(); 00144 00145 if ( (m_Filename[m_Filename.Size()-1] != NUX_SLASH_CHAR) || (m_Filename[m_Filename.Size()-1] != NUX_BACKSLASH_CHAR) ) 00146 m_Filename += (const TCHAR *) NUX_PATH_SEPARATOR_STRING; 00147 00148 m_Filename += GetLogDirectory(); 00149 00150 // Create the directory tree where the Logs file will be stored. 00151 GFileManager.MakeDirectory (m_Filename.GetTCharPtr(), 1); 00152 00153 m_Filename += (const TCHAR *) NUX_PATH_SEPARATOR_STRING; 00154 m_Filename += TEXT ("nux"); 00155 m_Filename += TEXT (".log"); 00156 00157 // if the file already exists, create a backup as we are going to overwrite it 00158 if (!m_Opened) 00159 { 00160 CreateBackupCopy (m_Filename.GetTCharPtr() ); 00161 } 00162 00163 // Open log file. 00164 m_LogSerializer = GFileManager.CreateFileWriter (m_Filename.GetTCharPtr(), NSerializer::Read | NSerializer::Write | NSerializer::OverWriteReadOnly | (m_Opened ? NSerializer::Append : 0) ); 00165 00166 if (m_LogSerializer) 00167 { 00168 m_Opened = true; 00169 #if UNICODE && !NUX_LOG_FILE_ANSI 00170 m_LogSerializer->Serialize ( (void *) &NUX_UTF16_BE[1], NUX_UTF16_BE[0] /*size*/ ); 00171 #endif 00172 LogFunction (NUX_MSG_SEVERITY_NONE, TEXT ("Log file open, %s"), GetFormattedLocalTime().GetTCharPtr()); 00173 } 00174 else 00175 { 00176 m_Closed = true; 00177 } 00178 00179 #endif 00180 00181 } 00182 00183 void LogFileOutput::Destructor() 00184 { 00185 Shutdown(); 00186 } 00187 00192 void LogFileOutput::Shutdown() 00193 { 00194 if (m_LogSerializer) 00195 { 00196 LogFunction (NUX_MSG_SEVERITY_NONE, TEXT ("Log file closed, %s"), GetFormattedLocalTime().GetTCharPtr()); 00197 Flush(); 00198 delete m_LogSerializer; 00199 m_LogSerializer = NULL; 00200 } 00201 00202 m_Closed = true; 00203 } 00204 00205 void LogFileOutput::Flush() 00206 { 00207 if (m_LogSerializer) 00208 { 00209 m_LogSerializer->Flush(); 00210 } 00211 } 00212 00213 00215 00219 void LogFileOutput::Serialize (const TCHAR *log_data, const TCHAR *log_prefix, int severity) 00220 { 00221 if (!_enabled) 00222 return; 00223 00224 if (_object_destroyed) 00225 return; 00226 00227 if (m_LogSerializer) 00228 { 00229 #if UNICODE && NUX_LOG_FILE_ANSI 00230 ANSICHAR ACh[1024]; 00231 INT DataOffset = 0; 00232 INT i; 00233 00234 while (log_data[DataOffset]) 00235 { 00236 for (i = 0; i < NUX_ARRAY_COUNT (ACh) && log_data[DataOffset]; i++, DataOffset++) 00237 { 00238 ACh[i] = ConvertTCHARToAnsiChar (log_data[DataOffset]); 00239 } 00240 00241 // serialize chunks of 1024 characters 00242 m_LogSerializer->Serialize (ACh, i); 00243 }; 00244 00245 for (i = 0; NUX_LINE_TERMINATOR[i]; i++) 00246 { 00247 ACh[i] = NUX_LINE_TERMINATOR[i]; 00248 } 00249 00250 m_LogSerializer->Serialize (ACh, i); 00251 #else 00252 NString Raw = NString (log_prefix) + NString (TEXT (": ") ) + NString (log_data) + NString (NUX_LINE_TERMINATOR); 00253 SerializeRaw (Raw.GetTCharPtr() ); 00254 #endif 00255 } 00256 } 00257 00258 void LogFileOutput::SerializeRaw (const TCHAR *log_data) 00259 { 00260 t_u32 s = (t_u32) StringLength (log_data) * sizeof (TCHAR); 00261 m_LogSerializer->Serialize (NUX_CONST_CAST (TCHAR *, log_data), s); 00262 } 00263 00264 void LogOutputRedirector::Constructor() 00265 { 00266 00267 } 00268 00269 void LogOutputRedirector::Destructor() 00270 { 00271 Shutdown(); 00272 } 00273 00274 void LogOutputRedirector::AddOutputDevice (LogOutputDevice *OutputDevice) 00275 { 00276 if ( OutputDevice ) 00277 { 00278 if (std::find (OutputDevices.begin(), OutputDevices.end(), OutputDevice) != OutputDevices.end() ) 00279 return; 00280 00281 OutputDevices.push_back (OutputDevice); 00282 } 00283 } 00284 00285 void LogOutputRedirector::RemoveOutputDevice (LogOutputDevice *OutputDevice) 00286 { 00287 std::vector<LogOutputDevice *>::iterator it = std::find (OutputDevices.begin(), OutputDevices.end(), OutputDevice); 00288 OutputDevices.erase (it); 00289 } 00290 00291 bool LogOutputRedirector::IsRedirectingTo (LogOutputDevice *OutputDevice) 00292 { 00293 if (std::find (OutputDevices.begin(), OutputDevices.end(), OutputDevice) != OutputDevices.end() ) 00294 return true; 00295 00296 return false; 00297 } 00298 00299 void LogOutputRedirector::Serialize (const TCHAR *log_data, const TCHAR *log_prefix, int severity) 00300 { 00301 if (!_enabled) 00302 return; 00303 00304 for (t_u32 OutputDeviceIndex = 0; OutputDeviceIndex < OutputDevices.size(); OutputDeviceIndex++) 00305 { 00306 OutputDevices[OutputDeviceIndex]->Serialize (log_data, log_prefix, severity); 00307 } 00308 } 00309 00310 void LogOutputRedirector::Flush() 00311 { 00312 for (t_u32 OutputDeviceIndex = 0; OutputDeviceIndex < OutputDevices.size(); OutputDeviceIndex++) 00313 { 00314 OutputDevices[OutputDeviceIndex]->Flush(); 00315 } 00316 } 00317 00318 void LogOutputRedirector::Shutdown() 00319 { 00320 for (t_u32 OutputDeviceIndex = 0; OutputDeviceIndex < OutputDevices.size(); OutputDeviceIndex++) 00321 { 00322 OutputDevices[OutputDeviceIndex]->Shutdown(); 00323 // do not delete the output device. This is the responsibility of the owwners. 00324 } 00325 00326 OutputDevices.clear(); 00327 } 00328 00329 00330 void VisualOutputConsole::Constructor() {} 00331 00332 void VisualOutputConsole::Destructor() {} 00333 00335 00339 void VisualOutputConsole::Serialize (const TCHAR *text, const TCHAR *log_prefix, int severity) 00340 { 00341 if (!_enabled) 00342 return; 00343 00344 #if defined (NUX_OS_WINDOWS) 00345 TCHAR Temp[4096]; 00346 00347 Snprintf (Temp, 4096, 4096 - 1, TEXT ("%s: %s%s"), log_prefix, text, NUX_LINE_TERMINATOR); 00348 OutputDebugString (Temp); 00349 #endif 00350 } 00351 00352 void PrintfOutputConsole::Constructor() {} 00353 00354 void PrintfOutputConsole::Destructor() {} 00355 00357 00361 void PrintfOutputConsole::Serialize (const TCHAR *text, const TCHAR *log_prefix, int severity) 00362 { 00363 if (!_enabled) 00364 return; 00365 00366 TCHAR Temp[4096]; 00367 #if defined (NUX_OS_WINDOWS) 00368 Snprintf (Temp, 4096, 4096 - 1, TEXT ("%s: %s%s"), log_prefix, text, NUX_LINE_TERMINATOR); 00369 00370 HANDLE hConsole; 00371 hConsole = GetStdHandle(STD_OUTPUT_HANDLE); 00372 00373 00374 if (severity == NUX_MSG_SEVERITY_CRITICAL) 00375 { 00376 SetConsoleTextAttribute(hConsole, FOREGROUND_RED|FOREGROUND_INTENSITY|BACKGROUND_BLUE|BACKGROUND_GREEN|BACKGROUND_INTENSITY); 00377 } 00378 else if (severity == NUX_MSG_SEVERITY_ALERT) 00379 { 00380 SetConsoleTextAttribute(hConsole, FOREGROUND_RED|FOREGROUND_INTENSITY); 00381 } 00382 else if (severity == NUX_MSG_SEVERITY_WARNING) 00383 { 00384 SetConsoleTextAttribute(hConsole, FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_INTENSITY); 00385 } 00386 else if (severity == NUX_MSG_SEVERITY_INFO) 00387 { 00388 SetConsoleTextAttribute(hConsole, FOREGROUND_GREEN|FOREGROUND_INTENSITY); 00389 } 00390 else if (severity == NUX_MSG_SEVERITY_NONE) 00391 { 00392 SetConsoleTextAttribute(hConsole, FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE|FOREGROUND_INTENSITY); 00393 } 00394 00395 printf ("%s", &Temp[0]); 00396 00397 SetConsoleTextAttribute(hConsole, FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE); 00398 00399 #elif defined (NUX_OS_LINUX) 00400 // {attr} is one of following 00401 // 00402 // 0 Reset All Attributes (return to normal mode) 00403 // 1 Bright (Usually turns on BOLD) 00404 // 2 Dim 00405 // 3 Underline 00406 // 5 Blink 00407 // 7 Reverse 00408 // 8 Hidden 00409 // 00410 // {fg} is one of the following 00411 // 00412 // 30 Black 00413 // 31 Red 00414 // 32 Green 00415 // 33 Yellow 00416 // 34 Blue 00417 // 35 Magenta 00418 // 36 Cyan 00419 // 37 White (greyish) 00420 // 38 White 00421 // 00422 // {bg} is one of the following 00423 // 00424 // 40 Black 00425 // 41 Red 00426 // 42 Green 00427 // 43 Yellow 00428 // 44 Blue 00429 // 45 Magenta 00430 // 46 Cyan 00431 // 47 White (greyish) 00432 // 48 White 00433 00434 int Foreground = 38; 00435 int Background = 48; 00436 int Bold = 0; 00437 00438 if (severity == NUX_MSG_SEVERITY_CRITICAL) 00439 { 00440 Foreground = 31; 00441 Background = 44; 00442 Bold = 1; 00443 } 00444 else if (severity == NUX_MSG_SEVERITY_ALERT) 00445 { 00446 Foreground = 31; 00447 Bold = 1; 00448 } 00449 else if (severity == NUX_MSG_SEVERITY_WARNING) 00450 { 00451 Foreground = 33; 00452 Bold = 1; 00453 } 00454 else if (severity == NUX_MSG_SEVERITY_INFO) 00455 { 00456 Foreground = 32; 00457 Bold = 1; 00458 } 00459 else if (severity == NUX_MSG_SEVERITY_NONE) 00460 { 00461 Foreground = 38; 00462 Bold = 0; 00463 } 00464 00465 00466 Snprintf (Temp, 4096, 4096 - 1, TEXT ("%c[%d;%d;%dm%s: %s%c[%d;%d;%dm%s"), 0x1B, Bold, Foreground, Background, log_prefix, text, 0x1B, 0, 38, 48, NUX_LINE_TERMINATOR); 00467 printf ("%s", &Temp[0]); 00468 00469 #else 00470 Snprintf (Temp, 4096, 4096 - 1, TEXT ("%s: %s%s"), log_prefix, text, NUX_LINE_TERMINATOR); 00471 printf ("%s", &Temp[0]); 00472 #endif 00473 } 00474 00475 00476 void NullOutput::Constructor() {} 00477 00478 void NullOutput::Destructor() {} 00479 00480 00481 } 00482