diff --git a/common/libeval/numeric_evaluator.cpp b/common/libeval/numeric_evaluator.cpp index 9559a6bee4..8cc26fae32 100644 --- a/common/libeval/numeric_evaluator.cpp +++ b/common/libeval/numeric_evaluator.cpp @@ -192,24 +192,44 @@ void NUMERIC_EVALUATOR::newString( const wxString& aString ) } -// Support for old school decimal separators (ie: "2K2") -bool NUMERIC_EVALUATOR::IsOldSchoolDecimalSeparator( char ch, double* siScaler ) +// Support for old school decimal separators (ie: "2K2") according to IEC 60062 +bool NUMERIC_EVALUATOR::IsOldSchoolDecimalSeparator( wxUniChar ch, double* siScaler ) +{ + if( ch == 'p' ) { *siScaler = 1.0e-12; return true; } + else if( ch == 'n' ) { *siScaler = 1.0e-9; return true; } + else if( ch == wxT( "µ" )[0] ) { *siScaler = 1.0e-6; return true; } + else if( ch == wxT( "μ" )[0] ) { *siScaler = 1.0e-6; return true; } + else if( ch == 'u' ) { *siScaler = 1.0e-6; return true; } + else if( ch == 'm' ) { *siScaler = 1.0e-3; return true; } + else if( ch == 'L' ) { *siScaler = 1.0e-3; return true; } + else if( ch == 'R' ) { *siScaler = 1.0; return true; } + else if( ch == 'F' ) { *siScaler = 1.0; return true; } + else if( ch == 'k' ) { *siScaler = 1.0e3; return true; } + else if( ch == 'K' ) { *siScaler = 1.0e3; return true; } + else if( ch == 'M' ) { *siScaler = 1.0e6; return true; } + else if( ch == 'G' ) { *siScaler = 1.0e9; return true; } + else if( ch == 'T' ) { *siScaler = 1.0e12; return true; } + else return false; +}; + + +// Limited version of above for 8-bit chars +bool NUMERIC_EVALUATOR::isOldSchoolDecimalSeparator( char ch, double* siScaler ) { switch( ch ) { - case 'a': *siScaler = 1.0e-18; return true; - case 'f': *siScaler = 1.0e-15; return true; case 'p': *siScaler = 1.0e-12; return true; case 'n': *siScaler = 1.0e-9; return true; case 'u': *siScaler = 1.0e-6; return true; case 'm': *siScaler = 1.0e-3; return true; - case 'k': + case 'L': *siScaler = 1.0e-3; return true; + case 'R': *siScaler = 1.0; return true; + case 'F': *siScaler = 1.0; return true; + case 'k': *siScaler = 1.0e3; return true; case 'K': *siScaler = 1.0e3; return true; case 'M': *siScaler = 1.0e6; return true; case 'G': *siScaler = 1.0e9; return true; case 'T': *siScaler = 1.0e12; return true; - case 'P': *siScaler = 1.0e15; return true; - case 'E': *siScaler = 1.0e18; return true; default: return false; } }; diff --git a/common/string_utils.cpp b/common/string_utils.cpp index e522c657db..93604511b9 100644 --- a/common/string_utils.cpp +++ b/common/string_utils.cpp @@ -975,7 +975,7 @@ bool WildCompareString( const wxString& pattern, const wxString& string_to_tst, bool ApplyModifier( double& value, const wxString& aString ) { /// Although the two 'μ's look the same, they are U+03BC and U+00B5 - static const wxString modifiers( wxT( "afpnuµμmkKMGTPE" ) ); + static const wxString modifiers( wxT( "afpnuµμmLRFkKMGTPE" ) ); if( !aString.length() ) return false; @@ -1005,6 +1005,7 @@ bool ApplyModifier( double& value, const wxString& aString ) return false; } + // Note: most of these are SI, but some (L, R, F) are IEC 60062. if( modifier == 'a' ) value *= 1.0e-18; else if( modifier == 'f' ) @@ -1015,8 +1016,10 @@ bool ApplyModifier( double& value, const wxString& aString ) value *= 1.0e-9; else if( modifier == 'u' || modifier == wxS( "µ" )[0] || modifier == wxS( "μ" )[0] ) value *= 1.0e-6; - else if( modifier == 'm' ) + else if( modifier == 'm' || modifier == 'L' ) value *= 1.0e-3; + else if( modifier == 'R' || modifier == 'F' ) + ; // unity scalar else if( modifier == 'k' || modifier == 'K' ) value *= 1.0e3; else if( modifier == 'M' ) @@ -1249,14 +1252,14 @@ int SplitString( const wxString& strToSplit, for( ; ii >= 0; ii-- ) { - double dummy; + double scale; wxUniChar c = strToSplit[ii]; if( wxIsdigit( c ) ) { continue; } - if( infix == 0 && NUMERIC_EVALUATOR::IsOldSchoolDecimalSeparator( c, &dummy ) ) + if( infix == 0 && NUMERIC_EVALUATOR::IsOldSchoolDecimalSeparator( c, &scale ) ) { infix = c; continue; @@ -1273,10 +1276,10 @@ int SplitString( const wxString& strToSplit, // If all that was left was digits, then just set the digits string if( ii < 0 ) + { *strDigits = strToSplit.substr( 0, position ); - - /* We were only looking for the last set of digits everything else is - * part of the preamble */ + } + // Otherwise everything else is part of the preamble else { *strDigits = strToSplit.substr( ii + 1, position - ii - 1 ); diff --git a/include/libeval/numeric_evaluator.h b/include/libeval/numeric_evaluator.h index 535b0b17c8..e4596cd02b 100644 --- a/include/libeval/numeric_evaluator.h +++ b/include/libeval/numeric_evaluator.h @@ -156,7 +156,8 @@ public: /* Remove all variables */ void ClearVar() { m_varMap.clear(); } - static bool IsOldSchoolDecimalSeparator( char ch, double* siScaler ); + static bool IsOldSchoolDecimalSeparator( wxUniChar ch, double* siScaler ); + static bool isOldSchoolDecimalSeparator( char ch, double* siScaler ); static bool IsDecimalSeparator( char ch, char localeSeparator, bool allowInfixNotation ); static bool IsDigit( char ch ); diff --git a/qa/tests/common/test_kicad_string.cpp b/qa/tests/common/test_kicad_string.cpp index 2d9313d463..70f764ab17 100644 --- a/qa/tests/common/test_kicad_string.cpp +++ b/qa/tests/common/test_kicad_string.cpp @@ -121,15 +121,17 @@ BOOST_AUTO_TEST_CASE( ValueCompare ) using CASE = std::pair, int>; const std::vector cases = { - { { "100", "10" }, 1 }, - { { "10K", "1K" }, 1 }, - { { "10K", "1K5" }, 1 }, - { { "10K", "10,000" }, 0 }, - { { "1K5", "1.5K" }, 0 }, - { { "1K5", "1,5K" }, 0 }, - { { "K5", "1K" }, -1 }, - { { "1K5", "K55" }, 1 }, - { { "1u5F", "1.5uF" }, 0 }, + { { wxT( "100" ), wxT( "10" ) }, 1 }, + { { wxT( "10K" ), wxT( "1K" ) }, 1 }, + { { wxT( "10K" ), wxT( "1K5" ) }, 1 }, + { { wxT( "10K" ), wxT( "10,000" ) }, 0 }, + { { wxT( "1K5" ), wxT( "1.5K" ) }, 0 }, + { { wxT( "1K5" ), wxT( "1,5K" ) }, 0 }, + { { wxT( "K5" ), wxT( "1K" ) }, -1 }, + { { wxT( "1K5" ), wxT( "K55" ) }, 1 }, + { { wxT( "1R5" ), wxT( "1.5" ) }, 0 }, + { { wxT( "1u5F" ), wxT( "1.5uF" ) }, 0 }, + { { wxT( "1µ5" ), wxT( "1u5" ) }, 0 }, }; for( const auto& c : cases )