Coverage Report

Created: 2026-10-28 07:19

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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.