//| Copyright: (C) 2020-2024 Kevin Larke //| License: GNU GPL version 3.0 or above. See the accompanying LICENSE file. #ifndef cwNumericConvert_H #define cwNumericConvert_H namespace cw { /* template< typename T > T minimum_value() { return 0; } template <> inline char minimum_value(){ return 0; } template <> inline int8_t minimum_value(){ return INT8_MIN; } template <> inline int16_t minimum_value(){ return INT16_MIN; } template <> inline int32_t minimum_value(){ return INT32_MIN; } template <> inline int64_t minimum_value(){ return INT64_MIN; } template <> inline float minimum_value(){ return FLT_MIN; } template <> inline double minimum_value(){ return DBL_MIN; } template< typename T > T maximum_value() { cwAssert(0); } template <> inline char maximum_value(){ return 255; } template <> inline int8_t maximum_value(){ return INT8_MAX; } template <> inline int16_t maximum_value(){ return INT16_MAX; } template <> inline int32_t maximum_value(){ return INT32_MAX; } template <> inline int64_t maximum_value(){ return INT64_MAX; } template <> inline uint8_t maximum_value(){ return UINT8_MAX; } template <> inline uint16_t maximum_value(){ return UINT16_MAX; } template <> inline uint32_t maximum_value(){ return UINT32_MAX; } template <> inline uint64_t maximum_value(){ return UINT64_MAX; } template <> inline bool maximum_value(){ std::numeric_limits::max(); } template <> inline float maximum_value(){ return FLT_MAX; } template <> inline double maximum_value(){ return DBL_MAX; } */ template< typename SRC_t, typename DST_t > rc_t numeric_convert( const SRC_t& src, DST_t& dst ) { // TODO: there is probably a way of using type_traits to make a more efficient comparison // and avoid the double conversion double d_min = 0; // std::numeric_limits::min() return smallest positive number which then fails this test when 'src' is zero. double d_max = std::numeric_limits::max(); if( (double)src <= d_max ) dst = src; else return cwLogError(kInvalidArgRC,"Numeric conversion failed. The source value is outside the range of the destination value. min:%f max:%f src:%f",d_min,d_max,(double)src ); return kOkRC; } template< typename SRC_t, typename DST_t > rc_t numeric_convert2( const SRC_t& src, DST_t& dst, const DST_t& minv, const DST_t& maxv ) { if( sizeof(SRC_t) < sizeof(DST_t) ) { dst = src; } else { if( minv <= src && src <= maxv ) dst = src; else { return cwLogError(kInvalidArgRC,"Numeric conversion failed. The source value is outside the range of the destination value." ); } } return kOkRC; } template< typename T > rc_t string_to_number( const char* s, T& valueRef ) { if( s == nullptr ) valueRef = 0; // BUG BUG BUG why is this not an error ???? else { int base = 10; errno = 0; if( strlen(s) >= 2 && s[0]=='0' && s[1]=='x' ) base = 16; long v = strtol(s,nullptr,base); if( v == 0 && errno != 0) return cwLogError(kOpFailRC,"String to number conversion failed on '%s'.", cwStringNullGuard(s)); return numeric_convert(v,valueRef); } return kOkRC; } template < > inline rc_t string_to_number( const char* s, double& valueRef ) { if( s == nullptr ) valueRef = 0; // BUG BUG BUG why is this not an error ???? else { errno = 0; valueRef = strtod(s,nullptr); if( valueRef == 0 && errno != 0) return cwLogError(kOpFailRC,"String to number conversion failed on '%s'.", cwStringNullGuard(s)); } return kOkRC; } template < > inline rc_t string_to_number( const char* s, float& valueRef ) { double d; rc_t rc; if((rc = string_to_number(s,d)) != kOkRC ) return rc; return numeric_convert(d,valueRef); } template < > inline rc_t string_to_number( const char* s, bool& valueRef ) { s = nextNonWhiteChar(s); if( s == nullptr ) valueRef = false; // BUG BUG BUG why is this not an error ???? else { if( strncmp( "true", s, 4) == 0 ) valueRef = true; else if( strncmp( "false", s, 5) == 0 ) valueRef = false; else return cwLogError(kOpFailRC,"String to number conversion failed on '%s'.", cwStringNullGuard(s)); } return kOkRC; } template< typename T > int number_to_string( const T& v, char* buf, int bufN, const char* fmt=nullptr ) { return snprintf(buf,bufN,fmt,v); } template < > inline int number_to_string( const int& v, char* buf, int bufN, const char* fmt ) { return snprintf(buf,bufN,fmt==nullptr ? "%i" : fmt, v); } template < > inline int number_to_string( const unsigned& v, char* buf, int bufN, const char* fmt ) { return snprintf(buf,bufN,fmt==nullptr ? "%i" : fmt, v); } template < > inline int number_to_string( const double& v, char* buf, int bufN, const char* fmt ) { return snprintf(buf,bufN,fmt==nullptr ? "%f" : fmt, v); } rc_t numericConvertTest( const test::test_args_t& args ); } #endif