QDTP: Fix handling of no-digit numeric fields
A numeric field with no digits is Intermediate, since digits can be typed into it. The testing for this was complicated by the fact that a sign might be either a sign in the field or the start of a following separator. Break out the testing of separator matching at the start of a view. This simplifies the existing checks for full separator match and we can use it in the no-digit numeric field's handling to make the check more robust (matching the whole separator, rather than only its first character). It incidentally prepares the way for other changes. Task-number: QTBUG-114909 Change-Id: I5abfccbcae3cba0979b4723c400de038fe2bf324 Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> (cherry picked from commit 61b2a6f5874275e92e37f4270a1817a4c101778d) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
f46856ae16
commit
7bbb12b5d8
@ -727,6 +727,14 @@ int QDateTimeParser::sectionMaxSize(int index) const
|
|||||||
return sectionMaxSize(sn.type, sn.count);
|
return sectionMaxSize(sn.type, sn.count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Separator matching
|
||||||
|
static int matchesSeparator(QStringView text, QStringView separator)
|
||||||
|
{
|
||||||
|
// -1 if not a match, else length of prefix of text that does match.
|
||||||
|
// For now, just check for exact match:
|
||||||
|
return text.startsWith(separator) ? separator.size() : -1;
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\internal
|
\internal
|
||||||
|
|
||||||
@ -845,12 +853,26 @@ QDateTimeParser::parseSection(const QDateTime ¤tValue, int sectionIndex, i
|
|||||||
case MinuteSection:
|
case MinuteSection:
|
||||||
case SecondSection:
|
case SecondSection:
|
||||||
case MSecSection: {
|
case MSecSection: {
|
||||||
|
const auto checkSeparator = [&result, field=QStringView{m_text}.sliced(offset),
|
||||||
|
negativeYearOffset, sectionIndex, this]() {
|
||||||
|
// No-digit field if next separator is here, otherwise invalid.
|
||||||
|
const auto &sep = separators.at(sectionIndex + 1);
|
||||||
|
if (matchesSeparator(field.sliced(negativeYearOffset), sep) != -1)
|
||||||
|
result = ParsedSection(Intermediate, 0, negativeYearOffset);
|
||||||
|
else if (negativeYearOffset && matchesSeparator(field, sep) != -1)
|
||||||
|
result = ParsedSection(Intermediate, 0, 0);
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
};
|
||||||
int used = negativeYearOffset;
|
int used = negativeYearOffset;
|
||||||
// We already sliced off the - sign if it was legitimately present.
|
// We already sliced off the - sign if it was acceptable.
|
||||||
|
// QLocale::toUInt() would accept a sign, so we must reject it overtly:
|
||||||
if (sectionTextRef.startsWith(u'-')
|
if (sectionTextRef.startsWith(u'-')
|
||||||
|| sectionTextRef.startsWith(u'+')) {
|
|| sectionTextRef.startsWith(u'+')) {
|
||||||
if (separators.at(sectionIndex + 1).startsWith(sectionTextRef[0]))
|
// However, a sign here may indicate a field with no digits, if it
|
||||||
result = ParsedSection(Intermediate, 0, used);
|
// starts the next separator:
|
||||||
|
checkSeparator();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
QStringView digitsStr = sectionTextRef.left(digitCount(sectionTextRef));
|
QStringView digitsStr = sectionTextRef.left(digitCount(sectionTextRef));
|
||||||
@ -884,13 +906,10 @@ QDateTimeParser::parseSection(const QDateTime ¤tValue, int sectionIndex, i
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (lastVal == -1) {
|
if (lastVal == -1) {
|
||||||
const auto &sep = separators.at(sectionIndex + 1);
|
if (!checkSeparator()) {
|
||||||
if (sep.startsWith(sectionTextRef[0])
|
|
||||||
|| (negate && sep.startsWith(m_text.at(offset))))
|
|
||||||
result = ParsedSection(Intermediate, 0, 0);
|
|
||||||
else
|
|
||||||
QDTPDEBUG << "invalid because" << sectionTextRef << "can't become a uint"
|
QDTPDEBUG << "invalid because" << sectionTextRef << "can't become a uint"
|
||||||
<< lastVal;
|
<< lastVal;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (negate)
|
if (negate)
|
||||||
lastVal = -lastVal;
|
lastVal = -lastVal;
|
||||||
@ -1182,13 +1201,14 @@ QDateTimeParser::scanString(const QDateTime &defaultValue, bool fixup) const
|
|||||||
for (int index = 0; index < sectionNodesCount; ++index) {
|
for (int index = 0; index < sectionNodesCount; ++index) {
|
||||||
Q_ASSERT(state != Invalid);
|
Q_ASSERT(state != Invalid);
|
||||||
const QString &separator = separators.at(index);
|
const QString &separator = separators.at(index);
|
||||||
if (QStringView{m_text}.mid(pos, separator.size()) != separator) {
|
int step = matchesSeparator(QStringView{m_text}.sliced(pos), separator);
|
||||||
QDTPDEBUG << "invalid because" << QStringView{m_text}.mid(pos, separator.size())
|
if (step == -1) {
|
||||||
<< "!=" << separator
|
QDTPDEBUG << "invalid because" << QStringView{m_text}.sliced(pos)
|
||||||
|
<< "does not start with" << separator
|
||||||
<< index << pos << currentSectionIndex;
|
<< index << pos << currentSectionIndex;
|
||||||
return StateNode();
|
return StateNode();
|
||||||
}
|
}
|
||||||
pos += separator.size();
|
pos += step;
|
||||||
sectionNodes[index].pos = pos;
|
sectionNodes[index].pos = pos;
|
||||||
int *current = nullptr;
|
int *current = nullptr;
|
||||||
int zoneOffset; // Needed to serve as *current when setting zone
|
int zoneOffset; // Needed to serve as *current when setting zone
|
||||||
@ -1287,9 +1307,10 @@ QDateTimeParser::scanString(const QDateTime &defaultValue, bool fixup) const
|
|||||||
isSet |= sn.type;
|
isSet |= sn.type;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (QStringView{m_text}.sliced(pos) != separators.last()) {
|
int step = matchesSeparator(QStringView{m_text}.sliced(pos), separators.last());
|
||||||
|
if (step == -1 || step + pos < m_text.size()) {
|
||||||
QDTPDEBUG << "invalid because" << QStringView{m_text}.sliced(pos)
|
QDTPDEBUG << "invalid because" << QStringView{m_text}.sliced(pos)
|
||||||
<< "!=" << separators.last() << pos;
|
<< "does not match" << separators.last() << pos;
|
||||||
return StateNode();
|
return StateNode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user