diff --git a/include/fc/exception/exception.hpp b/include/fc/exception/exception.hpp index 9a54db8..fc291c3 100644 --- a/include/fc/exception/exception.hpp +++ b/include/fc/exception/exception.hpp @@ -6,11 +6,32 @@ #include #include #include +#include + 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 dynamic_copy_exception()const; + virtual std::shared_ptr 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 my; }; + void to_variant( const exception& e, variant& v ); void from_variant( const variant& e, exception& ll ); typedef std::shared_ptr exception_ptr; @@ -86,7 +119,6 @@ namespace fc typedef optional 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 dynamic_copy_exception()const; + virtual NO_RETURN void dynamic_rethrow_exception()const; + virtual std::shared_ptr 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( log_message(), std::copy_exception(fc::forward(e)) ); + return std::make_shared( log_message(), + std::copy_exception(fc::forward(e)) ); #else - return std::make_shared( log_message(), std::make_exception_ptr(fc::forward(e)) ); + return std::make_shared( log_message(), + std::make_exception_ptr(fc::forward(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 + struct exception_builder : public base_exception_builder + { + virtual NO_RETURN void rethrow( const exception& e )const override + { + throw T( e ); + } + }; + + template + void register_exception() + { + static exception_builder 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 _registered_exceptions; }; +#define FC_REGISTER_EXCEPTION(r, unused, base) \ + fc::exception_factory::instance().register_exception(); + +#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 dynamic_copy_exception()const\ + { return std::make_shared( *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() ); \ + } diff --git a/include/fc/log/logger.hpp b/include/fc/log/logger.hpp index c662fce..221e709 100644 --- a/include/fc/log/logger.hpp +++ b/include/fc/log/logger.hpp @@ -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) ) diff --git a/src/exception.cpp b/src/exception.cpp index e6f7c0f..25bd2a6 100644 --- a/src/exception.cpp +++ b/src/exception.cpp @@ -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 unhandled_exception::dynamic_copy_exception()const { auto e = std::make_shared( *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(); - ll.my->_ecode = obj["type"].as(); - ll.my->_props = obj["props"]; + if( obj.contains( "stack" ) ) + ll.my->_elog = obj["stack"].as(); + 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( my->_elog ); - case detail::timeout_exception_code: - return std::make_shared( my->_elog ); - case detail::key_not_found_exception_code: - return std::make_shared( my->_elog ); - case detail::bad_cast_exception_code: - return std::make_shared( my->_elog ); - case detail::parse_error_exception_code: - return std::make_shared( my->_elog ); - case detail::canceled_exception_code: - return std::make_shared( my->_elog); - case detail::assert_exception_code: - return std::make_shared( my->_elog ); - case detail::file_not_found_exception_code: - return std::make_shared( my->_elog ); - case detail::invalid_arg_exception_code: - return std::make_shared( my->_elog ); - case detail::out_of_range_exception_code: - return std::make_shared( my->_elog ); - case detail::eof_exception_code: - return std::make_shared( my->_elog ); - case detail::db_in_use_exception_code: - return std::make_shared( my->_elog ); - case detail::invalid_operation_exception_code: - return std::make_shared( my->_elog ); - case detail::std_exception_code: - return std::make_shared( *this ); - case detail::unspecified_exception_code: - default: - return std::make_shared(*this); - } + return std::make_shared(*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