You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and dots ('.'), can be up to 35 characters long. Letters must be lowercase.
503 lines
14 KiB
503 lines
14 KiB
//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/exception/detail/clone_current_exception.hpp> |
|
#include <boost/shared_ptr.hpp> |
|
#include <stdexcept> |
|
#include <new> |
|
#include <ios> |
|
#include <cstdlib> |
|
|
|
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<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 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); |
|
c << |
|
throw_function(BOOST_CURRENT_FUNCTION) << |
|
throw_file(__FILE__) << |
|
throw_line(__LINE__); |
|
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_ATTRIBUTE_NORETURN |
|
inline |
|
void |
|
rethrow_exception( exception_ptr const & p ) |
|
{ |
|
BOOST_ASSERT(p); |
|
p.ptr_->rethrow(); |
|
BOOST_ASSERT(0); |
|
std::abort(); |
|
} |
|
|
|
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
|
|
|