//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 |