00001
00002
00003
00004
00005
00006
00007
00008 #ifndef IMP_EXCEPTION_H
00009 #define IMP_EXCEPTION_H
00010
00011 #include "kernel_config.h"
00012
00013 #include <boost/static_assert.hpp>
00014 #include <boost/type_traits.hpp>
00015
00016 #include <cassert>
00017 #include <cstring>
00018 #include <string>
00019 #include <iostream>
00020 #include <new>
00021 #include <sstream>
00022
00023 IMP_BEGIN_NAMESPACE
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048 class IMPEXPORT Exception
00049 {
00050 struct refstring {
00051 char message_[4096];
00052 int ct_;
00053 };
00054 refstring *str_;
00055 public:
00056 const char *what() const throw() {
00057 return str_? str_->message_: NULL;
00058 }
00059 Exception(const char *message) {
00060 str_= new (std::nothrow) refstring();
00061 if (str_ != NULL) {
00062 str_->ct_=1;
00063 std::strncpy(str_->message_, message, 4095);
00064 str_->message_[4095]='\0';
00065 }
00066 }
00067
00068
00069
00070
00071 virtual ~Exception() throw();
00072
00073 Exception(const Exception &o) {copy(o);}
00074 Exception &operator=(const Exception &o) {
00075 destroy();
00076 copy(o);
00077 return *this;
00078 }
00079 private:
00080 void destroy() {
00081 if (str_ != NULL) {
00082 --str_->ct_;
00083 if (str_->ct_==0) delete str_;
00084 }
00085 }
00086 void copy(const Exception &o) {
00087 str_=o.str_;
00088 if (str_!= NULL) ++str_->ct_;
00089 }
00090 };
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100 enum CheckLevel {NONE=0, USAGE=1, USAGE_AND_INTERNAL=2};
00101
00102
00103
00104
00105 IMPEXPORT CheckLevel get_maximum_check_level();
00106
00107 #if !defined(SWIG) && !defined(IMP_DOXYGEN)
00108 namespace internal {
00109 IMPEXPORT extern CheckLevel check_mode;
00110 }
00111 #endif
00112
00113
00114
00115
00116
00117
00118 inline void set_check_level(CheckLevel tf) {
00119 internal::check_mode= tf;
00120 }
00121
00122
00123
00124
00125 inline CheckLevel get_check_level() {
00126 return internal::check_mode;
00127 }
00128
00129
00130
00131
00132
00133
00134
00135 IMPEXPORT void set_print_exceptions(bool tf);
00136
00137 #ifdef IMP_DOXYGEN
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153 #define IMP_IF_CHECK(level)
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166 #define IMP_CHECK_CODE(expr)
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189 #define IMP_INTERNAL_CHECK(expr, message)
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209 #define IMP_USAGE_CHECK(expr, message)
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220 #define IMP_THROW(message, exception_name)
00221
00222
00223
00224
00225
00226
00227
00228
00229 #define IMP_FAILURE(message)
00230
00231
00232
00233
00234 #define IMP_NOT_IMPLEMENTED
00235
00236 #else // IMP_DOXYGEN
00237
00238 #define IMP_THROW(message, exception_name)do { \
00239 std::ostringstream oss; \
00240 oss << message << std::endl; \
00241 BOOST_STATIC_ASSERT((!(boost::is_base_of<IMP::UsageException, \
00242 exception_name>::value) \
00243 && !(boost::is_base_of<IMP::InternalException, \
00244 exception_name>::value) \
00245 && (boost::is_base_of<IMP::Exception, \
00246 exception_name>::value))); \
00247 throw exception_name(oss.str().c_str()); \
00248 } while (true)
00249 #define IMP_FAILURE(message) do { \
00250 std::ostringstream oss; \
00251 oss << message << std::endl; \
00252 IMP::internal::assert_fail(oss.str().c_str()); \
00253 throw InternalException(oss.str().c_str()); \
00254 } while (true)
00255 #define IMP_NOT_IMPLEMENTED do { \
00256 IMP::internal::assert_fail("This method is not implemented."); \
00257 throw InternalException("Not implemented"); \
00258 } while(true)
00259
00260 #if IMP_BUILD < IMP_FAST
00261 #define IMP_IF_CHECK(level) \
00262 if (level <= ::IMP::get_check_level())
00263 #define IMP_CHECK_CODE(expr) expr
00264
00265 #define IMP_INTERNAL_CHECK(expr, message) \
00266 do { \
00267 if (IMP::get_check_level() >= IMP::USAGE_AND_INTERNAL && !(expr)) { \
00268 std::ostringstream oss; \
00269 oss << message << std::endl \
00270 << " File \"" << __FILE__ << "\", line " << __LINE__ \
00271 << std::endl; \
00272 IMP::internal::assert_fail(oss.str().c_str()); \
00273 throw IMP::InternalException(oss.str().c_str()); \
00274 } \
00275 } while(false)
00276 #define IMP_USAGE_CHECK(expr, message) \
00277 do { \
00278 if (IMP::get_check_level() >= IMP::USAGE && !(expr)) { \
00279 std::ostringstream oss; \
00280 oss << message << std::endl; \
00281 IMP::internal::assert_fail(oss.str().c_str()); \
00282 throw IMP::UsageException(oss.str().c_str()); \
00283 } \
00284 } while (false)
00285 #else // IMP_BUILD < IMP_FAST
00286 #define IMP_IF_CHECK(level) if (0)
00287 #define IMP_CHECK_CODE(expr)
00288 #define IMP_INTERNAL_CHECK(expr, message)
00289 #define IMP_USAGE_CHECK(expr, message)
00290 #endif // IMP_BUILD < IMP_FAST
00291
00292
00293
00294 #endif // IMP_DOXYGEN
00295
00296
00297
00298
00299 #if !defined(SWIG) && !defined(IMP_DOXYGEN)
00300 namespace internal {
00301 IMPEXPORT void assert_fail(const char *msg);
00302 }
00303 #endif
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316 struct IMPEXPORT InternalException: public Exception
00317 {
00318 InternalException(const char *msg="Fatal error"): Exception(msg){}
00319 ~InternalException() throw();
00320 };
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332 class IMPEXPORT UsageException : public Exception
00333 {
00334 public:
00335 UsageException(const char *t): Exception(t){}
00336 ~UsageException() throw();
00337 };
00338
00339
00340
00341
00342 class IMPEXPORT ValueException : public Exception
00343 {
00344 public:
00345 ValueException(const char *t): Exception(t){}
00346 ~ValueException() throw();
00347 };
00348
00349
00350
00351
00352
00353 class IMPEXPORT IndexException: public Exception
00354 {
00355 public:
00356
00357 IndexException(const char *t): Exception(t){}
00358 ~IndexException() throw();
00359 };
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370 class IMPEXPORT IOException: public Exception
00371 {
00372 public:
00373 IOException(const char *t): Exception(t){}
00374 ~IOException() throw();
00375 };
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386 class IMPEXPORT ModelException: public Exception
00387 {
00388 public:
00389
00390 ModelException(const char *t): Exception(t){}
00391 ~ModelException() throw();
00392 };
00393
00394 IMP_END_NAMESPACE
00395
00396 #endif