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 <vector>
00030
00078 namespace wibble {
00079 namespace exception {
00080
00082
00090 void DefaultUnexpected();
00091
00094 class InstallUnexpected
00095 {
00096 protected:
00097 void (*old)();
00098 public:
00099 InstallUnexpected(void (*func)() = DefaultUnexpected);
00100 ~InstallUnexpected();
00101 };
00102
00103
00104 struct AddContext {
00105 static std::vector< std::string > s_context;
00106
00107 template< typename O >
00108 static void copyContext( O out ) {
00109 std::copy( s_context.begin(), s_context.end(), out );
00110 }
00111
00112 std::string m_context;
00113
00114 AddContext( std::string s )
00115 : m_context( s )
00116 {
00117 s_context.push_back( s );
00118 }
00119
00120 ~AddContext() {
00121 assert_eq( s_context.back(), m_context );
00122 s_context.pop_back();
00123 }
00124 };
00125
00127 class Context
00128 {
00129 protected:
00130 std::vector<std::string> m_context;
00131
00132 public:
00133 Context() throw ()
00134 {
00135 AddContext::copyContext( std::back_inserter( m_context ) );
00136 }
00137
00138 Context(const std::string& context) throw ()
00139 {
00140 AddContext::copyContext( std::back_inserter( m_context ) );
00141 addContext(context);
00142 }
00143
00144 void addContext(const std::string& c) throw () { m_context.push_back(c); }
00145 std::string formatContext() const throw ()
00146 {
00147 if (m_context.empty())
00148 return "no context information available";
00149
00150 std::string res;
00151 for (std::vector<std::string>::const_iterator i = m_context.begin();
00152 i != m_context.end(); i++)
00153 if (i == m_context.begin())
00154 res = *i;
00155 else
00156 res += ", " + *i;
00157 return res;
00158 }
00159
00160 const std::vector<std::string>& context() const throw ()
00161 {
00162 return m_context;
00163 }
00164 };
00165
00167
00173 class Generic : public std::exception, public Context
00174 {
00175 protected:
00176 mutable std::string m_formatted;
00177
00178 public:
00179 Generic() throw () {}
00180 Generic(const std::string& context) throw () : Context(context) {}
00181 virtual ~Generic() throw () {}
00182
00184 virtual const char* type() const throw () { return "Generic"; }
00185
00187 virtual std::string desc() const throw ()
00188 {
00189 return "an unspecified problem happened; if you see this message, please report a bug to the maintainer";
00190 }
00191
00199 virtual const std::string& fullInfo() const throw ()
00200 {
00201 if (m_formatted.empty())
00202 m_formatted = desc() + ". Context: " + formatContext();
00203 return m_formatted;
00204 }
00205
00206 virtual const char* what() const throw () { return fullInfo().c_str(); }
00207 };
00208
00211
00217 class Interrupted : public Generic
00218 {
00219 public:
00220 Interrupted() throw () {}
00221 Interrupted(const std::string& context) throw () : Generic(context) {}
00222
00223 virtual const char* type() const throw () { return "Interrupted"; }
00224 };
00225
00227
00234 class WaitInterrupted : public Interrupted
00235 {
00236 public:
00237 WaitInterrupted(const std::string& context) throw () :
00238 Interrupted(context) {}
00239
00240 virtual const char* type() const throw () { return "WaitInterrupted"; }
00241 };
00242
00244
00247 class Consistency : public Generic
00248 {
00249 std::string m_error;
00250
00251 public:
00252 Consistency(const std::string& context, const std::string& error = std::string()) throw () :
00253 Generic(context), m_error(error) {}
00254 ~Consistency() throw () {}
00255
00256 virtual const char* type() const throw () { return "Consistency"; }
00257
00258 virtual std::string desc() const throw ()
00259 {
00260 if (m_error.empty())
00261 return "consistency check failed";
00262 return m_error;
00263 }
00264 };
00265
00266 struct BadCast : public Consistency
00267 {
00268 BadCast( const std::string &context ) throw()
00269 : Consistency( context )
00270 {}
00271 ~BadCast() throw() {}
00272 virtual std::string typeinfo() const throw() { return "unknown types"; }
00273 virtual std::string desc() const throw() {
00274 return std::string( "bad cast: " ) + typeinfo();
00275 }
00276 };
00277
00278 template< typename From, typename To >
00279 struct BadCastExt : public BadCast
00280 {
00281 BadCastExt( const std::string &error = std::string() ) throw()
00282 : BadCast( error )
00283 {}
00284 ~BadCastExt() throw() {}
00285 virtual std::string typeinfo() const throw() { return std::string( "from " )
00286 + typeid( From ).name()
00287 + " to "
00288 + typeid( To ).name(); }
00289 };
00290
00300 class OutOfRange : public Consistency
00301 {
00302 protected:
00303 std::string m_var_desc;
00304
00305 public:
00306 OutOfRange(const std::string& var_desc, const std::string& context) throw ()
00307 : Consistency(context), m_var_desc(var_desc) {}
00308 ~OutOfRange() throw () {}
00309
00310 virtual const char* type() const throw () { return "OutOfRange"; }
00311
00313 virtual std::string var_desc() const throw () { return m_var_desc; }
00314
00315 virtual std::string desc() const throw () { return m_var_desc + " out of range"; }
00316 };
00317
00319
00334 template <class C>
00335 class ValOutOfRange : public OutOfRange
00336 {
00337 protected:
00338 C m_val;
00339 C m_inf;
00340 C m_sup;
00341
00342 public:
00346 ValOutOfRange(const std::string& var_desc, C val, C inf, C sup,
00347 const std::string& context) throw ()
00348 : OutOfRange(var_desc, context),
00349 m_val(val), m_inf(inf), m_sup(sup) {}
00350
00352
00353
00354 virtual C val() const throw () { return m_val; }
00356 virtual C inf() const throw () { return m_inf; }
00358 virtual C sup() const throw () { return m_sup; }
00360
00361 virtual const char* type() const throw ()
00362 {
00363 return "ValOutOfRange<>";
00364 }
00365
00366 virtual std::string desc() const throw ();
00367 };
00368
00370
00387 class System : public Generic
00388 {
00389 protected:
00390 int m_errno;
00391
00392 public:
00393 System(const std::string& context) throw ();
00394 System(int code, const std::string& context) throw ();
00395
00396 virtual const char* type() const throw () { return "System"; }
00397
00399 virtual int code() const throw () { return m_errno; }
00400
00402 virtual std::string desc() const throw ();
00403 };
00404
00406
00411 class File : public System
00412 {
00413 protected:
00414 std::string m_name;
00415
00416 public:
00417 File(const std::string& name, const std::string& context) throw () :
00418 System(context), m_name(name) {}
00419 ~File() throw () {}
00420
00421 virtual const char* type() const throw () { return "File"; }
00422
00423 virtual std::string desc() const throw () { return m_name + ": " + System::desc(); }
00424 };
00425
00426 }
00427 }
00428
00429
00430 #endif