| //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 <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/shared_ptr.hpp> |
| #include <stdexcept> |
| #include <new> |
| #include <ios> |
| |
| namespace |
| boost |
| { |
| typedef shared_ptr<exception_detail::clone_base const> exception_ptr; |
| |
| exception_ptr current_exception(); |
| |
| 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 x.value()->name(); |
| } |
| #endif |
| |
| namespace |
| exception_detail |
| { |
| struct |
| bad_alloc_: |
| boost::exception, |
| std::bad_alloc |
| { |
| }; |
| |
| template <int Dummy> |
| exception_ptr |
| get_bad_alloc() |
| { |
| bad_alloc_ ba; |
| exception_detail::clone_impl<bad_alloc_> c(ba); |
| c << |
| throw_function(BOOST_CURRENT_FUNCTION) << |
| throw_file(__FILE__) << |
| throw_line(__LINE__); |
| static exception_ptr ep(new exception_detail::clone_impl<bad_alloc_>(c)); |
| return ep; |
| } |
| |
| template <int Dummy> |
| struct |
| exception_ptr_bad_alloc |
| { |
| static exception_ptr const e; |
| }; |
| |
| template <int Dummy> |
| exception_ptr const |
| exception_ptr_bad_alloc<Dummy>:: |
| e = get_bad_alloc<Dummy>(); |
| } |
| |
| 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 |
| } |
| }; |
| |
| 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() |
| { |
| try |
| { |
| throw; |
| } |
| catch( |
| exception_detail::clone_base & e ) |
| { |
| return exception_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; |
| BOOST_ASSERT(!ret); |
| try |
| { |
| ret=exception_detail::current_exception_impl(); |
| } |
| catch( |
| std::bad_alloc & ) |
| { |
| ret=exception_detail::exception_ptr_bad_alloc<42>::e; |
| } |
| catch( |
| ... ) |
| { |
| try |
| { |
| ret=exception_detail::current_exception_std_exception(std::bad_exception()); |
| } |
| catch( |
| std::bad_alloc & ) |
| { |
| ret=exception_detail::exception_ptr_bad_alloc<42>::e; |
| } |
| catch( |
| ... ) |
| { |
| BOOST_ASSERT(0); |
| } |
| } |
| BOOST_ASSERT(ret); |
| return ret; |
| } |
| |
| inline |
| void |
| rethrow_exception( exception_ptr const & p ) |
| { |
| BOOST_ASSERT(p); |
| p->rethrow(); |
| } |
| |
| inline |
| std::string |
| diagnostic_information( exception_ptr const & p ) |
| { |
| if( p ) |
| try |
| { |
| rethrow_exception(p); |
| } |
| catch( |
| ... ) |
| { |
| return current_exception_diagnostic_information(); |
| } |
| 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 |