514 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			514 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
|   | //Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc. | ||
|  | 
 | ||
|  | //Distributed under the Boost Software License, Version 1.0. (See accompanying | ||
|  | //file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||
|  | 
 | ||
|  | #ifndef UUID_618474C2DE1511DEB74A388C56D89593 | ||
|  | #define UUID_618474C2DE1511DEB74A388C56D89593 | ||
|  | #if (__GNUC__*100+__GNUC_MINOR__>301) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) | ||
|  | #pragma GCC system_header | ||
|  | #endif | ||
|  | #if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) | ||
|  | #pragma warning(push,1) | ||
|  | #endif | ||
|  | 
 | ||
|  | #include <boost/config.hpp> | ||
|  | #ifdef BOOST_NO_EXCEPTIONS | ||
|  | #error This header requires exception handling to be enabled. | ||
|  | #endif | ||
|  | #include <boost/exception/exception.hpp> | ||
|  | #include <boost/exception/info.hpp> | ||
|  | #include <boost/exception/diagnostic_information.hpp> | ||
|  | #include <boost/exception/detail/type_info.hpp> | ||
|  | #include <boost/exception/detail/clone_current_exception.hpp> | ||
|  | #ifndef BOOST_NO_RTTI | ||
|  | #include <boost/core/demangle.hpp> | ||
|  | #endif | ||
|  | #include <boost/shared_ptr.hpp> | ||
|  | #include <stdexcept> | ||
|  | #include <new> | ||
|  | #include <ios> | ||
|  | #include <stdlib.h> | ||
|  | 
 | ||
