diff options
author | Ulf Hermann <ulf.hermann@theqtcompany.com> | 2015-10-19 14:52:19 +0200 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@theqtcompany.com> | 2015-11-23 14:13:42 +0000 |
commit | 15b5b3b3f01e400e46fe67babe593ede373dac4b (patch) | |
tree | 823f6a27092b9647dbe1f4a9004c99e9975e71c7 | |
parent | 726fed0d67013cbfac7921d3d4613ca83406fb0f (diff) |
Add flags to omit/reject padding in scientific notation exponents
The EcmaScript format for printing doubles in exponent form differs
from Qt's format only in this aspect. EcmaScript explicitly prohibits
leading zeroes in exponents. It is thus worthwhile to add those flags
in order to be able to generate and parse doubles in compliance with
EcmaScript.
[ChangeLog][QtCore][QLocale] Additional flags in QLocale::NumberOption
allow generating and parsing doubles in EcmaScript compliant format.
Change-Id: Ia7b82c2e67bb8b80bd890014ff5cd4563faf2a03
Reviewed-by: Lars Knoll <lars.knoll@theqtcompany.com>
-rw-r--r-- | src/corelib/io/qtextstream.cpp | 2 | ||||
-rw-r--r-- | src/corelib/tools/qbytearray.cpp | 4 | ||||
-rw-r--r-- | src/corelib/tools/qlocale.cpp | 90 | ||||
-rw-r--r-- | src/corelib/tools/qlocale.h | 5 | ||||
-rw-r--r-- | src/corelib/tools/qlocale.qdoc | 10 | ||||
-rw-r--r-- | src/corelib/tools/qlocale_p.h | 32 | ||||
-rw-r--r-- | src/corelib/tools/qlocale_tools.cpp | 5 | ||||
-rw-r--r-- | src/corelib/tools/qlocale_tools_p.h | 3 | ||||
-rw-r--r-- | src/corelib/tools/qstring.cpp | 13 | ||||
-rw-r--r-- | src/gui/util/qvalidator.cpp | 11 | ||||
-rw-r--r-- | tests/auto/corelib/tools/qlocale/tst_qlocale.cpp | 14 | ||||
-rw-r--r-- | tests/auto/gui/util/qdoublevalidator/tst_qdoublevalidator.cpp | 57 |
12 files changed, 172 insertions, 74 deletions
diff --git a/src/corelib/io/qtextstream.cpp b/src/corelib/io/qtextstream.cpp index a8fd2dd7ab..adf9e1aa55 100644 --- a/src/corelib/io/qtextstream.cpp +++ b/src/corelib/io/qtextstream.cpp @@ -2545,6 +2545,8 @@ QTextStream &QTextStream::operator<<(double f) flags |= QLocaleData::Alternate; if (locale() != QLocale::c() && !(locale().numberOptions() & QLocale::OmitGroupSeparator)) flags |= QLocaleData::ThousandsGroup; + if (!(locale().numberOptions() & QLocale::OmitLeadingZeroInExponent)) + flags |= QLocaleData::ZeroPadExponent; const QLocaleData *dd = d->locale.d->m_data; QString num = dd->doubleToString(f, d->params.realNumberPrecision, form, -1, flags); diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp index 3a6f5afa60..319af3ca03 100644 --- a/src/corelib/tools/qbytearray.cpp +++ b/src/corelib/tools/qbytearray.cpp @@ -3930,10 +3930,10 @@ QByteArray &QByteArray::setNum(qulonglong n, int base) QByteArray &QByteArray::setNum(double n, char f, int prec) { QLocaleData::DoubleForm form = QLocaleData::DFDecimal; - uint flags = 0; + uint flags = QLocaleData::ZeroPadExponent; if (qIsUpper(f)) - flags = QLocaleData::CapitalEorX; + flags |= QLocaleData::CapitalEorX; f = qToLower(f); switch (f) { diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp index 072d62f5c2..c91d267772 100644 --- a/src/corelib/tools/qlocale.cpp +++ b/src/corelib/tools/qlocale.cpp @@ -521,7 +521,7 @@ int qt_repeatCount(const QString &s, int i) } static const QLocaleData *default_data = 0; -static uint default_number_options = 0; +static QLocale::NumberOptions default_number_options = QLocale::DefaultNumberOptions; static const QLocaleData *const c_data = locale_data; static QLocalePrivate *c_private() @@ -699,7 +699,8 @@ static QLocalePrivate *localePrivateByName(const QString &name) if (name == QLatin1String("C")) return c_private(); const QLocaleData *data = findLocaleData(name); - return QLocalePrivate::create(data, data->m_language_id == QLocale::C ? QLocale::OmitGroupSeparator : 0); + return QLocalePrivate::create(data, data->m_language_id == QLocale::C ? + QLocale::OmitGroupSeparator : QLocale::DefaultNumberOptions); } static QLocalePrivate *findLocalePrivate(QLocale::Language language, QLocale::Script script, @@ -710,7 +711,7 @@ static QLocalePrivate *findLocalePrivate(QLocale::Language language, QLocale::Sc const QLocaleData *data = QLocaleData::findLocaleData(language, script, country); - int numberOptions = 0; + QLocale::NumberOptions numberOptions = QLocale::DefaultNumberOptions; // If not found, should default to system if (data->m_language_id == QLocale::C && language != QLocale::C) { @@ -903,7 +904,7 @@ void QLocale::setNumberOptions(NumberOptions options) */ QLocale::NumberOptions QLocale::numberOptions() const { - return static_cast<NumberOption>(d->m_numberOptions); + return static_cast<NumberOptions>(d->m_numberOptions); } /*! @@ -1071,13 +1072,13 @@ QString QLocale::name() const } static qlonglong toIntegral_helper(const QLocaleData *d, const QChar *data, int len, bool *ok, - QLocaleData::GroupSeparatorMode mode, qlonglong) + QLocale::NumberOptions mode, qlonglong) { return d->stringToLongLong(data, len, 10, ok, mode); } static qulonglong toIntegral_helper(const QLocaleData *d, const QChar *data, int len, bool *ok, - QLocaleData::GroupSeparatorMode mode, qulonglong) + QLocale::NumberOptions mode, qulonglong) { return d->stringToUnsLongLong(data, len, 10, ok, mode); } @@ -1089,13 +1090,8 @@ T toIntegral_helper(const QLocalePrivate *d, const QChar *data, int len, bool *o const bool isUnsigned = T(0) < T(-1); typedef typename QtPrivate::QConditional<isUnsigned, qulonglong, qlonglong>::Type Int64; - QLocaleData::GroupSeparatorMode mode - = d->m_numberOptions & QLocale::RejectGroupSeparator - ? QLocaleData::FailOnGroupSeparators - : QLocaleData::ParseGroupSeparators; - // we select the right overload by the last, unused parameter - Int64 val = toIntegral_helper(d->m_data, data, len, ok, mode, Int64()); + Int64 val = toIntegral_helper(d->m_data, data, len, ok, d->m_numberOptions, Int64()); if (T(val) != val) { if (ok) *ok = false; @@ -1314,12 +1310,7 @@ float QLocale::toFloat(const QString &s, bool *ok) const double QLocale::toDouble(const QString &s, bool *ok) const { - QLocaleData::GroupSeparatorMode mode - = d->m_numberOptions & RejectGroupSeparator - ? QLocaleData::FailOnGroupSeparators - : QLocaleData::ParseGroupSeparators; - - return d->m_data->stringToDouble(s.constData(), s.size(), ok, mode); + return d->m_data->stringToDouble(s.constData(), s.size(), ok, d->m_numberOptions); } /*! @@ -1488,12 +1479,7 @@ float QLocale::toFloat(const QStringRef &s, bool *ok) const double QLocale::toDouble(const QStringRef &s, bool *ok) const { - QLocaleData::GroupSeparatorMode mode - = d->m_numberOptions & RejectGroupSeparator - ? QLocaleData::FailOnGroupSeparators - : QLocaleData::ParseGroupSeparators; - - return d->m_data->stringToDouble(s.constData(), s.size(), ok, mode); + return d->m_data->stringToDouble(s.constData(), s.size(), ok, d->m_numberOptions); } @@ -2019,6 +2005,8 @@ QString QLocale::toString(double i, char f, int prec) const if (!(d->m_numberOptions & OmitGroupSeparator)) flags |= QLocaleData::ThousandsGroup; + if (!(d->m_numberOptions & OmitLeadingZeroInExponent)) + flags |= QLocaleData::ZeroPadExponent; return d->m_data->doubleToString(i, prec, form, -1, flags); } @@ -2787,7 +2775,7 @@ QString QLocaleData::doubleToString(const QChar _zero, const QChar plus, const Q case DFExponent: { num_str = exponentForm(_zero, decimal, exponential, group, plus, minus, digits, decpt, precision, PMDecimalDigits, - always_show_decpt); + always_show_decpt, flags & ZeroPadExponent); break; } case DFDecimal: { @@ -2816,7 +2804,7 @@ QString QLocaleData::doubleToString(const QChar _zero, const QChar plus, const Q if (decpt != digits.length() && (decpt <= -4 || decpt > cutoff)) num_str = exponentForm(_zero, decimal, exponential, group, plus, minus, digits, decpt, precision, mode, - always_show_decpt); + always_show_decpt, flags & ZeroPadExponent); else num_str = decimalForm(_zero, decimal, group, digits, decpt, precision, mode, @@ -3035,9 +3023,8 @@ QString QLocaleData::unsLongLongToString(const QChar zero, const QChar group, number. We can't detect junk here, since we don't even know the base of the number. */ -bool QLocaleData::numberToCLocale(const QChar *str, int len, - GroupSeparatorMode group_sep_mode, - CharBuff *result) const +bool QLocaleData::numberToCLocale(const QChar *str, int len, QLocale::NumberOptions number_options, + CharBuff *result) const { const QChar *uc = str; int l = len; @@ -3059,6 +3046,7 @@ bool QLocaleData::numberToCLocale(const QChar *str, int len, int decpt_idx = -1; int last_separator_idx = -1; int start_of_digits_idx = -1; + int exponent_idx = -1; while (idx < l) { const QChar in = uc[idx]; @@ -3077,7 +3065,19 @@ bool QLocaleData::numberToCLocale(const QChar *str, int len, else break; } - if (group_sep_mode == ParseGroupSeparators) { + + if (number_options & QLocale::RejectLeadingZeroInExponent) { + if (out == 'e' || out == 'E') { + exponent_idx = idx; + } else if (exponent_idx != -1) { + if (out >= '1' && out <= '9') + exponent_idx = -1; // leading digit is not 0, forget exponent_idx + else if (out == '0' && idx < l - 1) + return false; + } + } + + if (!(number_options & QLocale::RejectGroupSeparator)) { if (start_of_digits_idx == -1 && out >= '0' && out <= '9') { start_of_digits_idx = idx; } else if (out == ',') { @@ -3120,7 +3120,7 @@ bool QLocaleData::numberToCLocale(const QChar *str, int len, ++idx; } - if (group_sep_mode == ParseGroupSeparators) { + if (!(number_options & QLocale::RejectGroupSeparator)) { // group separator post-processing // did we end in a separator? if (last_separator_idx + 1 == idx) @@ -3135,7 +3135,7 @@ bool QLocaleData::numberToCLocale(const QChar *str, int len, } bool QLocaleData::validateChars(const QString &str, NumberMode numMode, QByteArray *buff, - int decDigits, bool rejectGroupSeparators) const + int decDigits, QLocale::NumberOptions number_options) const { buff->clear(); buff->reserve(str.length()); @@ -3157,6 +3157,13 @@ bool QLocaleData::validateChars(const QString &str, NumberMode numMode, QByteArr if (dec && decDigits != -1 && decDigits < ++decDigitCnt) return false; } + + // The only non-digit character after the 'e' can be '+' or '-'. + // If a zero is directly after that, then the exponent is zero-padded. + if ((number_options & QLocale::RejectLeadingZeroInExponent) && c == '0' && eCnt > 0 && + !lastWasDigit) + return false; + lastWasDigit = true; } else { switch (c) { @@ -3196,7 +3203,8 @@ bool QLocaleData::validateChars(const QString &str, NumberMode numMode, QByteArr case ',': //it can only be placed after a digit which is before the decimal point - if (rejectGroupSeparators || !lastWasDigit || decPointCnt > 0) + if ((number_options & QLocale::RejectGroupSeparator) || !lastWasDigit || + decPointCnt > 0) return false; break; @@ -3228,10 +3236,10 @@ bool QLocaleData::validateChars(const QString &str, NumberMode numMode, QByteArr } double QLocaleData::stringToDouble(const QChar *begin, int len, bool *ok, - GroupSeparatorMode group_sep_mode) const + QLocale::NumberOptions number_options) const { CharBuff buff; - if (!numberToCLocale(begin, len, group_sep_mode, &buff)) { + if (!numberToCLocale(begin, len, number_options, &buff)) { if (ok != 0) *ok = false; return 0.0; @@ -3244,11 +3252,11 @@ double QLocaleData::stringToDouble(const QChar *begin, int len, bool *ok, return d; } -qlonglong QLocaleData::stringToLongLong(const QChar *begin, int len, int base, - bool *ok, GroupSeparatorMode group_sep_mode) const +qlonglong QLocaleData::stringToLongLong(const QChar *begin, int len, int base, bool *ok, + QLocale::NumberOptions number_options) const { CharBuff buff; - if (!numberToCLocale(begin, len, group_sep_mode, &buff)) { + if (!numberToCLocale(begin, len, number_options, &buff)) { if (ok != 0) *ok = false; return 0; @@ -3257,11 +3265,11 @@ qlonglong QLocaleData::stringToLongLong(const QChar *begin, int len, int base, return bytearrayToLongLong(buff.constData(), base, ok); } -qulonglong QLocaleData::stringToUnsLongLong(const QChar *begin, int len, int base, - bool *ok, GroupSeparatorMode group_sep_mode) const +qulonglong QLocaleData::stringToUnsLongLong(const QChar *begin, int len, int base, bool *ok, + QLocale::NumberOptions number_options) const { CharBuff buff; - if (!numberToCLocale(begin, len, group_sep_mode, &buff)) { + if (!numberToCLocale(begin, len, number_options, &buff)) { if (ok != 0) *ok = false; return 0; diff --git a/src/corelib/tools/qlocale.h b/src/corelib/tools/qlocale.h index f64a25bd00..e90354138c 100644 --- a/src/corelib/tools/qlocale.h +++ b/src/corelib/tools/qlocale.h @@ -843,8 +843,11 @@ public: enum FormatType { LongFormat, ShortFormat, NarrowFormat }; enum NumberOption { + DefaultNumberOptions = 0x0, OmitGroupSeparator = 0x01, - RejectGroupSeparator = 0x02 + RejectGroupSeparator = 0x02, + OmitLeadingZeroInExponent = 0x04, + RejectLeadingZeroInExponent = 0x08 }; Q_DECLARE_FLAGS(NumberOptions, NumberOption) diff --git a/src/corelib/tools/qlocale.qdoc b/src/corelib/tools/qlocale.qdoc index 03095d88d2..76195ab666 100644 --- a/src/corelib/tools/qlocale.qdoc +++ b/src/corelib/tools/qlocale.qdoc @@ -930,12 +930,22 @@ conversions. They can be retrieved with numberOptions() and set with setNumberOptions(). + \value DefaultNumberOptions This option represents the default behavior, with + group separators and with one leading zero in single digit exponents. \value OmitGroupSeparator If this option is set, the number-to-string functions will not insert group separators in their return values. The default is to insert group separators. \value RejectGroupSeparator If this option is set, the string-to-number functions will fail if they encounter group separators in their input. The default is to accept numbers containing correctly placed group separators. + \value OmitLeadingZeroInExponent If this option is set, the number-to-string + functions will not pad exponents with zeroes when printing floating point + numbers in scientific notation. The default is to add one leading zero to + single digit exponents. + \value RejectLeadingZeroInExponent If this option is set, the string-to-number + functions will fail if they encounter an exponent padded with zeroes when + parsing a floating point number in scientific notation. The default is to + accept such padding. \sa setNumberOptions(), numberOptions() */ diff --git a/src/corelib/tools/qlocale_p.h b/src/corelib/tools/qlocale_p.h index d943612ff1..65d4d58def 100644 --- a/src/corelib/tools/qlocale_p.h +++ b/src/corelib/tools/qlocale_p.h @@ -195,14 +195,10 @@ public: ShowBase = 0x80, UppercaseBase = 0x100, + ZeroPadExponent = 0x200, ForcePoint = Alternate }; - enum GroupSeparatorMode { - FailOnGroupSeparators, - ParseGroupSeparators - }; - enum NumberMode { IntegerMode, DoubleStandardMode, DoubleScientificMode }; typedef QVarLengthArray<char, 256> CharBuff; @@ -250,24 +246,26 @@ public: return float(d); } - double stringToDouble(const QChar *begin, int len, bool *ok, GroupSeparatorMode group_sep_mode) const; - qint64 stringToLongLong(const QChar *begin, int len, int base, bool *ok, GroupSeparatorMode group_sep_mode) const; - quint64 stringToUnsLongLong(const QChar *begin, int len, int base, bool *ok, GroupSeparatorMode group_sep_mode) const; + double stringToDouble(const QChar *begin, int len, bool *ok, + QLocale::NumberOptions number_options) const; + qint64 stringToLongLong(const QChar *begin, int len, int base, bool *ok, + QLocale::NumberOptions number_options) const; + quint64 stringToUnsLongLong(const QChar *begin, int len, int base, bool *ok, + QLocale::NumberOptions number_options) const; // these functions are used in QIntValidator (QtGui) Q_CORE_EXPORT static double bytearrayToDouble(const char *num, bool *ok, bool *overflow = 0); Q_CORE_EXPORT static qint64 bytearrayToLongLong(const char *num, int base, bool *ok, bool *overflow = 0); Q_CORE_EXPORT static quint64 bytearrayToUnsLongLong(const char *num, int base, bool *ok); - bool numberToCLocale(const QChar *str, int len, - GroupSeparatorMode group_sep_mode, - CharBuff *result) const; + bool numberToCLocale(const QChar *str, int len, QLocale::NumberOptions number_options, + CharBuff *result) const; inline char digitToCLocale(QChar c) const; // this function is used in QIntValidator (QtGui) - Q_CORE_EXPORT bool validateChars(const QString &str, NumberMode numMode, - QByteArray *buff, int decDigits = -1, - bool rejectGroupSeparators = false) const; + Q_CORE_EXPORT bool validateChars( + const QString &str, NumberMode numMode, QByteArray *buff, int decDigits = -1, + QLocale::NumberOptions number_options = QLocale::DefaultNumberOptions) const; public: quint16 m_language_id, m_script_id, m_country_id; @@ -315,7 +313,9 @@ public: class Q_CORE_EXPORT QLocalePrivate { public: - static QLocalePrivate *create(const QLocaleData *data, int numberOptions = 0) + static QLocalePrivate *create( + const QLocaleData *data, + QLocale::NumberOptions numberOptions = QLocale::DefaultNumberOptions) { QLocalePrivate *retval = new QLocalePrivate; retval->m_data = data; @@ -362,7 +362,7 @@ public: const QLocaleData *m_data; QBasicAtomicInt ref; - quint16 m_numberOptions; + QLocale::NumberOptions m_numberOptions; }; template <> diff --git a/src/corelib/tools/qlocale_tools.cpp b/src/corelib/tools/qlocale_tools.cpp index 890f63af0a..cdc654904e 100644 --- a/src/corelib/tools/qlocale_tools.cpp +++ b/src/corelib/tools/qlocale_tools.cpp @@ -495,7 +495,8 @@ QString &exponentForm(QChar zero, QChar decimal, QChar exponential, QChar group, QChar plus, QChar minus, QString &digits, int decpt, int precision, PrecisionMode pm, - bool always_show_decpt) + bool always_show_decpt, + bool leading_zero_in_exponent) { int exp = decpt - 1; @@ -515,7 +516,7 @@ QString &exponentForm(QChar zero, QChar decimal, QChar exponential, digits.append(exponential); digits.append(QLocaleData::longLongToString(zero, group, plus, minus, - exp, 2, 10, -1, QLocaleData::AlwaysShowSign)); + exp, leading_zero_in_exponent ? 2 : 1, 10, -1, QLocaleData::AlwaysShowSign)); return digits; } diff --git a/src/corelib/tools/qlocale_tools_p.h b/src/corelib/tools/qlocale_tools_p.h index 3ddf75d000..3a8036c642 100644 --- a/src/corelib/tools/qlocale_tools_p.h +++ b/src/corelib/tools/qlocale_tools_p.h @@ -89,7 +89,8 @@ QString &exponentForm(QChar zero, QChar decimal, QChar exponential, QChar group, QChar plus, QChar minus, QString &digits, int decpt, int precision, PrecisionMode pm, - bool always_show_decpt); + bool always_show_decpt, + bool leading_zero_in_exponent); inline bool isZero(double d) { diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index e34e2e7612..1cb5e4ff06 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -5877,7 +5877,7 @@ static void append_utf8(QString &qs, const char *cs, int len) static uint parse_flag_characters(const char * &c) Q_DECL_NOTHROW { - uint flags = 0; + uint flags = QLocaleData::ZeroPadExponent; while (true) { switch (*c) { case '#': flags |= QLocaleData::Alternate; break; @@ -6249,7 +6249,7 @@ qlonglong QString::toIntegral_helper(const QChar *data, int len, bool *ok, int b } #endif - return QLocaleData::c()->stringToLongLong(data, len, base, ok, QLocaleData::FailOnGroupSeparators); + return QLocaleData::c()->stringToLongLong(data, len, base, ok, QLocale::RejectGroupSeparator); } @@ -6289,7 +6289,8 @@ qulonglong QString::toIntegral_helper(const QChar *data, uint len, bool *ok, int } #endif - return QLocaleData::c()->stringToUnsLongLong(data, len, base, ok, QLocaleData::FailOnGroupSeparators); + return QLocaleData::c()->stringToUnsLongLong(data, len, base, ok, + QLocale::RejectGroupSeparator); } /*! @@ -6490,7 +6491,7 @@ ushort QString::toUShort(bool *ok, int base) const double QString::toDouble(bool *ok) const { - return QLocaleData::c()->stringToDouble(constData(), size(), ok, QLocaleData::FailOnGroupSeparators); + return QLocaleData::c()->stringToDouble(constData(), size(), ok, QLocale::RejectGroupSeparator); } /*! @@ -7738,6 +7739,8 @@ QString QString::arg(double a, int fieldWidth, char fmt, int prec, QChar fillCha if (!(locale.numberOptions() & QLocale::OmitGroupSeparator)) flags |= QLocaleData::ThousandsGroup; + if (!(locale.numberOptions() & QLocale::OmitLeadingZeroInExponent)) + flags |= QLocaleData::ZeroPadExponent; locale_arg = locale.d->m_data->doubleToString(a, prec, form, fieldWidth, flags); } @@ -10458,7 +10461,7 @@ ushort QStringRef::toUShort(bool *ok, int base) const double QStringRef::toDouble(bool *ok) const { - return QLocaleData::c()->stringToDouble(constData(), size(), ok, QLocaleData::FailOnGroupSeparators); + return QLocaleData::c()->stringToDouble(constData(), size(), ok, QLocale::RejectGroupSeparator); } /*! diff --git a/src/gui/util/qvalidator.cpp b/src/gui/util/qvalidator.cpp index 4a92b7ea3a..aceda62a2a 100644 --- a/src/gui/util/qvalidator.cpp +++ b/src/gui/util/qvalidator.cpp @@ -399,8 +399,8 @@ static qlonglong pow10(int exp) QValidator::State QIntValidator::validate(QString & input, int&) const { QByteArray buff; - if (!locale().d->m_data->validateChars(input, QLocaleData::IntegerMode, &buff, - -1, locale().numberOptions() & QLocale::RejectGroupSeparator)) { + if (!locale().d->m_data->validateChars(input, QLocaleData::IntegerMode, &buff, -1, + locale().numberOptions())) { return Invalid; } @@ -439,8 +439,8 @@ QValidator::State QIntValidator::validate(QString & input, int&) const void QIntValidator::fixup(QString &input) const { QByteArray buff; - if (!locale().d->m_data->validateChars(input, QLocaleData::IntegerMode, &buff, - -1, locale().numberOptions() & QLocale::RejectGroupSeparator)) { + if (!locale().d->m_data->validateChars(input, QLocaleData::IntegerMode, &buff, -1, + locale().numberOptions())) { return; } bool ok, overflow; @@ -663,8 +663,7 @@ QValidator::State QDoubleValidatorPrivate::validateWithLocale(QString &input, QL { Q_Q(const QDoubleValidator); QByteArray buff; - if (!locale.d->m_data->validateChars(input, numMode, &buff, q->dec, - locale.numberOptions() & QLocale::RejectGroupSeparator)) { + if (!locale.d->m_data->validateChars(input, numMode, &buff, q->dec, locale.numberOptions())) { return QValidator::Invalid; } diff --git a/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp b/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp index 683f7490e5..ee45f95d83 100644 --- a/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp +++ b/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp @@ -1698,6 +1698,20 @@ void tst_QLocale::numberOptions() QLocale locale2 = locale; QCOMPARE(locale2.numberOptions(), QLocale::RejectGroupSeparator); + + QCOMPARE(locale.toString(12.4, 'e', 2), QString("1.24e+01")); + locale.setNumberOptions(QLocale::OmitLeadingZeroInExponent); + QCOMPARE(locale.numberOptions(), QLocale::OmitLeadingZeroInExponent); + QCOMPARE(locale.toString(12.4, 'e', 2), QString("1.24e+1")); + + locale.toDouble(QString("1.24e+01"), &ok); + QVERIFY(ok); + locale.setNumberOptions(QLocale::RejectLeadingZeroInExponent); + QCOMPARE(locale.numberOptions(), QLocale::RejectLeadingZeroInExponent); + locale.toDouble(QString("1.24e+1"), &ok); + QVERIFY(ok); + locale.toDouble(QString("1.24e+01"), &ok); + QVERIFY(!ok); } void tst_QLocale::negativeNumbers() diff --git a/tests/auto/gui/util/qdoublevalidator/tst_qdoublevalidator.cpp b/tests/auto/gui/util/qdoublevalidator/tst_qdoublevalidator.cpp index 78ab769137..f810a92dc5 100644 --- a/tests/auto/gui/util/qdoublevalidator/tst_qdoublevalidator.cpp +++ b/tests/auto/gui/util/qdoublevalidator/tst_qdoublevalidator.cpp @@ -43,6 +43,8 @@ class tst_QDoubleValidator : public QObject private slots: void validate_data(); void validate(); + void zeroPaddedExponent_data(); + void zeroPaddedExponent(); void validateThouSep_data(); void validateThouSep(); void validateIntEquiv_data(); @@ -240,6 +242,61 @@ void tst_QDoubleValidator::validate() dv.setNotation(QDoubleValidator::StandardNotation); QCOMPARE((int)dv.validate(value, dummy), (int)standard_state); } + +void tst_QDoubleValidator::zeroPaddedExponent_data() +{ + QTest::addColumn<double>("minimum"); + QTest::addColumn<double>("maximum"); + QTest::addColumn<int>("decimals"); + QTest::addColumn<QString>("value"); + QTest::addColumn<bool>("rejectZeroPaddedExponent"); + QTest::addColumn<QValidator::State>("state"); + + QTest::newRow("data01") << 1229.0 << 1231.0 << 0 << QString("123e+1") << false << ACC; + QTest::newRow("data02") << 12290.0 << 12310.0 << 0 << QString("123e2") << false << ACC; + QTest::newRow("data03") << 12.290 << 12.310 << 2 << QString("123e-") << false << ITM; + QTest::newRow("data04") << 12.290 << 12.310 << 2 << QString("123e-1") << false << ACC; + QTest::newRow("data05") << 1.2290 << 1.2310 << 3 << QString("123e-2") << false << ACC; + + QTest::newRow("data11") << 1229.0 << 1231.0 << 0 << QString("123e+1") << true << ACC; + QTest::newRow("data12") << 12290.0 << 12310.0 << 0 << QString("123e2") << true << ACC; + QTest::newRow("data13") << 12.290 << 12.310 << 2 << QString("123e-") << true << ITM; + QTest::newRow("data14") << 12.290 << 12.310 << 2 << QString("123e-1") << true << ACC; + QTest::newRow("data15") << 1.2290 << 1.2310 << 3 << QString("123e-2") << true << ACC; + + QTest::newRow("data21") << 1229.0 << 1231.0 << 0 << QString("123e+01") << false << ACC; + QTest::newRow("data22") << 12290.0 << 12310.0 << 0 << QString("123e02") << false << ACC; + QTest::newRow("data23") << 12.290 << 12.310 << 2 << QString("123e-0") << false << ITM; + QTest::newRow("data24") << 12.290 << 12.310 << 2 << QString("123e-01") << false << ACC; + QTest::newRow("data25") << 1.2290 << 1.2310 << 3 << QString("123e-02") << false << ACC; + + QTest::newRow("data31") << 1229.0 << 1231.0 << 0 << QString("123e+01") << true << INV; + QTest::newRow("data32") << 12290.0 << 12310.0 << 0 << QString("123e02") << true << INV; + QTest::newRow("data33") << 12.290 << 12.310 << 2 << QString("123e-0") << true << INV; + QTest::newRow("data34") << 12.290 << 12.310 << 2 << QString("123e-01") << true << INV; + QTest::newRow("data35") << 1.2290 << 1.2310 << 3 << QString("123e-02") << true << INV; + +} + +void tst_QDoubleValidator::zeroPaddedExponent() +{ + QFETCH(double, minimum); + QFETCH(double, maximum); + QFETCH(int, decimals); + QFETCH(QString, value); + QFETCH(bool, rejectZeroPaddedExponent); + QFETCH(QValidator::State, state); + + QLocale locale(QLocale::C); + if (rejectZeroPaddedExponent) + locale.setNumberOptions(QLocale::RejectLeadingZeroInExponent); + + QDoubleValidator dv(minimum, maximum, decimals, 0); + dv.setLocale(locale); + int dummy; + QCOMPARE((int)dv.validate(value, dummy), (int)state); +} + void tst_QDoubleValidator::notifySignals() { QLocale::setDefault(QLocale("C")); |