QMetaEnum: refactor keysToValue

- Show warning messages for malformed keys string
- Use QBAV instead of QL1SV, some methods in the public API may get
  QU8SV overloads in later commits
- Extend unittests; also rename the unittest, it's really testing
  key(s)ToValue()

Change-Id: Iec944ef4c2c5d18ab038cb933e954cf50c912523
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
bb10
Ahmad Samir 2023-10-30 13:02:03 +02:00
parent 7c41f31efa
commit e90705687f
2 changed files with 76 additions and 5 deletions

View File

@ -3240,6 +3240,51 @@ const char *QMetaEnum::valueToKey(int value) const
return nullptr;
}
static bool parseEnumFlags(QByteArrayView v, QVarLengthArray<QByteArrayView, 10> &list)
{
v = v.trimmed();
if (v.empty()) {
qWarning("QMetaEnum::keysToValue: empty keys string.");
return false;
}
qsizetype sep = v.indexOf('|', 0);
if (sep == 0) {
qWarning("QMetaEnum::keysToValue: malformed keys string, starts with '|', \"%s\"",
v.constData());
return false;
}
if (sep == -1) { // One flag
list.push_back(v);
return true;
}
if (v.endsWith('|')) {
qWarning("QMetaEnum::keysToValue: malformed keys string, ends with '|', \"%s\"",
v.constData());
return false;
}
const auto begin = v.begin();
const auto end = v.end();
auto b = begin;
for (; b != end && sep != -1; sep = v.indexOf('|', sep)) {
list.push_back({b, begin + sep});
++sep; // Skip over '|'
b = begin + sep;
if (*b == '|') {
qWarning("QMetaEnum::keysToValue: malformed keys string, has two consecutive '|': "
"\"%s\"", v.constData());
return false;
}
}
// The rest of the string
list.push_back({b, end});
return true;
}
/*!
Returns the value derived from combining together the values of
the \a keys using the OR operator, or -1 if \a keys is not
@ -3266,7 +3311,11 @@ int QMetaEnum::keysToValue(const char *keys, bool *ok) const
};
int value = 0;
for (const QLatin1StringView &untrimmed : qTokenize(QLatin1StringView{keys}, u'|')) {
QVarLengthArray<QByteArrayView, 10> list;
const bool r = parseEnumFlags(QByteArrayView{keys}, list);
if (!r)
return -1;
for (const auto &untrimmed : list) {
const auto parsed = parse_scope(untrimmed.trimmed());
if (parsed.scope && *parsed.scope != objectClassName(mobj))
return -1; // wrong type name in qualified name

View File

@ -312,8 +312,8 @@ private slots:
void normalizedType_data();
void normalizedType();
void customPropertyType();
void checkScope_data();
void checkScope();
void keysToValue_data();
void keysToValue(); // Also keyToValue()
void propertyNotify();
void propertyConstant();
void propertyFinal();
@ -2339,7 +2339,7 @@ void tst_QMetaObject::customPropertyType()
QCOMPARE(prop.metaType().id(), QMetaType::QVariantList);
}
void tst_QMetaObject::checkScope_data()
void tst_QMetaObject::keysToValue_data()
{
QTest::addColumn<QObject *>("object");
QTest::addColumn<QByteArray>("name");
@ -2353,7 +2353,7 @@ void tst_QMetaObject::checkScope_data()
}
void tst_QMetaObject::checkScope()
void tst_QMetaObject::keysToValue()
{
QFETCH(QObject *, object);
QFETCH(QByteArray, name);
@ -2419,6 +2419,28 @@ void tst_QMetaObject::checkScope()
QCOMPARE(mf.keysToValue("MyNamespace::" + name + "::MyFlag2|MyNamespace::" + name + "::MyFlag2", &ok), 2);
QCOMPARE(ok, true);
QCOMPARE(QLatin1String(mf.valueToKeys(3)), QLatin1String("MyFlag1|MyFlag2"));
// Test flags with extra '|'
QTest::ignoreMessage(QtWarningMsg,
QRegularExpression(u"QMetaEnum::keysToValue: malformed keys string, ends with '|'.+"_s));
QCOMPARE(mf.keysToValue("MyFlag1|MyFlag2|", &ok), -1);
QCOMPARE(ok, false);
QTest::ignoreMessage(QtWarningMsg,
QRegularExpression(u"QMetaEnum::keysToValue: malformed keys string, starts with '|'.+"_s));
QCOMPARE(mf.keysToValue("|MyFlag1|MyFlag2|", &ok), -1);
QCOMPARE(ok, false);
QTest::ignoreMessage(QtWarningMsg,
QRegularExpression(
u"QMetaEnum::keysToValue: malformed keys string, has two consecutive '|'.+"_s));
QCOMPARE(mf.keysToValue("MyFlag1||MyFlag2", &ok), -1);
QCOMPARE(ok, false);
// Test empty string
QTest::ignoreMessage(QtWarningMsg, "QMetaEnum::keysToValue: empty keys string.");
QCOMPARE(mf.keysToValue("", &ok), -1);
QCOMPARE(ok, false);
}
void tst_QMetaObject::propertyNotify()