Back to index

nux  3.0.0
OutputDevice.cpp
Go to the documentation of this file.
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     int   BufferSize = 1024;
00103     int   NewBufferSize     = 0;
00104     TCHAR  *Buffer          = NULL;
00105     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     unsigned int s = (unsigned int) 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 (unsigned int 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 (unsigned int OutputDeviceIndex = 0; OutputDeviceIndex < OutputDevices.size(); OutputDeviceIndex++)
00313     {
00314       OutputDevices[OutputDeviceIndex]->Flush();
00315     }
00316   }
00317 
00318   void LogOutputRedirector::Shutdown()
00319   {
00320     for (unsigned int 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