Fix and cleanup safe spec; cryptonomex/graphene#10
This commit is contained in:
parent
2ef7583f90
commit
0391665471
3 changed files with 179 additions and 138 deletions
|
|
@ -1,7 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
/**
|
/**
|
||||||
* @file exception.hpp
|
* @file exception.hpp
|
||||||
* @brief Defines exception's used by fc
|
* @brief Defines exception's used by fc
|
||||||
*/
|
*/
|
||||||
#include <fc/log/logger.hpp>
|
#include <fc/log/logger.hpp>
|
||||||
#include <fc/optional.hpp>
|
#include <fc/optional.hpp>
|
||||||
|
|
@ -13,10 +13,10 @@ namespace fc
|
||||||
{
|
{
|
||||||
namespace detail { class exception_impl; }
|
namespace detail { class exception_impl; }
|
||||||
|
|
||||||
enum exception_code
|
enum exception_code
|
||||||
{
|
{
|
||||||
/** for exceptions we threw that don't have an assigned code */
|
/** for exceptions we threw that don't have an assigned code */
|
||||||
unspecified_exception_code = 0,
|
unspecified_exception_code = 0,
|
||||||
unhandled_exception_code = 1, ///< for unhandled 3rd party exceptions
|
unhandled_exception_code = 1, ///< for unhandled 3rd party exceptions
|
||||||
timeout_exception_code = 2, ///< timeout exceptions
|
timeout_exception_code = 2, ///< timeout exceptions
|
||||||
file_not_found_exception_code = 3,
|
file_not_found_exception_code = 3,
|
||||||
|
|
@ -35,7 +35,8 @@ namespace fc
|
||||||
udt_error_code = 17,
|
udt_error_code = 17,
|
||||||
aes_error_code = 18,
|
aes_error_code = 18,
|
||||||
overflow_code = 19,
|
overflow_code = 19,
|
||||||
underflow_code = 20
|
underflow_code = 20,
|
||||||
|
divide_by_zero_code = 21
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -46,21 +47,21 @@ namespace fc
|
||||||
* new log_message is added to the exception.
|
* new log_message is added to the exception.
|
||||||
*
|
*
|
||||||
* exception's are designed to be serialized to a variant and
|
* exception's are designed to be serialized to a variant and
|
||||||
* deserialized from an variant.
|
* deserialized from an variant.
|
||||||
*
|
*
|
||||||
* @see FC_THROW_EXCEPTION
|
* @see FC_THROW_EXCEPTION
|
||||||
* @see FC_RETHROW_EXCEPTION
|
* @see FC_RETHROW_EXCEPTION
|
||||||
* @see FC_RETHROW_EXCEPTIONS
|
* @see FC_RETHROW_EXCEPTIONS
|
||||||
*/
|
*/
|
||||||
class exception
|
class exception
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum code_enum
|
enum code_enum
|
||||||
{
|
{
|
||||||
code_value = unspecified_exception_code
|
code_value = unspecified_exception_code
|
||||||
};
|
};
|
||||||
|
|
||||||
exception( int64_t code = unspecified_exception_code,
|
exception( int64_t code = unspecified_exception_code,
|
||||||
const std::string& name_value = "exception",
|
const std::string& name_value = "exception",
|
||||||
const std::string& what_value = "unspecified");
|
const std::string& what_value = "unspecified");
|
||||||
exception( log_message&&, int64_t code = unspecified_exception_code,
|
exception( log_message&&, int64_t code = unspecified_exception_code,
|
||||||
|
|
@ -83,7 +84,7 @@ namespace fc
|
||||||
*/
|
*/
|
||||||
const log_messages& get_log()const;
|
const log_messages& get_log()const;
|
||||||
void append_log( log_message m );
|
void append_log( log_message m );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a detailed string including file, line, method,
|
* Generates a detailed string including file, line, method,
|
||||||
* and other information that is generally only useful for
|
* and other information that is generally only useful for
|
||||||
|
|
@ -97,7 +98,7 @@ namespace fc
|
||||||
std::string to_string( log_level ll = log_level::info )const;
|
std::string to_string( log_level ll = log_level::info )const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Throw this exception as its most derived type.
|
* Throw this exception as its most derived type.
|
||||||
*
|
*
|
||||||
* @note does not return.
|
* @note does not return.
|
||||||
*/
|
*/
|
||||||
|
|
@ -106,7 +107,7 @@ namespace fc
|
||||||
/**
|
/**
|
||||||
* This is equivalent to:
|
* This is equivalent to:
|
||||||
* @code
|
* @code
|
||||||
* try { throwAsDynamic_exception(); }
|
* try { throwAsDynamic_exception(); }
|
||||||
* catch( ... ) { return std::current_exception(); }
|
* catch( ... ) { return std::current_exception(); }
|
||||||
* @endcode
|
* @endcode
|
||||||
*/
|
*/
|
||||||
|
|
@ -132,21 +133,21 @@ namespace fc
|
||||||
* @brief re-thrown whenever an unhandled exception is caught.
|
* @brief re-thrown whenever an unhandled exception is caught.
|
||||||
* @ingroup serializable
|
* @ingroup serializable
|
||||||
* Any exceptions thrown by 3rd party libraries that are not
|
* Any exceptions thrown by 3rd party libraries that are not
|
||||||
* caught get wrapped in an unhandled_exception exception.
|
* caught get wrapped in an unhandled_exception exception.
|
||||||
*
|
*
|
||||||
* The original exception is captured as a std::exception_ptr
|
* The original exception is captured as a std::exception_ptr
|
||||||
* which may be rethrown. The std::exception_ptr does not
|
* which may be rethrown. The std::exception_ptr does not
|
||||||
* propgate across process boundaries.
|
* propgate across process boundaries.
|
||||||
*/
|
*/
|
||||||
class unhandled_exception : public exception
|
class unhandled_exception : public exception
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum code_enum {
|
enum code_enum {
|
||||||
code_value = unhandled_exception_code,
|
code_value = unhandled_exception_code,
|
||||||
};
|
};
|
||||||
unhandled_exception( log_message&& m, std::exception_ptr e = std::current_exception() );
|
unhandled_exception( log_message&& m, std::exception_ptr e = std::current_exception() );
|
||||||
unhandled_exception( log_messages );
|
unhandled_exception( log_messages );
|
||||||
unhandled_exception( const exception& );
|
unhandled_exception( const exception& );
|
||||||
|
|
||||||
std::exception_ptr get_inner_exception()const;
|
std::exception_ptr get_inner_exception()const;
|
||||||
|
|
||||||
|
|
@ -160,10 +161,10 @@ namespace fc
|
||||||
fc::exception_ptr copy_exception( T&& e )
|
fc::exception_ptr copy_exception( T&& e )
|
||||||
{
|
{
|
||||||
#if defined(_MSC_VER) && (_MSC_VER < 1700)
|
#if defined(_MSC_VER) && (_MSC_VER < 1700)
|
||||||
return std::make_shared<unhandled_exception>( log_message(),
|
return std::make_shared<unhandled_exception>( log_message(),
|
||||||
std::copy_exception(fc::forward<T>(e)) );
|
std::copy_exception(fc::forward<T>(e)) );
|
||||||
#else
|
#else
|
||||||
return std::make_shared<unhandled_exception>( log_message(),
|
return std::make_shared<unhandled_exception>( log_message(),
|
||||||
std::make_exception_ptr(fc::forward<T>(e)) );
|
std::make_exception_ptr(fc::forward<T>(e)) );
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
@ -177,7 +178,7 @@ namespace fc
|
||||||
virtual NO_RETURN void rethrow( const exception& e )const = 0;
|
virtual NO_RETURN void rethrow( const exception& e )const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct exception_builder : public base_exception_builder
|
struct exception_builder : public base_exception_builder
|
||||||
{
|
{
|
||||||
virtual NO_RETURN void rethrow( const exception& e )const override
|
virtual NO_RETURN void rethrow( const exception& e )const override
|
||||||
|
|
@ -195,7 +196,7 @@ namespace fc
|
||||||
(void)itr; // in release builds this hides warnings
|
(void)itr; // in release builds this hides warnings
|
||||||
_registered_exceptions[T::code_value] = &builder;
|
_registered_exceptions[T::code_value] = &builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NO_RETURN rethrow( const exception& e )const;
|
void NO_RETURN rethrow( const exception& e )const;
|
||||||
|
|
||||||
static exception_factory& instance()
|
static exception_factory& instance()
|
||||||
|
|
@ -248,7 +249,7 @@ namespace fc
|
||||||
else fc::exception::dynamic_rethrow_exception(); \
|
else fc::exception::dynamic_rethrow_exception(); \
|
||||||
} \
|
} \
|
||||||
};
|
};
|
||||||
|
|
||||||
#define FC_DECLARE_EXCEPTION( TYPE, CODE, WHAT ) \
|
#define FC_DECLARE_EXCEPTION( TYPE, CODE, WHAT ) \
|
||||||
FC_DECLARE_DERIVED_EXCEPTION( TYPE, fc::exception, CODE, WHAT )
|
FC_DECLARE_DERIVED_EXCEPTION( TYPE, fc::exception, CODE, WHAT )
|
||||||
|
|
||||||
|
|
@ -267,8 +268,8 @@ namespace fc
|
||||||
FC_DECLARE_EXCEPTION( out_of_range_exception, out_of_range_exception_code, "Out of Range" );
|
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 */
|
/** @brief if an operation is unsupported or not valid this may be thrown */
|
||||||
FC_DECLARE_EXCEPTION( invalid_operation_exception,
|
FC_DECLARE_EXCEPTION( invalid_operation_exception,
|
||||||
invalid_operation_exception_code,
|
invalid_operation_exception_code,
|
||||||
"Invalid Operation" );
|
"Invalid Operation" );
|
||||||
/** @brief if an host name can not be resolved this may be thrown */
|
/** @brief if an host name can not be resolved this may be thrown */
|
||||||
FC_DECLARE_EXCEPTION( unknown_host_exception,
|
FC_DECLARE_EXCEPTION( unknown_host_exception,
|
||||||
|
|
@ -289,6 +290,7 @@ namespace fc
|
||||||
FC_DECLARE_EXCEPTION( aes_exception, aes_error_code, "AES error" );
|
FC_DECLARE_EXCEPTION( aes_exception, aes_error_code, "AES error" );
|
||||||
FC_DECLARE_EXCEPTION( overflow_exception, overflow_code, "Integer Overflow" );
|
FC_DECLARE_EXCEPTION( overflow_exception, overflow_code, "Integer Overflow" );
|
||||||
FC_DECLARE_EXCEPTION( underflow_exception, underflow_code, "Integer Underflow" );
|
FC_DECLARE_EXCEPTION( underflow_exception, underflow_code, "Integer Underflow" );
|
||||||
|
FC_DECLARE_EXCEPTION( divide_by_zero_exception, divide_by_zero_code, "Integer Divide By Zero" );
|
||||||
|
|
||||||
std::string except_str();
|
std::string except_str();
|
||||||
|
|
||||||
|
|
@ -333,7 +335,7 @@ namespace fc
|
||||||
throw EXCEPTION_TYPE( FC_LOG_MESSAGE( error, "", FC_FORMAT_ARG_PARAMS(__VA_ARGS__) ) ); \
|
throw EXCEPTION_TYPE( FC_LOG_MESSAGE( error, "", FC_FORMAT_ARG_PARAMS(__VA_ARGS__) ) ); \
|
||||||
FC_MULTILINE_MACRO_END
|
FC_MULTILINE_MACRO_END
|
||||||
|
|
||||||
//#define FC_THROW( FORMAT, ... )
|
//#define FC_THROW( FORMAT, ... )
|
||||||
// FC_INDIRECT_EXPAND workas around a bug in Visual C++ variadic macro processing that prevents it
|
// FC_INDIRECT_EXPAND workas around a bug in Visual C++ variadic macro processing that prevents it
|
||||||
// from separating __VA_ARGS__ into separate tokens
|
// from separating __VA_ARGS__ into separate tokens
|
||||||
#define FC_INDIRECT_EXPAND(MACRO, ARGS) MACRO ARGS
|
#define FC_INDIRECT_EXPAND(MACRO, ARGS) MACRO ARGS
|
||||||
|
|
@ -343,7 +345,7 @@ namespace fc
|
||||||
FC_MULTILINE_MACRO_END
|
FC_MULTILINE_MACRO_END
|
||||||
|
|
||||||
#define FC_EXCEPTION( EXCEPTION_TYPE, FORMAT, ... ) \
|
#define FC_EXCEPTION( EXCEPTION_TYPE, FORMAT, ... ) \
|
||||||
EXCEPTION_TYPE( FC_LOG_MESSAGE( error, FORMAT, __VA_ARGS__ ) )
|
EXCEPTION_TYPE( FC_LOG_MESSAGE( error, FORMAT, __VA_ARGS__ ) )
|
||||||
/**
|
/**
|
||||||
* @def FC_THROW_EXCEPTION( EXCEPTION, FORMAT, ... )
|
* @def FC_THROW_EXCEPTION( EXCEPTION, FORMAT, ... )
|
||||||
* @param EXCEPTION a class in the Phoenix::Athena::API namespace that inherits
|
* @param EXCEPTION a class in the Phoenix::Athena::API namespace that inherits
|
||||||
|
|
|
||||||
|
|
@ -13,126 +13,164 @@ namespace fc {
|
||||||
*
|
*
|
||||||
* It can only be used on built-in types. In particular,
|
* It can only be used on built-in types. In particular,
|
||||||
* safe<uint128_t> is buggy and should not be used.
|
* safe<uint128_t> is buggy and should not be used.
|
||||||
|
*
|
||||||
|
* Implemented using spec from:
|
||||||
|
* https://www.securecoding.cert.org/confluence/display/c/INT32-C.+Ensure+that+operations+on+signed+integers+do+not+result+in+overflow
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct safe
|
struct safe
|
||||||
{
|
{
|
||||||
|
T value = 0;
|
||||||
|
|
||||||
template<typename O>
|
template<typename O>
|
||||||
safe( O o ):value(o){}
|
safe( O o ):value(o){}
|
||||||
safe(){}
|
safe(){}
|
||||||
safe( const safe& o ):value(o.value){}
|
safe( const safe& o ):value(o.value){}
|
||||||
|
|
||||||
static safe max()
|
|
||||||
{ return std::numeric_limits<T>::max(); }
|
|
||||||
static safe min()
|
static safe min()
|
||||||
{ return std::numeric_limits<T>::min(); }
|
|
||||||
|
|
||||||
safe& operator += ( const safe& b )
|
|
||||||
{
|
{
|
||||||
if( b.value > 0 && value > (std::numeric_limits<T>::max() - b.value) ) FC_CAPTURE_AND_THROW( overflow_exception, (*this)(b) );
|
return std::numeric_limits<T>::min();
|
||||||
if( b.value < 0 && value < (std::numeric_limits<T>::min() - b.value) ) FC_CAPTURE_AND_THROW( underflow_exception, (*this)(b) );
|
|
||||||
value += b.value;
|
|
||||||
return *this;
|
|
||||||
}
|
}
|
||||||
|
static safe max()
|
||||||
|
{
|
||||||
|
return std::numeric_limits<T>::max();
|
||||||
|
}
|
||||||
|
|
||||||
friend safe operator + ( const safe& a, const safe& b )
|
friend safe operator + ( const safe& a, const safe& b )
|
||||||
{
|
{
|
||||||
if( b.value > 0 && a.value > std::numeric_limits<T>::max() - b.value ) FC_CAPTURE_AND_THROW( overflow_exception, (a)(b) );
|
if( b.value > 0 && a.value > (std::numeric_limits<T>::max() - b.value) ) FC_CAPTURE_AND_THROW( overflow_exception, (a)(b) );
|
||||||
if( b.value < 0 && a.value < std::numeric_limits<T>::min() - b.value ) FC_CAPTURE_AND_THROW( underflow_exception, (a)(b) );
|
if( b.value < 0 && a.value < (std::numeric_limits<T>::min() - b.value) ) FC_CAPTURE_AND_THROW( underflow_exception, (a)(b) );
|
||||||
return safe(a.value+b.value);
|
return safe( a.value + b.value );
|
||||||
}
|
}
|
||||||
safe& operator *= ( safe v ) { value *= v.value; return *this; }
|
|
||||||
safe& operator /= ( safe v ) { FC_ASSERT(v.value != 0); value /= v.value; return *this; }
|
|
||||||
safe& operator -= ( const safe& b ) { return *this += safe(-b.value); }
|
|
||||||
safe operator -()const
|
|
||||||
{
|
|
||||||
if( value == std::numeric_limits<T>::min() )
|
|
||||||
FC_CAPTURE_AND_THROW( overflow_exception, (value) );
|
|
||||||
return safe(-value);
|
|
||||||
}
|
|
||||||
|
|
||||||
safe operator++(int) { safe bak = *this; *this += 1; return bak; }
|
|
||||||
safe& operator++() { return *this += 1; }
|
|
||||||
safe operator--(int) { safe bak = *this; *this -= 1; return bak; }
|
|
||||||
safe& operator--() { return *this -= 1; }
|
|
||||||
|
|
||||||
friend safe operator - ( const safe& a, const safe& b )
|
friend safe operator - ( const safe& a, const safe& b )
|
||||||
{
|
{
|
||||||
safe tmp(a); tmp -= b; return tmp;
|
if( b.value > 0 && a.value < (std::numeric_limits<T>::min() + b.value) ) FC_CAPTURE_AND_THROW( underflow_exception, (a)(b) );
|
||||||
|
if( b.value < 0 && a.value > (std::numeric_limits<T>::max() + b.value) ) FC_CAPTURE_AND_THROW( overflow_exception, (a)(b) );
|
||||||
|
return safe( a.value - b.value );
|
||||||
|
}
|
||||||
|
|
||||||
|
friend safe operator * ( const safe& a, const safe& b )
|
||||||
|
{
|
||||||
|
if( a.value > 0 )
|
||||||
|
{
|
||||||
|
if( b.value > 0 )
|
||||||
|
{
|
||||||
|
if( a.value > (std::numeric_limits<T>::max() / b.value) ) FC_CAPTURE_AND_THROW( overflow_exception, (a)(b) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( b.value < (std::numeric_limits<T>::min() / a.value) ) FC_CAPTURE_AND_THROW( underflow_exception, (a)(b) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( b.value > 0 )
|
||||||
|
{
|
||||||
|
if( a.value < (std::numeric_limits<T>::min() / b.value) ) FC_CAPTURE_AND_THROW( underflow_exception, (a)(b) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( a.value != 0 && b.value < (std::numeric_limits<T>::max() / a.value) ) FC_CAPTURE_AND_THROW( overflow_exception, (a)(b) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return safe( a.value * b.value );
|
||||||
|
}
|
||||||
|
|
||||||
|
friend safe operator / ( const safe& a, const safe& b )
|
||||||
|
{
|
||||||
|
if( b.value == 0 ) FC_CAPTURE_AND_THROW( divide_by_zero_exception, (a)(b) );
|
||||||
|
if( a.value == std::numeric_limits<T>::min() && b.value == -1 ) FC_CAPTURE_AND_THROW( overflow_exception, (a)(b) );
|
||||||
|
return safe( a.value / b.value );
|
||||||
|
}
|
||||||
|
friend safe operator % ( const safe& a, const safe& b )
|
||||||
|
{
|
||||||
|
if( b.value == 0 ) FC_CAPTURE_AND_THROW( divide_by_zero_exception, (a)(b) );
|
||||||
|
if( a.value == std::numeric_limits<T>::min() && b.value == -1 ) FC_CAPTURE_AND_THROW( overflow_exception, (a)(b) );
|
||||||
|
return safe( a.value % b.value );
|
||||||
|
}
|
||||||
|
|
||||||
|
safe operator - ()const
|
||||||
|
{
|
||||||
|
if( value == std::numeric_limits<T>::min() ) FC_CAPTURE_AND_THROW( overflow_exception, (*this) );
|
||||||
|
return safe( -value );
|
||||||
|
}
|
||||||
|
|
||||||
|
safe& operator += ( const safe& b )
|
||||||
|
{
|
||||||
|
value = (*this + b).value;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
safe& operator -= ( const safe& b )
|
||||||
|
{
|
||||||
|
value = (*this - b).value;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
safe& operator *= ( const safe& b )
|
||||||
|
{
|
||||||
|
value = (*this * b).value;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
safe& operator /= ( const safe& b )
|
||||||
|
{
|
||||||
|
value = (*this / b).value;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
safe& operator %= ( const safe& b )
|
||||||
|
{
|
||||||
|
value = (*this % b).value;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
safe& operator++()
|
||||||
|
{
|
||||||
|
*this += 1;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
safe operator++( int )
|
||||||
|
{
|
||||||
|
safe bak = *this;
|
||||||
|
*this += 1;
|
||||||
|
return bak;
|
||||||
|
}
|
||||||
|
|
||||||
|
safe& operator--()
|
||||||
|
{
|
||||||
|
*this -= 1;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
safe operator--( int )
|
||||||
|
{
|
||||||
|
safe bak = *this;
|
||||||
|
*this -= 1;
|
||||||
|
return bak;
|
||||||
}
|
}
|
||||||
|
|
||||||
friend bool operator == ( const safe& a, const safe& b )
|
friend bool operator == ( const safe& a, const safe& b )
|
||||||
{
|
{
|
||||||
return a.value == b.value;
|
return a.value == b.value;
|
||||||
}
|
|
||||||
friend bool operator == ( const safe& a, const T& b )
|
|
||||||
{
|
|
||||||
return a.value == b;
|
|
||||||
}
|
|
||||||
friend bool operator == ( const T& a, const safe& b )
|
|
||||||
{
|
|
||||||
return a == b.value;
|
|
||||||
}
|
|
||||||
friend bool operator != ( const safe& a, const safe& b )
|
|
||||||
{
|
|
||||||
return a.value != b.value;
|
|
||||||
}
|
|
||||||
friend bool operator != ( const safe& a, const T& b )
|
|
||||||
{
|
|
||||||
return a.value != b;
|
|
||||||
}
|
|
||||||
friend bool operator != ( const T& a, const safe& b )
|
|
||||||
{
|
|
||||||
return a != b.value;
|
|
||||||
}
|
}
|
||||||
friend bool operator < ( const safe& a, const safe& b )
|
friend bool operator < ( const safe& a, const safe& b )
|
||||||
{
|
{
|
||||||
return a.value < b.value;
|
return a.value < b.value;
|
||||||
}
|
|
||||||
friend bool operator < ( const safe& a, const T& b )
|
|
||||||
{
|
|
||||||
return a.value < b;
|
|
||||||
}
|
|
||||||
friend bool operator < ( const T& a, const safe& b )
|
|
||||||
{
|
|
||||||
return a < b.value;
|
|
||||||
}
|
}
|
||||||
friend bool operator > ( const safe& a, const safe& b )
|
friend bool operator > ( const safe& a, const safe& b )
|
||||||
{
|
{
|
||||||
return a.value > b.value;
|
return a.value > b.value;
|
||||||
}
|
}
|
||||||
friend bool operator > ( const safe& a, const T& b )
|
|
||||||
|
friend bool operator != ( const safe& a, const safe& b )
|
||||||
{
|
{
|
||||||
return a.value > b;
|
return !(a == b);
|
||||||
}
|
|
||||||
friend bool operator > ( const T& a, const safe& b )
|
|
||||||
{
|
|
||||||
return a > b.value;
|
|
||||||
}
|
|
||||||
friend bool operator >= ( const safe& a, const safe& b )
|
|
||||||
{
|
|
||||||
return a.value >= b.value;
|
|
||||||
}
|
|
||||||
friend bool operator >= ( const safe& a, const T& b )
|
|
||||||
{
|
|
||||||
return a.value >= b;
|
|
||||||
}
|
|
||||||
friend bool operator >= ( const T& a, const safe& b )
|
|
||||||
{
|
|
||||||
return a >= b.value;
|
|
||||||
}
|
}
|
||||||
friend bool operator <= ( const safe& a, const safe& b )
|
friend bool operator <= ( const safe& a, const safe& b )
|
||||||
{
|
{
|
||||||
return a.value <= b.value;
|
return !(a > b );
|
||||||
}
|
}
|
||||||
friend bool operator <= ( const safe& a, const T& b )
|
friend bool operator >= ( const safe& a, const safe& b )
|
||||||
{
|
{
|
||||||
return a.value <= b;
|
return !(a < b);
|
||||||
}
|
}
|
||||||
friend bool operator <= ( const T& a, const safe& b )
|
|
||||||
{
|
|
||||||
return a <= b.value;
|
|
||||||
}
|
|
||||||
T value = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ namespace fc
|
||||||
(aes_exception)
|
(aes_exception)
|
||||||
(overflow_exception)
|
(overflow_exception)
|
||||||
(underflow_exception)
|
(underflow_exception)
|
||||||
|
(divide_by_zero_exception)
|
||||||
)
|
)
|
||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
|
|
@ -39,7 +40,7 @@ namespace fc
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
exception::exception( log_messages&& msgs, int64_t code,
|
exception::exception( log_messages&& msgs, int64_t code,
|
||||||
const std::string& name_value,
|
const std::string& name_value,
|
||||||
const std::string& what_value )
|
const std::string& what_value )
|
||||||
:my( new detail::exception_impl() )
|
:my( new detail::exception_impl() )
|
||||||
{
|
{
|
||||||
|
|
@ -49,18 +50,18 @@ namespace fc
|
||||||
my->_elog = fc::move(msgs);
|
my->_elog = fc::move(msgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
unhandled_exception::unhandled_exception( log_message&& m, std::exception_ptr e )
|
unhandled_exception::unhandled_exception( log_message&& m, std::exception_ptr e )
|
||||||
:exception( fc::move(m) )
|
:exception( fc::move(m) )
|
||||||
{
|
{
|
||||||
_inner = e;
|
_inner = e;
|
||||||
}
|
}
|
||||||
unhandled_exception::unhandled_exception( const exception& r )
|
unhandled_exception::unhandled_exception( const exception& r )
|
||||||
:exception(r)
|
:exception(r)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
unhandled_exception::unhandled_exception( log_messages m )
|
unhandled_exception::unhandled_exception( log_messages m )
|
||||||
:exception()
|
:exception()
|
||||||
{ my->_elog = fc::move(m); }
|
{ my->_elog = fc::move(m); }
|
||||||
|
|
||||||
std::exception_ptr unhandled_exception::get_inner_exception()const { return _inner; }
|
std::exception_ptr unhandled_exception::get_inner_exception()const { return _inner; }
|
||||||
|
|
||||||
|
|
@ -77,9 +78,9 @@ namespace fc
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
exception::exception( int64_t code,
|
exception::exception( int64_t code,
|
||||||
const std::string& name_value,
|
const std::string& name_value,
|
||||||
const std::string& what_value )
|
const std::string& what_value )
|
||||||
:my( new detail::exception_impl() )
|
:my( new detail::exception_impl() )
|
||||||
{
|
{
|
||||||
my->_code = code;
|
my->_code = code;
|
||||||
|
|
@ -87,8 +88,8 @@ namespace fc
|
||||||
my->_name = name_value;
|
my->_name = name_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
exception::exception( log_message&& msg,
|
exception::exception( log_message&& msg,
|
||||||
int64_t code,
|
int64_t code,
|
||||||
const std::string& name_value,
|
const std::string& name_value,
|
||||||
const std::string& what_value )
|
const std::string& what_value )
|
||||||
:my( new detail::exception_impl() )
|
:my( new detail::exception_impl() )
|
||||||
|
|
@ -116,7 +117,7 @@ namespace fc
|
||||||
( "name", e.name() )
|
( "name", e.name() )
|
||||||
( "message", e.what() )
|
( "message", e.what() )
|
||||||
( "stack", e.get_log() );
|
( "stack", e.get_log() );
|
||||||
|
|
||||||
}
|
}
|
||||||
void from_variant( const variant& v, exception& ll )
|
void from_variant( const variant& v, exception& ll )
|
||||||
{
|
{
|
||||||
|
|
@ -136,7 +137,7 @@ namespace fc
|
||||||
{
|
{
|
||||||
my->_elog.emplace_back( fc::move(m) );
|
my->_elog.emplace_back( fc::move(m) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a detailed string including file, line, method,
|
* Generates a detailed string including file, line, method,
|
||||||
* and other information that is generally only useful for
|
* and other information that is generally only useful for
|
||||||
|
|
@ -189,26 +190,26 @@ namespace fc
|
||||||
exception_factory::instance().rethrow( *this );
|
exception_factory::instance().rethrow( *this );
|
||||||
}
|
}
|
||||||
|
|
||||||
exception_ptr exception::dynamic_copy_exception()const
|
exception_ptr exception::dynamic_copy_exception()const
|
||||||
{
|
{
|
||||||
return std::make_shared<exception>(*this);
|
return std::make_shared<exception>(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
fc::string except_str()
|
fc::string except_str()
|
||||||
{
|
{
|
||||||
return boost::current_exception_diagnostic_information();
|
return boost::current_exception_diagnostic_information();
|
||||||
}
|
}
|
||||||
|
|
||||||
void throw_bad_enum_cast( int64_t i, const char* e )
|
void throw_bad_enum_cast( int64_t i, const char* e )
|
||||||
{
|
{
|
||||||
FC_THROW_EXCEPTION( bad_cast_exception,
|
FC_THROW_EXCEPTION( bad_cast_exception,
|
||||||
"invalid index '${key}' in enum '${enum}'",
|
"invalid index '${key}' in enum '${enum}'",
|
||||||
("key",i)("enum",e) );
|
("key",i)("enum",e) );
|
||||||
}
|
}
|
||||||
void throw_bad_enum_cast( const char* k, const char* e )
|
void throw_bad_enum_cast( const char* k, const char* e )
|
||||||
{
|
{
|
||||||
FC_THROW_EXCEPTION( bad_cast_exception,
|
FC_THROW_EXCEPTION( bad_cast_exception,
|
||||||
"invalid name '${key}' in enum '${enum}'",
|
"invalid name '${key}' in enum '${enum}'",
|
||||||
("key",k)("enum",e) );
|
("key",k)("enum",e) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue