//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 defined(__GNUC__) && !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 #ifdef BOOST_NO_EXCEPTIONS #error This header requires exception handling to be enabled. #endif #include #include #include #include #include #include #include #include #include #include namespace boost { class exception_ptr; BOOST_ATTRIBUTE_NORETURN void rethrow_exception( exception_ptr const & ); exception_ptr current_exception(); class exception_ptr { typedef boost::shared_ptr 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 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 original_exception_type; inline std::string to_string( original_exception_type const & x ) { return 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 exception_ptr get_static_exception_object() { Exception ba; exception_detail::clone_impl c(ba); c << throw_function(BOOST_CURRENT_FUNCTION) << throw_file(__FILE__) << throw_line(__LINE__); static exception_ptr ep(shared_ptr(new exception_detail::clone_impl(c))); return ep; } template struct exception_ptr_static_exception_object { static exception_ptr const e; }; template exception_ptr const exception_ptr_static_exception_object:: e = get_static_exception_object(); } #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 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 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 void add_original_type( E const & e ) { #ifndef BOOST_NO_RTTI (*this) << original_exception_type(&typeid(e)); #endif } }; #ifdef BOOST_NO_RTTI template boost::exception const * get_boost_exception( T const * ) { try { throw; } catch( boost::exception & x ) { return &x; } catch(...) { return 0; } } #else template boost::exception const * get_boost_exception( T const * x ) { return dynamic_cast(x); } #endif template 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(e1,*e2)); else return boost::copy_exception(current_exception_std_exception_wrapper(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(e)); } case exception_detail::clone_current_exception_result:: bad_alloc: { BOOST_ASSERT(!e); return exception_detail::exception_ptr_static_exception_object::e; } case exception_detail::clone_current_exception_result:: bad_exception: { BOOST_ASSERT(!e); return exception_detail::exception_ptr_static_exception_object::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(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::e; } catch( ... ) { ret=exception_detail::exception_ptr_static_exception_object::e; } BOOST_ASSERT(ret); return ret; } BOOST_ATTRIBUTE_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 ) { if( p ) try { rethrow_exception(p); } catch( ... ) { return current_exception_diagnostic_information(); } return ""; } 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