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