mirror of
https://github.com/boostorg/exception.git
synced 2025-07-16 05:52:14 +02:00
Boost Exception major refactoring: works with or without RTTI, vastly improved boost::throw_exception integration.
[SVN r48905]
This commit is contained in:
61
include/boost/exception/detail/error_info_impl.hpp
Normal file
61
include/boost/exception/detail/error_info_impl.hpp
Normal file
@ -0,0 +1,61 @@
|
||||
//Copyright (c) 2006-2008 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_CE6983AC753411DDA764247956D89593
|
||||
#define UUID_CE6983AC753411DDA764247956D89593
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace
|
||||
boost
|
||||
{
|
||||
namespace
|
||||
exception_detail
|
||||
{
|
||||
class
|
||||
error_info_base
|
||||
{
|
||||
public:
|
||||
|
||||
virtual char const * tag_typeid_name() const = 0;
|
||||
virtual std::string value_as_string() const = 0;
|
||||
|
||||
protected:
|
||||
|
||||
virtual
|
||||
~error_info_base() throw()
|
||||
{
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
template <class Tag,class T>
|
||||
class
|
||||
error_info:
|
||||
public exception_detail::error_info_base
|
||||
{
|
||||
public:
|
||||
|
||||
typedef T value_type;
|
||||
|
||||
error_info( value_type const & value );
|
||||
~error_info() throw();
|
||||
|
||||
value_type const &
|
||||
value() const
|
||||
{
|
||||
return value_;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
char const * tag_typeid_name() const;
|
||||
std::string value_as_string() const;
|
||||
|
||||
value_type const value_;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@ -6,8 +6,8 @@
|
||||
#ifndef UUID_6F463AC838DF11DDA3E6909F56D89593
|
||||
#define UUID_6F463AC838DF11DDA3E6909F56D89593
|
||||
|
||||
#include <boost/exception/detail/type_info.hpp>
|
||||
#include <iomanip>
|
||||
#include <typeinfo>
|
||||
#include <ios>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
@ -24,7 +24,7 @@ boost
|
||||
object_hex_dump( T const & x, size_t max_size=16 )
|
||||
{
|
||||
std::ostringstream s;
|
||||
s << "type: " << typeid(x).name() << ", size: " << sizeof(T) << ", dump: ";
|
||||
s << "type: " << type_name<T>() << ", size: " << sizeof(T) << ", dump: ";
|
||||
size_t n=sizeof(T)>max_size?max_size:sizeof(T);
|
||||
s.fill('0');
|
||||
s.width(2);
|
||||
|
130
include/boost/exception/detail/type_info.hpp
Normal file
130
include/boost/exception/detail/type_info.hpp
Normal file
@ -0,0 +1,130 @@
|
||||
//Copyright (c) 2006-2008 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_C3E1741C754311DDB2834CCA55D89593
|
||||
#define UUID_C3E1741C754311DDB2834CCA55D89593
|
||||
|
||||
#include <boost/detail/sp_typeinfo.hpp>
|
||||
#include <boost/current_function.hpp>
|
||||
|
||||
namespace
|
||||
boost
|
||||
{
|
||||
template <class T>
|
||||
inline
|
||||
char const *
|
||||
tag_type_name()
|
||||
{
|
||||
#ifdef BOOST_NO_TYPEID
|
||||
return BOOST_CURRENT_FUNCTION;
|
||||
#else
|
||||
return typeid(T*).name();
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline
|
||||
char const *
|
||||
type_name()
|
||||
{
|
||||
#ifdef BOOST_NO_TYPEID
|
||||
return BOOST_CURRENT_FUNCTION;
|
||||
#else
|
||||
return typeid(T).name();
|
||||
#endif
|
||||
}
|
||||
|
||||
namespace
|
||||
exception_detail
|
||||
{
|
||||
#ifdef BOOST_NO_TYPEID
|
||||
struct
|
||||
type_info_
|
||||
{
|
||||
detail::sp_typeinfo type_;
|
||||
char const * name_;
|
||||
|
||||
explicit
|
||||
type_info_( detail::sp_typeinfo type, char const * name ):
|
||||
type_(type),
|
||||
name_(name)
|
||||
{
|
||||
}
|
||||
|
||||
friend
|
||||
bool
|
||||
operator==( type_info_ const & a, type_info_ const & b )
|
||||
{
|
||||
return a.type_==b.type_;
|
||||
}
|
||||
|
||||
friend
|
||||
bool
|
||||
operator<( type_info_ const & a, type_info_ const & b )
|
||||
{
|
||||
return a.type_<b.type_;
|
||||
}
|
||||
|
||||
char const *
|
||||
name() const
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
};
|
||||
#else
|
||||
struct
|
||||
type_info_
|
||||
{
|
||||
detail::sp_typeinfo const * type_;
|
||||
|
||||
explicit
|
||||
type_info_( detail::sp_typeinfo const & type ):
|
||||
type_(&type)
|
||||
{
|
||||
}
|
||||
|
||||
type_info_( detail::sp_typeinfo const & type, char const * ):
|
||||
type_(&type)
|
||||
{
|
||||
}
|
||||
|
||||
friend
|
||||
bool
|
||||
operator==( type_info_ const & a, type_info_ const & b )
|
||||
{
|
||||
return (*a.type_)==(*b.type_);
|
||||
}
|
||||
|
||||
friend
|
||||
bool
|
||||
operator<( type_info_ const & a, type_info_ const & b )
|
||||
{
|
||||
return 0!=(a.type_->before(*b.type_));
|
||||
}
|
||||
|
||||
char const *
|
||||
name() const
|
||||
{
|
||||
return type_->name();
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
inline
|
||||
bool
|
||||
operator!=( type_info_ const & a, type_info_ const & b )
|
||||
{
|
||||
return !(a==b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define BOOST_EXCEPTION_STATIC_TYPEID(T) ::boost::exception_detail::type_info_(BOOST_SP_TYPEID(T),::boost::tag_type_name<T>())
|
||||
|
||||
#ifndef BOOST_NO_RTTI
|
||||
#define BOOST_EXCEPTION_DYNAMIC_TYPEID(x) ::boost::exception_detail::type_info_(typeid(x))
|
||||
#endif
|
||||
|
||||
#endif
|
@ -6,21 +6,58 @@
|
||||
#ifndef UUID_0552D49838DD11DD90146B8956D89593
|
||||
#define UUID_0552D49838DD11DD90146B8956D89593
|
||||
|
||||
#include <boost/exception/exception.hpp>
|
||||
#include <boost/exception/get_error_info.hpp>
|
||||
#include <exception>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
namespace
|
||||
boost
|
||||
{
|
||||
namespace
|
||||
exception_detail
|
||||
{
|
||||
inline
|
||||
char const *
|
||||
get_diagnostic_information( exception const & x )
|
||||
{
|
||||
if( error_info_container * c=x.data_.get() )
|
||||
try
|
||||
{
|
||||
return c->diagnostic_information();
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
std::string
|
||||
diagnostic_information( std::exception const & x )
|
||||
diagnostic_information( exception const & x )
|
||||
{
|
||||
if( exception const * be = dynamic_cast<exception const *>(&x) )
|
||||
return be->diagnostic_information();
|
||||
std::ostringstream tmp;
|
||||
if( boost::shared_ptr<char const * const> f=get_error_info<throw_file>(x) )
|
||||
{
|
||||
tmp << *f;
|
||||
if( boost::shared_ptr<int const> l=get_error_info<throw_line>(x) )
|
||||
tmp << '(' << *l << "): ";
|
||||
}
|
||||
tmp << "Throw in function ";
|
||||
if( boost::shared_ptr<char const * const> fn=get_error_info<throw_function>(x) )
|
||||
tmp << *fn;
|
||||
else
|
||||
return std::string("[ what: ") + x.what() + ", type: " + typeid(x).name() + " ]";
|
||||
tmp << "(unknown)";
|
||||
#ifndef BOOST_NO_RTTI
|
||||
tmp << "\nDynamic exception type: " << BOOST_EXCEPTION_DYNAMIC_TYPEID(x).name();
|
||||
if( std::exception const * e=dynamic_cast<std::exception const *>(&x) )
|
||||
tmp << "\nstd::exception::what: " << e->what();
|
||||
#endif
|
||||
if( char const * s=exception_detail::get_diagnostic_information(x) )
|
||||
if( *s )
|
||||
tmp << '\n' << s;
|
||||
return tmp.str();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,154 +3,4 @@
|
||||
//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_78CC85B2914F11DC8F47B48E55D89593
|
||||
#define UUID_78CC85B2914F11DC8F47B48E55D89593
|
||||
|
||||
#include <boost/exception/exception.hpp>
|
||||
#include <boost/exception/detail/cloning_base.hpp>
|
||||
#include <boost/detail/atomic_count.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <new>
|
||||
|
||||
namespace
|
||||
boost
|
||||
{
|
||||
namespace
|
||||
exception_detail
|
||||
{
|
||||
class
|
||||
clone_base:
|
||||
public counted_base
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void rethrow() const=0;
|
||||
};
|
||||
|
||||
struct
|
||||
bad_alloc_impl:
|
||||
public clone_base,
|
||||
public std::bad_alloc
|
||||
{
|
||||
void
|
||||
add_ref() const
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
release() const
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
rethrow() const
|
||||
{
|
||||
throw *this;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
clone_base * make_clone( T const & );
|
||||
|
||||
template <class T>
|
||||
class
|
||||
clone_impl:
|
||||
public T,
|
||||
public cloning_base
|
||||
{
|
||||
public:
|
||||
|
||||
explicit
|
||||
clone_impl( T const & x ):
|
||||
T(x)
|
||||
{
|
||||
if( boost::exception * be1=dynamic_cast<boost::exception *>(this) )
|
||||
if( boost::exception const * be2=dynamic_cast<boost::exception const *>(&x) )
|
||||
*be1 = *be2;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
clone_base const *
|
||||
clone() const
|
||||
{
|
||||
return make_clone<T>(*this);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class
|
||||
exception_clone:
|
||||
public T,
|
||||
public clone_base
|
||||
{
|
||||
public:
|
||||
|
||||
explicit
|
||||
exception_clone( T const & x ):
|
||||
T(x),
|
||||
count_(0)
|
||||
{
|
||||
if( boost::exception * be1=dynamic_cast<boost::exception *>(this) )
|
||||
if( boost::exception const * be2=dynamic_cast<boost::exception const *>(&x) )
|
||||
*be1 = *be2;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
detail::atomic_count mutable count_;
|
||||
|
||||
void
|
||||
add_ref() const
|
||||
{
|
||||
++count_;
|
||||
}
|
||||
|
||||
void
|
||||
release() const
|
||||
{
|
||||
if( !--count_ )
|
||||
delete this;
|
||||
}
|
||||
|
||||
void
|
||||
rethrow() const
|
||||
{
|
||||
throw clone_impl<T>(*this);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
inline
|
||||
clone_base *
|
||||
make_clone( T const & x )
|
||||
{
|
||||
try
|
||||
{
|
||||
return new exception_clone<T>(x);
|
||||
}
|
||||
catch(
|
||||
std::bad_alloc & )
|
||||
{
|
||||
static bad_alloc_impl bad_alloc;
|
||||
return &bad_alloc;
|
||||
}
|
||||
catch(
|
||||
... )
|
||||
{
|
||||
BOOST_ASSERT(0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline
|
||||
exception_detail::clone_impl<T>
|
||||
enable_current_exception( T const & x )
|
||||
{
|
||||
return exception_detail::clone_impl<T>(x);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -3,104 +3,4 @@
|
||||
//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_0C5D492E909711DCB658AD4556D89593
|
||||
#define UUID_0C5D492E909711DCB658AD4556D89593
|
||||
|
||||
#include <boost/exception/exception.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <stddef.h>
|
||||
|
||||
namespace
|
||||
boost
|
||||
{
|
||||
namespace
|
||||
exception_detail
|
||||
{
|
||||
template <class T>
|
||||
struct
|
||||
error_info_injector:
|
||||
public T,
|
||||
public exception
|
||||
{
|
||||
explicit
|
||||
error_info_injector( T const & x ):
|
||||
T(x)
|
||||
{
|
||||
}
|
||||
|
||||
~error_info_injector() throw()
|
||||
{
|
||||
}
|
||||
|
||||
char const *
|
||||
diagnostic_information() const throw()
|
||||
{
|
||||
return boost::exception::_diagnostic_information(T::what());
|
||||
}
|
||||
};
|
||||
|
||||
struct large_size { char c[256]; };
|
||||
large_size dispatch( exception * );
|
||||
|
||||
struct small_size { };
|
||||
small_size dispatch( void * );
|
||||
|
||||
template <class,size_t>
|
||||
struct enable_error_info_helper;
|
||||
|
||||
template <class T>
|
||||
struct
|
||||
enable_error_info_helper<T,sizeof(large_size)>
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct
|
||||
enable_error_info_helper<T,sizeof(small_size)>
|
||||
{
|
||||
typedef error_info_injector<T> type;
|
||||
};
|
||||
|
||||
#if BOOST_WORKAROUND(__BORLANDC__,BOOST_TESTED_AT(0x582))
|
||||
template <class T>
|
||||
struct
|
||||
sizeof_dispatch
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(int, value = sizeof(dispatch((T*)0)) );
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct
|
||||
enable_error_info_return_type
|
||||
{
|
||||
typedef typename enable_error_info_helper<T,sizeof_dispatch<T>::value>::type type;
|
||||
};
|
||||
#else
|
||||
template <class T>
|
||||
struct
|
||||
enable_error_info_return_type
|
||||
{
|
||||
typedef typename enable_error_info_helper<T,sizeof(dispatch((T*)0))>::type type;
|
||||
};
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline
|
||||
#if !BOOST_WORKAROUND(__BORLANDC__,BOOST_TESTED_AT(0x582))
|
||||
typename
|
||||
#endif
|
||||
exception_detail::enable_error_info_return_type<T>::type
|
||||
enable_error_info( T const & x )
|
||||
{
|
||||
return
|
||||
#if !BOOST_WORKAROUND(__BORLANDC__,BOOST_TESTED_AT(0x582))
|
||||
typename
|
||||
#endif
|
||||
exception_detail::enable_error_info_return_type<T>::type(x);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -3,14 +3,4 @@
|
||||
//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_0E57632CCA3011DCB876FD9955D89593
|
||||
#define UUID_0E57632CCA3011DCB876FD9955D89593
|
||||
|
||||
namespace
|
||||
boost
|
||||
{
|
||||
template <class Tag,class T>
|
||||
class error_info;
|
||||
}
|
||||
|
||||
#endif
|
||||
namespace boost { template <class Tag,class T> class error_info; }
|
||||
|
@ -6,115 +6,390 @@
|
||||
#ifndef UUID_274DA366004E11DCB1DDFE2E56D89593
|
||||
#define UUID_274DA366004E11DCB1DDFE2E56D89593
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
#include <boost/exception/detail/counted_base.hpp>
|
||||
#include <boost/intrusive_ptr.hpp>
|
||||
#include <typeinfo>
|
||||
|
||||
namespace
|
||||
boost
|
||||
{
|
||||
template <class T>
|
||||
namespace
|
||||
exception_detail
|
||||
{
|
||||
template <class T>
|
||||
class
|
||||
refcount_ptr
|
||||
{
|
||||
public:
|
||||
|
||||
refcount_ptr():
|
||||
px_(0)
|
||||
{
|
||||
}
|
||||
|
||||
~refcount_ptr()
|
||||
{
|
||||
release();
|
||||
}
|
||||
|
||||
refcount_ptr( refcount_ptr const & x ):
|
||||
px_(x.px_)
|
||||
{
|
||||
add_ref();
|
||||
}
|
||||
|
||||
refcount_ptr &
|
||||
operator=( refcount_ptr const & x )
|
||||
{
|
||||
adopt(x.px_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void
|
||||
adopt( T * px )
|
||||
{
|
||||
release();
|
||||
px_=px;
|
||||
add_ref();
|
||||
}
|
||||
|
||||
T *
|
||||
get() const
|
||||
{
|
||||
return px_;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
T * px_;
|
||||
|
||||
void
|
||||
add_ref()
|
||||
{
|
||||
if( px_ )
|
||||
px_->add_ref();
|
||||
}
|
||||
|
||||
void
|
||||
release()
|
||||
{
|
||||
if( px_ )
|
||||
px_->release();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class Tag,class T>
|
||||
class error_info;
|
||||
|
||||
typedef error_info<struct tag_throw_function,char const *> throw_function;
|
||||
typedef error_info<struct tag_throw_file,char const *> throw_file;
|
||||
typedef error_info<struct tag_throw_line,int> throw_line;
|
||||
|
||||
template <>
|
||||
class
|
||||
error_info<tag_throw_function,char const *>
|
||||
{
|
||||
public:
|
||||
typedef char const * value_type;
|
||||
value_type v_;
|
||||
explicit
|
||||
error_info( value_type v ):
|
||||
v_(v)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
class
|
||||
error_info<tag_throw_file,char const *>
|
||||
{
|
||||
public:
|
||||
typedef char const * value_type;
|
||||
value_type v_;
|
||||
explicit
|
||||
error_info( value_type v ):
|
||||
v_(v)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
class
|
||||
error_info<tag_throw_line,int>
|
||||
{
|
||||
public:
|
||||
typedef int value_type;
|
||||
value_type v_;
|
||||
explicit
|
||||
error_info( value_type v ):
|
||||
v_(v)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template <class E,class Tag,class T>
|
||||
E const & operator<<( E const &, error_info<Tag,T> const & );
|
||||
|
||||
class exception;
|
||||
|
||||
template <class>
|
||||
class shared_ptr;
|
||||
|
||||
namespace
|
||||
exception_detail
|
||||
{
|
||||
class error_info_base;
|
||||
struct type_info_;
|
||||
|
||||
struct
|
||||
error_info_container:
|
||||
public exception_detail::counted_base
|
||||
error_info_container
|
||||
{
|
||||
virtual char const * diagnostic_information( char const *, std::type_info const & ) const = 0;
|
||||
virtual shared_ptr<error_info_base const> get( std::type_info const & ) const = 0;
|
||||
virtual void set( shared_ptr<error_info_base const> const & ) = 0;
|
||||
virtual char const * diagnostic_information() const = 0;
|
||||
virtual shared_ptr<error_info_base const> get( type_info_ const & ) const = 0;
|
||||
virtual void set( shared_ptr<error_info_base const> const &, type_info_ const & ) = 0;
|
||||
virtual void add_ref() const = 0;
|
||||
virtual void release() const = 0;
|
||||
|
||||
protected:
|
||||
|
||||
virtual
|
||||
~error_info_container() throw()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template <class>
|
||||
struct get_info;
|
||||
|
||||
template <>
|
||||
struct get_info<throw_function>;
|
||||
|
||||
template <>
|
||||
struct get_info<throw_file>;
|
||||
|
||||
template <>
|
||||
struct get_info<throw_line>;
|
||||
|
||||
char const * get_diagnostic_information( exception const & );
|
||||
}
|
||||
|
||||
template <class Tag,class T>
|
||||
class error_info;
|
||||
|
||||
template <class E,class Tag,class T>
|
||||
E const & operator<<( E const &, error_info<Tag,T> const & );
|
||||
|
||||
template <class ErrorInfo,class E>
|
||||
shared_ptr<typename ErrorInfo::value_type const> get_error_info( E const & );
|
||||
|
||||
class
|
||||
exception
|
||||
{
|
||||
public:
|
||||
|
||||
virtual
|
||||
char const *
|
||||
diagnostic_information() const throw()
|
||||
{
|
||||
return _diagnostic_information(0);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
exception()
|
||||
exception():
|
||||
throw_function_(0),
|
||||
throw_file_(0),
|
||||
throw_line_(-1)
|
||||
{
|
||||
}
|
||||
|
||||
exception( exception const & e ):
|
||||
data_(e.data_)
|
||||
{
|
||||
}
|
||||
|
||||
char const *
|
||||
_diagnostic_information( char const * std_what ) const throw()
|
||||
{
|
||||
if( data_ )
|
||||
try
|
||||
{
|
||||
char const * w = data_->diagnostic_information(std_what,typeid(*this));
|
||||
BOOST_ASSERT(0!=w);
|
||||
return w;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
}
|
||||
return std_what ? std_what : typeid(*this).name();
|
||||
}
|
||||
|
||||
#if BOOST_WORKAROUND( BOOST_MSVC, BOOST_TESTED_AT(1500) )
|
||||
//Force class exception to be abstract.
|
||||
//Otherwise, MSVC bug allows throw exception(), even though the copy constructor is protected.
|
||||
virtual ~exception() throw()=0;
|
||||
#else
|
||||
#if BOOST_WORKAROUND( __GNUC__, BOOST_TESTED_AT(4) )
|
||||
virtual //Disable bogus GCC warning.
|
||||
#endif
|
||||
~exception() throw()
|
||||
#ifdef __HP_aCC
|
||||
//On HP aCC, this protected copy constructor prevents throwing boost::exception.
|
||||
//On all other platforms, the same effect is achieved by the pure virtual destructor.
|
||||
exception( exception const & x ) throw():
|
||||
data_(x.data_),
|
||||
throw_function_(x.throw_function_),
|
||||
throw_file_(x.throw_file_),
|
||||
throw_line_(x.throw_line_)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
virtual ~exception() throw()
|
||||
#ifndef __HP_aCC
|
||||
= 0 //Workaround for HP aCC, =0 incorrectly leads to link errors.
|
||||
#endif
|
||||
;
|
||||
|
||||
private:
|
||||
|
||||
shared_ptr<exception_detail::error_info_base const> get( std::type_info const & ) const;
|
||||
void set( shared_ptr<exception_detail::error_info_base const> const & ) const;
|
||||
template <class E>
|
||||
friend
|
||||
E const &
|
||||
operator<<( E const & x, throw_function const & y )
|
||||
{
|
||||
x.throw_function_=y.v_;
|
||||
return x;
|
||||
}
|
||||
|
||||
template <class E>
|
||||
friend
|
||||
E const &
|
||||
operator<<( E const & x, throw_file const & y )
|
||||
{
|
||||
x.throw_file_=y.v_;
|
||||
return x;
|
||||
}
|
||||
|
||||
template <class E>
|
||||
friend
|
||||
E const &
|
||||
operator<<( E const & x, throw_line const & y )
|
||||
{
|
||||
x.throw_line_=y.v_;
|
||||
return x;
|
||||
}
|
||||
|
||||
friend char const * exception_detail::get_diagnostic_information( exception const & );
|
||||
|
||||
template <class E,class Tag,class T>
|
||||
friend E const & operator<<( E const &, error_info<Tag,T> const & );
|
||||
|
||||
template <class ErrorInfo,class E>
|
||||
friend shared_ptr<typename ErrorInfo::value_type const> get_error_info( E const & );
|
||||
template <class>
|
||||
friend struct exception_detail::get_info;
|
||||
friend struct exception_detail::get_info<throw_function>;
|
||||
friend struct exception_detail::get_info<throw_file>;
|
||||
friend struct exception_detail::get_info<throw_line>;
|
||||
|
||||
intrusive_ptr<exception_detail::error_info_container> mutable data_;
|
||||
mutable exception_detail::refcount_ptr<exception_detail::error_info_container> data_;
|
||||
mutable char const * throw_function_;
|
||||
mutable char const * throw_file_;
|
||||
mutable int throw_line_;
|
||||
};
|
||||
|
||||
#if BOOST_WORKAROUND( BOOST_MSVC, BOOST_TESTED_AT(1500) ) //See above.
|
||||
inline
|
||||
exception::
|
||||
~exception() throw()
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace
|
||||
exception_detail
|
||||
{
|
||||
template <class T>
|
||||
struct
|
||||
error_info_injector:
|
||||
public T,
|
||||
public exception
|
||||
{
|
||||
explicit
|
||||
error_info_injector( T const & x ):
|
||||
T(x)
|
||||
{
|
||||
}
|
||||
|
||||
~error_info_injector() throw()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct large_size { char c[256]; };
|
||||
large_size dispatch( exception * );
|
||||
|
||||
struct small_size { };
|
||||
small_size dispatch( void * );
|
||||
|
||||
template <class,int>
|
||||
struct enable_error_info_helper;
|
||||
|
||||
template <class T>
|
||||
struct
|
||||
enable_error_info_helper<T,sizeof(large_size)>
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct
|
||||
enable_error_info_helper<T,sizeof(small_size)>
|
||||
{
|
||||
typedef error_info_injector<T> type;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct
|
||||
enable_error_info_return_type
|
||||
{
|
||||
typedef typename enable_error_info_helper<T,sizeof(dispatch((T*)0))>::type type;
|
||||
};
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline
|
||||
typename
|
||||
exception_detail::enable_error_info_return_type<T>::type
|
||||
enable_error_info( T const & x )
|
||||
{
|
||||
return typename exception_detail::enable_error_info_return_type<T>::type(x);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace
|
||||
exception_detail
|
||||
{
|
||||
class
|
||||
clone_base
|
||||
{
|
||||
public:
|
||||
|
||||
virtual clone_base const * clone() const = 0;
|
||||
virtual void rethrow() const = 0;
|
||||
|
||||
virtual
|
||||
~clone_base() throw()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
inline
|
||||
void
|
||||
copy_boost_exception( exception * a, exception const * b )
|
||||
{
|
||||
*a = *b;
|
||||
}
|
||||
|
||||
inline
|
||||
void
|
||||
copy_boost_exception( void *, void const * )
|
||||
{
|
||||
}
|
||||
|
||||
template <class T>
|
||||
class
|
||||
clone_impl:
|
||||
public T,
|
||||
public clone_base
|
||||
{
|
||||
public:
|
||||
|
||||
explicit
|
||||
clone_impl( T const & x ):
|
||||
T(x)
|
||||
{
|
||||
copy_boost_exception(this,&x);
|
||||
}
|
||||
|
||||
~clone_impl() throw()
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
clone_base const *
|
||||
clone() const
|
||||
{
|
||||
return new clone_impl(*this);
|
||||
}
|
||||
|
||||
void
|
||||
rethrow() const
|
||||
{
|
||||
throw*this;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline
|
||||
exception_detail::clone_impl<T>
|
||||
enable_current_exception( T const & x )
|
||||
{
|
||||
return exception_detail::clone_impl<T>(x);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
145
include/boost/exception/get_error_info.hpp
Normal file
145
include/boost/exception/get_error_info.hpp
Normal file
@ -0,0 +1,145 @@
|
||||
//Copyright (c) 2006-2008 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_1A590226753311DD9E4CCF6156D89593
|
||||
#define UUID_1A590226753311DD9E4CCF6156D89593
|
||||
|
||||
#include <boost/exception/exception.hpp>
|
||||
#include <boost/exception/detail/error_info_impl.hpp>
|
||||
#include <boost/exception/detail/type_info.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <string.h>
|
||||
|
||||
namespace
|
||||
boost
|
||||
{
|
||||
namespace
|
||||
exception_detail
|
||||
{
|
||||
struct
|
||||
strwrap
|
||||
{
|
||||
char const * str;
|
||||
strwrap( char const * s ):
|
||||
str(init(s))
|
||||
{
|
||||
}
|
||||
~strwrap()
|
||||
{
|
||||
delete[] str;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
strwrap( strwrap const & );
|
||||
strwrap & operator=( strwrap const & );
|
||||
|
||||
static
|
||||
char const *
|
||||
init( char const * s )
|
||||
{
|
||||
size_t n=1+strlen(s);
|
||||
char * str = new char[n];
|
||||
(void) memcpy(str,s,n);
|
||||
return str;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct
|
||||
get_info<throw_function>
|
||||
{
|
||||
static
|
||||
shared_ptr<char const * const>
|
||||
get( exception const & x )
|
||||
{
|
||||
if( x.throw_function_ )
|
||||
{
|
||||
shared_ptr<strwrap> s(new strwrap(x.throw_function_));
|
||||
return shared_ptr<char const *>(s,&s->str);
|
||||
}
|
||||
else
|
||||
return shared_ptr<char const * const>();
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct
|
||||
get_info<throw_file>
|
||||
{
|
||||
static
|
||||
shared_ptr<char const * const>
|
||||
get( exception const & x )
|
||||
{
|
||||
if( x.throw_file_ )
|
||||
{
|
||||
shared_ptr<strwrap> s(new strwrap(x.throw_file_));
|
||||
return shared_ptr<char const *>(s,&s->str);
|
||||
}
|
||||
else
|
||||
return shared_ptr<char const * const>();
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct
|
||||
get_info<throw_line>
|
||||
{
|
||||
static
|
||||
shared_ptr<int const>
|
||||
get( exception const & x )
|
||||
{
|
||||
if( x.throw_line_!=-1 )
|
||||
return boost::shared_ptr<int>(new int(x.throw_line_));
|
||||
else
|
||||
return shared_ptr<int const>();
|
||||
}
|
||||
};
|
||||
|
||||
template <class ErrorInfo>
|
||||
struct
|
||||
get_info
|
||||
{
|
||||
static
|
||||
shared_ptr<typename ErrorInfo::value_type const>
|
||||
get( exception const & x )
|
||||
{
|
||||
if( exception_detail::error_info_container * c=x.data_.get() )
|
||||
if( shared_ptr<exception_detail::error_info_base const> eib = c->get(BOOST_EXCEPTION_STATIC_TYPEID(ErrorInfo)) )
|
||||
{
|
||||
#ifndef BOOST_NO_RTTI
|
||||
BOOST_ASSERT( 0!=dynamic_cast<ErrorInfo const *>(eib.get()) );
|
||||
#endif
|
||||
ErrorInfo const * w = static_cast<ErrorInfo const *>(eib.get());
|
||||
return shared_ptr<typename ErrorInfo::value_type const>(eib,&w->value());
|
||||
}
|
||||
return shared_ptr<typename ErrorInfo::value_type const>();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#ifdef BOOST_NO_RTTI
|
||||
template <class ErrorInfo>
|
||||
inline
|
||||
shared_ptr<typename ErrorInfo::value_type const>
|
||||
get_error_info( boost::exception const & x )
|
||||
{
|
||||
return exception_detail::get_info<ErrorInfo>::get(x);
|
||||
}
|
||||
#else
|
||||
template <class ErrorInfo,class E>
|
||||
inline
|
||||
shared_ptr<typename ErrorInfo::value_type const>
|
||||
get_error_info( E const & some_exception )
|
||||
{
|
||||
if( exception const * x = dynamic_cast<exception const *>(&some_exception) )
|
||||
return exception_detail::get_info<ErrorInfo>::get(*x);
|
||||
else
|
||||
return shared_ptr<typename ErrorInfo::value_type const>();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
@ -6,108 +6,46 @@
|
||||
#ifndef UUID_8D22C4CA9CC811DCAA9133D256D89593
|
||||
#define UUID_8D22C4CA9CC811DCAA9133D256D89593
|
||||
|
||||
#include <boost/type.hpp>
|
||||
#include <boost/exception/exception.hpp>
|
||||
#include <boost/exception/error_info.hpp>
|
||||
#include <boost/exception/to_string_stub.hpp>
|
||||
#include <boost/current_function.hpp>
|
||||
#include <boost/exception/detail/error_info_impl.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <map>
|
||||
|
||||
#define BOOST_ERROR_INFO\
|
||||
::boost::throw_function(BOOST_CURRENT_FUNCTION) <<\
|
||||
::boost::throw_file(__FILE__) <<\
|
||||
::boost::throw_line((int)__LINE__)
|
||||
|
||||
namespace
|
||||
boost
|
||||
{
|
||||
typedef error_info<struct tag_throw_function,char const *> throw_function;
|
||||
typedef error_info<struct tag_throw_file,char const *> throw_file;
|
||||
typedef error_info<struct tag_throw_line,int> throw_line;
|
||||
|
||||
namespace
|
||||
exception_detail
|
||||
template <class Tag,class T>
|
||||
inline
|
||||
error_info<Tag,T>::
|
||||
error_info( value_type const & value ):
|
||||
value_(value)
|
||||
{
|
||||
class
|
||||
error_info_base
|
||||
{
|
||||
public:
|
||||
|
||||
virtual std::type_info const & tag_typeid() const = 0;
|
||||
virtual std::string value_as_string() const = 0;
|
||||
|
||||
protected:
|
||||
|
||||
#if BOOST_WORKAROUND( __GNUC__, BOOST_TESTED_AT(4) )
|
||||
virtual //Disable bogus GCC warning.
|
||||
#endif
|
||||
~error_info_base()
|
||||
{
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
template <class Tag,class T>
|
||||
class
|
||||
error_info:
|
||||
public exception_detail::error_info_base
|
||||
{
|
||||
public:
|
||||
|
||||
typedef T value_type;
|
||||
|
||||
error_info( value_type const & value ):
|
||||
value_(value)
|
||||
{
|
||||
}
|
||||
|
||||
value_type const &
|
||||
value() const
|
||||
{
|
||||
return value_;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
std::type_info const &
|
||||
tag_typeid() const
|
||||
{
|
||||
return typeid(type<Tag>);
|
||||
}
|
||||
|
||||
std::string
|
||||
value_as_string() const
|
||||
{
|
||||
return to_string_stub(value_);
|
||||
}
|
||||
|
||||
value_type const value_;
|
||||
};
|
||||
|
||||
template <class E,class Tag,class T>
|
||||
inline
|
||||
E const &
|
||||
operator<<( E const & x, error_info<Tag,T> const & v )
|
||||
error_info<Tag,T>::
|
||||
~error_info() throw()
|
||||
{
|
||||
shared_ptr< error_info<Tag,T> > p( new error_info<Tag,T>(v) );
|
||||
x.set(p);
|
||||
return x;
|
||||
}
|
||||
|
||||
template <class ErrorInfo,class E>
|
||||
template <class Tag,class T>
|
||||
inline
|
||||
shared_ptr<typename ErrorInfo::value_type const>
|
||||
get_error_info( E const & some_exception )
|
||||
char const *
|
||||
error_info<Tag,T>::
|
||||
tag_typeid_name() const
|
||||
{
|
||||
if( exception const * x = dynamic_cast<exception const *>(&some_exception) )
|
||||
if( shared_ptr<exception_detail::error_info_base const> eib = x->get(typeid(ErrorInfo)) )
|
||||
{
|
||||
BOOST_ASSERT( 0!=dynamic_cast<ErrorInfo const *>(eib.get()) );
|
||||
ErrorInfo const * w = static_cast<ErrorInfo const *>(eib.get());
|
||||
return shared_ptr<typename ErrorInfo::value_type const>(eib,&w->value());
|
||||
}
|
||||
return shared_ptr<typename ErrorInfo::value_type const>();
|
||||
return tag_type_name<Tag>();
|
||||
}
|
||||
|
||||
template <class Tag,class T>
|
||||
inline
|
||||
std::string
|
||||
error_info<Tag,T>::
|
||||
value_as_string() const
|
||||
{
|
||||
return to_string_stub(value_);
|
||||
}
|
||||
|
||||
namespace
|
||||
@ -128,81 +66,57 @@ virtual //Disable bogus GCC warning.
|
||||
{
|
||||
}
|
||||
|
||||
shared_ptr<error_info_base const>
|
||||
get( std::type_info const & ti ) const
|
||||
void
|
||||
set( shared_ptr<error_info_base const> const & x, type_info_ const & typeid_ )
|
||||
{
|
||||
error_info_map::const_iterator i=info_.find(typeinfo(ti));
|
||||
BOOST_ASSERT(x);
|
||||
info_[typeid_] = x;
|
||||
diagnostic_info_str_.clear();
|
||||
}
|
||||
|
||||
shared_ptr<error_info_base const>
|
||||
get( type_info_ const & ti ) const
|
||||
{
|
||||
error_info_map::const_iterator i=info_.find(ti);
|
||||
if( info_.end()!=i )
|
||||
{
|
||||
shared_ptr<error_info_base const> const & p = i->second;
|
||||
BOOST_ASSERT( typeid(*p)==ti );
|
||||
#ifndef BOOST_NO_RTTI
|
||||
BOOST_ASSERT( BOOST_EXCEPTION_DYNAMIC_TYPEID(*p)==ti );
|
||||
#endif
|
||||
return p;
|
||||
}
|
||||
return shared_ptr<error_info_base const>();
|
||||
}
|
||||
|
||||
void
|
||||
set( shared_ptr<error_info_base const> const & x )
|
||||
{
|
||||
BOOST_ASSERT(x);
|
||||
info_[typeinfo(typeid(*x))] = x;
|
||||
what_.clear();
|
||||
}
|
||||
|
||||
char const *
|
||||
diagnostic_information( char const * std_what, std::type_info const & exception_type ) const
|
||||
diagnostic_information() const
|
||||
{
|
||||
if( what_.empty() )
|
||||
if( diagnostic_info_str_.empty() )
|
||||
{
|
||||
std::string tmp;
|
||||
if( std_what )
|
||||
{
|
||||
tmp += std_what;
|
||||
tmp += '\n';
|
||||
}
|
||||
tmp += "Dynamic exception type: ";
|
||||
tmp += exception_type.name();
|
||||
tmp += '\n';
|
||||
for( error_info_map::const_iterator i=info_.begin(),end=info_.end(); i!=end; ++i )
|
||||
{
|
||||
shared_ptr<error_info_base const> const & x = i->second;
|
||||
tmp += '[';
|
||||
tmp += x->tag_typeid().name();
|
||||
tmp += x->tag_typeid_name();
|
||||
tmp += "] = ";
|
||||
tmp += x->value_as_string();
|
||||
tmp += '\n';
|
||||
}
|
||||
what_.swap(tmp);
|
||||
diagnostic_info_str_.swap(tmp);
|
||||
}
|
||||
return what_.c_str();
|
||||
return diagnostic_info_str_.c_str();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
friend class exception;
|
||||
friend class boost::exception;
|
||||
|
||||
struct
|
||||
typeinfo
|
||||
{
|
||||
std::type_info const * type;
|
||||
|
||||
explicit
|
||||
typeinfo( std::type_info const & t ):
|
||||
type(&t)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
operator<( typeinfo const & b ) const
|
||||
{
|
||||
return 0!=(type->before(*b.type));
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::map< typeinfo, shared_ptr<error_info_base const> > error_info_map;
|
||||
typedef std::map< type_info_, shared_ptr<error_info_base const> > error_info_map;
|
||||
error_info_map info_;
|
||||
std::string mutable what_;
|
||||
int mutable count_;
|
||||
mutable std::string diagnostic_info_str_;
|
||||
mutable int count_;
|
||||
|
||||
void
|
||||
add_ref() const
|
||||
@ -219,25 +133,18 @@ virtual //Disable bogus GCC warning.
|
||||
};
|
||||
}
|
||||
|
||||
template <class E,class Tag,class T>
|
||||
inline
|
||||
void
|
||||
exception::
|
||||
set( shared_ptr<exception_detail::error_info_base const> const & x ) const
|
||||
E const &
|
||||
operator<<( E const & x, error_info<Tag,T> const & v )
|
||||
{
|
||||
if( !data_ )
|
||||
data_ = intrusive_ptr<exception_detail::error_info_container>(new exception_detail::error_info_container_impl);
|
||||
data_->set(x);
|
||||
}
|
||||
|
||||
inline
|
||||
shared_ptr<exception_detail::error_info_base const>
|
||||
exception::
|
||||
get( std::type_info const & ti ) const
|
||||
{
|
||||
if( data_ )
|
||||
return data_->get(ti);
|
||||
else
|
||||
return shared_ptr<exception_detail::error_info_base const>();
|
||||
typedef error_info<Tag,T> error_info_tag_t;
|
||||
shared_ptr<error_info_tag_t> p( new error_info_tag_t(v) );
|
||||
exception_detail::error_info_container * c;
|
||||
if( !(c=x.data_.get()) )
|
||||
x.data_.adopt(c=new exception_detail::error_info_container_impl);
|
||||
c->set(p,BOOST_EXCEPTION_STATIC_TYPEID(error_info_tag_t));
|
||||
return x;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,19 +6,80 @@
|
||||
#ifndef UUID_FA5836A2CADA11DC8CD47C8555D89593
|
||||
#define UUID_FA5836A2CADA11DC8CD47C8555D89593
|
||||
|
||||
#include <boost/exception/enable_current_exception.hpp>
|
||||
#include <boost/exception/exception.hpp>
|
||||
#include <boost/exception/detail/cloning_base.hpp>
|
||||
#include <boost/exception/detail/type_info.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <stdexcept>
|
||||
#include <new>
|
||||
|
||||
namespace
|
||||
boost
|
||||
{
|
||||
class exception_ptr;
|
||||
exception_ptr current_exception();
|
||||
void rethrow_exception( exception_ptr const & );
|
||||
|
||||
class
|
||||
exception_ptr
|
||||
{
|
||||
typedef bool exception_ptr::*unspecified_bool_type;
|
||||
friend exception_ptr current_exception();
|
||||
friend void rethrow_exception( exception_ptr const & );
|
||||
|
||||
shared_ptr<exception_detail::clone_base const> c_;
|
||||
bool bad_alloc_;
|
||||
|
||||
struct
|
||||
bad_alloc_tag
|
||||
{
|
||||
};
|
||||
|
||||
explicit
|
||||
exception_ptr( bad_alloc_tag ):
|
||||
bad_alloc_(true)
|
||||
{
|
||||
}
|
||||
|
||||
explicit
|
||||
exception_ptr( shared_ptr<exception_detail::clone_base const> const & c ):
|
||||
c_(c),
|
||||
bad_alloc_(false)
|
||||
{
|
||||
BOOST_ASSERT(c);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
exception_ptr():
|
||||
bad_alloc_(false)
|
||||
{
|
||||
}
|
||||
|
||||
operator unspecified_bool_type() const
|
||||
{
|
||||
return (bad_alloc_ || c_) ? &exception_ptr::bad_alloc_ : 0;
|
||||
}
|
||||
|
||||
friend
|
||||
bool
|
||||
operator==( exception_ptr const & a, exception_ptr const & b )
|
||||
{
|
||||
return a.c_==b.c_ && a.bad_alloc_==b.bad_alloc_;
|
||||
}
|
||||
|
||||
friend
|
||||
bool
|
||||
operator!=( exception_ptr const & a, exception_ptr const & b )
|
||||
{
|
||||
return !(a==b);
|
||||
}
|
||||
};
|
||||
|
||||
class
|
||||
unknown_exception:
|
||||
public exception,
|
||||
public std::exception
|
||||
public std::exception,
|
||||
public exception_detail::clone_base
|
||||
{
|
||||
public:
|
||||
|
||||
@ -35,9 +96,21 @@ boost
|
||||
~unknown_exception() throw()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
typedef intrusive_ptr<exception_detail::clone_base const> exception_ptr;
|
||||
private:
|
||||
|
||||
clone_base const *
|
||||
clone() const
|
||||
{
|
||||
return new unknown_exception(*this);
|
||||
}
|
||||
|
||||
void
|
||||
rethrow() const
|
||||
{
|
||||
throw*this;
|
||||
}
|
||||
};
|
||||
|
||||
namespace
|
||||
exception_detail
|
||||
@ -46,7 +119,8 @@ boost
|
||||
class
|
||||
current_exception_std_exception_wrapper:
|
||||
public T,
|
||||
public boost::exception
|
||||
public boost::exception,
|
||||
public clone_base
|
||||
{
|
||||
public:
|
||||
|
||||
@ -65,41 +139,150 @@ boost
|
||||
~current_exception_std_exception_wrapper() throw()
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
clone_base const *
|
||||
clone() const
|
||||
{
|
||||
return new current_exception_std_exception_wrapper(*this);
|
||||
}
|
||||
|
||||
void
|
||||
rethrow() const
|
||||
{
|
||||
throw *this;
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef BOOST_NO_RTTI
|
||||
template <class T>
|
||||
exception const *
|
||||
get_boost_exception( T const * )
|
||||
{
|
||||
try
|
||||
{
|
||||
throw;
|
||||
}
|
||||
catch(
|
||||
exception & x )
|
||||
{
|
||||
return &x;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#else
|
||||
template <class T>
|
||||
exception const *
|
||||
get_boost_exception( T const * x )
|
||||
{
|
||||
return dynamic_cast<exception const *>(x);
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class T>
|
||||
inline
|
||||
exception_ptr
|
||||
shared_ptr<clone_base const>
|
||||
current_exception_std_exception( T const & e1 )
|
||||
{
|
||||
if( boost::exception const * e2 = dynamic_cast<boost::exception const *>(&e1) )
|
||||
return exception_ptr(exception_detail::make_clone(current_exception_std_exception_wrapper<T>(e1,*e2)));
|
||||
if( boost::exception const * e2 = get_boost_exception(&e1) )
|
||||
return shared_ptr<clone_base const>(new current_exception_std_exception_wrapper<T>(e1,*e2));
|
||||
else
|
||||
return exception_ptr(exception_detail::make_clone(current_exception_std_exception_wrapper<T>(e1)));
|
||||
return shared_ptr<clone_base const>(new current_exception_std_exception_wrapper<T>(e1));
|
||||
}
|
||||
|
||||
inline
|
||||
exception_ptr
|
||||
shared_ptr<clone_base const>
|
||||
current_exception_unknown_exception()
|
||||
{
|
||||
return exception_ptr(exception_detail::make_clone(unknown_exception()));
|
||||
return shared_ptr<clone_base const>(new unknown_exception());
|
||||
}
|
||||
|
||||
inline
|
||||
exception_ptr
|
||||
shared_ptr<clone_base const>
|
||||
current_exception_unknown_boost_exception( boost::exception const & e )
|
||||
{
|
||||
return shared_ptr<clone_base const>(new unknown_exception(e));
|
||||
}
|
||||
|
||||
inline
|
||||
shared_ptr<clone_base const>
|
||||
current_exception_unknown_std_exception( std::exception const & e )
|
||||
{
|
||||
if( boost::exception const * be = dynamic_cast<boost::exception const *>(&e) )
|
||||
return exception_ptr(exception_detail::make_clone(unknown_exception(*be)));
|
||||
if( boost::exception const * be = get_boost_exception(&e) )
|
||||
return current_exception_unknown_boost_exception(*be);
|
||||
else
|
||||
return current_exception_unknown_exception();
|
||||
}
|
||||
|
||||
inline
|
||||
exception_ptr
|
||||
current_exception_unknown_boost_exception( boost::exception const & e )
|
||||
shared_ptr<clone_base const>
|
||||
current_exception_impl()
|
||||
{
|
||||
return exception_ptr(exception_detail::make_clone(unknown_exception(e)));
|
||||
try
|
||||
{
|
||||
throw;
|
||||
}
|
||||
catch(
|
||||
exception_detail::clone_base & e )
|
||||
{
|
||||
return shared_ptr<exception_detail::clone_base const>(e.clone());
|
||||
}
|
||||
catch(
|
||||
std::invalid_argument & 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::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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -109,65 +292,30 @@ boost
|
||||
{
|
||||
try
|
||||
{
|
||||
throw;
|
||||
return exception_ptr(exception_detail::current_exception_impl());
|
||||
}
|
||||
catch(
|
||||
exception_detail::cloning_base & e )
|
||||
std::bad_alloc & )
|
||||
{
|
||||
exception_detail::clone_base const * c = e.clone();
|
||||
BOOST_ASSERT(c!=0);
|
||||
return exception_ptr(c);
|
||||
}
|
||||
catch(
|
||||
std::invalid_argument & 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::bad_alloc & e )
|
||||
{
|
||||
return exception_detail::current_exception_std_exception(e);
|
||||
}
|
||||
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);
|
||||
}
|
||||
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();
|
||||
try
|
||||
{
|
||||
return exception_ptr(exception_detail::current_exception_std_exception(std::bad_exception()));
|
||||
}
|
||||
catch(
|
||||
std::bad_alloc & )
|
||||
{
|
||||
}
|
||||
catch(
|
||||
... )
|
||||
{
|
||||
BOOST_ASSERT(0);
|
||||
}
|
||||
}
|
||||
return exception_ptr(exception_ptr::bad_alloc_tag());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
@ -179,7 +327,8 @@ boost
|
||||
{
|
||||
throw enable_current_exception(e);
|
||||
}
|
||||
catch( ... )
|
||||
catch(
|
||||
... )
|
||||
{
|
||||
return current_exception();
|
||||
}
|
||||
@ -189,7 +338,11 @@ boost
|
||||
void
|
||||
rethrow_exception( exception_ptr const & p )
|
||||
{
|
||||
p->rethrow();
|
||||
BOOST_ASSERT(p);
|
||||
if( p.bad_alloc_ )
|
||||
throw enable_current_exception(std::bad_alloc());
|
||||
else
|
||||
p.c_->rethrow();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,11 +24,7 @@
|
||||
#include <boost/detail/workaround.hpp>
|
||||
#include <exception>
|
||||
|
||||
#if !defined( BOOST_EXCEPTION_DISABLE ) && defined( BOOST_NO_TYPEID )
|
||||
# define BOOST_EXCEPTION_DISABLE
|
||||
#endif
|
||||
|
||||
#if !defined( BOOST_EXCEPTION_DISABLE ) && defined( __BORLANDC__ ) && BOOST_WORKAROUND( __BORLANDC__, < 0x590 )
|
||||
#if !defined( BOOST_EXCEPTION_DISABLE ) && defined( __BORLANDC__ ) && BOOST_WORKAROUND( __BORLANDC__, <= 0x593 )
|
||||
# define BOOST_EXCEPTION_DISABLE
|
||||
#endif
|
||||
|
||||
@ -37,8 +33,14 @@
|
||||
#endif
|
||||
|
||||
#if !defined( BOOST_NO_EXCEPTIONS ) && !defined( BOOST_EXCEPTION_DISABLE )
|
||||
# include <boost/exception/enable_current_exception.hpp>
|
||||
# include <boost/exception/enable_error_info.hpp>
|
||||
# include <boost/exception/exception.hpp>
|
||||
# include <boost/current_function.hpp>
|
||||
# define BOOST_THROW_EXCEPTION(x) ::boost::throw_exception(::boost::enable_error_info(x) <<\
|
||||
::boost::throw_function(BOOST_CURRENT_FUNCTION) <<\
|
||||
::boost::throw_file(__FILE__) <<\
|
||||
::boost::throw_line((int)__LINE__))
|
||||
#else
|
||||
# define BOOST_THROW_EXCEPTION(x) ::boost::throw_exception(x)
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
|
Reference in New Issue
Block a user