Go to the documentation of this file.00001
00002 #ifndef WIBBLE_EXCEPTION_H
00003 #define WIBBLE_EXCEPTION_H
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <wibble/test.h>
00026 #include <exception>
00027 #include <typeinfo>
00028 #include <string>
00029 #include <sstream>
00030 #include <iterator>
00031 #include <vector>
00032
00080 namespace wibble {
00081 namespace exception {
00082
00084
00092 void DefaultUnexpected();
00093
00096 class InstallUnexpected
00097 {
00098 protected:
00099 void (*old)();
00100 public:
00101 InstallUnexpected(void (*func)() = DefaultUnexpected);
00102 ~InstallUnexpected();
00103 };
00104
00105
00106 struct AddContext {
00107 static std::vector< std::string > *s_context;
00108
00109 static std::vector< std::string > &context() {
00110 if ( s_context )
00111 return *s_context;
00112 s_context = new std::vector< std::string >();
00113 return *s_context;
00114 }
00115
00116 template< typename O >
00117 static void copyContext( O out ) {
00118 std::copy( context().begin(), context().end(), out );
00119 }
00120
00121 std::string m_context;
00122
00123 AddContext( std::string s )
00124 : m_context( s )
00125 {
00126 context().push_back( s );
00127 }
00128
00129 ~AddContext() {
00130 assert_eq( context().back(), m_context );
00131 context().pop_back();
00132 }
00133 };
00134
00136 class Context
00137 {
00138 protected:
00139 std::vector<std::string> m_context;
00140
00141 public:
00142 Context() throw ()
00143 {
00144 AddContext::copyContext( std::back_inserter( m_context ) );
00145 }
00146
00147 Context(const std::string& context) throw ()
00148 {
00149 AddContext::copyContext( std::back_inserter( m_context ) );
00150 addContext(context);
00151 }
00152
00153 void addContext(const std::string& c) throw () { m_context.push_back(c); }
00154 std::string formatContext() const throw ()
00155 {
00156 if (m_context.empty())
00157 return "no context information available";
00158
00159 std::stringstream res;
00160 std::copy( m_context.begin(), m_context.end(),
00161 std::ostream_iterator< std::string >( res, ", \n " ) );
00162 std::string r = res.str();
00163 return std::string( r, 0, r.length() - 7 );
00164 }
00165
00166 const std::vector<std::string>& context() const throw ()
00167 {
00168 return m_context;
00169 }
00170 };
00171
00173
00179 class Generic : public std::exception, public Context
00180 {
00181 protected:
00182 mutable std::string m_formatted;
00183
00184 public:
00185 Generic() throw () {}
00186 Generic(const std::string& context) throw () : Context(context) {}
00187 virtual ~Generic() throw () {}
00188
00190 virtual const char* type() const throw () { return "Generic"; }
00191
00193 virtual std::string desc() const throw ()
00194 {
00195 return "an unspecified problem happened; if you see this message, please report a bug to the maintainer";
00196 }
00197
00205 virtual const std::string& fullInfo() const throw ()
00206 {
00207 if (m_formatted.empty())
00208 m_formatted = desc() + ". Context:\n "
00209 + formatContext();
00210 return m_formatted;
00211 }
00212
00213 virtual const char* what() const throw () { return fullInfo().c_str(); }
00214 };
00215
00218
00224 class Interrupted : public Generic
00225 {
00226 public:
00227 Interrupted() throw () {}
00228 Interrupted(const std::string& context) throw () : Generic(context) {}
00229
00230 virtual const char* type() const throw () { return "Interrupted"; }
00231 };
00232
00234
00241 class WaitInterrupted : public Interrupted
00242 {
00243 public:
00244 WaitInterrupted(const std::string& context) throw () :
00245 Interrupted(context) {}
00246
00247 virtual const char* type() const throw () { return "WaitInterrupted"; }
00248 };
00249
00251
00254 class Consistency : public Generic
00255 {
00256 std::string m_error;
00257
00258 public:
00259 Consistency(const std::string& context, const std::string& error = std::string()) throw () :
00260 Generic(context), m_error(error) {}
00261 ~Consistency() throw () {}
00262
00263 virtual const char* type() const throw () { return "Consistency"; }
00264
00265 virtual std::string desc() const throw ()
00266 {
00267 if (m_error.empty())
00268 return "consistency check failed";
00269 return m_error;
00270 }
00271 };
00272
00273 struct BadCast : public Consistency
00274 {
00275 BadCast( const std::string &context ) throw()
00276 : Consistency( context )
00277 {}
00278 ~BadCast() throw() {}
00279 virtual std::string typeinfo() const throw() { return "unknown types"; }
00280 virtual std::string desc() const throw() {
00281 return std::string( "bad cast: " ) + typeinfo();
00282 }
00283 };
00284
00285 template< typename From, typename To >
00286 struct BadCastExt : public BadCast
00287 {
00288 BadCastExt( const std::string &error = std::string() ) throw()
00289 : BadCast( error )
00290 {}
00291 ~BadCastExt() throw() {}
00292 virtual std::string typeinfo() const throw() { return std::string( "from " )
00293 + typeid( From ).name()
00294 + " to "
00295 + typeid( To ).name(); }
00296 };
00297
00307 class OutOfRange : public Consistency
00308 {
00309 protected:
00310 std::string m_var_desc;
00311
00312 public:
00313 OutOfRange(const std::string& var_desc, const std::string& context) throw ()
00314 : Consistency(context), m_var_desc(var_desc) {}
00315 ~OutOfRange() throw () {}
00316
00317 virtual const char* type() const throw () { return "OutOfRange"; }
00318
00320 virtual std::string var_desc() const throw () { return m_var_desc; }
00321
00322 virtual std::string desc() const throw () { return m_var_desc + " out of range"; }
00323 };
00324
00326
00341 template <class C>
00342 class ValOutOfRange : public OutOfRange
00343 {
00344 protected:
00345 C m_val;
00346 C m_inf;
00347 C m_sup;
00348
00349 public:
00353 ValOutOfRange(const std::string& var_desc, C val, C inf, C sup,
00354 const std::string& context) throw ()
00355 : OutOfRange(var_desc, context),
00356 m_val(val), m_inf(inf), m_sup(sup) {}
00357
00359
00360
00361 virtual C val() const throw () { return m_val; }
00363 virtual C inf() const throw () { return m_inf; }
00365 virtual C sup() const throw () { return m_sup; }
00367
00368 virtual const char* type() const throw ()
00369 {
00370 return "ValOutOfRange<>";
00371 }
00372
00373 virtual std::string desc() const throw ();
00374 };
00375
00377
00394 class System : public Generic
00395 {
00396 protected:
00397 int m_errno;
00398
00399 public:
00400 System(const std::string& context) throw ();
00401 System(int code, const std::string& context) throw ();
00402
00403 virtual const char* type() const throw () { return "System"; }
00404
00406 virtual int code() const throw () { return m_errno; }
00407
00409 virtual std::string desc() const throw ();
00410 };
00411
00413
00418 class File : public System
00419 {
00420 protected:
00421 std::string m_name;
00422
00423 public:
00424 File(const std::string& name, const std::string& context) throw () :
00425 System(context), m_name(name) {}
00426 ~File() throw () {}
00427
00428 virtual const char* type() const throw () { return "File"; }
00429
00430 virtual std::string desc() const throw () { return m_name + ": " + System::desc(); }
00431 };
00432
00433 }
00434 }
00435
00436
00437 #endif