• Main Page
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

exception.h

Go to the documentation of this file.
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

Generated on Sun Feb 17 2013 02:35:43 for wibble by  doxygen 1.7.1