added type for safe int ops

This commit is contained in:
Daniel Larimer 2015-02-19 11:39:17 -05:00
parent cf4ed08d4b
commit ec66863902
7 changed files with 101 additions and 2 deletions

View file

@ -84,3 +84,5 @@ namespace std
}
};
}
#include <fc/reflect/reflect.hpp>
FC_REFLECT_TYPENAME( fc::sha224 )

View file

@ -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();

View file

@ -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 );
}

View file

@ -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
View 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;
};
}

View file

@ -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 );

View file

@ -21,6 +21,8 @@ namespace fc
(null_optional)
(udt_exception)
(aes_exception)
(overflow_exception)
(underflow_exception)
)
namespace detail