upgrade exception handling to support custom types in 3rd party libraries

This commit is contained in:
Daniel Larimer 2014-06-06 16:42:42 -04:00
parent 0a2a9ec25b
commit d046526974
3 changed files with 228 additions and 299 deletions

View file

@ -6,11 +6,32 @@
#include <fc/log/log_message.hpp>
#include <fc/optional.hpp>
#include <exception>
#include <unordered_map>
namespace fc
{
namespace detail { class exception_impl; }
enum exception_code
{
/** for exceptions we threw that don't have an assigned code */
unspecified_exception_code = 0,
unhandled_exception_code = 1, ///< for unhandled 3rd party exceptions
timeout_exception_code = 2, ///< timeout exceptions
file_not_found_exception_code = 3,
parse_error_exception_code = 4,
invalid_arg_exception_code = 5,
key_not_found_exception_code = 6,
bad_cast_exception_code = 7,
out_of_range_exception_code = 8,
canceled_exception_code = 9,
assert_exception_code = 10,
eof_exception_code = 11,
std_exception_code = 13,
invalid_operation_exception_code = 14
};
/**
* @brief Used to generate a useful error report when an exception is thrown.
* @ingroup serializable
@ -28,13 +49,27 @@ namespace fc
class exception
{
public:
exception();
exception( log_message&& );
enum code_enum
{
code_value = unspecified_exception_code
};
exception( int64_t code = unspecified_exception_code,
const std::string& name_value = "exception",
const std::string& what_value = "unspecified");
exception( log_message&&, int64_t code = unspecified_exception_code,
const std::string& name_value = "exception",
const std::string& what_value = "unspecified");
exception( log_messages&&, int64_t code = unspecified_exception_code,
const std::string& name_value = "exception",
const std::string& what_value = "unspecified");
exception( const exception& e );
exception( exception&& e );
~exception();
virtual const char* what()const throw() { return "exception"; }
const char* name()const throw();
int64_t code()const throw();
virtual const char* what()const throw();
/**
* @return a reference to log messages that have
@ -69,16 +104,14 @@ namespace fc
* catch( ... ) { return std::current_exception(); }
* @endcode
*/
virtual std::shared_ptr<exception> dynamic_copy_exception()const;
virtual std::shared_ptr<exception> dynamic_copy_exception()const;
protected:
friend void to_variant( const exception& e, variant& v );
friend void from_variant( const variant& e, exception& ll );
virtual void from_variant( const variant& ){}
virtual void to_variant( variant& ){}
protected:
std::unique_ptr<detail::exception_impl> my;
};
void to_variant( const exception& e, variant& v );
void from_variant( const variant& e, exception& ll );
typedef std::shared_ptr<exception> exception_ptr;
@ -86,7 +119,6 @@ namespace fc
typedef optional<exception> oexception;
/**
* @brief re-thrown whenever an unhandled exception is caught.
* @ingroup serializable
@ -100,14 +132,17 @@ namespace fc
class unhandled_exception : public exception
{
public:
enum code_enum {
code_value = unhandled_exception_code,
};
unhandled_exception( log_message&& m, std::exception_ptr e = std::current_exception() );
unhandled_exception( log_messages );
unhandled_exception( const exception& );
virtual const char* what()const throw() { return "Unhandled _exception"; }
std::exception_ptr get_inner_exception()const;
virtual NO_RETURN void dynamic_rethrow_exception()const;
virtual std::shared_ptr<exception> dynamic_copy_exception()const;
virtual NO_RETURN void dynamic_rethrow_exception()const;
virtual std::shared_ptr<exception> dynamic_copy_exception()const;
private:
std::exception_ptr _inner;
};
@ -116,78 +151,120 @@ namespace fc
fc::exception_ptr copy_exception( T&& e )
{
#if defined(_MSC_VER) && (_MSC_VER < 1700)
return std::make_shared<unhandled_exception>( log_message(), std::copy_exception(fc::forward<T>(e)) );
return std::make_shared<unhandled_exception>( log_message(),
std::copy_exception(fc::forward<T>(e)) );
#else
return std::make_shared<unhandled_exception>( log_message(), std::make_exception_ptr(fc::forward<T>(e)) );
return std::make_shared<unhandled_exception>( log_message(),
std::make_exception_ptr(fc::forward<T>(e)) );
#endif
}
/**
* @brief wraps unhanlded std::exception's
* @ingroup serializable
*
* This exception allows the 'what' field of unhandled std::exceptions
* to be propagated across process boundaries.
*/
class std_exception : public unhandled_exception
{
public:
std_exception( log_message&& m, std::exception_ptr e, const char* w );
std_exception( log_messages );
std_exception( const exception& c);
virtual const char* what()const throw() { return _what.c_str(); }
protected:
void from_variant( const variant& v );
void to_variant( variant& v );
class exception_factory
{
public:
struct base_exception_builder
{
virtual NO_RETURN void rethrow( const exception& e )const = 0;
};
template<typename T>
struct exception_builder : public base_exception_builder
{
virtual NO_RETURN void rethrow( const exception& e )const override
{
throw T( e );
}
};
template<typename T>
void register_exception()
{
static exception_builder<T> builder;
auto itr = _registered_exceptions.find( T::code_value );
assert( itr == _registered_exceptions.end() );
_registered_exceptions[T::code_value] = &builder;
}
void rethrow( const exception& e )const;
static exception_factory& instance()
{
static exception_factory once;
return once;
}
private:
string _what;
std::unordered_map<int64_t,base_exception_builder*> _registered_exceptions;
};
#define FC_REGISTER_EXCEPTION(r, unused, base) \
fc::exception_factory::instance().register_exception<base>();
#define FC_REGISTER_EXCEPTIONS( SEQ )\
\
static bool exception_init = []()->bool{ \
BOOST_PP_SEQ_FOR_EACH( FC_REGISTER_EXCEPTION, v, SEQ ) \
return true; \
}(); \
#define FC_DECLARE_EXCEPTION( TYPE, WHAT ) \
class TYPE : public exception \
#define FC_DECLARE_EXCEPTION( TYPE, CODE, WHAT ) \
class TYPE : public fc::exception \
{ \
public: \
TYPE( log_message&& m ); \
TYPE( log_messages ); \
TYPE( const TYPE& c ); \
TYPE(); \
virtual const char* what()const throw() { return WHAT; } \
enum code_enum { \
code_value = CODE, \
}; \
TYPE( fc::log_message&& m ) \
:exception( fc::move(m), CODE, BOOST_PP_STRINGIZE(TYPE), WHAT ){}\
TYPE( fc::log_messages msgs ) \
:exception( fc::move( msgs ), CODE, BOOST_PP_STRINGIZE(TYPE), WHAT ) {} \
TYPE( const TYPE& c ) \
:exception(c){} \
TYPE( const exception& c ) \
:exception(c){} \
TYPE():exception(){}\
\
virtual std::shared_ptr<exception> dynamic_copy_exception()const\
{ return std::make_shared<TYPE>( *this ); } \
virtual NO_RETURN void dynamic_rethrow_exception()const \
{ if( code() == CODE ) throw *this;\
else fc::exception::dynamic_rethrow_exception(); \
} \
};
FC_DECLARE_EXCEPTION( timeout_exception, "Timeout" );
FC_DECLARE_EXCEPTION( file_not_found_exception, "File Not Found" );
FC_DECLARE_EXCEPTION( timeout_exception, timeout_exception_code, "Timeout" );
FC_DECLARE_EXCEPTION( file_not_found_exception, file_not_found_exception_code, "File Not Found" );
/**
* @brief report's parse errors
*/
FC_DECLARE_EXCEPTION( parse_error_exception, "Parse Error" );
FC_DECLARE_EXCEPTION( invalid_arg_exception, "Invalid Argument" );
FC_DECLARE_EXCEPTION( parse_error_exception, parse_error_exception_code, "Parse Error" );
FC_DECLARE_EXCEPTION( invalid_arg_exception, invalid_arg_exception_code, "Invalid Argument" );
/**
* @brief reports when a key, guid, or other item is not found.
*/
FC_DECLARE_EXCEPTION( key_not_found_exception, "Key Not Found" );
FC_DECLARE_EXCEPTION( bad_cast_exception, "Bad Cast" );
FC_DECLARE_EXCEPTION( out_of_range_exception, "Out of Range" );
FC_DECLARE_EXCEPTION( key_not_found_exception, key_not_found_exception_code, "Key Not Found" );
FC_DECLARE_EXCEPTION( bad_cast_exception, bad_cast_exception_code, "Bad Cast" );
FC_DECLARE_EXCEPTION( out_of_range_exception, out_of_range_exception_code, "Out of Range" );
/** @brief if an operation is unsupported or not valid this may be thrown */
FC_DECLARE_EXCEPTION( invalid_operation_exception, "Invalid Operation" );
FC_DECLARE_EXCEPTION( invalid_operation_exception,
invalid_operation_exception_code,
"Invalid Operation" );
/**
* @brief used to report a canceled Operation
*/
FC_DECLARE_EXCEPTION( canceled_exception, "Canceled" );
FC_DECLARE_EXCEPTION( canceled_exception, canceled_exception_code, "Canceled" );
/**
* @brief used inplace of assert() to report violations of pre conditions.
*/
FC_DECLARE_EXCEPTION( assert_exception, "Assert Exception" );
FC_DECLARE_EXCEPTION( eof_exception, "End Of File" );
FC_DECLARE_EXCEPTION( db_in_use_exception, "Database already in use" );
FC_DECLARE_EXCEPTION( assert_exception, assert_exception_code, "Assert Exception" );
FC_DECLARE_EXCEPTION( eof_exception, eof_exception_code, "End Of File" );
std::string except_str();
} // namespace fc
/**
@ -199,7 +276,7 @@ namespace fc
*/
#define FC_ASSERT( TEST, ... ) \
FC_EXPAND_MACRO( \
do { if( !(TEST) ) { FC_THROW_EXCEPTION( assert_exception, #TEST ": " __VA_ARGS__ ); } } while(0); \
do { if( !(TEST) ) { FC_THROW_EXCEPTION( fc::assert_exception, #TEST ": " __VA_ARGS__ ); } } while(0); \
)
#define FC_THROW( FORMAT, ... ) \
@ -208,7 +285,7 @@ do { if( !(TEST) ) { FC_THROW_EXCEPTION( assert_exception, #TEST ": " __VA_ARGS
} while(0)
#define FC_EXCEPTION( EXCEPTION_TYPE, FORMAT, ... ) \
fc::EXCEPTION_TYPE( FC_LOG_MESSAGE( error, FORMAT, __VA_ARGS__ ) )
EXCEPTION_TYPE( FC_LOG_MESSAGE( error, FORMAT, __VA_ARGS__ ) )
/**
* @def FC_THROW_EXCEPTION( EXCEPTION, FORMAT, ... )
* @param EXCEPTION a class in the Phoenix::Athena::API namespace that inherits
@ -216,7 +293,7 @@ do { if( !(TEST) ) { FC_THROW_EXCEPTION( assert_exception, #TEST ": " __VA_ARGS
*/
#define FC_THROW_EXCEPTION( EXCEPTION, FORMAT, ... ) \
do { \
throw fc::EXCEPTION( FC_LOG_MESSAGE( error, FORMAT, __VA_ARGS__ ) ); \
throw EXCEPTION( FC_LOG_MESSAGE( error, FORMAT, __VA_ARGS__ ) ); \
} while(0)
@ -239,13 +316,27 @@ do { if( !(TEST) ) { FC_THROW_EXCEPTION( assert_exception, #TEST ": " __VA_ARGS
catch( fc::exception& er ) { \
FC_RETHROW_EXCEPTION( er, LOG_LEVEL, FORMAT, __VA_ARGS__ ); \
} catch( const std::exception& e ) { \
fc::std_exception fce( \
FC_LOG_MESSAGE( LOG_LEVEL, "what: ${what} - " FORMAT,__VA_ARGS__("what",e.what())), \
std::current_exception(), \
fc::exception fce( \
FC_LOG_MESSAGE( LOG_LEVEL, "${what}" FORMAT,__VA_ARGS__("what",e.what())), \
fc::std_exception_code,\
typeid(e).name(), \
e.what() ) ; throw fce;\
} catch( ... ) { \
throw fc::unhandled_exception( \
FC_LOG_MESSAGE( LOG_LEVEL, FORMAT,__VA_ARGS__), \
std::current_exception() ); \
}
#define FC_CAPTURE_AND_RETHROW( SEQ ) \
catch( fc::exception& er ) { \
FC_RETHROW_EXCEPTION( er, fc::log_level::warn, "", FC_FORMAT_ARG_PARAMS(SEQ) ); \
} catch( const std::exception& e ) { \
fc::exception fce( \
FC_LOG_MESSAGE( fc::log_level::warn, "${what}",FC_FORMAT_ARG_PARAMS(SEQ)("what",e.what())), \
fc::std_exception_code,\
typeid(e).name(), \
e.what() ) ; throw fce;\
} catch( ... ) { \
throw fc::unhandled_exception( \
FC_LOG_MESSAGE( fc::log_level::warn, "",FC_FORMAT_ARG_PARAMS(SEQ)), \
std::current_exception() ); \
}

View file

@ -136,4 +136,8 @@ namespace fc
#define idump( SEQ ) \
ilog( FC_FORMAT(SEQ), FC_FORMAT_ARG_PARAMS(SEQ) )
#define wdump( SEQ ) \
wlog( FC_FORMAT(SEQ), FC_FORMAT_ARG_PARAMS(SEQ) )
#define edump( SEQ ) \
elog( FC_FORMAT(SEQ), FC_FORMAT_ARG_PARAMS(SEQ) )

View file

@ -6,144 +6,34 @@
namespace fc
{
FC_REGISTER_EXCEPTIONS( (timeout_exception)
(file_not_found_exception)
(parse_error_exception)
(invalid_arg_exception)
(invalid_operation_exception)
(key_not_found_exception)
(bad_cast_exception)
(out_of_range_exception)
(canceled_exception)
(assert_exception)
(eof_exception)
)
namespace detail
{
enum exception_code
{
unspecified_exception_code = 0, ///< for exceptions we threw that don't have an assigned code
unhandled_exception_code = 1, ///< for unhandled 3rd party exceptions
timeout_exception_code = 2, ///< timeout exceptions
file_not_found_exception_code = 3,
parse_error_exception_code = 4,
invalid_arg_exception_code = 5,
key_not_found_exception_code = 6,
bad_cast_exception_code = 7,
out_of_range_exception_code = 8,
canceled_exception_code = 9,
assert_exception_code = 10,
eof_exception_code = 11,
db_in_use_exception_code = 12,
std_exception_code = 14,
invalid_operation_exception_code = 15
};
void to_variant( detail::exception_code e, variant& v )
{
switch( e )
{
case unhandled_exception_code:
v = "unhandled";
break;
case timeout_exception_code:
v = "timeout";
break;
case key_not_found_exception_code:
v = "invalid_key";
break;
case bad_cast_exception_code:
v = "bad_cast";
break;
case file_not_found_exception_code:
v = "file_not_found";
break;
case parse_error_exception_code:
v = "parse_error";
break;
case invalid_arg_exception_code:
v = "invalid_arg";
break;
case out_of_range_exception_code:
v = "out_of_range";
break;
case canceled_exception_code:
v = "canceled";
break;
case assert_exception_code:
v = "assert";
break;
case std_exception_code:
v = "std";
break;
case eof_exception_code:
v = "eof";
break;
case db_in_use_exception_code:
v = "db_in_use";
break;
case invalid_operation_exception_code:
v = "invalid_operation";
break;
case unspecified_exception_code:
default:
v = "unspecified";
break;
}
}
void from_variant( const variant& e, detail::exception_code& ll )
{
string v = e.as_string();
if( v == "unspecified" ) ll = unspecified_exception_code;
else if( v == "unhandled" ) ll = unhandled_exception_code;
else if( v == "timeout" ) ll = timeout_exception_code;
else if( v == "key_not_found" ) ll = key_not_found_exception_code;
else if( v == "bad_cast" ) ll = bad_cast_exception_code;
else if( v == "file_not_found" ) ll = file_not_found_exception_code;
else if( v == "parse_error" ) ll = parse_error_exception_code;
else if( v == "invalid_arg" ) ll = invalid_arg_exception_code;
else if( v == "out_of_range" ) ll = out_of_range_exception_code;
else if( v == "canceled" ) ll = canceled_exception_code;
else if( v == "assert" ) ll = assert_exception_code;
else if( v == "std" ) ll = std_exception_code;
else if( v == "eof" ) ll = eof_exception_code;
else if( v == "db_in_use") ll = db_in_use_exception_code;
else if( v == "invalid_operation") ll = invalid_operation_exception_code;
else FC_THROW_EXCEPTION( bad_cast_exception,
"Invalid Error Report _code '${code}'",
("code", v) );
}
class exception_impl
{
public:
exception_code _ecode;
std::string _name;
std::string _what;
int64_t _code;
log_messages _elog;
variant _props;
};
}
std_exception::std_exception( log_message&& m, std::exception_ptr e, const char* w )
:unhandled_exception( fc::move(m), e )
{
my->_ecode = detail::std_exception_code;
_what = w;
}
std_exception::std_exception( const exception& e )
:unhandled_exception(e)
{
from_variant( my->_props );
}
std_exception::std_exception( log_messages m )
:unhandled_exception(fc::move(m) )
{
my->_ecode = detail::std_exception_code;
}
void std_exception::from_variant( const variant& v )
{
_what = v.get_object()["what"].as_string();
}
void std_exception::to_variant( variant& v )
{
v = variant_object( "what", _what );
}
unhandled_exception::unhandled_exception( log_message&& m, std::exception_ptr e )
:exception( fc::move(m) )
{
my->_ecode = detail::unhandled_exception_code;
_inner = e;
}
unhandled_exception::unhandled_exception( const exception& r )
@ -152,15 +42,16 @@ namespace fc
}
unhandled_exception::unhandled_exception( log_messages m )
:exception()
{ my->_elog = fc::move(m);
my->_ecode = detail::unhandled_exception_code;
}
{ my->_elog = fc::move(m); }
std::exception_ptr unhandled_exception::get_inner_exception()const { return _inner; }
NO_RETURN void unhandled_exception::dynamic_rethrow_exception()const
{
if( !(_inner == std::exception_ptr()) ) std::rethrow_exception( _inner );
else { fc::exception::dynamic_rethrow_exception(); }
}
std::shared_ptr<exception> unhandled_exception::dynamic_copy_exception()const
{
auto e = std::make_shared<unhandled_exception>( *this );
@ -168,69 +59,64 @@ namespace fc
return e;
}
#define FC_EXCEPTION_IMPL( TYPE ) \
TYPE::TYPE( log_message&& m ) \
:exception( fc::move(m) ) { my->_ecode = detail::TYPE ##_code; } \
TYPE::TYPE(){ my->_ecode = detail::TYPE ##_code; } \
TYPE::TYPE(const TYPE& t):exception(t){} \
TYPE::TYPE( log_messages m ) \
:exception() { my->_elog = fc::move(m); my->_ecode = detail::TYPE ##_code; }
FC_EXCEPTION_IMPL(timeout_exception)
FC_EXCEPTION_IMPL(file_not_found_exception)
FC_EXCEPTION_IMPL(parse_error_exception)
FC_EXCEPTION_IMPL(invalid_arg_exception)
FC_EXCEPTION_IMPL(key_not_found_exception)
FC_EXCEPTION_IMPL(bad_cast_exception)
FC_EXCEPTION_IMPL(out_of_range_exception)
FC_EXCEPTION_IMPL(invalid_operation_exception);
FC_EXCEPTION_IMPL(canceled_exception)
FC_EXCEPTION_IMPL(assert_exception)
FC_EXCEPTION_IMPL(eof_exception)
FC_EXCEPTION_IMPL(db_in_use_exception)
exception::exception()
exception::exception( int64_t code,
const std::string& name_value,
const std::string& what_value )
:my( new detail::exception_impl() )
{
my->_ecode = detail::unspecified_exception_code;
my->_code = code;
my->_what = what_value;
my->_name = name_value;
}
exception::exception( log_message&& msg)
exception::exception( log_message&& msg,
int64_t code,
const std::string& name_value,
const std::string& what_value )
:my( new detail::exception_impl() )
{
my->_ecode = detail::unspecified_exception_code;
my->_code = code;
my->_what = what_value;
my->_name = name_value;
my->_elog.push_back( fc::move( msg ) );
}
exception::exception( const exception& c )
:my( new detail::exception_impl(*c.my) )
{
}
{ }
exception::exception( exception&& c )
:my( fc::move(c.my) ){}
exception::~exception(){}
const char* exception::name()const throw() { return my->_name.c_str(); }
const char* exception::what()const throw() { return my->_what.c_str(); }
int64_t exception::code()const throw() { return my->_code; }
exception::~exception(){}
void to_variant( const exception& e, variant& v )
{
v = mutable_variant_object( "stack", e.my->_elog )
( "type", e.my->_ecode)
( "props", e.my->_props );
v = mutable_variant_object( "code", e.code() )
( "name", e.name() )
( "message", e.what() )
( "stack", e.get_log() );
}
void from_variant( const variant& v, exception& ll )
{
auto obj = v.get_object();
ll.my->_elog = obj["stack"].as<log_messages>();
ll.my->_ecode = obj["type"].as<detail::exception_code>();
ll.my->_props = obj["props"];
if( obj.contains( "stack" ) )
ll.my->_elog = obj["stack"].as<log_messages>();
if( obj.contains( "code" ) )
ll.my->_code = obj["code"].as_int64();
if( obj.contains( "name" ) )
ll.my->_name = obj["name"].as_string();
if( obj.contains( "message" ) )
ll.my->_what = obj["message"].as_string();
}
const log_messages& exception::get_log()const { return my->_elog; }
void exception::append_log( log_message m )
void exception::append_log( log_message m )
{
my->_elog.push_back( fc::move(m) );
my->_elog.emplace_back( fc::move(m) );
}
/**
@ -241,7 +127,7 @@ namespace fc
string exception::to_detail_string( log_level ll )const
{
fc::stringstream ss;
ss << variant(my->_ecode).as_string() <<"\n";
ss << variant(my->_code).as_string() <<"\n";
for( auto itr = my->_elog.begin(); itr != my->_elog.end(); )
{
ss << itr->get_message() <<"\n"; //fc::format_string( itr->get_format(), itr->get_data() ) <<"\n";
@ -259,7 +145,7 @@ namespace fc
string exception::to_string( log_level ll )const
{
fc::stringstream ss;
ss << what() << "(" << variant(my->_ecode).as_string() <<")\n";
ss << what() << "(" << variant(my->_code).as_string() <<")\n";
for( auto itr = my->_elog.begin(); itr != my->_elog.end(); ++itr )
{
ss << fc::format_string( itr->get_format(), itr->get_data() ) <<"\n";
@ -268,6 +154,13 @@ namespace fc
return ss.str();
}
void NO_RETURN exception_factory::rethrow( const exception& e )const
{
auto itr = _registered_exceptions.find( e.code() );
if( itr != _registered_exceptions.end() )
itr->second->rethrow( e );
throw e;
}
/**
* Rethrows the exception restoring the proper type based upon
* the error code. This is used to propagate exception types
@ -275,89 +168,30 @@ namespace fc
*/
NO_RETURN void exception::dynamic_rethrow_exception()const
{
switch( my->_ecode )
{
case detail::unhandled_exception_code:
throw unhandled_exception( my->_elog );
case detail::timeout_exception_code:
throw timeout_exception( my->_elog );
case detail::key_not_found_exception_code:
throw key_not_found_exception( my->_elog );
case detail::bad_cast_exception_code:
throw bad_cast_exception( my->_elog );
case detail::parse_error_exception_code:
throw parse_error_exception( my->_elog );
case detail::canceled_exception_code:
throw canceled_exception( my->_elog);
case detail::assert_exception_code:
throw assert_exception( my->_elog );
case detail::file_not_found_exception_code:
throw file_not_found_exception( my->_elog );
case detail::invalid_arg_exception_code:
throw invalid_arg_exception( my->_elog );
case detail::out_of_range_exception_code:
throw out_of_range_exception( my->_elog );
case detail::eof_exception_code:
throw eof_exception( my->_elog );
case detail::db_in_use_exception_code:
throw db_in_use_exception( my->_elog );
case detail::invalid_operation_exception_code:
throw invalid_operation_exception( my->_elog );
case detail::std_exception_code:
throw std_exception( *this );
case detail::unspecified_exception_code:
default:
throw fc::exception(*this);
}
exception_factory::instance().rethrow( *this );
}
exception_ptr exception::dynamic_copy_exception()const
{
switch( my->_ecode )
{
case detail::unhandled_exception_code:
return std::make_shared<unhandled_exception>( my->_elog );
case detail::timeout_exception_code:
return std::make_shared<timeout_exception>( my->_elog );
case detail::key_not_found_exception_code:
return std::make_shared<key_not_found_exception>( my->_elog );
case detail::bad_cast_exception_code:
return std::make_shared<bad_cast_exception>( my->_elog );
case detail::parse_error_exception_code:
return std::make_shared<parse_error_exception>( my->_elog );
case detail::canceled_exception_code:
return std::make_shared<canceled_exception>( my->_elog);
case detail::assert_exception_code:
return std::make_shared<assert_exception>( my->_elog );
case detail::file_not_found_exception_code:
return std::make_shared<file_not_found_exception>( my->_elog );
case detail::invalid_arg_exception_code:
return std::make_shared<invalid_arg_exception>( my->_elog );
case detail::out_of_range_exception_code:
return std::make_shared<out_of_range_exception>( my->_elog );
case detail::eof_exception_code:
return std::make_shared<eof_exception>( my->_elog );
case detail::db_in_use_exception_code:
return std::make_shared<db_in_use_exception>( my->_elog );
case detail::invalid_operation_exception_code:
return std::make_shared<invalid_operation_exception>( my->_elog );
case detail::std_exception_code:
return std::make_shared<std_exception>( *this );
case detail::unspecified_exception_code:
default:
return std::make_shared<exception>(*this);
}
return std::make_shared<exception>(*this);
}
fc::string except_str()
{
return boost::current_exception_diagnostic_information();
}
void throw_bad_enum_cast( int64_t i, const char* e )
{
FC_THROW_EXCEPTION( bad_cast_exception, "invalid index '${key}' in enum '${enum}'", ("key",i)("enum",e) );
FC_THROW_EXCEPTION( bad_cast_exception,
"invalid index '${key}' in enum '${enum}'",
("key",i)("enum",e) );
}
void throw_bad_enum_cast( const char* k, const char* e )
{
FC_THROW_EXCEPTION( bad_cast_exception, "invalid name '${key}' in enum '${enum}'", ("key",k)("enum",e) );
FC_THROW_EXCEPTION( bad_cast_exception,
"invalid name '${key}' in enum '${enum}'",
("key",k)("enum",e) );
}
} // fc