diff --git a/include/fc/crypto/sha224.hpp b/include/fc/crypto/sha224.hpp index 9ea9290..3411e7c 100644 --- a/include/fc/crypto/sha224.hpp +++ b/include/fc/crypto/sha224.hpp @@ -84,3 +84,5 @@ namespace std } }; } +#include +FC_REFLECT_TYPENAME( fc::sha224 ) diff --git a/include/fc/exception/exception.hpp b/include/fc/exception/exception.hpp index 1457214..baffcdf 100644 --- a/include/fc/exception/exception.hpp +++ b/include/fc/exception/exception.hpp @@ -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(); diff --git a/include/fc/io/raw.hpp b/include/fc/io/raw.hpp index 7e58330..3d3c0b5 100644 --- a/include/fc/io/raw.hpp +++ b/include/fc/io/raw.hpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #define MAX_ARRAY_ALLOC_SIZE (1024*1024*10) @@ -162,11 +163,24 @@ namespace fc { vi.value = static_cast(v); } + template inline void unpack( Stream& s, const T& vi ) + { + T tmp; + unpack( s, tmp ); + FC_ASSERT( vi == tmp ); + } + template inline void pack( Stream& s, const char* v ) { pack( s, fc::string(v) ); } + template + void pack( Stream& s, const safe& v ) { pack( s, v.value ); } + + template + void unpack( Stream& s, fc::safe& v ) { unpack( s, v.value ); } + // optional template - inline void pack( Stream& s, const fc::optional& v ) { + void pack( Stream& s, const fc::optional& v ) { pack( s, bool(!!v) ); if( !!v ) pack( s, *v ); } diff --git a/include/fc/io/raw_fwd.hpp b/include/fc/io/raw_fwd.hpp index 922782e..69247f9 100644 --- a/include/fc/io/raw_fwd.hpp +++ b/include/fc/io/raw_fwd.hpp @@ -1,6 +1,7 @@ #pragma once #include #include +#include #include #include #include @@ -48,7 +49,10 @@ namespace fc { template void unpack( Stream& s, fc::optional& v ); + template void unpack( Stream& s, const T& v ); template void pack( Stream& s, const fc::optional& v ); + template void pack( Stream& s, const safe& v ); + template void unpack( Stream& s, fc::safe& v ); template void unpack( Stream& s, time_point& ); template void pack( Stream& s, const time_point& ); diff --git a/include/fc/safe.hpp b/include/fc/safe.hpp new file mode 100644 index 0000000..be606c3 --- /dev/null +++ b/include/fc/safe.hpp @@ -0,0 +1,64 @@ +#pragma once +#include + +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 + struct safe + { + template + 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::max() - b.value) ) FC_CAPTURE_AND_THROW( overflow_exception, (*this)(b) ); + if( b.value < 0 && value < (std::numeric_limits::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::max() - b.value ) FC_CAPTURE_AND_THROW( overflow_exception, (a)(b) ); + if( b.value < 0 && a.value < std::numeric_limits::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; + }; + +} diff --git a/include/fc/variant.hpp b/include/fc/variant.hpp index c9c2d29..995dc5a 100644 --- a/include/fc/variant.hpp +++ b/include/fc/variant.hpp @@ -30,11 +30,14 @@ namespace fc class time_point; class time_point_sec; class microseconds; + template struct safe; struct blob { std::vector data; }; void to_variant( const blob& var, variant& vo ); void from_variant( const variant& var, blob& vo ); + template void to_variant( const safe& s, variant& v ); + template void from_variant( const variant& v, safe& 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& p ); + /** * @brief stores null, int64, uint64, double, bool, string, std::vector, * and variant_object's. @@ -480,6 +484,11 @@ namespace fc from_variant( var, *vo ); } } + template + void to_variant( const safe& s, variant& v ) { v = s.value; } + + template + void from_variant( const variant& v, safe& s ) { s.value = v.as_uint64(); } variant operator + ( const variant& a, const variant& b ); variant operator - ( const variant& a, const variant& b ); diff --git a/src/exception.cpp b/src/exception.cpp index 15ce8da..922fad0 100644 --- a/src/exception.cpp +++ b/src/exception.cpp @@ -21,6 +21,8 @@ namespace fc (null_optional) (udt_exception) (aes_exception) + (overflow_exception) + (underflow_exception) ) namespace detail