wibble 0.1.28
|
00001 // -*- C++ -*- 00002 #ifndef WIBBLE_EXCEPTION_H 00003 #define WIBBLE_EXCEPTION_H 00004 00005 /* 00006 * Generic base exception hierarchy 00007 * 00008 * Copyright (C) 2003,2004,2005,2006 Enrico Zini <enrico@debian.org> 00009 * 00010 * This library is free software; you can redistribute it and/or 00011 * modify it under the terms of the GNU Lesser General Public 00012 * License as published by the Free Software Foundation; either 00013 * version 2.1 of the License, or (at your option) any later version. 00014 * 00015 * This library is distributed in the hope that it will be useful, 00016 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00018 * Lesser General Public License for more details. 00019 * 00020 * You should have received a copy of the GNU Lesser General Public 00021 * License along with this library; if not, write to the Free Software 00022 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00023 */ 00024 00025 #include <wibble/test.h> // for assert 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 // TODO this needs to be made useful with threading as well 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 // vim:set ts=4 sw=4: 00437 #endif