diff options
author | Eike Rathke <erack@redhat.com> | 2017-10-27 18:00:32 +0200 |
---|---|---|
committer | Eike Rathke <erack@redhat.com> | 2017-10-27 18:29:44 +0200 |
commit | 7616e1c18869cda8a924e26337e3f1c83cbb7efe (patch) | |
tree | 3f9e4e7b290ab7f91d03c0e1ca8b5aa11bcfa376 | |
parent | dc520c7759fde6e765afece23b78b5ca6dece5b1 (diff) |
LocaleDataWrapper::stringToDouble() w/ decimalSeparatorAlternative, tdf#81671
To be used instead of rtl::math::stringToDouble() if locale
dependent separators are involved.
Change-Id: I54359c981901dc57b3d9312b0bfd2f2a14fccb33
-rw-r--r-- | include/unotools/localedatawrapper.hxx | 59 | ||||
-rw-r--r-- | unotools/source/i18n/localedatawrapper.cxx | 41 |
2 files changed, 100 insertions, 0 deletions
diff --git a/include/unotools/localedatawrapper.hxx b/include/unotools/localedatawrapper.hxx index a5f1988f1db4..02b416250adc 100644 --- a/include/unotools/localedatawrapper.hxx +++ b/include/unotools/localedatawrapper.hxx @@ -24,6 +24,7 @@ #include <com/sun/star/i18n/LocaleItem.hpp> #include <com/sun/star/i18n/reservedWords.hpp> #include <rtl/ustring.hxx> +#include <rtl/math.h> #include <i18nlangtag/languagetag.hxx> #include <unotools/readwritemutexguard.hxx> #include <unotools/unotoolsdllapi.h> @@ -240,6 +241,64 @@ public: const OUString& getLongDateYearSep() const { return getOneLocaleItem( css::i18n::LocaleItem::LONG_DATE_YEAR_SEPARATOR ); } + /** A wrapper around rtl::math::stringToDouble() using the locale dependent + decimal separator, group separator, and if needed decimal separator + alternative. + + The decimal separator is tried first, if the conversion does not match + the entire string then the decimal separator alternative is tried if it + occurs in the string and was the reason to stop. + + Leading blanks are skipped, trailing blanks are not skipped. The number + is parsed up to the first non-floating point number character, same as + rtl::math::stringToDouble() does. The caller is responsible for proper + error checking and end comparison. + + @param rString + The string to parse as floating point number. + @param bUseGroupSep + Whether group separator is used/accepted during parsing. + @param pStatus + Pointer to receive the conversion status as in + rtl::math::stringToDouble(). + @param pParseEnd + Pointer to receive the parse end (exclusive) as in + rtl::math::stringToDouble(). + @return The floating point number as parsed. + */ + double stringToDouble( const OUString& rString, bool bUseGroupSep, + rtl_math_ConversionStatus* pStatus, sal_Int32* pParseEnd ) const; + + /** A wrapper around rtl_math_uStringToDouble() using the locale dependent + decimal separator, group separator, and if needed decimal separator + alternative. + + The decimal separator is tried first, if the conversion does not match + the entire string then the decimal separator alternative is tried if it + occurs in the string and was the reason to stop. + + Leading blanks are skipped, trailing blanks are not skipped. The number + is parsed up to the first non-floating point number character, same as + rtl_math_uStringToDouble() does. The caller is responsible for proper + error checking and end comparison. + + @param pBegin + The string position to start parsing a floating point number. + @param pEnd + The string position to stop parsing, exclusive. + @param bUseGroupSep + Whether group separator is used/accepted during parsing. + @param pStatus + Pointer to receive the conversion status as in + rtl_math_uStringToDouble(). + @param pParseEnd + Pointer to receive the parse end (exclusive) as in + rtl_math_uStringToDouble(). + @return The floating point number as parsed. + */ + double stringToDouble( const sal_Unicode* pBegin, const sal_Unicode* pEnd, bool bUseGroupSep, + rtl_math_ConversionStatus* pStatus, const sal_Unicode** ppParseEnd ) const; + // currency const OUString& getCurrSymbol() const; const OUString& getCurrBankSymbol() const; diff --git a/unotools/source/i18n/localedatawrapper.cxx b/unotools/source/i18n/localedatawrapper.cxx index 52269c291fcc..2f125f6b8e14 100644 --- a/unotools/source/i18n/localedatawrapper.cxx +++ b/unotools/source/i18n/localedatawrapper.cxx @@ -41,6 +41,7 @@ #include <rtl/ustrbuf.hxx> #include <osl/diagnose.h> #include <sal/macros.h> +#include <rtl/math.hxx> static const sal_uInt16 nCurrFormatInvalid = 0xffff; static const sal_uInt16 nCurrFormatDefault = 0; @@ -1747,6 +1748,46 @@ OUString LocaleDataWrapper::getCurr( sal_Int64 nNumber, sal_uInt16 nDecimals, return aNumber; } +// --- number parsing ------------------------------------------------- + +double LocaleDataWrapper::stringToDouble( const OUString& rString, bool bUseGroupSep, + rtl_math_ConversionStatus* pStatus, sal_Int32* pParseEnd ) const +{ + const sal_Unicode cGroupSep = (bUseGroupSep ? getNumThousandSep()[0] : 0); + rtl_math_ConversionStatus eStatus = rtl_math_ConversionStatus_Ok; + sal_Int32 nParseEnd = 0; + double fValue = rtl::math::stringToDouble( rString, getNumDecimalSep()[0], cGroupSep, &eStatus, &nParseEnd); + bool bTryAlt = (nParseEnd < rString.getLength() && !getNumDecimalSepAlt().isEmpty() && + rString[nParseEnd] == getNumDecimalSepAlt().toChar()); + // Try re-parsing with alternative if that was the reason to stop. + if (bTryAlt) + fValue = rtl::math::stringToDouble( rString, getNumDecimalSepAlt().toChar(), cGroupSep, &eStatus, &nParseEnd); + if (pStatus) + *pStatus = eStatus; + if (pParseEnd) + *pParseEnd = nParseEnd; + return fValue; +} + +double LocaleDataWrapper::stringToDouble( const sal_Unicode* pBegin, const sal_Unicode* pEnd, bool bUseGroupSep, + rtl_math_ConversionStatus* pStatus, const sal_Unicode** ppParseEnd ) const +{ + const sal_Unicode cGroupSep = (bUseGroupSep ? getNumThousandSep()[0] : 0); + rtl_math_ConversionStatus eStatus = rtl_math_ConversionStatus_Ok; + const sal_Unicode* pParseEnd = nullptr; + double fValue = rtl_math_uStringToDouble( pBegin, pEnd, getNumDecimalSep()[0], cGroupSep, &eStatus, &pParseEnd); + bool bTryAlt = (pParseEnd < pEnd && !getNumDecimalSepAlt().isEmpty() && + *pParseEnd == getNumDecimalSepAlt().toChar()); + // Try re-parsing with alternative if that was the reason to stop. + if (bTryAlt) + fValue = rtl_math_uStringToDouble( pBegin, pEnd, getNumDecimalSepAlt().toChar(), cGroupSep, &eStatus, &pParseEnd); + if (pStatus) + *pStatus = eStatus; + if (ppParseEnd) + *ppParseEnd = pParseEnd; + return fValue; +} + // --- mixed ---------------------------------------------------------- LanguageTag LocaleDataWrapper::getLoadedLanguageTag() const |