/* ======================================================================== * (C) 2000 Vienna University of Technology * ======================================================================== * PROJECT: Urban Viz * ========================================================================*/ /** several error checking/log facilities. * * for char-strings, 'String' is typedef'd for convenience * This library can be used with old style iostreams * (define \c OLDSTREAM for that) * * $Header: /usr/local/cvsyare/cvsyamp/src/yareutils/merror.cpp,v 1.1 2002/11/14 15:22:58 wimmer Exp $ * @author Michael Wimmer * @file */ /* ========================================================================*/ #include "merror.h" // The following is to allow this to be compiled with new and old style // iostreams. Special care has to be taken because in ms iostreams, // strstream has a different name and behaves differently! #ifndef OLDSTREAM # include # include # define ERRSTD std #else # include # if defined(_MSC_VER) && !defined(__SGI_STL) # define MS_STRSTREAM # include # else # include # endif # define ERRSTD #endif // --------------------------------------------------------------------------- // PrivateErrHandler class definition // --------------------------------------------------------------------------- // a few functions encapsulated in a class so initialization is easier class PrivateErrHandler { public: /// constructor PrivateErrHandler(); /// will be forwarded to outside macros inline ERRSTD::ostream &GetCurrentLogStream(); /// output the current logstream inline void PrintLogStream(bool overrideconsole); /// init the logstream (especially the logfile) void InitLogStream(const char *filename, bool _logtoconsole); /// who handles the console stream void SetConsoleStreamHandler(LogStreamToConsoleFunc handler); /// console only on/off bool SetLogStream(bool _logtoconsole); /// whether to log to file or not void SetLogToFile(bool yesno); private: // the logfile ERRSTD::ofstream log_ofstream; // the logstring (i.e., the primary logging target) ERRSTD::strstream log_ostrstream; // log only to console? bool logtoconsole; // log to file also? bool logtofile; LogStreamToConsoleFunc CurrentLogStreamToConsoleFunc; /// just goes to cout inline static void DefaultLogStreamToConsoleFunc( const char *consolestring); // shoudn't be used PrivateErrHandler(const PrivateErrHandler &) {} PrivateErrHandler &operator=(const PrivateErrHandler &) { return *this; } }; // --------------------------------------------------------------------------- // PrivateErrHandler class implementation // --------------------------------------------------------------------------- PrivateErrHandler::PrivateErrHandler() :CurrentLogStreamToConsoleFunc(DefaultLogStreamToConsoleFunc), logtoconsole(false), logtofile(true) { } void PrivateErrHandler::SetLogToFile(bool yesno) { logtofile = yesno; } inline ERRSTD::ostream &PrivateErrHandler::GetCurrentLogStream() { return log_ostrstream; } inline void PrivateErrHandler::PrintLogStream(bool overrideconsole) { // Note: this is only used with the old strstream, not with ostringstream log_ostrstream << ERRSTD::ends; if (log_ofstream && (logtofile || !logtoconsole)) log_ofstream << log_ostrstream.str() << ERRSTD::flush; if (logtoconsole || overrideconsole || !log_ofstream) CurrentLogStreamToConsoleFunc(log_ostrstream.str()); // Note: this was used with ostringstream, but not compatible // with old iostreams //log_ostringstream.str(""); log_ostrstream.rdbuf()->freeze(false); log_ostrstream.seekp(0); } void PrivateErrHandler::InitLogStream(const char *filename, bool _logtoconsole) { // Note: only works on new iostreams! #ifdef MS_STRSTREAM log_ofstream.rdbuf()->setbuf(NULL, 0); #else log_ofstream.rdbuf()->pubsetbuf(NULL, 0); #endif // SGI bug: ios::in assumed! log_ofstream.open(filename,ERRSTD::ios::out|ERRSTD::ios::trunc); if (!log_ofstream) { EOUT("Could not open logfile!"); } SetLogStream(_logtoconsole); OUT0("Logfile opened\n"); } void PrivateErrHandler::SetConsoleStreamHandler( LogStreamToConsoleFunc handler) { if (handler == NULL) CurrentLogStreamToConsoleFunc = DefaultLogStreamToConsoleFunc; else CurrentLogStreamToConsoleFunc = handler; } bool PrivateErrHandler::SetLogStream(bool _logtoconsole) { bool x = logtoconsole; logtoconsole = _logtoconsole; return x; } void PrivateErrHandler::DefaultLogStreamToConsoleFunc( const char *consolestring) { ERRSTD::cout << consolestring; } // --------------------------------------------------------------------------- // Private C-access functions // --------------------------------------------------------------------------- static PrivateErrHandler *theErrHandler = NULL; inline static void _ErrInitDefault() { static bool initialized = false; if (!initialized) { theErrHandler = new PrivateErrHandler; initialized = true; } } // --------------------------------------------------------------------------- // Public interface - exposed to macros // --------------------------------------------------------------------------- // logstream used by macros - this is necessary so that logstreams don't // give an error if used in global constructors (which are constructed // prior to the logfile) ERRSTD::ostream &_GetLogStream() { _ErrInitDefault(); return theErrHandler->GetCurrentLogStream(); } ERRSTD::ostream &_LogStreamDone(ERRSTD::ostream &os, bool overrideconsole) { _ErrInitDefault(); theErrHandler->PrintLogStream(overrideconsole); return os; } // --------------------------------------------------------------------------- // Public interface - exposed directly to application // --------------------------------------------------------------------------- void SetConsoleStreamHandler(LogStreamToConsoleFunc handler) { _ErrInitDefault(); theErrHandler->SetConsoleStreamHandler(handler); } void InitLogStream(const char *filename, bool logtofile) { _ErrInitDefault(); theErrHandler->InitLogStream(filename, !logtofile); } bool SetLogStream(bool logtofile) { _ErrInitDefault(); return !theErrHandler->SetLogStream(!logtofile); } void SetLogToFile(bool yesno) { _ErrInitDefault(); theErrHandler->SetLogToFile(yesno); } // --------------------------------------------------------------------------- // Win32-stuff // --------------------------------------------------------------------------- #ifdef WIN32 #define WIN32_LEAN_AND_MEAN #define NOMINMAX #include // for MessageBox and stuff void Msg(const char *msg, const char *title) { // MessageBox(NULL, msg, title, MB_OK); } /// gets WIN32 API error message (used by CHKMS-macros) char *GetErrorStringMS(DWORD errorValue) { LPVOID lpMsgBuf; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_MAX_WIDTH_MASK, NULL, errorValue, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR) &lpMsgBuf, 0, NULL ); //String message; char *message; if (lpMsgBuf) { message = (char *)lpMsgBuf; // Free the buffer. LocalFree( lpMsgBuf ); } else { message = "No error message returned"; } return message; } #else // nop functions for non-Win32 systems void Msg(const char *msg, const char *title) {} char *GetErrorStringMS(unsigned long errorValue) { return ""; } #endif