/src/openbabel/include/openbabel/oberror.h
Line | Count | Source |
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 | 0 | { return os << er.message(); }; |
70 | | |
71 | | /** \return The method which caused this error |
72 | | (typically supplied via the __FUNCTION__ compiler macro **/ |
73 | 0 | std::string GetMethod() const { return _method; } |
74 | | //! \return The main error message |
75 | 0 | std::string GetError() const { return _errorMsg; } |
76 | | //! \return A more detailed explanation of the error (optional) |
77 | 0 | std::string GetExplanation() const { return _explanation; } |
78 | | //! \return A possible cause for the error (optional) |
79 | 0 | std::string GetPossibleCause() const { return _possibleCause; } |
80 | | //! \return The suggested workaround or remedy for the error (optional) |
81 | 0 | std::string GetSuggestedRemedy() const { return _suggestedRemedy; } |
82 | | //! \return The severity level of this error |
83 | 0 | 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) |
126 | 0 | void StartLogging() { _logging = true; } |
127 | | //! Stop logging messages completely |
128 | 11 | void StopLogging() { _logging = false; } |
129 | | |
130 | | //! Set the maximum number of entries (or 0 for no limit) |
131 | 0 | void SetMaxLogEntries(unsigned int max) { _maxEntries = max; } |
132 | | //! \return the current maximum number of entries (default = 0 for no limit) |
133 | 0 | unsigned int GetMaxLogEntries() { return _maxEntries; } |
134 | | |
135 | | //! Clear the current message log entirely |
136 | 0 | 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) |
140 | 0 | void SetOutputLevel(const obMessageLevel level) { _outputLevel = level; } |
141 | | //! \return the current output level |
142 | 7 | obMessageLevel GetOutputLevel() { return _outputLevel; } |
143 | | |
144 | 0 | void SetOutputStream(std::ostream *os) { _outputStream = os; } |
145 | 0 | 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 |
153 | 0 | unsigned int GetErrorMessageCount() { return _messageCount[obError];} |
154 | | //! \return Count of messages received at the obWarning level |
155 | 0 | unsigned int GetWarningMessageCount() { return _messageCount[obWarning];} |
156 | | //! \return Count of messages received at the obInfo level |
157 | 0 | unsigned int GetInfoMessageCount() { return _messageCount[obInfo];} |
158 | | //! \return Count of messages received at the obAuditMsg level |
159 | 0 | unsigned int GetAuditMessageCount() { return _messageCount[obAuditMsg];} |
160 | | //! \return Count of messages received at the obDebug level |
161 | 0 | 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() |
205 | 0 | virtual ~obLogBuf() { sync(); } |
206 | | |
207 | | protected: |
208 | | //! Call OBMessageHandler::ThrowError() and flush the buffer |
209 | | int sync() |
210 | 0 | { |
211 | 0 | obErrorLog.ThrowError("", str(), obInfo); |
212 | 0 | str(std::string()); // clear the buffer |
213 | 0 | return 0; |
214 | 0 | } |
215 | | }; |
216 | | |
217 | | } // end namespace OpenBabel |
218 | | |
219 | | #endif |
220 | | |
221 | | //! \file oberror.h |
222 | | //! \brief Handle error messages, warnings, notices, etc. |