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 template< typename O >
00110 static void copyContext( O out ) {
00111 std::copy( s_context.begin(), s_context.end(), out );
00112 }
00113
00114 std::string m_context;
00115
00116 AddContext( std::string s )
00117 : m_context( s )
00118 {
00119 s_context.push_back( s );
00120 }
00121
00122 ~AddContext() {
00123 assert_eq( s_context.back(), m_context );
00124 s_context.pop_back();
00125 }
00126 };
00127
00129 class Context
00130 {
00131 protected:
00132 std::vector<std::string> m_context;
00133
00134 public:
00135 Context() throw ()
00136 {
00137 AddContext::copyContext( std::back_inserter( m_context ) );
00138 }
00139
00140 Context(const std::string& context) throw ()
00141 {
00142 AddContext::copyContext( std::back_inserter( m_context ) );
00143 addContext(context);
00144 }
00145
00146 void addContext(const std::string& c) throw () { m_context.push_back(c); }
00147 std::string formatContext() const throw ()
00148 {
00149 if (m_context.empty())
00150 return "no context information available";
00151
00152 std::stringstream res;
00153 std::copy( m_context.begin(), m_context.end(),
00154 std::ostream_iterator< std::string >( res, ", " ) );
00155 std::string r = res.str();
00156 return std::string( r, 0, r.length() - 2 );
00157 }
00158
00159 const std::vector<std::string>& context() const throw ()
00160 {
00161 return m_context;
00162 }
00163 };
00164
00166
00172 class Generic : public std::exception, public Context
00173 {
00174 protected:
00175 mutable std::string m_formatted;
00176
00177 public:
00178 Generic() throw () {}
00179 Generic(const std::string& context) throw () : Context(context) {}
00180 virtual ~Generic() throw () {}
00181
00183 virtual const char* type() const throw () { return "Generic"; }
00184
00186 virtual std::string desc() const throw ()
00187 {
00188 return "an unspecified problem happened; if you see this message, please report a bug to the maintainer";
00189 }
00190
00198 virtual const std::string& fullInfo() const throw ()
00199 {
00200 if (m_formatted.empty())
00201 m_formatted = desc() + ". Context: " + formatContext();
00202 return m_formatted;
00203 }
00204
00205 virtual const char* what() const throw () { return fullInfo().c_str(); }
00206 };
00207
00210
00216 class Interrupted : public Generic
00217 {
00218 public:
00219 Interrupted() throw () {}
00220 Interrupted(const std::string& context) throw () : Generic(context) {}
00221
00222 virtual const char* type() const throw () { return "Interrupted"; }
00223 };
00224
00226
00233 class WaitInterrupted : public Interrupted
00234 {
00235 public:
00236 WaitInterrupted(const std::string& context) throw () :
00237 Interrupted(context) {}
00238
00239 virtual const char* type() const throw () { return "WaitInterrupted"; }
00240 };
00241
00243
00246 class Consistency : public Generic
00247 {
00248 std::string m_error;
00249
00250 public:
00251 Consistency(const std::string& context, const std::string& error = std::string()) throw () :
00252 Generic(context), m_error(error) {}
00253 ~Consistency() throw () {}
00254
00255 virtual const char* type() const throw () { return "Consistency"; }
00256
00257 virtual std::string desc() const throw ()
00258 {
00259 if (m_error.empty())
00260 return "consistency check failed";
00261 return m_error;
00262 }
00263 };
00264
00265 struct BadCast : public Consistency
00266 {
00267 BadCast( const std::string &context ) throw()
00268 : Consistency( context )
00269 {}
00270 ~BadCast() throw() {}
00271 virtual std::string typeinfo() const throw() { return "unknown types"; }
00272 virtual std::string desc() const throw() {
00273 return std::string( "bad cast: " ) + typeinfo();
00274 }
00275 };
00276
00277 template< typename From, typename To >
00278 struct BadCastExt : public BadCast
00279 {
00280 BadCastExt( const std::string &error = std::string() ) throw()
00281 : BadCast( error )
00282 {}
00283 ~BadCastExt() throw() {}
00284 virtual std::string typeinfo() const throw() { return std::string( "from " )
00285 + typeid( From ).name()
00286 + " to "
00287 + typeid( To ).name(); }
00288 };
00289
00299 class OutOfRange : public Consistency
00300 {
00301 protected:
00302 std::string m_var_desc;
00303
00304 public:
00305 OutOfRange(const std::string& var_desc, const std::string& context) throw ()
00306 : Consistency(context), m_var_desc(var_desc) {}
00307 ~OutOfRange() throw () {}
00308
00309 virtual const char* type() const throw () { return "OutOfRange"; }
00310
00312 virtual std::string var_desc() const throw () { return m_var_desc; }
00313
00314 virtual std::string desc() const throw () { return m_var_desc + " out of range"; }
00315 };
00316
00318
00333 template <class C>
00334 class ValOutOfRange : public OutOfRange
00335 {
00336 protected:
00337 C m_val;
00338 C m_inf;
00339 C m_sup;
00340
00341 public:
00345 ValOutOfRange(const std::string& var_desc, C val, C inf, C sup,
00346 const std::string& context) throw ()
00347 : OutOfRange(var_desc, context),
00348 m_val(val), m_inf(inf), m_sup(sup) {}
00349
00351
00352
00353 virtual C val() const throw () { return m_val; }
00355 virtual C inf() const throw () { return m_inf; }
00357 virtual C sup() const throw () { return m_sup; }
00359
00360 virtual const char* type() const throw ()
00361 {
00362 return "ValOutOfRange<>";
00363 }
00364
00365 virtual std::string desc() const throw ();
00366 };
00367
00369
00386 class System : public Generic
00387 {
00388 protected:
00389 int m_errno;
00390
00391 public:
00392 System(const std::string& context) throw ();
00393 System(int code, const std::string& context) throw ();
00394
00395 virtual const char* type() const throw () { return "System"; }
00396
00398 virtual int code() const throw () { return m_errno; }
00399
00401 virtual std::string desc() const throw ();
00402 };
00403
00405
00410 class File : public System
00411 {
00412 protected:
00413 std::string m_name;
00414
00415 public:
00416 File(const std::string& name, const std::string& context) throw () :
00417 System(context), m_name(name) {}
00418 ~File() throw () {}
00419
00420 virtual const char* type() const throw () { return "File"; }
00421
00422 virtual std::string desc() const throw () { return m_name + ": " + System::desc(); }
00423 };
00424
00425 }
00426 }
00427
00428
00429 #endif