diff options
author | Eike Rathke <erack@redhat.com> | 2012-04-03 20:57:19 +0200 |
---|---|---|
committer | Eike Rathke <erack@redhat.com> | 2012-04-03 20:57:19 +0200 |
commit | 35fed09a0c5560b56ba53c64da8dea28bf88acff (patch) | |
tree | 6314c60575b1cf4325f38bbb3cf2747b6c0be7a7 /sc | |
parent | d701d7b68344854b9a67583bbd38f40d061e6cb4 (diff) |
resolved fdo#39716 CSV import numbers in scientific notation
Diffstat (limited to 'sc')
-rw-r--r-- | sc/source/core/tool/stringutil.cxx | 52 |
1 files changed, 42 insertions, 10 deletions
diff --git a/sc/source/core/tool/stringutil.cxx b/sc/source/core/tool/stringutil.cxx index 58e84e943766..263e22c8b711 100644 --- a/sc/source/core/tool/stringutil.cxx +++ b/sc/source/core/tool/stringutil.cxx @@ -48,9 +48,15 @@ ScSetStringParam::ScSetStringParam() : bool ScStringUtil::parseSimpleNumber( const OUString& rStr, sal_Unicode dsep, sal_Unicode gsep, double& rVal) { - if (gsep == 0x00A0) - // unicode space to ascii space - gsep = 0x0020; + // Actually almost the entire pre-check is unnecessary and we could call + // rtl::math::stringToDouble() just after having exchanged ascii space with + // non-breaking space, if it wasn't for check of grouped digits. The NaN + // and Inf cases that are accepted by stringToDouble() could be detected + // using rtl::math::isFinite() on the result. + + /* TODO: The grouped digits check isn't even valid for locales that do not + * group in thousands ... e.g. Indian locales. But that's something also + * the number scanner doesn't implement yet, only the formatter. */ OUStringBuffer aBuf; @@ -60,6 +66,7 @@ bool ScStringUtil::parseSimpleNumber( const sal_Unicode* pLast = p + (n-1); sal_Int32 nPosDSep = -1, nPosGSep = -1; sal_uInt32 nDigitCount = 0; + sal_Int32 nPosExponent = -1; // Skip preceding spaces. for (i = 0; i < n; ++i, ++p) @@ -88,9 +95,9 @@ bool ScStringUtil::parseSimpleNumber( for (i = 0; i < n; ++i, ++p) { sal_Unicode c = *p; - if (c == 0x00A0) - // unicode space to ascii space - c = 0x0020; + if (c == 0x0020 && gsep == 0x00A0) + // ascii space to unicode space if that is group separator + c = 0x00A0; if (sal_Unicode('0') <= c && c <= sal_Unicode('9')) { @@ -132,17 +139,40 @@ bool ScStringUtil::parseSimpleNumber( // must be exactly 3 digits since the last group separator. return false; + if (nPosExponent >= 0) + // not allowed in exponent. + return false; + nPosGSep = i; nDigitCount = 0; } else if (c == sal_Unicode('-') || c == sal_Unicode('+')) { - // A sign must be the first character if it's given. - if (i == 0) + // A sign must be the first character if it's given, or immediately + // follow the exponent character if present. + if (i == 0 || (nPosExponent >= 0 && i == nPosExponent + 1)) aBuf.append(c); else return false; } + else if (c == sal_Unicode('E') || c == sal_Unicode('e')) + { + // this is an exponent designator. + + if (nPosExponent >= 0) + // Only one exponent allowed. + return false; + + if (nPosGSep >= 0 && nDigitCount != 3) + // must be exactly 3 digits since the last group separator. + return false; + + aBuf.append(c); + nPosExponent = i; + nPosDSep = -1; + nPosGSep = -1; + nDigitCount = 0; + } else return false; } @@ -155,8 +185,10 @@ bool ScStringUtil::parseSimpleNumber( rtl_math_ConversionStatus eStatus = rtl_math_ConversionStatus_Ok; sal_Int32 nParseEnd = 0; - rVal = ::rtl::math::stringToDouble(aBuf.makeStringAndClear(), dsep, gsep, &eStatus, &nParseEnd); - if (eStatus != rtl_math_ConversionStatus_Ok) + OUString aString( aBuf.makeStringAndClear()); + rVal = ::rtl::math::stringToDouble( aString, dsep, gsep, &eStatus, &nParseEnd); + if (eStatus != rtl_math_ConversionStatus_Ok || nParseEnd < aString.getLength()) + // Not a valid number or not entire string consumed. return false; return true; |