Compare commits

...

1 Commits

Author SHA1 Message Date
Lemongrass3110
036a5b1950 Refactored safe math to templates
This way it can also be used for smaller numeric types.
2024-02-26 22:16:09 +01:00
2 changed files with 54 additions and 56 deletions

View File

@ -69,52 +69,6 @@ int levenshtein(const std::string &s1, const std::string &s2)
return result; return result;
} }
bool rathena::util::safe_substraction( int64 a, int64 b, int64& result ){
#if __has_builtin( __builtin_sub_overflow ) || ( defined( __GNUC__ ) && !defined( __clang__ ) && defined( GCC_VERSION ) && GCC_VERSION >= 50100 )
return __builtin_sub_overflow( a, b, &result );
#else
bool overflow = false;
if( b < 0 ){
if( a > ( INT64_MAX + b ) ){
overflow = true;
}
}else{
if( a < ( INT64_MIN + b ) ){
overflow = true;
}
}
result = a - b;
return overflow;
#endif
}
bool rathena::util::safe_multiplication( int64 a, int64 b, int64& result ){
#if __has_builtin( __builtin_mul_overflow ) || ( defined( __GNUC__ ) && !defined( __clang__ ) && defined( GCC_VERSION ) && GCC_VERSION >= 50100 )
return __builtin_mul_overflow( a, b, &result );
#else
result = a * b;
if( a > 0 ){
if( b > 0 ){
return result < 0;
}else if( b < 0 ){
return result > 0;
}
}else if( a < 0 ){
if( b > 0 ){
return result > 0;
}else if( b < 0 ){
return result < 0;
}
}
return false;
#endif
}
void rathena::util::string_left_pad_inplace(std::string& str, char padding, size_t num) void rathena::util::string_left_pad_inplace(std::string& str, char padding, size_t num)
{ {
str.insert(0, min(0, num - str.length()), padding); str.insert(0, min(0, num - str.length()), padding);

View File

@ -233,26 +233,25 @@ namespace rathena {
} }
} }
template <typename T, typename = std::enable_if<std::is_integral<T>::value, T>::type>
bool safe_addition( T a, T b, T& result ){
#if __has_builtin( __builtin_add_overflow ) || ( defined( __GNUC__ ) && !defined( __clang__ ) && defined( GCC_VERSION ) && GCC_VERSION >= 50100 ) #if __has_builtin( __builtin_add_overflow ) || ( defined( __GNUC__ ) && !defined( __clang__ ) && defined( GCC_VERSION ) && GCC_VERSION >= 50100 )
template <typename T> bool safe_addition(T a, T b, T &result) {
return __builtin_add_overflow( a, b, &result ); return __builtin_add_overflow( a, b, &result );
}
#else #else
template <typename T> bool safe_addition( T a, T b, T& result ){
bool overflow = false; bool overflow = false;
if( std::numeric_limits<T>::is_signed ){ if( std::numeric_limits<T>::is_signed ){
if( b < 0 ){ if( b < 0 ){
if( a < ( (std::numeric_limits<T>::min)() - b ) ){ if( a < ( std::numeric_limits<T>::min() - b ) ){
overflow = true; overflow = true;
} }
}else{ }else{
if( a > ( (std::numeric_limits<T>::max)() - b ) ){ if( a > ( std::numeric_limits<T>::max() - b ) ){
overflow = true; overflow = true;
} }
} }
}else{ }else{
if( a > ( (std::numeric_limits<T>::max)() - b ) ){ if( a > ( std::numeric_limits<T>::max() - b ) ){
overflow = true; overflow = true;
} }
} }
@ -260,11 +259,56 @@ namespace rathena {
result = a + b; result = a + b;
return overflow; return overflow;
}
#endif #endif
}
bool safe_substraction( int64 a, int64 b, int64& result ); template <typename T, typename = std::enable_if<std::is_integral<T>::value, T>::type>
bool safe_multiplication( int64 a, int64 b, int64& result ); bool safe_substraction( T a, T b, T& result ){
#if __has_builtin( __builtin_sub_overflow ) || ( defined( __GNUC__ ) && !defined( __clang__ ) && defined( GCC_VERSION ) && GCC_VERSION >= 50100 )
return __builtin_sub_overflow( a, b, &result );
#else
bool overflow = false;
if( b < 0 ){
if( a > ( std::numeric_limits<T>::max() + b ) ){
overflow = true;
}
}else{
if( a < ( std::numeric_limits<T>::min() + b ) ){
overflow = true;
}
}
result = a - b;
return overflow;
#endif
}
template <typename T, typename = std::enable_if<std::is_integral<T>::value, T>::type>
bool safe_multiplication( T a, T b, T& result ){
#if __has_builtin( __builtin_mul_overflow ) || ( defined( __GNUC__ ) && !defined( __clang__ ) && defined( GCC_VERSION ) && GCC_VERSION >= 50100 )
return __builtin_mul_overflow( a, b, &result );
#else
result = a * b;
if( a > 0 ){
if( b > 0 ){
return result < 0;
}else if( b < 0 ){
return result > 0;
}
}else if( a < 0 ){
if( b > 0 ){
return result > 0;
}else if( b < 0 ){
return result < 0;
}
}
return false;
#endif
}
/** /**
* Safely add values without overflowing. * Safely add values without overflowing.