100 * \brief Generic exception class. |
100 * \brief Generic exception class. |
101 * |
101 * |
102 * Base class for exceptions used in LEMON. |
102 * Base class for exceptions used in LEMON. |
103 */ |
103 */ |
104 class Exception : public std::exception { |
104 class Exception : public std::exception { |
105 protected: |
105 public: |
106 ///\e |
106 ///\e |
107 const char *message; |
107 Exception() {} |
108 |
|
109 public: |
|
110 ///\e |
|
111 Exception() throw() : message(0) {} |
|
112 ///\e |
|
113 explicit Exception(const char *msg) throw() |
|
114 : message(msg) {} |
|
115 ///\e |
108 ///\e |
116 virtual ~Exception() throw() {} |
109 virtual ~Exception() throw() {} |
|
110 |
|
111 ///\e |
|
112 virtual const char* exceptionName() const { |
|
113 return "lemon::Exception"; |
|
114 } |
117 |
115 |
118 ///\e |
116 ///\e |
119 virtual const char* what() const throw() { |
117 virtual const char* what() const throw() { |
120 if( message ) return message; |
118 return exceptionName(); |
121 return "lemon::Exception"; |
119 } |
122 } |
120 }; |
123 }; |
121 |
124 |
122 /** |
125 ///\e |
123 * \brief One of the two main subclasses of \ref Exception. |
|
124 * |
|
125 * Logic errors represent problems in the internal logic of a program; |
|
126 * in theory, these are preventable, and even detectable before the |
|
127 * program runs (e.g., violations of class invariants). |
|
128 * |
|
129 * For a typical example \see UninitializedParameterError. |
|
130 */ |
126 class LogicError : public Exception { |
131 class LogicError : public Exception { |
127 public: |
132 public: |
128 ///\e |
133 virtual const char* exceptionName() const { |
129 explicit LogicError() {} |
134 return "lemon::LogicError"; |
130 ///\e |
135 } |
131 explicit LogicError(const char *s) |
136 }; |
132 : Exception(s) {} |
137 |
133 }; |
138 |
134 |
139 /** |
135 ///\e |
140 * \brief One of the two main subclasses of \ref Exception. |
|
141 * |
|
142 * Runtime errors represent problems outside the scope of a program; |
|
143 * they cannot be easily predicted and can generally only be caught as |
|
144 * the program executes. |
|
145 */ |
136 class RuntimeError : public Exception { |
146 class RuntimeError : public Exception { |
137 public: |
147 public: |
138 ///\e |
148 virtual const char* exceptionName() const { |
139 explicit RuntimeError() {} |
149 return "lemon::RuntimeError"; |
140 ///\e |
150 } |
141 explicit RuntimeError(const char *s) |
|
142 : Exception(s) {} |
|
143 }; |
151 }; |
144 |
152 |
145 ///\e |
153 ///\e |
146 class RangeError : public RuntimeError { |
154 class RangeError : public RuntimeError { |
147 public: |
155 public: |
148 ///\e |
156 virtual const char* exceptionName() const { |
149 explicit RangeError(const char *s) |
157 return "lemon::RangeError"; |
150 : RuntimeError(s) {} |
158 } |
151 }; |
159 }; |
152 |
160 |
153 ///\e |
161 ///\e |
154 class IOError : public RuntimeError { |
162 class IOError : public RuntimeError { |
155 public: |
163 public: |
156 ///\e |
164 virtual const char* exceptionName() const { |
157 explicit IOError(const char *s) |
165 return "lemon::IOError"; |
158 : RuntimeError(s) {} |
166 } |
159 }; |
167 }; |
160 |
168 |
161 ///\e |
169 ///\e |
162 class DataFormatError : public IOError { |
170 class DataFormatError : public IOError { |
163 protected: |
171 protected: |
164 int line; |
172 const char *_message; |
165 boost::shared_ptr<std::string> file; |
173 int _line; |
166 |
174 boost::shared_ptr<std::string> _file; |
167 public: |
175 |
168 ///\e |
176 public: |
169 explicit DataFormatError(const char *message) |
177 ///\e |
170 : IOError(message), line(0) {} |
178 explicit DataFormatError(const char *the_message) |
|
179 : _message(the_message), _line(0) {} |
171 ///\e |
180 ///\e |
172 DataFormatError(const std::string &file_name, int line_num, |
181 DataFormatError(const std::string &file_name, int line_num, |
173 const char *message) |
182 const char *the_message) |
174 : IOError(message), line(line_num) { set_file(file_name); } |
183 : _message(the_message), _line(line_num) { file(file_name); } |
175 |
184 |
176 ///\e |
185 ///\e |
177 void set_line(int line_num) { line=line_num; } |
186 void line(int line_num) { _line=line_num; } |
178 ///\e |
187 ///\e |
179 void set_file(const std::string &file_name) { |
188 void message(char *the_message) { _message=the_message; } |
180 try { |
189 ///\e |
181 file.reset(new std::string); |
190 void file(const std::string &file_name) { |
182 *file = file_name; |
191 try { |
|
192 _file.reset(new std::string); |
|
193 *_file = file_name; |
183 } |
194 } |
184 catch(...) { |
195 catch(...) { |
185 file.reset(); |
196 _file.reset(); |
186 } |
197 } |
187 } |
198 } |
188 |
199 |
189 ///\e |
200 ///\e |
190 int get_line() const { return line; } |
201 int line() const { return _line; } |
|
202 ///\e |
|
203 const char* message() const { return _message; } |
191 |
204 |
192 /// \brief Returns the filename. |
205 /// \brief Returns the filename. |
193 /// |
206 /// |
194 /// Returns \e "(unknown)" if the filename was not specified. |
207 /// Returns \e "(unknown)" if the filename was not specified. |
195 const char* get_file() const { |
208 const char* file() const { |
196 if( file ) |
209 if( _file ) |
197 return file->c_str(); |
210 return _file->c_str(); |
198 else |
211 else |
199 return "(unknown)"; |
212 return "(unknown)"; |
200 } |
213 } |
201 |
214 |
202 ///\e |
215 ///\e |
203 virtual const char* what() const throw() { |
216 virtual const char* what() const throw() { |
204 const char *mes = 0; |
217 const char *mes = 0; |
205 try { |
218 try { |
206 std::ostringstream ostr; |
219 std::ostringstream ostr; |
207 ostr << IOError::what(); |
220 ostr << _message; |
208 if( file || line ) { |
221 if( _file || _line ) { |
209 ostr << " ("; |
222 ostr << " ("; |
210 if( file ) ostr << "in file '" << *file << "'"; |
223 if( _file ) ostr << "in file '" << *_file << "'"; |
211 if( file && line ) ostr << " "; |
224 if( _file && _line ) ostr << " "; |
212 if( line ) ostr << "at line " << line; |
225 if( _line ) ostr << "at line " << _line; |
213 ostr << ")"; |
226 ostr << ")"; |
214 } |
227 } |
215 mes = ostr.str().c_str(); |
228 mes = ostr.str().c_str(); |
216 } |
229 } |
217 catch(...) {} |
230 catch(...) {} |
218 if( mes ) return mes; |
231 if( mes ) return mes; |
|
232 return exceptionName(); |
|
233 } |
|
234 |
|
235 virtual const char* exceptionName() const { |
219 return "lemon::DataFormatError"; |
236 return "lemon::DataFormatError"; |
220 } |
237 } |
221 |
238 |
222 virtual ~DataFormatError() throw() {} |
239 virtual ~DataFormatError() throw() {} |
223 }; |
240 }; |
309 #ifndef LEMON_ASSERT_ABORT |
330 #ifndef LEMON_ASSERT_ABORT |
310 # define LEMON_ASSERT_ABORT 1 |
331 # define LEMON_ASSERT_ABORT 1 |
311 #endif |
332 #endif |
312 |
333 |
313 #ifndef LEMON_ASSERT_HANDLER |
334 #ifndef LEMON_ASSERT_HANDLER |
314 # define LEMON_ASSERT_HANDLER ::lemon::assert_fail |
335 # ifdef LEMON_ASSERT_EXCEPTION |
|
336 # define LEMON_ASSERT_HANDLER ::lemon::assert_fail_throw |
|
337 # else |
|
338 # define LEMON_ASSERT_HANDLER ::lemon::assert_fail |
|
339 # endif |
315 #endif |
340 #endif |
316 |
341 |
317 #if defined(NDEBUG) || defined(LEMON_DISABLE_ASSERTS) |
342 #if defined(NDEBUG) || defined(LEMON_DISABLE_ASSERTS) |
318 |
343 |
319 # define LEMON_ASSERT(exp, msg) (static_cast<void> (0)) |
344 # define LEMON_ASSERT(exp, msg) (static_cast<void> (0)) |
320 |
345 |
321 #else |
346 #else |
322 |
347 |
323 /** |
348 /** |
324 * \brief Macro for assertions with customizable message |
349 * \brief Macro for assertions with customizable message |
|
350 * |
|
351 * Macro for assertions with customizable message. |
|
352 * |
|
353 * The behaviour can be customized with LEMON_ASSERT_HANDLER, |
|
354 * LEMON_ASSERT_EXCEPTION and LEMON_ASSERT_ABORT defines. Asserts can be |
|
355 * disabled by defining either NDEBUG or LEMON_DISABLE_ASSERTS macros. |
|
356 * |
|
357 * \todo We should provide some way to reset to the default behaviour, |
|
358 * shouldn't we? |
|
359 * |
|
360 * \todo This whole 'assert' business should be placed in a separate |
|
361 * include file. |
325 * |
362 * |
326 * \todo __PRETTY_FUNCTION__ should be replaced by something |
363 * \todo __PRETTY_FUNCTION__ should be replaced by something |
327 * compiler-independant, like BOOST_CURRENT_FUNCTION |
364 * compiler-independant, like BOOST_CURRENT_FUNCTION |
328 */ |
365 */ |
329 |
366 |