33 namespace lemon { |
33 namespace lemon { |
34 |
34 |
35 /// \addtogroup exceptions |
35 /// \addtogroup exceptions |
36 /// @{ |
36 /// @{ |
37 |
37 |
38 /// \brief Exception safe wrapper class. |
38 /// \brief Generic exception class. |
39 /// |
39 /// |
40 /// Exception safe wrapper class to implement the members of exceptions. |
|
41 template <typename _Type> |
|
42 class ExceptionMember { |
|
43 public: |
|
44 typedef _Type Type; |
|
45 |
|
46 ExceptionMember() throw() { |
|
47 try { |
|
48 ptr.reset(new Type()); |
|
49 } catch (...) {} |
|
50 } |
|
51 |
|
52 ExceptionMember(const Type& type) throw() { |
|
53 try { |
|
54 ptr.reset(new Type()); |
|
55 if (ptr.get() == 0) return; |
|
56 *ptr = type; |
|
57 } catch (...) {} |
|
58 } |
|
59 |
|
60 ExceptionMember(const ExceptionMember& copy) throw() { |
|
61 try { |
|
62 if (!copy.valid()) return; |
|
63 ptr.reset(new Type()); |
|
64 if (ptr.get() == 0) return; |
|
65 *ptr = copy.get(); |
|
66 } catch (...) {} |
|
67 } |
|
68 |
|
69 ExceptionMember& operator=(const ExceptionMember& copy) throw() { |
|
70 if (ptr.get() == 0) return; |
|
71 try { |
|
72 if (!copy.valid()) return; |
|
73 *ptr = copy.get(); |
|
74 } catch (...) {} |
|
75 } |
|
76 |
|
77 void set(const Type& type) throw() { |
|
78 if (ptr.get() == 0) return; |
|
79 try { |
|
80 *ptr = type; |
|
81 } catch (...) {} |
|
82 } |
|
83 |
|
84 const Type& get() const { |
|
85 return *ptr; |
|
86 } |
|
87 |
|
88 bool valid() const throw() { |
|
89 return ptr.get() != 0; |
|
90 } |
|
91 |
|
92 private: |
|
93 std::auto_ptr<_Type> ptr; |
|
94 }; |
|
95 |
|
96 /// Exception-safe convenient error message builder class. |
|
97 |
|
98 /// Helper class which provides a convenient ostream-like (operator << |
|
99 /// based) interface to create a string message. Mostly useful in |
|
100 /// exception classes (therefore the name). |
|
101 class ErrorMessage { |
|
102 protected: |
|
103 ///\e |
|
104 |
|
105 mutable std::auto_ptr<std::ostringstream> buf; |
|
106 |
|
107 ///\e |
|
108 bool init() throw() { |
|
109 try { |
|
110 buf.reset(new std::ostringstream); |
|
111 } |
|
112 catch(...) { |
|
113 buf.reset(); |
|
114 } |
|
115 return buf.get(); |
|
116 } |
|
117 |
|
118 public: |
|
119 |
|
120 ///\e |
|
121 ErrorMessage() throw() { init(); } |
|
122 |
|
123 ErrorMessage(const ErrorMessage& em) throw() : buf(em.buf) { } |
|
124 |
|
125 ///\e |
|
126 ErrorMessage(const char *msg) throw() { |
|
127 init(); |
|
128 *this << msg; |
|
129 } |
|
130 |
|
131 ///\e |
|
132 ErrorMessage(const std::string &msg) throw() { |
|
133 init(); |
|
134 *this << msg; |
|
135 } |
|
136 |
|
137 ///\e |
|
138 template <typename T> |
|
139 ErrorMessage& operator<<(const T &t) throw() { |
|
140 if( ! buf.get() ) return *this; |
|
141 |
|
142 try { |
|
143 *buf << t; |
|
144 } |
|
145 catch(...) { |
|
146 buf.reset(); |
|
147 } |
|
148 return *this; |
|
149 } |
|
150 |
|
151 ///\e |
|
152 const char* message() throw() { |
|
153 if( ! buf.get() ) return 0; |
|
154 |
|
155 const char* mes = 0; |
|
156 try { |
|
157 mes = buf->str().c_str(); |
|
158 } |
|
159 catch(...) {} |
|
160 return mes; |
|
161 } |
|
162 |
|
163 }; |
|
164 |
|
165 /// Generic exception class. |
|
166 |
|
167 /// Base class for exceptions used in LEMON. |
40 /// Base class for exceptions used in LEMON. |
168 /// |
41 /// |
169 class Exception : public std::exception { |
42 class Exception : public std::exception { |
170 public: |
43 public: |
171 ///\e |
44 ///\e Constructor |
172 Exception() {} |
45 Exception() {} |
173 ///\e |
46 ///\e Virtual destructor |
174 virtual ~Exception() throw() {} |
47 virtual ~Exception() throw() {} |
175 ///\e |
48 ///\e A short description of the exception |
176 virtual const char* what() const throw() { |
49 virtual const char* what() const throw() { |
177 return "lemon::Exception"; |
50 return "lemon::Exception"; |
178 } |
51 } |
179 }; |
52 }; |
180 |
53 |
181 /// One of the two main subclasses of \ref Exception. |
54 /// \brief Input-Output error |
182 |
55 /// |
183 /// Logic errors represent problems in the internal logic of a program; |
56 /// This exception is thrown when a file operation cannot be |
184 /// in theory, these are preventable, and even detectable before the |
57 /// succeeded. |
185 /// program runs (e.g. violations of class invariants). |
58 class IoError : public Exception { |
186 /// |
59 protected: |
187 /// A typical example for this is \ref UninitializedParameter. |
60 std::string _message; |
188 class LogicError : public Exception { |
61 std::string _file; |
|
62 |
|
63 mutable std::string _what; |
189 public: |
64 public: |
|
65 |
|
66 /// Copy constructor |
|
67 IoError(const IoError &error) { |
|
68 message(error._message); |
|
69 file(error._file); |
|
70 } |
|
71 |
|
72 /// Constructor |
|
73 explicit IoError(const char *message) { |
|
74 IoError::message(message); |
|
75 } |
|
76 |
|
77 /// Constructor |
|
78 explicit IoError(const std::string &message) { |
|
79 IoError::message(message); |
|
80 } |
|
81 |
|
82 /// Constructor |
|
83 IoError(const std::string &file, const char *message) { |
|
84 IoError::message(message); |
|
85 IoError::file(file); |
|
86 } |
|
87 |
|
88 /// Constructor |
|
89 IoError(const std::string &file, const std::string &message) { |
|
90 IoError::message(message); |
|
91 IoError::file(file); |
|
92 } |
|
93 |
|
94 /// Virtual destructor |
|
95 virtual ~IoError() throw() {} |
|
96 |
|
97 /// Set the error message |
|
98 void message(const char *message) { |
|
99 try { |
|
100 _message = message; |
|
101 } catch (...) {} |
|
102 } |
|
103 |
|
104 /// Set the error message |
|
105 void message(const std::string& message) { |
|
106 try { |
|
107 _message = message; |
|
108 } catch (...) {} |
|
109 } |
|
110 |
|
111 /// Set the file name |
|
112 void file(const std::string &file) { |
|
113 try { |
|
114 _file = file; |
|
115 } catch (...) {} |
|
116 } |
|
117 |
|
118 /// Returns the error message |
|
119 const std::string& message() const { |
|
120 return _message; |
|
121 } |
|
122 |
|
123 /// \brief Returns the filename |
|
124 /// |
|
125 /// Returns the filename or empty string if the filename was not |
|
126 /// specified. |
|
127 const std::string& file() const { |
|
128 return _file; |
|
129 } |
|
130 |
|
131 /// \brief Returns a short error message |
|
132 /// |
|
133 /// Returns a short error message which contains the message, the |
|
134 /// file name and the line number. |
190 virtual const char* what() const throw() { |
135 virtual const char* what() const throw() { |
191 return "lemon::LogicError"; |
136 try { |
192 } |
137 _what.clear(); |
193 }; |
138 std::ostringstream oss; |
194 |
139 oss << "lemon:IoError" << ": "; |
195 /// \ref Exception for uninitialized parameters. |
140 oss << message(); |
196 |
141 if (!file().empty()) { |
197 /// This error represents problems in the initialization |
142 oss << " ("; |
198 /// of the parameters of the algorithms. |
143 if (!file().empty()) oss << "with file '" << file() << "'"; |
199 class UninitializedParameter : public LogicError { |
144 oss << ")"; |
200 public: |
|
201 virtual const char* what() const throw() { |
|
202 return "lemon::UninitializedParameter"; |
|
203 } |
|
204 }; |
|
205 |
|
206 |
|
207 /// One of the two main subclasses of \ref Exception. |
|
208 |
|
209 /// Runtime errors represent problems outside the scope of a program; |
|
210 /// they cannot be easily predicted and can generally only be caught |
|
211 /// as the program executes. |
|
212 class RuntimeError : public Exception { |
|
213 public: |
|
214 virtual const char* what() const throw() { |
|
215 return "lemon::RuntimeError"; |
|
216 } |
|
217 }; |
|
218 |
|
219 ///\e |
|
220 class RangeError : public RuntimeError { |
|
221 public: |
|
222 virtual const char* what() const throw() { |
|
223 return "lemon::RangeError"; |
|
224 } |
|
225 }; |
|
226 |
|
227 ///\e |
|
228 class IoError : public RuntimeError { |
|
229 public: |
|
230 virtual const char* what() const throw() { |
|
231 return "lemon::IoError"; |
|
232 } |
|
233 }; |
|
234 |
|
235 ///\e |
|
236 class DataFormatError : public IoError { |
|
237 protected: |
|
238 ExceptionMember<std::string> _message; |
|
239 ExceptionMember<std::string> _file; |
|
240 int _line; |
|
241 |
|
242 mutable ExceptionMember<std::string> _message_holder; |
|
243 public: |
|
244 |
|
245 DataFormatError(const DataFormatError &dfe) : |
|
246 IoError(dfe), _message(dfe._message), _file(dfe._file), |
|
247 _line(dfe._line) {} |
|
248 |
|
249 ///\e |
|
250 explicit DataFormatError(const char *the_message) |
|
251 : _message(the_message), _line(0) {} |
|
252 |
|
253 ///\e |
|
254 DataFormatError(const std::string &file_name, int line_num, |
|
255 const char *the_message) |
|
256 : _message(the_message), _line(line_num) { file(file_name); } |
|
257 |
|
258 ///\e |
|
259 void line(int ln) { _line = ln; } |
|
260 ///\e |
|
261 void message(const std::string& msg) { _message.set(msg); } |
|
262 ///\e |
|
263 void file(const std::string &fl) { _file.set(fl); } |
|
264 |
|
265 ///\e |
|
266 int line() const { return _line; } |
|
267 ///\e |
|
268 const char* message() const { |
|
269 if (_message.valid() && !_message.get().empty()) { |
|
270 return _message.get().c_str(); |
|
271 } else { |
|
272 return 0; |
|
273 } |
|
274 } |
|
275 |
|
276 /// \brief Returns the filename. |
|
277 /// |
|
278 /// Returns \e null if the filename was not specified. |
|
279 const char* file() const { |
|
280 if (_file.valid() && !_file.get().empty()) { |
|
281 return _file.get().c_str(); |
|
282 } else { |
|
283 return 0; |
|
284 } |
|
285 } |
|
286 |
|
287 ///\e |
|
288 virtual const char* what() const throw() { |
|
289 try { |
|
290 std::ostringstream ostr; |
|
291 ostr << "lemon:DataFormatError" << ": "; |
|
292 if (message()) ostr << message(); |
|
293 if( file() || line() != 0 ) { |
|
294 ostr << " ("; |
|
295 if( file() ) ostr << "in file '" << file() << "'"; |
|
296 if( file() && line() != 0 ) ostr << " "; |
|
297 if( line() != 0 ) ostr << "at line " << line(); |
|
298 ostr << ")"; |
|
299 } |
145 } |
300 _message_holder.set(ostr.str()); |
146 _what = oss.str(); |
301 } |
147 } |
302 catch (...) {} |
148 catch (...) {} |
303 if( _message_holder.valid()) return _message_holder.get().c_str(); |
149 if (!_what.empty()) return _what.c_str(); |
304 return "lemon:DataFormatError"; |
150 else return "lemon:IoError"; |
305 } |
151 } |
306 |
152 |
307 virtual ~DataFormatError() throw() {} |
|
308 }; |
153 }; |
309 |
154 |
310 ///\e |
155 /// \brief Format error |
311 class FileOpenError : public IoError { |
156 /// |
|
157 /// This class is used to indicate if an input file has wrong |
|
158 /// formatting, or a data representation is not legal. |
|
159 class FormatError : public Exception { |
312 protected: |
160 protected: |
313 ExceptionMember<std::string> _file; |
161 std::string _message; |
314 |
162 std::string _file; |
315 mutable ExceptionMember<std::string> _message_holder; |
163 int _line; |
|
164 |
|
165 mutable std::string _what; |
316 public: |
166 public: |
317 |
167 |
318 FileOpenError(const FileOpenError &foe) : |
168 /// Copy constructor |
319 IoError(foe), _file(foe._file) {} |
169 FormatError(const FormatError &error) { |
320 |
170 message(error._message); |
321 ///\e |
171 file(error._file); |
322 explicit FileOpenError(const std::string& fl) |
172 line(error._line); |
323 : _file(fl) {} |
173 } |
324 |
174 |
325 |
175 /// Constructor |
326 ///\e |
176 explicit FormatError(const char *message) { |
327 void file(const std::string &fl) { _file.set(fl); } |
177 FormatError::message(message); |
328 |
178 _line = 0; |
329 /// \brief Returns the filename. |
179 } |
330 /// |
180 |
331 /// Returns \e null if the filename was not specified. |
181 /// Constructor |
332 const char* file() const { |
182 explicit FormatError(const std::string &message) { |
333 if (_file.valid() && !_file.get().empty()) { |
183 FormatError::message(message); |
334 return _file.get().c_str(); |
184 _line = 0; |
335 } else { |
185 } |
336 return 0; |
186 |
337 } |
187 /// Constructor |
338 } |
188 FormatError(const std::string &file, int line, const char *message) { |
339 |
189 FormatError::message(message); |
340 ///\e |
190 FormatError::file(file); |
|
191 FormatError::line(line); |
|
192 } |
|
193 |
|
194 /// Constructor |
|
195 FormatError(const std::string &file, int line, const std::string &message) { |
|
196 FormatError::message(message); |
|
197 FormatError::file(file); |
|
198 FormatError::line(line); |
|
199 } |
|
200 |
|
201 /// Virtual destructor |
|
202 virtual ~FormatError() throw() {} |
|
203 |
|
204 /// Set the line number |
|
205 void line(int line) { _line = line; } |
|
206 |
|
207 /// Set the error message |
|
208 void message(const char *message) { |
|
209 try { |
|
210 _message = message; |
|
211 } catch (...) {} |
|
212 } |
|
213 |
|
214 /// Set the error message |
|
215 void message(const std::string& message) { |
|
216 try { |
|
217 _message = message; |
|
218 } catch (...) {} |
|
219 } |
|
220 |
|
221 /// Set the file name |
|
222 void file(const std::string &file) { |
|
223 try { |
|
224 _file = file; |
|
225 } catch (...) {} |
|
226 } |
|
227 |
|
228 /// \brief Returns the line number |
|
229 /// |
|
230 /// Returns the line number or zero if it was not specified. |
|
231 int line() const { return _line; } |
|
232 |
|
233 /// Returns the error message |
|
234 const std::string& message() const { |
|
235 return _message; |
|
236 } |
|
237 |
|
238 /// \brief Returns the filename |
|
239 /// |
|
240 /// Returns the filename or empty string if the filename was not |
|
241 /// specified. |
|
242 const std::string& file() const { |
|
243 return _file; |
|
244 } |
|
245 |
|
246 /// \brief Returns a short error message |
|
247 /// |
|
248 /// Returns a short error message which contains the message, the |
|
249 /// file name and the line number. |
341 virtual const char* what() const throw() { |
250 virtual const char* what() const throw() { |
342 try { |
251 try { |
343 std::ostringstream ostr; |
252 _what.clear(); |
344 ostr << "lemon::FileOpenError" << ": "; |
253 std::ostringstream oss; |
345 ostr << "Cannot open file - " << file(); |
254 oss << "lemon:FormatError" << ": "; |
346 _message_holder.set(ostr.str()); |
255 oss << message(); |
|
256 if (!file().empty() || line() != 0) { |
|
257 oss << " ("; |
|
258 if (!file().empty()) oss << "in file '" << file() << "'"; |
|
259 if (!file().empty() && line() != 0) oss << " "; |
|
260 if (line() != 0) oss << "at line " << line(); |
|
261 oss << ")"; |
|
262 } |
|
263 _what = oss.str(); |
347 } |
264 } |
348 catch (...) {} |
265 catch (...) {} |
349 if( _message_holder.valid()) return _message_holder.get().c_str(); |
266 if (!_what.empty()) return _what.c_str(); |
350 return "lemon::FileOpenError"; |
267 else return "lemon:FormatError"; |
351 } |
268 } |
352 virtual ~FileOpenError() throw() {} |
269 |
353 }; |
270 }; |
354 |
271 |
355 class IoParameterError : public IoError { |
|
356 protected: |
|
357 ExceptionMember<std::string> _message; |
|
358 ExceptionMember<std::string> _file; |
|
359 |
|
360 mutable ExceptionMember<std::string> _message_holder; |
|
361 public: |
|
362 |
|
363 IoParameterError(const IoParameterError &ile) : |
|
364 IoError(ile), _message(ile._message), _file(ile._file) {} |
|
365 |
|
366 ///\e |
|
367 explicit IoParameterError(const char *the_message) |
|
368 : _message(the_message) {} |
|
369 |
|
370 ///\e |
|
371 IoParameterError(const char *file_name, const char *the_message) |
|
372 : _message(the_message), _file(file_name) {} |
|
373 |
|
374 ///\e |
|
375 void message(const std::string& msg) { _message.set(msg); } |
|
376 ///\e |
|
377 void file(const std::string &fl) { _file.set(fl); } |
|
378 |
|
379 ///\e |
|
380 const char* message() const { |
|
381 if (_message.valid()) { |
|
382 return _message.get().c_str(); |
|
383 } else { |
|
384 return 0; |
|
385 } |
|
386 } |
|
387 |
|
388 /// \brief Returns the filename. |
|
389 /// |
|
390 /// Returns \c 0 if the filename was not specified. |
|
391 const char* file() const { |
|
392 if (_file.valid()) { |
|
393 return _file.get().c_str(); |
|
394 } else { |
|
395 return 0; |
|
396 } |
|
397 } |
|
398 |
|
399 ///\e |
|
400 virtual const char* what() const throw() { |
|
401 try { |
|
402 std::ostringstream ostr; |
|
403 if (message()) ostr << message(); |
|
404 if (file()) ostr << "(when reading file '" << file() << "')"; |
|
405 _message_holder.set(ostr.str()); |
|
406 } |
|
407 catch (...) {} |
|
408 if( _message_holder.valid() ) return _message_holder.get().c_str(); |
|
409 return "lemon:IoParameterError"; |
|
410 } |
|
411 virtual ~IoParameterError() throw() {} |
|
412 }; |
|
413 |
|
414 /// @} |
272 /// @} |
415 |
273 |
416 } |
274 } |
417 |
275 |
418 #endif // LEMON_ERROR_H |
276 #endif // LEMON_ERROR_H |