added type for safe int ops
This commit is contained in:
parent
cf4ed08d4b
commit
ec66863902
7 changed files with 101 additions and 2 deletions
|
|
@ -84,3 +84,5 @@ namespace std
|
|||
}
|
||||
};
|
||||
}
|
||||
#include <fc/reflect/reflect.hpp>
|
||||
FC_REFLECT_TYPENAME( fc::sha224 )
|
||||
|
|
|
|||
|
|
@ -33,7 +33,9 @@ namespace fc
|
|||
unknown_host_exception_code = 15,
|
||||
null_optional_code = 16,
|
||||
udt_error_code = 17,
|
||||
aes_error_code = 18
|
||||
aes_error_code = 18,
|
||||
overflow_code = 19,
|
||||
underflow_code = 20
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -285,6 +287,8 @@ namespace fc
|
|||
FC_DECLARE_EXCEPTION( null_optional, null_optional_code, "null optional" );
|
||||
FC_DECLARE_EXCEPTION( udt_exception, udt_error_code, "UDT error" );
|
||||
FC_DECLARE_EXCEPTION( aes_exception, aes_error_code, "AES error" );
|
||||
FC_DECLARE_EXCEPTION( overflow_exception, overflow_code, "Integer Overflow" );
|
||||
FC_DECLARE_EXCEPTION( underflow_exception, underflow_code, "Integer Underflow" );
|
||||
|
||||
std::string except_str();
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
#include <fc/time.hpp>
|
||||
#include <fc/filesystem.hpp>
|
||||
#include <fc/exception/exception.hpp>
|
||||
#include <fc/safe.hpp>
|
||||
#include <map>
|
||||
|
||||
#define MAX_ARRAY_ALLOC_SIZE (1024*1024*10)
|
||||
|
|
@ -162,11 +163,24 @@ namespace fc {
|
|||
vi.value = static_cast<uint32_t>(v);
|
||||
}
|
||||
|
||||
template<typename Stream, typename T> inline void unpack( Stream& s, const T& vi )
|
||||
{
|
||||
T tmp;
|
||||
unpack( s, tmp );
|
||||
FC_ASSERT( vi == tmp );
|
||||
}
|
||||
|
||||
template<typename Stream> inline void pack( Stream& s, const char* v ) { pack( s, fc::string(v) ); }
|
||||
|
||||
template<typename Stream, typename T>
|
||||
void pack( Stream& s, const safe<T>& v ) { pack( s, v.value ); }
|
||||
|
||||
template<typename Stream, typename T>
|
||||
void unpack( Stream& s, fc::safe<T>& v ) { unpack( s, v.value ); }
|
||||
|
||||
// optional
|
||||
template<typename Stream, typename T>
|
||||
inline void pack( Stream& s, const fc::optional<T>& v ) {
|
||||
void pack( Stream& s, const fc::optional<T>& v ) {
|
||||
pack( s, bool(!!v) );
|
||||
if( !!v ) pack( s, *v );
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
#include <fc/io/varint.hpp>
|
||||
#include <fc/array.hpp>
|
||||
#include <fc/safe.hpp>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <unordered_set>
|
||||
|
|
@ -48,7 +49,10 @@ namespace fc {
|
|||
|
||||
|
||||
template<typename Stream, typename T> void unpack( Stream& s, fc::optional<T>& v );
|
||||
template<typename Stream, typename T> void unpack( Stream& s, const T& v );
|
||||
template<typename Stream, typename T> void pack( Stream& s, const fc::optional<T>& v );
|
||||
template<typename Stream, typename T> void pack( Stream& s, const safe<T>& v );
|
||||
template<typename Stream, typename T> void unpack( Stream& s, fc::safe<T>& v );
|
||||
|
||||
template<typename Stream> void unpack( Stream& s, time_point& );
|
||||
template<typename Stream> void pack( Stream& s, const time_point& );
|
||||
|
|
|
|||
64
include/fc/safe.hpp
Normal file
64
include/fc/safe.hpp
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
#pragma once
|
||||
#include <fc/exception/exception.hpp>
|
||||
|
||||
namespace fc {
|
||||
|
||||
/**
|
||||
* This type is designed to provide automatic checks for
|
||||
* integer overflow and default initialization. It will
|
||||
* throw an exception on overflow conditions.
|
||||
*/
|
||||
template<typename T>
|
||||
struct safe
|
||||
{
|
||||
template<typename O>
|
||||
safe( O o ):value(o){}
|
||||
safe(){}
|
||||
safe( const safe& o ):value(o.value){}
|
||||
|
||||
|
||||
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) );
|
||||
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;
|
||||
}
|
||||
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>::min() - b.value ) FC_CAPTURE_AND_THROW( underflow_exception, (a)(b) );
|
||||
return safe(a.value+b.value);
|
||||
}
|
||||
safe& operator -= ( const safe& b ) { return *this += safe(-b.value); }
|
||||
safe operator -()const{ return safe(-value); }
|
||||
|
||||
friend safe operator - ( const safe& a, const safe& b )
|
||||
{
|
||||
safe tmp(a); tmp -= b; return tmp;
|
||||
}
|
||||
|
||||
friend bool operator == ( const safe& a, const safe& b )
|
||||
{
|
||||
return a.value == b.value;
|
||||
}
|
||||
friend bool operator < ( const safe& a, const safe& b )
|
||||
{
|
||||
return a.value < b.value;
|
||||
}
|
||||
friend bool operator > ( const safe& a, const safe& b )
|
||||
{
|
||||
return a.value > b.value;
|
||||
}
|
||||
friend bool operator >= ( const safe& a, const safe& b )
|
||||
{
|
||||
return a.value >= b.value;
|
||||
}
|
||||
friend bool operator <= ( const safe& a, const safe& b )
|
||||
{
|
||||
return a.value <= b.value;
|
||||
}
|
||||
T value = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -30,11 +30,14 @@ namespace fc
|
|||
class time_point;
|
||||
class time_point_sec;
|
||||
class microseconds;
|
||||
template<typename T> struct safe;
|
||||
|
||||
struct blob { std::vector<char> data; };
|
||||
|
||||
void to_variant( const blob& var, variant& vo );
|
||||
void from_variant( const variant& var, blob& vo );
|
||||
template<typename T> void to_variant( const safe<T>& s, variant& v );
|
||||
template<typename T> void from_variant( const variant& v, safe<T>& s );
|
||||
|
||||
void to_variant( const uint8_t& var, variant& vo );
|
||||
void from_variant( const variant& var, uint8_t& vo );
|
||||
|
|
@ -111,6 +114,7 @@ namespace fc
|
|||
void from_variant( const variant& v, std::pair<A,B>& p );
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief stores null, int64, uint64, double, bool, string, std::vector<variant>,
|
||||
* and variant_object's.
|
||||
|
|
@ -480,6 +484,11 @@ namespace fc
|
|||
from_variant( var, *vo );
|
||||
}
|
||||
}
|
||||
template<typename T>
|
||||
void to_variant( const safe<T>& s, variant& v ) { v = s.value; }
|
||||
|
||||
template<typename T>
|
||||
void from_variant( const variant& v, safe<T>& s ) { s.value = v.as_uint64(); }
|
||||
|
||||
variant operator + ( const variant& a, const variant& b );
|
||||
variant operator - ( const variant& a, const variant& b );
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@ namespace fc
|
|||
(null_optional)
|
||||
(udt_exception)
|
||||
(aes_exception)
|
||||
(overflow_exception)
|
||||
(underflow_exception)
|
||||
)
|
||||
|
||||
namespace detail
|
||||
|
|
|
|||
Loading…
Reference in a new issue