summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/text/qlocale.cpp28
-rw-r--r--src/corelib/text/qlocale_p.h18
-rw-r--r--src/gui/util/qvalidator.cpp48
3 files changed, 57 insertions, 37 deletions
diff --git a/src/corelib/text/qlocale.cpp b/src/corelib/text/qlocale.cpp
index b5edfdefe8..87a6585421 100644
--- a/src/corelib/text/qlocale.cpp
+++ b/src/corelib/text/qlocale.cpp
@@ -4205,11 +4205,12 @@ bool QLocaleData::numberToCLocale(QStringView s, QLocale::NumberOptions number_o
return true;
}
-bool QLocaleData::validateChars(QStringView str, NumberMode numMode, QByteArray *buff,
- int decDigits, QLocale::NumberOptions number_options) const
+ParsingResult
+QLocaleData::validateChars(QStringView str, NumberMode numMode, int decDigits,
+ QLocale::NumberOptions number_options) const
{
- buff->clear();
- buff->reserve(str.size());
+ ParsingResult result;
+ result.buff.reserve(str.size());
enum { Whole, Fractional, Exponent } state = Whole;
const bool scientific = numMode == DoubleScientificMode;
@@ -4227,14 +4228,14 @@ bool QLocaleData::validateChars(QStringView str, NumberMode numMode, QByteArray
case Fractional:
// If a double has too many digits in its fractional part it is Invalid.
if (decDigits-- == 0)
- return false;
+ return {};
break;
case Exponent:
if (!isAsciiDigit(last)) {
// This is the first digit in the exponent (there may have beena '+'
// or '-' in before). If it's a zero, the exponent is zero-padded.
if (c == '0' && (number_options & QLocale::RejectLeadingZeroInExponent))
- return false;
+ return {};
}
break;
}
@@ -4245,7 +4246,7 @@ bool QLocaleData::validateChars(QStringView str, NumberMode numMode, QByteArray
// If an integer has a decimal point, it is Invalid.
// A double can only have one, at the end of its whole-number part.
if (numMode == IntegerMode || state != Whole)
- return false;
+ return {};
// Even when decDigits is 0, we do allow the decimal point to be
// present - just as long as no digits follow it.
@@ -4256,14 +4257,14 @@ bool QLocaleData::validateChars(QStringView str, NumberMode numMode, QByteArray
case '-':
// A sign can only appear at the start or after the e of scientific:
if (last != '\0' && !(scientific && last == 'e'))
- return false;
+ return {};
break;
case ',':
// Grouping is only allowed after a digit in the whole-number portion:
if ((number_options & QLocale::RejectGroupSeparator) || state != Whole
|| !isAsciiDigit(last)) {
- return false;
+ return {};
}
// We could check grouping sizes are correct, but fixup()s are
// probably better off correcting any misplacement instead.
@@ -4272,7 +4273,7 @@ bool QLocaleData::validateChars(QStringView str, NumberMode numMode, QByteArray
case 'e':
// Only one e is allowed and only in scientific:
if (!scientific || state == Exponent)
- return false;
+ return {};
state = Exponent;
break;
@@ -4282,16 +4283,17 @@ bool QLocaleData::validateChars(QStringView str, NumberMode numMode, QByteArray
// validators don't accept those values.
// For anything else, tokens.nextToken() must have returned 0.
Q_ASSERT(!c || c == 'a' || c == 'f' || c == 'i' || c == 'n');
- return false;
+ return {};
}
}
last = c;
if (c != ',') // Skip grouping
- buff->append(c);
+ result.buff.append(c);
}
- return true;
+ result.state = ParsingResult::Acceptable;
+ return result;
}
double QLocaleData::stringToDouble(QStringView str, bool *ok,
diff --git a/src/corelib/text/qlocale_p.h b/src/corelib/text/qlocale_p.h
index 649f75fbeb..2c36f9bdaf 100644
--- a/src/corelib/text/qlocale_p.h
+++ b/src/corelib/text/qlocale_p.h
@@ -214,6 +214,18 @@ Q_DECLARE_TYPEINFO(QLocaleId, Q_PRIMITIVE_TYPE);
using CharBuff = QVarLengthArray<char, 256>;
+struct ParsingResult
+{
+ enum State { // A duplicate of QValidator::State
+ Invalid,
+ Intermediate,
+ Acceptable
+ };
+
+ State state = Invalid;
+ CharBuff buff;
+};
+
struct QLocaleData
{
public:
@@ -361,9 +373,9 @@ public:
[[nodiscard]] inline NumericData numericData(NumberMode mode) const;
// this function is used in QIntValidator (QtGui)
- [[nodiscard]] Q_CORE_EXPORT bool validateChars(
- QStringView str, NumberMode numMode, QByteArray *buff, int decDigits = -1,
- QLocale::NumberOptions number_options = QLocale::DefaultNumberOptions) const;
+ [[nodiscard]] Q_CORE_EXPORT ParsingResult
+ validateChars(QStringView str, NumberMode numMode, int decDigits = -1,
+ QLocale::NumberOptions number_options = QLocale::DefaultNumberOptions) const;
// Access to assorted data members:
[[nodiscard]] QLocaleId id() const
diff --git a/src/gui/util/qvalidator.cpp b/src/gui/util/qvalidator.cpp
index ce6c7a98a3..4f788c5190 100644
--- a/src/gui/util/qvalidator.cpp
+++ b/src/gui/util/qvalidator.cpp
@@ -363,8 +363,12 @@ static qlonglong pow10(int exp)
}
template <typename T> static inline
-std::optional<QValidator::State> initialResultCheck(T min, T max, const QByteArray &buff)
+std::optional<QValidator::State> initialResultCheck(T min, T max, const ParsingResult &result)
{
+ if (result.state == ParsingResult::Invalid)
+ return QValidator::Invalid;
+
+ const CharBuff &buff = result.buff;
if (buff.isEmpty())
return QValidator::Intermediate;
@@ -376,21 +380,23 @@ std::optional<QValidator::State> initialResultCheck(T min, T max, const QByteArr
if (buff.size() == 1 && (ch == '-' || ch == '+'))
return QValidator::Intermediate;
+ if (result.state == ParsingResult::Intermediate)
+ return QValidator::Intermediate;
+
return std::nullopt;
}
QValidator::State QIntValidator::validate(QString & input, int&) const
{
- QByteArray buff;
- if (!locale().d->m_data->validateChars(input, QLocaleData::IntegerMode, &buff, -1,
- locale().numberOptions())) {
- return Invalid;
- }
+ ParsingResult result =
+ locale().d->m_data->validateChars(input, QLocaleData::IntegerMode, -1,
+ locale().numberOptions());
- std::optional<QValidator::State> opt = initialResultCheck(b, t, buff);
+ std::optional<State> opt = initialResultCheck(b, t, result);
if (opt)
return *opt;
+ const CharBuff &buff = result.buff;
bool ok;
qlonglong entered = QLocaleData::bytearrayToLongLong(buff, 10, &ok);
if (!ok)
@@ -421,11 +427,12 @@ QValidator::State QIntValidator::validate(QString & input, int&) const
/*! \reimp */
void QIntValidator::fixup(QString &input) const
{
- QByteArray buff;
- if (!locale().d->m_data->validateChars(input, QLocaleData::IntegerMode, &buff, -1,
- locale().numberOptions())) {
+ auto [parseState, buff] =
+ locale().d->m_data->validateChars(input, QLocaleData::IntegerMode, -1,
+ locale().numberOptions());
+ if (parseState == ParsingResult::Invalid)
return;
- }
+
bool ok;
qlonglong entered = QLocaleData::bytearrayToLongLong(buff, 10, &ok);
if (ok)
@@ -653,12 +660,10 @@ QValidator::State QDoubleValidator::validate(QString & input, int &) const
QValidator::State QDoubleValidatorPrivate::validateWithLocale(QString &input, QLocaleData::NumberMode numMode, const QLocale &locale) const
{
Q_Q(const QDoubleValidator);
- QByteArray buff;
- if (!locale.d->m_data->validateChars(input, numMode, &buff, q->dec, locale.numberOptions())) {
- return QValidator::Invalid;
- }
+ ParsingResult result =
+ locale.d->m_data->validateChars(input, numMode, q->dec, locale.numberOptions());
- std::optional<QValidator::State> opt = initialResultCheck(q->b, q->t, buff);
+ std::optional<QValidator::State> opt = initialResultCheck(q->b, q->t, result);
if (opt)
return *opt;
@@ -739,15 +744,16 @@ void QDoubleValidatorPrivate::fixupWithLocale(QString &input, QLocaleData::Numbe
const QLocale &locale) const
{
Q_Q(const QDoubleValidator);
- QByteArray buff;
// Passing -1 as the number of decimals, because fixup() exists to improve
// an Intermediate value, if it can.
- if (!locale.d->m_data->validateChars(input, numMode, &buff, -1, locale.numberOptions()))
+ auto [parseState, buff] =
+ locale.d->m_data->validateChars(input, numMode, -1, locale.numberOptions());
+ if (parseState == ParsingResult::Invalid)
return;
- // buff now contains data in C locale.
+ // buff contains data in C locale.
bool ok = false;
- const double entered = buff.toDouble(&ok);
+ const double entered = QByteArrayView(buff).toDouble(&ok);
if (ok) {
// Here we need to adjust the output format accordingly
char mode;
@@ -771,7 +777,7 @@ void QDoubleValidatorPrivate::fixupWithLocale(QString &input, QLocaleData::Numbe
if (eIndex < 0)
eIndex = buff.size();
precision = eIndex - (buff.contains('.') ? 1 : 0)
- - (buff.startsWith('-') || buff.startsWith('+') ? 1 : 0);
+ - (buff[0] == '-' || buff[0] == '+' ? 1 : 0);
}
// Use q->dec to limit the number of decimals, because we want the
// fixup() result to pass validate().