30 #include <cstdlib> |
30 #include <cstdlib> |
31 #include <memory> |
31 #include <memory> |
32 |
32 |
33 namespace lemon { |
33 namespace lemon { |
34 |
34 |
35 /// \addtogroup exceptions |
35 /// \addtogroup exceptions |
36 /// @{ |
36 /// @{ |
|
37 |
|
38 /// \brief Exception safe wrapper class. |
|
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) { |
|
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) { |
|
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 { |
|
89 return ptr.get() != 0; |
|
90 } |
|
91 |
|
92 private: |
|
93 std::auto_ptr<_Type> ptr; |
|
94 }; |
37 |
95 |
38 /// Exception-safe convenient "error message" class. |
96 /// Exception-safe convenient "error message" class. |
39 |
97 |
40 /// Helper class which provides a convenient ostream-like (operator << |
98 /// Helper class which provides a convenient ostream-like (operator << |
41 /// based) interface to create a string message. Mostly useful in |
99 /// based) interface to create a string message. Mostly useful in |
188 }; |
247 }; |
189 |
248 |
190 ///\e |
249 ///\e |
191 class DataFormatError : public IOError { |
250 class DataFormatError : public IOError { |
192 protected: |
251 protected: |
193 const char *_message; |
252 ExceptionMember<std::string> _message; |
|
253 ExceptionMember<std::string> _file; |
194 int _line; |
254 int _line; |
195 |
255 |
196 ///\todo Much better solution is boost::shared_ptr |
256 mutable ExceptionMember<std::string> _message_holder; |
197 mutable |
|
198 std::auto_ptr<std::string> _file; |
|
199 |
|
200 public: |
257 public: |
201 |
258 |
202 DataFormatError(const DataFormatError &dfe) : |
259 DataFormatError(const DataFormatError &dfe) : |
203 IOError(dfe), _message(dfe._message), _line(dfe._line), |
260 IOError(dfe), _message(dfe._message), _file(dfe._file), |
204 _file(dfe._file) {} |
261 _line(dfe._line) {} |
205 |
262 |
206 ///\e |
263 ///\e |
207 explicit DataFormatError(const char *the_message) |
264 explicit DataFormatError(const char *the_message) |
208 : _message(the_message), _line(0) {} |
265 : _message(the_message), _line(0) {} |
|
266 |
209 ///\e |
267 ///\e |
210 DataFormatError(const std::string &file_name, int line_num, |
268 DataFormatError(const std::string &file_name, int line_num, |
211 const char *the_message) |
269 const char *the_message) |
212 : _message(the_message), _line(line_num) { file(file_name); } |
270 : _message(the_message), _line(line_num) { file(file_name); } |
213 |
271 |
214 ///\e |
272 ///\e |
215 void line(int line_num) { _line=line_num; } |
273 void line(int line) { _line = line; } |
216 ///\e |
274 ///\e |
217 void message(char *the_message) { _message=the_message; } |
275 void message(const std::string& message) { _message.set(message); } |
218 ///\e |
276 ///\e |
219 void file(const std::string &file_name) { |
277 void file(const std::string &file) { _file.set(file); } |
220 try { |
278 |
221 _file.reset(new std::string); |
|
222 *_file = file_name; |
|
223 } |
|
224 catch(...) { |
|
225 _file.reset(); |
|
226 } |
|
227 } |
|
228 |
|
229 ///\e |
279 ///\e |
230 int line() const { return _line; } |
280 int line() const { return _line; } |
231 ///\e |
281 ///\e |
232 const char* message() const { return _message; } |
282 const char* message() const { |
|
283 if (_message.valid() && !_message.get().empty()) { |
|
284 return _message.get().c_str(); |
|
285 } else { |
|
286 return 0; |
|
287 } |
|
288 } |
233 |
289 |
234 /// \brief Returns the filename. |
290 /// \brief Returns the filename. |
235 /// |
291 /// |
236 /// Returns \e "(unknown)" if the filename was not specified. |
292 /// Returns \e null if the filename was not specified. |
237 const char* file() const { |
293 const char* file() const { |
238 if( _file.get() ) |
294 if (_file.valid() && !_file.get().empty()) { |
239 return _file->c_str(); |
295 return _file.get().c_str(); |
240 else |
296 } else { |
241 return "(unknown)"; |
297 return 0; |
|
298 } |
242 } |
299 } |
243 |
300 |
244 ///\e |
301 ///\e |
245 virtual const char* what() const throw() { |
302 virtual const char* what() const throw() { |
246 const char *mes = 0; |
|
247 try { |
303 try { |
248 std::ostringstream ostr; |
304 std::ostringstream ostr; |
249 ostr << _message; |
305 if (message()) ostr << message(); |
250 if( _file.get() || _line ) { |
306 if( file() || line() != 0 ) { |
251 ostr << " ("; |
307 ostr << " ("; |
252 if( _file.get() ) ostr << "in file '" << *_file << "'"; |
308 if( file() ) ostr << "in file '" << file() << "'"; |
253 if( _file.get() && _line ) ostr << " "; |
309 if( file() && line() != 0 ) ostr << " "; |
254 if( _line ) ostr << "at line " << _line; |
310 if( line() != 0 ) ostr << "at line " << line(); |
255 ostr << ")"; |
311 ostr << ")"; |
256 } |
312 } |
257 mes = ostr.str().c_str(); |
313 _message_holder.set(ostr.str()); |
258 } |
314 } |
259 catch(...) {} |
315 catch (...) {} |
260 if( mes ) return mes; |
316 if( _message_holder.valid()) return _message_holder.get().c_str(); |
261 return exceptionName(); |
317 return exceptionName(); |
262 } |
318 } |
263 |
319 |
264 virtual const char* exceptionName() const { |
320 virtual const char* exceptionName() const { |
265 return "lemon::DataFormatError"; |
321 return "lemon::DataFormatError"; |
266 } |
322 } |
267 |
323 |
268 virtual ~DataFormatError() throw() {} |
324 virtual ~DataFormatError() throw() {} |
|
325 }; |
|
326 |
|
327 class IOLogicError : public IOError, public LogicError { |
|
328 protected: |
|
329 ExceptionMember<std::string> _message; |
|
330 ExceptionMember<std::string> _file; |
|
331 int _line; |
|
332 |
|
333 mutable ExceptionMember<std::string> _message_holder; |
|
334 public: |
|
335 |
|
336 IOLogicError(const IOLogicError &ile) : |
|
337 IOError(ile), LogicError(ile), |
|
338 _message(ile._message), _file(ile._file) {} |
|
339 |
|
340 ///\e |
|
341 explicit IOLogicError(const char *the_message) |
|
342 : _message(the_message), _line(0) {} |
|
343 |
|
344 ///\e |
|
345 IOLogicError(const char *file_name, const char *the_message) |
|
346 : _message(file_name), _file(file_name) {} |
|
347 |
|
348 ///\e |
|
349 void message(const std::string& message) { _message.set(message); } |
|
350 ///\e |
|
351 void file(const std::string &file) { _file.set(file); } |
|
352 |
|
353 ///\e |
|
354 const char* message() const { |
|
355 if (_message.valid()) { |
|
356 return _message.get().c_str(); |
|
357 } else { |
|
358 return 0; |
|
359 } |
|
360 } |
|
361 |
|
362 /// \brief Returns the filename. |
|
363 /// |
|
364 /// Returns \e null if the filename was not specified. |
|
365 const char* file() const { |
|
366 if (_file.valid()) { |
|
367 return _file.get().c_str(); |
|
368 } else { |
|
369 return 0; |
|
370 } |
|
371 } |
|
372 |
|
373 ///\e |
|
374 virtual const char* what() const throw() { |
|
375 try { |
|
376 std::ostringstream ostr; |
|
377 if (message()) ostr << message(); |
|
378 if (file()) ostr << "(when reading file '" << file() << "')"; |
|
379 _message_holder.set(ostr.str()); |
|
380 } |
|
381 catch (...) {} |
|
382 if( _message_holder.valid() ) return _message_holder.get().c_str(); |
|
383 return exceptionName(); |
|
384 } |
|
385 |
|
386 virtual const char* exceptionName() const { |
|
387 return "lemon::IOLogicError"; |
|
388 } |
|
389 |
|
390 virtual ~IOLogicError() throw() {} |
269 }; |
391 }; |
270 |
392 |
271 |
393 |
272 ///\e |
394 ///\e |
273 class AssertionFailedError : public LogicError { |
395 class AssertionFailedError : public LogicError { |