Add support for scoped enums to QMetaObjectBuilder

Change-Id: I7b3c3973ff4396a854014f5b2b671b71007e80da
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Reviewed-by: Olivier Goffart (Woboq GmbH) <ogoffart@woboq.com>
This commit is contained in:
Michael Brasser 2017-04-21 09:42:53 -05:00 committed by Michael Brasser
parent bfcc2902a4
commit 47fdb2c8e3
3 changed files with 46 additions and 3 deletions

View File

@ -190,12 +190,13 @@ class QMetaEnumBuilderPrivate
{ {
public: public:
QMetaEnumBuilderPrivate(const QByteArray& _name) QMetaEnumBuilderPrivate(const QByteArray& _name)
: name(_name), isFlag(false) : name(_name), isFlag(false), isScoped(false)
{ {
} }
QByteArray name; QByteArray name;
bool isFlag; bool isFlag;
bool isScoped;
QList<QByteArray> keys; QList<QByteArray> keys;
QVector<int> values; QVector<int> values;
}; };
@ -637,6 +638,7 @@ QMetaEnumBuilder QMetaObjectBuilder::addEnumerator(const QMetaEnum& prototype)
{ {
QMetaEnumBuilder en = addEnumerator(prototype.name()); QMetaEnumBuilder en = addEnumerator(prototype.name());
en.setIsFlag(prototype.isFlag()); en.setIsFlag(prototype.isFlag());
en.setIsScoped(prototype.isScoped());
int count = prototype.keyCount(); int count = prototype.keyCount();
for (int index = 0; index < count; ++index) for (int index = 0; index < count; ++index)
en.addKey(prototype.key(index), prototype.value(index)); en.addKey(prototype.key(index), prototype.value(index));
@ -1408,12 +1410,13 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
Q_ASSERT(!buf || dataIndex == pmeta->enumeratorData); Q_ASSERT(!buf || dataIndex == pmeta->enumeratorData);
for (const auto &enumerator : d->enumerators) { for (const auto &enumerator : d->enumerators) {
int name = strings.enter(enumerator.name); int name = strings.enter(enumerator.name);
int isFlag = (int)(enumerator.isFlag); int isFlag = enumerator.isFlag ? EnumIsFlag : 0;
int isScoped = enumerator.isScoped ? EnumIsScoped : 0;
int count = enumerator.keys.size(); int count = enumerator.keys.size();
int enumOffset = enumIndex; int enumOffset = enumIndex;
if (buf) { if (buf) {
data[dataIndex] = name; data[dataIndex] = name;
data[dataIndex + 1] = isFlag; data[dataIndex + 1] = isFlag | isScoped;
data[dataIndex + 2] = count; data[dataIndex + 2] = count;
data[dataIndex + 3] = enumOffset; data[dataIndex + 3] = enumOffset;
} }
@ -1641,6 +1644,7 @@ void QMetaObjectBuilder::serialize(QDataStream& stream) const
for (const auto &enumerator : d->enumerators) { for (const auto &enumerator : d->enumerators) {
stream << enumerator.name; stream << enumerator.name;
stream << enumerator.isFlag; stream << enumerator.isFlag;
stream << enumerator.isScoped;
stream << enumerator.keys; stream << enumerator.keys;
stream << enumerator.values; stream << enumerator.values;
} }
@ -1807,6 +1811,7 @@ void QMetaObjectBuilder::deserialize
addEnumerator(name); addEnumerator(name);
QMetaEnumBuilderPrivate &enumerator = d->enumerators[index]; QMetaEnumBuilderPrivate &enumerator = d->enumerators[index];
stream >> enumerator.isFlag; stream >> enumerator.isFlag;
stream >> enumerator.isScoped;
stream >> enumerator.keys; stream >> enumerator.keys;
stream >> enumerator.values; stream >> enumerator.values;
if (enumerator.keys.size() != enumerator.values.size()) { if (enumerator.keys.size() != enumerator.values.size()) {
@ -2632,6 +2637,31 @@ void QMetaEnumBuilder::setIsFlag(bool value)
d->isFlag = value; d->isFlag = value;
} }
/*!
Return \c true if this enumerator should be considered scoped (C++11 enum class).
\sa setIsScoped()
*/
bool QMetaEnumBuilder::isScoped() const
{
QMetaEnumBuilderPrivate *d = d_func();
if (d)
return d->isScoped;
return false;
}
/*!
Sets this enumerator to be a scoped enum if \value is true
\sa isScoped()
*/
void QMetaEnumBuilder::setIsScoped(bool value)
{
QMetaEnumBuilderPrivate *d = d_func();
if (d)
d->isScoped = value;
}
/*! /*!
Returns the number of keys. Returns the number of keys.

View File

@ -300,6 +300,9 @@ public:
bool isFlag() const; bool isFlag() const;
void setIsFlag(bool value); void setIsFlag(bool value);
bool isScoped() const;
void setIsScoped(bool value);
int keyCount() const; int keyCount() const;
QByteArray key(int index) const; QByteArray key(int index) const;
int value(int index) const; int value(int index) const;

View File

@ -806,6 +806,7 @@ void tst_QMetaObjectBuilder::enumerator()
QMetaEnumBuilder enum1 = builder.addEnumerator("foo"); QMetaEnumBuilder enum1 = builder.addEnumerator("foo");
QCOMPARE(enum1.name(), QByteArray("foo")); QCOMPARE(enum1.name(), QByteArray("foo"));
QVERIFY(!enum1.isFlag()); QVERIFY(!enum1.isFlag());
QVERIFY(!enum1.isScoped());
QCOMPARE(enum1.keyCount(), 0); QCOMPARE(enum1.keyCount(), 0);
QCOMPARE(enum1.index(), 0); QCOMPARE(enum1.index(), 0);
QCOMPARE(builder.enumeratorCount(), 1); QCOMPARE(builder.enumeratorCount(), 1);
@ -814,6 +815,7 @@ void tst_QMetaObjectBuilder::enumerator()
QMetaEnumBuilder enum2 = builder.addEnumerator("bar"); QMetaEnumBuilder enum2 = builder.addEnumerator("bar");
QCOMPARE(enum2.name(), QByteArray("bar")); QCOMPARE(enum2.name(), QByteArray("bar"));
QVERIFY(!enum2.isFlag()); QVERIFY(!enum2.isFlag());
QVERIFY(!enum2.isScoped());
QCOMPARE(enum2.keyCount(), 0); QCOMPARE(enum2.keyCount(), 0);
QCOMPARE(enum2.index(), 1); QCOMPARE(enum2.index(), 1);
QCOMPARE(builder.enumeratorCount(), 2); QCOMPARE(builder.enumeratorCount(), 2);
@ -827,6 +829,7 @@ void tst_QMetaObjectBuilder::enumerator()
// Modify the attributes on enum1. // Modify the attributes on enum1.
enum1.setIsFlag(true); enum1.setIsFlag(true);
enum1.setIsScoped(true);
QCOMPARE(enum1.addKey("ABC", 0), 0); QCOMPARE(enum1.addKey("ABC", 0), 0);
QCOMPARE(enum1.addKey("DEF", 1), 1); QCOMPARE(enum1.addKey("DEF", 1), 1);
QCOMPARE(enum1.addKey("GHI", -1), 2); QCOMPARE(enum1.addKey("GHI", -1), 2);
@ -834,6 +837,7 @@ void tst_QMetaObjectBuilder::enumerator()
// Check that enum1 is changed, but enum2 is not. // Check that enum1 is changed, but enum2 is not.
QCOMPARE(enum1.name(), QByteArray("foo")); QCOMPARE(enum1.name(), QByteArray("foo"));
QVERIFY(enum1.isFlag()); QVERIFY(enum1.isFlag());
QVERIFY(enum1.isScoped());
QCOMPARE(enum1.keyCount(), 3); QCOMPARE(enum1.keyCount(), 3);
QCOMPARE(enum1.index(), 0); QCOMPARE(enum1.index(), 0);
QCOMPARE(enum1.key(0), QByteArray("ABC")); QCOMPARE(enum1.key(0), QByteArray("ABC"));
@ -845,6 +849,7 @@ void tst_QMetaObjectBuilder::enumerator()
QCOMPARE(enum1.value(2), -1); QCOMPARE(enum1.value(2), -1);
QCOMPARE(enum2.name(), QByteArray("bar")); QCOMPARE(enum2.name(), QByteArray("bar"));
QVERIFY(!enum2.isFlag()); QVERIFY(!enum2.isFlag());
QVERIFY(!enum2.isScoped());
QCOMPARE(enum2.keyCount(), 0); QCOMPARE(enum2.keyCount(), 0);
QCOMPARE(enum2.index(), 1); QCOMPARE(enum2.index(), 1);
@ -856,6 +861,7 @@ void tst_QMetaObjectBuilder::enumerator()
// This time check that only method2 changed. // This time check that only method2 changed.
QCOMPARE(enum1.name(), QByteArray("foo")); QCOMPARE(enum1.name(), QByteArray("foo"));
QVERIFY(enum1.isFlag()); QVERIFY(enum1.isFlag());
QVERIFY(enum1.isScoped());
QCOMPARE(enum1.keyCount(), 3); QCOMPARE(enum1.keyCount(), 3);
QCOMPARE(enum1.index(), 0); QCOMPARE(enum1.index(), 0);
QCOMPARE(enum1.key(0), QByteArray("ABC")); QCOMPARE(enum1.key(0), QByteArray("ABC"));
@ -867,6 +873,7 @@ void tst_QMetaObjectBuilder::enumerator()
QCOMPARE(enum1.value(2), -1); QCOMPARE(enum1.value(2), -1);
QCOMPARE(enum2.name(), QByteArray("bar")); QCOMPARE(enum2.name(), QByteArray("bar"));
QVERIFY(enum2.isFlag()); QVERIFY(enum2.isFlag());
QVERIFY(!enum2.isScoped());
QCOMPARE(enum2.keyCount(), 2); QCOMPARE(enum2.keyCount(), 2);
QCOMPARE(enum2.index(), 1); QCOMPARE(enum2.index(), 1);
QCOMPARE(enum2.key(0), QByteArray("XYZ")); QCOMPARE(enum2.key(0), QByteArray("XYZ"));
@ -879,6 +886,7 @@ void tst_QMetaObjectBuilder::enumerator()
enum1.removeKey(2); enum1.removeKey(2);
QCOMPARE(enum1.name(), QByteArray("foo")); QCOMPARE(enum1.name(), QByteArray("foo"));
QVERIFY(enum1.isFlag()); QVERIFY(enum1.isFlag());
QVERIFY(enum1.isScoped());
QCOMPARE(enum1.keyCount(), 2); QCOMPARE(enum1.keyCount(), 2);
QCOMPARE(enum1.index(), 0); QCOMPARE(enum1.index(), 0);
QCOMPARE(enum1.key(0), QByteArray("ABC")); QCOMPARE(enum1.key(0), QByteArray("ABC"));
@ -889,6 +897,7 @@ void tst_QMetaObjectBuilder::enumerator()
QCOMPARE(enum1.value(2), -1); QCOMPARE(enum1.value(2), -1);
QCOMPARE(enum2.name(), QByteArray("bar")); QCOMPARE(enum2.name(), QByteArray("bar"));
QVERIFY(enum2.isFlag()); QVERIFY(enum2.isFlag());
QVERIFY(!enum2.isScoped());
QCOMPARE(enum2.keyCount(), 2); QCOMPARE(enum2.keyCount(), 2);
QCOMPARE(enum2.index(), 1); QCOMPARE(enum2.index(), 1);
QCOMPARE(enum2.key(0), QByteArray("XYZ")); QCOMPARE(enum2.key(0), QByteArray("XYZ"));
@ -903,6 +912,7 @@ void tst_QMetaObjectBuilder::enumerator()
enum2 = builder.enumerator(0); enum2 = builder.enumerator(0);
QCOMPARE(enum2.name(), QByteArray("bar")); QCOMPARE(enum2.name(), QByteArray("bar"));
QVERIFY(enum2.isFlag()); QVERIFY(enum2.isFlag());
QVERIFY(!enum2.isScoped());
QCOMPARE(enum2.keyCount(), 2); QCOMPARE(enum2.keyCount(), 2);
QCOMPARE(enum2.index(), 0); QCOMPARE(enum2.index(), 0);
QCOMPARE(enum2.key(0), QByteArray("XYZ")); QCOMPARE(enum2.key(0), QByteArray("XYZ"));