|  | namespace | ||
|  | boost | ||
|  |     { | ||
|  |     class exception_ptr; | ||
|  |     BOOST_NORETURN void rethrow_exception( exception_ptr const & ); | ||
|  |     exception_ptr current_exception(); | ||
|  | 
 | ||
|  |     class | ||
|  |     exception_ptr | ||
|  |         { | ||
|  |         typedef boost::shared_ptr<exception_detail::clone_base const> impl; | ||
|  |         impl ptr_; | ||
|  |         friend void rethrow_exception( exception_ptr const & ); | ||
|  |         typedef exception_detail::clone_base const * (impl::*unspecified_bool_type)() const; | ||
|  |         public: | ||
|  |         exception_ptr() | ||
|  |             { | ||
|  |             } | ||
|  |         explicit | ||
|  |         exception_ptr( impl const & ptr ): | ||
|  |             ptr_(ptr) | ||
|  |             { | ||
|  |             } | ||
|  |         bool | ||
|  |         operator==( exception_ptr const & other ) const | ||
|  |             { | ||
|  |             return ptr_==other.ptr_; | ||
|  |             } | ||
|  |         bool | ||
|  |         operator!=( exception_ptr const & other ) const | ||
|  |             { | ||
|  |             return ptr_!=other.ptr_; | ||
|  |             } | ||
|  |         operator unspecified_bool_type() const | ||
|  |             { | ||
|  |             return ptr_?&impl::get:0; | ||
|  |             } | ||
|  |         }; | ||
|  | 
 | ||
|  |     template <class T> | ||
|  |     inline | ||
|  |     exception_ptr | ||
|  |     copy_exception( T const & e ) | ||
|  |         { | ||
|  |         try | ||
|  |             { | ||
|  |             throw enable_current_exception(e); | ||
|  |             } | ||
|  |         catch( | ||
|  |         ... ) | ||
|  |             { | ||
|  |             return current_exception(); | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  | #ifndef BOOST_NO_RTTI | ||
|  |     typedef error_info<struct tag_original_exception_type,std::type_info const *> original_exception_type; | ||
|  | 
 | ||
|  |     inline | ||
|  |     std::string | ||
|  |     to_string( original_exception_type const & x ) | ||
|  |         { | ||
|  |         return core::demangle(x.value()->name()); | ||
|  |         } | ||
|  | #endif | ||
|  | 
 | ||
|  |     namespace | ||
|  |     exception_detail | ||
|  |         { | ||
|  |         struct | ||
|  |         bad_alloc_: | ||
|  |             boost::exception, | ||
|  |             std::bad_alloc | ||
|  |                 { | ||
|  |                 ~bad_alloc_() throw() { } | ||
|  |                 }; | ||
|  | 
 | ||
|  |         struct | ||
|  |         bad_exception_: | ||
|  |             boost::exception, | ||
|  |             std::bad_exception | ||
|  |                 { | ||
|  |                 ~bad_exception_() throw() { } | ||
|  |                 }; | ||
|  | 
 | ||
|  |         template <class Exception> | ||
|  |         exception_ptr | ||
|  |         get_static_exception_object() | ||
|  |             { | ||
|  |             Exception ba; | ||
|  |             exception_detail::clone_impl<Exception> c(ba); | ||
|  | #ifndef BOOST_EXCEPTION_DISABLE | ||
|  |             c << | ||
|  |                 throw_function(BOOST_CURRENT_FUNCTION) << | ||
|  |                 throw_file(__FILE__) << | ||
|  |                 throw_line(__LINE__); | ||
|  | #endif | ||
|  |             static exception_ptr ep(shared_ptr<exception_detail::clone_base const>(new exception_detail::clone_impl<Exception>(c))); | ||
|  |             return ep; | ||
|  |             } | ||
|  | 
 | ||
|  |         template <class Exception> | ||
|  |         struct | ||
|  |         exception_ptr_static_exception_object | ||
|  |             { | ||
|  |             static exception_ptr const e; | ||
|  |             }; | ||
|  | 
 | ||
|  |         template <class Exception> | ||
|  |         exception_ptr const | ||
|  |         exception_ptr_static_exception_object<Exception>:: | ||
|  |         e = get_static_exception_object<Exception>(); | ||
|  |         } | ||
|  | 
 | ||
|  | #if defined(__GNUC__) | ||
|  | # if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4) | ||
|  | #  pragma GCC visibility push (default) | ||
|  | # endif | ||
|  | #endif | ||
|  |     class | ||
|  |     unknown_exception: | ||
|  |         public boost::exception, | ||
|  |         public std::exception | ||
|  |         { | ||
|  |         public: | ||
|  | 
 | ||
|  |         unknown_exception() | ||
|  |             { | ||
|  |             } | ||
|  | 
 | ||
|  |         explicit | ||
|  |         unknown_exception( std::exception const & e ) | ||
|  |             { | ||
|  |             add_original_type(e); | ||
|  |             } | ||
|  | 
 | ||
|  |         explicit | ||
|  |         unknown_exception( boost::exception const & e ): | ||
|  |             boost::exception(e) | ||
|  |             { | ||
|  |             add_original_type(e); | ||
|  |             } | ||
|  | 
 | ||
|  |         ~unknown_exception() throw() | ||
|  |             { | ||
|  |             } | ||
|  | 
 | ||
|  |         private: | ||
|  | 
 | ||
|  |         template <class E> | ||
|  |         void | ||
|  |         add_original_type( E const & e ) | ||
|  |             { | ||
|  | #ifndef BOOST_NO_RTTI | ||
|  |             (*this) << original_exception_type(&typeid(e)); | ||
|  | #endif | ||
|  |             } | ||
|  |         }; | ||
|  | #if defined(__GNUC__) | ||
|  | # if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4) | ||
|  | #  pragma GCC visibility pop | ||
|  | # endif | ||
|  | #endif | ||
|  | 
 | ||
|  |     namespace | ||
|  |     exception_detail | ||
|  |         { | ||
|  |         template <class T> | ||
|  |         class | ||
|  |         current_exception_std_exception_wrapper: | ||
|  |             public T, | ||
|  |             public boost::exception | ||
|  |             { | ||
|  |             public: | ||
|  | 
 | ||
|  |             explicit | ||
|  |             current_exception_std_exception_wrapper( T const & e1 ): | ||
|  |                 T(e1) | ||
|  |                 { | ||
|  |                 add_original_type(e1); | ||
|  |                 } | ||
|  | 
 | ||
|  |             current_exception_std_exception_wrapper( T const & e1, boost::exception const & e2 ): | ||
|  |                 T(e1), | ||
|  |                 boost::exception(e2) | ||
|  |                 { | ||
|  |                 add_original_type(e1); | ||
|  |                 } | ||
|  | 
 | ||
|  |             ~current_exception_std_exception_wrapper() throw() | ||
|  |                 { | ||
|  |                 } | ||
|  | 
 | ||
|  |             private: | ||
|  | 
 | ||
|  |             template <class E> | ||
|  |             void | ||
|  |             add_original_type( E const & e ) | ||
|  |                 { | ||
|  | #ifndef BOOST_NO_RTTI | ||
|  |                 (*this) << original_exception_type(&typeid(e)); | ||
|  | #endif | ||
|  |                 } | ||
|  |             }; | ||
|  | 
 | ||
|  | #ifdef BOOST_NO_RTTI | ||
|  |         template <class T> | ||
|  |         boost::exception const * | ||
|  |         get_boost_exception( T const * ) | ||
|  |             { | ||
|  |             try | ||
|  |                 { | ||
|  |                 throw; | ||
|  |                 } | ||
|  |             catch( | ||
|  |             boost::exception & x ) | ||
|  |                 { | ||
|  |                 return &x; | ||
|  |                 } | ||
|  |             catch(...) | ||
|  |                 { | ||
|  |                 return 0; | ||
|  |                 } | ||
|  |             } | ||
|  | #else | ||
|  |         template <class T> | ||
|  |         boost::exception const * | ||
|  |         get_boost_exception( T const * x ) | ||
|  |             { | ||
|  |             return dynamic_cast<boost::exception const *>(x); | ||
|  |             } | ||
|  | #endif | ||
|  | 
 | ||
|  |         template <class T> | ||
|  |         inline | ||
|  |         exception_ptr | ||
|  |         current_exception_std_exception( T const & e1 ) | ||
|  |             { | ||
|  |             if( boost::exception const * e2 = get_boost_exception(&e1) ) | ||
|  |                 return boost::copy_exception(current_exception_std_exception_wrapper<T>(e1,*e2)); | ||
|  |             else | ||
|  |                 return boost::copy_exception(current_exception_std_exception_wrapper<T>(e1)); | ||
|  |             } | ||
|  | 
 | ||
|  |         inline | ||
|  |         exception_ptr | ||
|  |         current_exception_unknown_exception() | ||
|  |             { | ||
|  |             return boost::copy_exception(unknown_exception()); | ||
|  |             } | ||
|  | 
 | ||
|  |         inline | ||
|  |         exception_ptr | ||
|  |         current_exception_unknown_boost_exception( boost::exception const & e ) | ||
|  |             { | ||
|  |             return boost::copy_exception(unknown_exception(e)); | ||
|  |             } | ||
|  | 
 | ||
|  |         inline | ||
|  |         exception_ptr | ||
|  |         current_exception_unknown_std_exception( std::exception const & e ) | ||
|  |             { | ||
|  |             if( boost::exception const * be = get_boost_exception(&e) ) | ||
|  |                 return current_exception_unknown_boost_exception(*be); | ||
|  |             else | ||
|  |                 return boost::copy_exception(unknown_exception(e)); | ||
|  |             } | ||
|  | 
 | ||
|  |         inline | ||
|  |         exception_ptr | ||
|  |         current_exception_impl() | ||
|  |             { | ||
|  |             exception_detail::clone_base const * e=0; | ||
|  |             switch( | ||
|  |             exception_detail::clone_current_exception(e) ) | ||
|  |                 { | ||
|  |                 case exception_detail::clone_current_exception_result:: | ||
|  |                 success: | ||
|  |                     { | ||
|  |                     BOOST_ASSERT(e!=0); | ||
|  |                     return exception_ptr(shared_ptr<exception_detail::clone_base const>(e)); | ||
|  |                     } | ||
|  |                 case exception_detail::clone_current_exception_result:: | ||
|  |                 bad_alloc: | ||
|  |                     { | ||
|  |                     BOOST_ASSERT(!e); | ||
|  |                     return exception_detail::exception_ptr_static_exception_object<bad_alloc_>::e; | ||
|  |                     } | ||
|  |                 case exception_detail::clone_current_exception_result:: | ||
|  |                 bad_exception: | ||
|  |                     { | ||
|  |                     BOOST_ASSERT(!e); | ||
|  |                     return exception_detail::exception_ptr_static_exception_object<bad_exception_>::e; | ||
|  |                     } | ||
|  |                 default: | ||
|  |                     BOOST_ASSERT(0); | ||
|  |                 case exception_detail::clone_current_exception_result:: | ||
|  |                 not_supported: | ||
|  |                     { | ||
|  |                     BOOST_ASSERT(!e); | ||
|  |                     try | ||
|  |                         { | ||
|  |                         throw; | ||
|  |                         } | ||
|  |                     catch( | ||
|  |                     exception_detail::clone_base & e ) | ||
|  |                         { | ||
|  |                         return exception_ptr(shared_ptr<exception_detail::clone_base const>(e.clone())); | ||
|  |                         } | ||
|  |                     catch( | ||
|  |                     std::domain_error & e ) | ||
|  |                         { | ||
|  |                         return exception_detail::current_exception_std_exception(e); | ||
|  |                         } | ||
|  |                     catch( | ||
|  |                     std::invalid_argument & e ) | ||
|  |                         { | ||
|  |                         return exception_detail::current_exception_std_exception(e); | ||
|  |                         } | ||
|  |                     catch( | ||
|  |                     std::length_error & e ) | ||
|  |                         { | ||
|  |                         return exception_detail::current_exception_std_exception(e); | ||
|  |                         } | ||
|  |                     catch( | ||
|  |                     std::out_of_range & e ) | ||
|  |                         { | ||
|  |                         return exception_detail::current_exception_std_exception(e); | ||
|  |                         } | ||
|  |                     catch( | ||
|  |                     std::logic_error & e ) | ||
|  |                         { | ||
|  |                         return exception_detail::current_exception_std_exception(e); | ||
|  |                         } | ||
|  |                     catch( | ||
|  |                     std::range_error & e ) | ||
|  |                         { | ||
|  |                         return exception_detail::current_exception_std_exception(e); | ||
|  |                         } | ||
|  |                     catch( | ||
|  |                     std::overflow_error & e ) | ||
|  |                         { | ||
|  |                         return exception_detail::current_exception_std_exception(e); | ||
|  |                         } | ||
|  |                     catch( | ||
|  |                     std::underflow_error & e ) | ||
|  |                         { | ||
|  |                         return exception_detail::current_exception_std_exception(e); | ||
|  |                         } | ||
|  |                     catch( | ||
|  |                     std::ios_base::failure & e ) | ||
|  |                         { | ||
|  |                         return exception_detail::current_exception_std_exception(e); | ||
|  |                         } | ||
|  |                     catch( | ||
|  |                     std::runtime_error & e ) | ||
|  |                         { | ||
|  |                         return exception_detail::current_exception_std_exception(e); | ||
|  |                         } | ||
|  |                     catch( | ||
|  |                     std::bad_alloc & e ) | ||
|  |                         { | ||
|  |                         return exception_detail::current_exception_std_exception(e); | ||
|  |                         } | ||
|  | #ifndef BOOST_NO_TYPEID | ||
|  |                     catch( | ||
|  |                     std::bad_cast & e ) | ||
|  |                         { | ||
|  |                         return exception_detail::current_exception_std_exception(e); | ||
|  |                         } | ||
|  |                     catch( | ||
|  |                     std::bad_typeid & e ) | ||
|  |                         { | ||
|  |                         return exception_detail::current_exception_std_exception(e); | ||
|  |                         } | ||
|  | #endif | ||
|  |                     catch( | ||
|  |                     std::bad_exception & e ) | ||
|  |                         { | ||
|  |                         return exception_detail::current_exception_std_exception(e); | ||
|  |                         } | ||
|  |                     catch( | ||
|  |                     std::exception & e ) | ||
|  |                         { | ||
|  |                         return exception_detail::current_exception_unknown_std_exception(e); | ||
|  |                         } | ||
|  |                     catch( | ||
|  |                     boost::exception & e ) | ||
|  |                         { | ||
|  |                         return exception_detail::current_exception_unknown_boost_exception(e); | ||
|  |                         } | ||
|  |                     catch( | ||
|  |                     ... ) | ||
|  |                         { | ||
|  |                         return exception_detail::current_exception_unknown_exception(); | ||
|  |                         } | ||
|  |                     } | ||
|  |                 } | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  |     inline | ||
|  |     exception_ptr | ||
|  |     current_exception() | ||
|  |         { | ||
|  |         exception_ptr ret; | ||
|  |         try | ||
|  |             { | ||
|  |             ret=exception_detail::current_exception_impl(); | ||
|  |             } | ||
|  |         catch( | ||
|  |         std::bad_alloc & ) | ||
|  |             { | ||
|  |             ret=exception_detail::exception_ptr_static_exception_object<exception_detail::bad_alloc_>::e; | ||
|  |             } | ||
|  |         catch( | ||
|  |         ... ) | ||
|  |             { | ||
|  |             ret=exception_detail::exception_ptr_static_exception_object<exception_detail::bad_exception_>::e; | ||
|  |             } | ||
|  |         BOOST_ASSERT(ret); | ||
|  |         return ret; | ||
|  |         } | ||
|  | 
 | ||
|  |     BOOST_NORETURN | ||
|  |     inline | ||
|  |     void | ||
|  |     rethrow_exception( exception_ptr const & p ) | ||
|  |         { | ||
|  |         BOOST_ASSERT(p); | ||
|  |         p.ptr_->rethrow(); | ||
|  |         BOOST_ASSERT(0); | ||
|  |         #if defined(UNDER_CE) | ||
|  |             // some CE platforms don't define ::abort() | ||
|  |             exit(-1); | ||
|  |         #else | ||
|  |             abort(); | ||
|  |         #endif | ||
|  |         } | ||
|  | 
 | ||
|  |     inline | ||
|  |     std::string | ||
|  |     diagnostic_information( exception_ptr const & p, bool verbose=true ) | ||
|  |         { | ||
|  |         if( p ) | ||
|  |             try | ||
|  |                 { | ||
|  |                 rethrow_exception(p); | ||
|  |                 } | ||
|  |             catch( | ||
|  |             ... ) | ||
|  |                 { | ||
|  |                 return current_exception_diagnostic_information(verbose); | ||
|  |                 } | ||
|  |         return "<empty>"; | ||
|  |         } | ||
|  | 
 | ||
|  |     inline | ||
|  |     std::string | ||
|  |     to_string( exception_ptr const & p ) | ||
|  |         { | ||
|  |         std::string s='\n'+diagnostic_information(p); | ||
|  |         std::string padding("  "); | ||
|  |         std::string r; | ||
|  |         bool f=false; | ||
|  |         for( std::string::const_iterator i=s.begin(),e=s.end(); i!=e; ++i ) | ||
|  |             { | ||
|  |             if( f ) | ||
|  |                 r+=padding; | ||
|  |             char c=*i; | ||
|  |             r+=c; | ||
|  |             f=(c=='\n'); | ||
|  |             } | ||
|  |         return r; | ||
|  |         } | ||
|  |     } | ||
|  | 
 | ||
|  | #if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) | ||
|  | #pragma warning(pop) | ||
|  | #endif | ||
|  | #endif |