1 /********************************************************************** 2 oberror.h - Handle error messages, warnings, notices, etc. 3 4 Copyright (C) 2002 by Stefan Kebekus 5 Some portions Copyright (C) 2003-2006 by Geoffrey R. Hutchison 6 7 This file is part of the Open Babel project. 8 For more information, see <http://openbabel.org/> 9 10 This program is free software; you can redistribute it and/or modify 11 it under the terms of the GNU General Public License as published by 12 the Free Software Foundation version 2 of the License. 13 14 This program is distributed in the hope that it will be useful, but 15 WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 General Public License for more details. 18 ***********************************************************************/ 19 20 #ifndef OB_ERROR_H 21 #define OB_ERROR_H 22 23 #include <openbabel/babelconfig.h> 24 25 #include <iosfwd> 26 #include <sstream> 27 #include <string> 28 #include <vector> 29 #include <deque> 30 31 #ifndef OBERROR 32 #define OBERROR 33 #endif 34 35 namespace OpenBabel 36 { 37 38 //! \brief Levels of error and audit messages to allow filtering 39 enum obMessageLevel { 40 obError, //!< for critical errors (e.g., cannot read a file) 41 obWarning, //!< for non-critical problems (e.g., molecule appears empty) 42 obInfo, //!< for informative messages (e.g., file is a non-standard format) 43 obAuditMsg, //!< for messages auditing methods which destroy or perceive molecular data (e.g., kekulization, atom typing, etc.) 44 obDebug //!< for messages only useful for debugging purposes 45 }; 46 47 enum errorQualifier {always, onceOnly}; 48 49 /** \class OBError oberror.h <openbabel/oberror.h> 50 \brief Customizable error handling and logging -- store a message, 51 including the method yielding the error, causes, etc. **/ 52 class OBERROR OBError 53 { 54 public: 55 56 //! Constructor for an error message e.g. OBError(__FUNCTION__, " message ") 57 OBError( const std::string &method = "", 58 const std::string &errorMsg = "", 59 const std::string &explanation = "", 60 const std::string &possibleCause = "", 61 const std::string &suggestedRemedy = "", 62 const obMessageLevel = obDebug ); 63 64 //! \return A formatted message string, including optional explanations, etc. 65 std::string message(void) const; 66 67 //! Output a formatted message string 68 friend std::ostream& operator<< ( std::ostream &os, const OBError &er ) 69 { return os << er.message(); }; 70 71 /** \return The method which caused this error 72 (typically supplied via the __FUNCTION__ compiler macro **/ GetMethod()73 std::string GetMethod() const { return _method; } 74 //! \return The main error message GetError()75 std::string GetError() const { return _errorMsg; } 76 //! \return A more detailed explanation of the error (optional) GetExplanation()77 std::string GetExplanation() const { return _explanation; } 78 //! \return A possible cause for the error (optional) GetPossibleCause()79 std::string GetPossibleCause() const { return _possibleCause; } 80 //! \return The suggested workaround or remedy for the error (optional) GetSuggestedRemedy()81 std::string GetSuggestedRemedy() const { return _suggestedRemedy; } 82 //! \return The severity level of this error GetLevel()83 obMessageLevel GetLevel() const { return _level; } 84 85 bool operator== (const OBError&)const; 86 87 protected: 88 89 //! The method causing the error (typically from the compiler macro __FUNCTION__) 90 std::string _method; 91 //! The actual error message 92 std::string _errorMsg; 93 //! Optional explanation message: more detailed than the brief error 94 std::string _explanation; 95 //! Optional cause message 96 std::string _possibleCause; 97 //! Optional workaround or remedy 98 std::string _suggestedRemedy; 99 100 //! The severity level: used for filtering via OBMessageHandler 101 obMessageLevel _level; 102 }; 103 104 //! \brief Handle error messages, warnings, debugging information and the like 105 // More documentation in oberror.cpp 106 class OBERROR OBMessageHandler 107 { 108 protected: 109 //! Count of messages at each message level 110 unsigned int _messageCount[5]; 111 112 public: 113 OBMessageHandler(); 114 ~OBMessageHandler(); 115 116 //! Throw an error with an already-formatted OBError object 117 void ThrowError(OBError err, errorQualifier qqualifier = always); 118 //! Throw an error in the specified method with an appropriate level 119 void ThrowError(const std::string &method, const std::string &errorMsg, 120 obMessageLevel level = obDebug, errorQualifier qualifier = always); 121 122 //! \return all messages matching a specified level 123 std::vector<std::string> GetMessagesOfLevel(const obMessageLevel); 124 125 //! Start logging messages (default) StartLogging()126 void StartLogging() { _logging = true; } 127 //! Stop logging messages completely StopLogging()128 void StopLogging() { _logging = false; } 129 130 //! Set the maximum number of entries (or 0 for no limit) SetMaxLogEntries(unsigned int max)131 void SetMaxLogEntries(unsigned int max) { _maxEntries = max; } 132 //! \return the current maximum number of entries (default = 0 for no limit) GetMaxLogEntries()133 unsigned int GetMaxLogEntries() { return _maxEntries; } 134 135 //! Clear the current message log entirely ClearLog()136 void ClearLog() { _messageList.clear(); } 137 138 //! \brief Set the level of messages to output 139 //! (i.e., messages with at least this priority will be output) SetOutputLevel(const obMessageLevel level)140 void SetOutputLevel(const obMessageLevel level) { _outputLevel = level; } 141 //! \return the current output level GetOutputLevel()142 obMessageLevel GetOutputLevel() { return _outputLevel; } 143 SetOutputStream(std::ostream * os)144 void SetOutputStream(std::ostream *os) { _outputStream = os; } GetOutputStream()145 std::ostream* GetOutputStream() { return _outputStream; } 146 147 //! Start "wrapping" messages to cerr into ThrowError calls 148 bool StartErrorWrap(); 149 //! Turn off "wrapping" messages, restoring normal cerr use (default) 150 bool StopErrorWrap(); 151 152 //! \return Count of messages received at the obError level GetErrorMessageCount()153 unsigned int GetErrorMessageCount() { return _messageCount[obError];} 154 //! \return Count of messages received at the obWarning level GetWarningMessageCount()155 unsigned int GetWarningMessageCount() { return _messageCount[obWarning];} 156 //! \return Count of messages received at the obInfo level GetInfoMessageCount()157 unsigned int GetInfoMessageCount() { return _messageCount[obInfo];} 158 //! \return Count of messages received at the obAuditMsg level GetAuditMessageCount()159 unsigned int GetAuditMessageCount() { return _messageCount[obAuditMsg];} 160 //! \return Count of messages received at the obDebug level GetDebugMessageCount()161 unsigned int GetDebugMessageCount() { return _messageCount[obDebug];} 162 //! \return Summary of messages received at all levels 163 std::string GetMessageSummary(); 164 165 protected: 166 //! Log of messages for later retrieval via GetMessagesOfLevel() 167 std::deque<OBError> _messageList; 168 169 //! Filtering level for messages and logging (messages of lower priority will be ignored 170 obMessageLevel _outputLevel; 171 172 // self-explanatory 173 std::ostream *_outputStream; 174 175 //! Whether messages will be logged into _messageList 176 bool _logging; 177 //! The maximum size of _messageList log 178 unsigned int _maxEntries; 179 180 //! The default stream buffer for the output stream (saved if wrapping is ued) 181 std::streambuf *_inWrapStreamBuf; 182 //! The filtered obLogBuf stream buffer to wrap error messages 183 std::streambuf *_filterStreamBuf; 184 }; 185 186 //! Global OBMessageHandler error handler 187 OBERROR extern OBMessageHandler obErrorLog; 188 189 //! \class obLogBuf oberror.h <openbabel/oberror.h> 190 //! \brief A minimal streambuf derivative to wrap calls to cerr into calls to OBMessageHandler as needed 191 /** This class is used for internal use, via OBMessageHandler::StartErrorWrap() 192 To use this class, use the global OBMessageHandler object @p obErrorLog: 193 \code 194 obErrorLog.StartErrorWrap(); // All output to cerr will become OBErrors 195 cerr << " This is error 1" << endl; // flush output, create a new error 196 cerr << " Error 2" << endl; 197 cerr << " Error 3: Done with output wrapping." << endl; 198 obErrorLog.StopErrorWrap(); // return to default behavior 199 \endcode 200 **/ 201 class OBERROR obLogBuf : public std::stringbuf 202 { 203 public: 204 //! Close the output buffer, flush, and call OBMessageHandler::ThrowError() ~obLogBuf()205 virtual ~obLogBuf() { sync(); } 206 207 protected: 208 //! Call OBMessageHandler::ThrowError() and flush the buffer sync()209 int sync() 210 { 211 obErrorLog.ThrowError("", str(), obInfo); 212 str(std::string()); // clear the buffer 213 return 0; 214 } 215 }; 216 217 } // end namespace OpenBabel 218 219 #endif 220 221 //! \file oberror.h 222 //! \brief Handle error messages, warnings, notices, etc. 223