summaryrefslogtreecommitdiff
path: root/boost/exception/detail/exception_ptr.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/exception/detail/exception_ptr.hpp')
-rw-r--r--boost/exception/detail/exception_ptr.hpp503
1 files changed, 503 insertions, 0 deletions
diff --git a/boost/exception/detail/exception_ptr.hpp b/boost/exception/detail/exception_ptr.hpp
new file mode 100644
index 0000000000..b6ccf7e18c
--- /dev/null
+++ b/boost/exception/detail/exception_ptr.hpp
@@ -0,0 +1,503 @@
+//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