Utils: Some microoptimization in the persistentsettings writing

In some cases the exact type of a tag is not needed.

Change-Id: I0e46d12c5dde34734e7e711dd940b9aa570d23f7
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
hjk
2023-09-12 10:51:03 +02:00
parent 19672406b4
commit ba20b249c9

View File

@@ -95,18 +95,14 @@ static QRect stringToRectangle(const QString &v)
namespace Utils { namespace Utils {
struct Context // Basic context containing element name string constants. const QString qtCreatorElement("qtcreator");
{ const QString dataElement("data");
Context() {} const QString variableElement("variable");
const QString qtCreatorElement = QString("qtcreator"); const QString typeAttribute("type");
const QString dataElement = QString("data"); const QString valueElement("value");
const QString variableElement = QString("variable"); const QString valueListElement("valuelist");
const QString typeAttribute = QString("type"); const QString valueMapElement("valuemap");
const QString valueElement = QString("value"); const QString keyAttribute("key");
const QString valueListElement = QString("valuelist");
const QString valueMapElement = QString("valuemap");
const QString keyAttribute = QString("key");
};
struct ParseValueStackEntry struct ParseValueStackEntry
{ {
@@ -160,22 +156,16 @@ void ParseValueStackEntry::addChild(const Key &key, const QVariant &v)
} }
} }
class ParseContext : public Context class ParseContext
{ {
public: public:
Store parse(const FilePath &file); Store parse(const FilePath &file);
private: private:
enum Element { QtCreatorElement, DataElement, VariableElement,
SimpleValueElement, ListValueElement, MapValueElement, UnknownElement };
Element element(const QStringView &r) const;
static inline bool isValueElement(Element e)
{ return e == SimpleValueElement || e == ListValueElement || e == MapValueElement; }
QVariant readSimpleValue(QXmlStreamReader &r, const QXmlStreamAttributes &attributes) const; QVariant readSimpleValue(QXmlStreamReader &r, const QXmlStreamAttributes &attributes) const;
bool handleStartElement(QXmlStreamReader &r); bool handleStartElement(QXmlStreamReader &r);
bool handleEndElement(const QStringView &name); bool handleEndElement(const QStringView name);
static QString formatWarning(const QXmlStreamReader &r, const QString &message); static QString formatWarning(const QXmlStreamReader &r, const QString &message);
@@ -215,19 +205,14 @@ Store ParseContext::parse(const FilePath &file)
bool ParseContext::handleStartElement(QXmlStreamReader &r) bool ParseContext::handleStartElement(QXmlStreamReader &r)
{ {
const QStringView name = r.name(); const QStringView name = r.name();
const Element e = element(name); if (name == variableElement) {
if (e == VariableElement) {
m_currentVariableName = keyFromString(r.readElementText()); m_currentVariableName = keyFromString(r.readElementText());
return false; return false;
} }
if (!ParseContext::isValueElement(e)) if (name == valueElement) {
return false; const QXmlStreamAttributes attributes = r.attributes();
const Key key = attributes.hasAttribute(keyAttribute) ?
const QXmlStreamAttributes attributes = r.attributes(); keyFromString(attributes.value(keyAttribute).toString()) : Key();
const Key key = attributes.hasAttribute(keyAttribute) ?
keyFromString(attributes.value(keyAttribute).toString()) : Key();
switch (e) {
case SimpleValueElement: {
// This reads away the end element, so, handle end element right here. // This reads away the end element, so, handle end element right here.
const QVariant v = readSimpleValue(r, attributes); const QVariant v = readSimpleValue(r, attributes);
if (!v.isValid()) { if (!v.isValid()) {
@@ -237,22 +222,26 @@ bool ParseContext::handleStartElement(QXmlStreamReader &r)
m_valueStack.push_back(ParseValueStackEntry(v, key)); m_valueStack.push_back(ParseValueStackEntry(v, key));
return handleEndElement(name); return handleEndElement(name);
} }
case ListValueElement: if (name == valueListElement) {
const QXmlStreamAttributes attributes = r.attributes();
const Key key = attributes.hasAttribute(keyAttribute) ?
keyFromString(attributes.value(keyAttribute).toString()) : Key();
m_valueStack.push_back(ParseValueStackEntry(QVariant::List, key)); m_valueStack.push_back(ParseValueStackEntry(QVariant::List, key));
break; return false;
case MapValueElement: }
if (name == valueMapElement) {
const QXmlStreamAttributes attributes = r.attributes();
const Key key = attributes.hasAttribute(keyAttribute) ?
keyFromString(attributes.value(keyAttribute).toString()) : Key();
m_valueStack.push_back(ParseValueStackEntry(QVariant::Map, key)); m_valueStack.push_back(ParseValueStackEntry(QVariant::Map, key));
break; return false;
default:
break;
} }
return false; return false;
} }
bool ParseContext::handleEndElement(const QStringView &name) bool ParseContext::handleEndElement(const QStringView name)
{ {
const Element e = element(name); if (name == valueElement || name == valueListElement || name == valueMapElement) {
if (ParseContext::isValueElement(e)) {
QTC_ASSERT(!m_valueStack.isEmpty(), return true); QTC_ASSERT(!m_valueStack.isEmpty(), return true);
const ParseValueStackEntry top = m_valueStack.pop(); const ParseValueStackEntry top = m_valueStack.pop();
if (m_valueStack.isEmpty()) { // Last element? -> Done with that variable. if (m_valueStack.isEmpty()) { // Last element? -> Done with that variable.
@@ -262,8 +251,9 @@ bool ParseContext::handleEndElement(const QStringView &name)
return false; return false;
} }
m_valueStack.top().addChild(top.key, top.value()); m_valueStack.top().addChild(top.key, top.value());
return false;
} }
return e == QtCreatorElement; return name == qtCreatorElement;
} }
QString ParseContext::formatWarning(const QXmlStreamReader &r, const QString &message) QString ParseContext::formatWarning(const QXmlStreamReader &r, const QString &message)
@@ -278,23 +268,6 @@ QString ParseContext::formatWarning(const QXmlStreamReader &r, const QString &me
return result; return result;
} }
ParseContext::Element ParseContext::element(const QStringView &r) const
{
if (r == valueElement)
return SimpleValueElement;
if (r == valueListElement)
return ListValueElement;
if (r == valueMapElement)
return MapValueElement;
if (r == qtCreatorElement)
return QtCreatorElement;
if (r == dataElement)
return DataElement;
if (r == variableElement)
return VariableElement;
return UnknownElement;
}
QVariant ParseContext::readSimpleValue(QXmlStreamReader &r, const QXmlStreamAttributes &attributes) const QVariant ParseContext::readSimpleValue(QXmlStreamReader &r, const QXmlStreamAttributes &attributes) const
{ {
// Simple value // Simple value
@@ -363,40 +336,39 @@ static QString xmlAttrFromKey(const Key &key) { return stringFromKey(key); }
static Key xmlAttrFromKey(const Key &key) { return key; } static Key xmlAttrFromKey(const Key &key) { return key; }
#endif #endif
static void writeVariantValue(QXmlStreamWriter &w, const Context &ctx, static void writeVariantValue(QXmlStreamWriter &w, const QVariant &variant, const Key &key = {})
const QVariant &variant, const Key &key = {})
{ {
static const int storeId = qMetaTypeId<Store>(); static const int storeId = qMetaTypeId<Store>();
const int variantType = variant.typeId(); const int variantType = variant.typeId();
if (variantType == QMetaType::QStringList || variantType == QMetaType::QVariantList) { if (variantType == QMetaType::QStringList || variantType == QMetaType::QVariantList) {
w.writeStartElement(ctx.valueListElement); w.writeStartElement(valueListElement);
w.writeAttribute(ctx.typeAttribute, "QVariantList"); w.writeAttribute(typeAttribute, "QVariantList");
if (!key.isEmpty()) if (!key.isEmpty())
w.writeAttribute(ctx.keyAttribute, xmlAttrFromKey(key)); w.writeAttribute(keyAttribute, xmlAttrFromKey(key));
const QList<QVariant> list = variant.toList(); const QList<QVariant> list = variant.toList();
for (const QVariant &var : list) for (const QVariant &var : list)
writeVariantValue(w, ctx, var); writeVariantValue(w, var);
w.writeEndElement(); w.writeEndElement();
} else if (variantType == storeId || variantType == QMetaType::QVariantMap) { } else if (variantType == storeId || variantType == QMetaType::QVariantMap) {
w.writeStartElement(ctx.valueMapElement); w.writeStartElement(valueMapElement);
w.writeAttribute(ctx.typeAttribute, "QVariantMap"); w.writeAttribute(typeAttribute, "QVariantMap");
if (!key.isEmpty()) if (!key.isEmpty())
w.writeAttribute(ctx.keyAttribute, xmlAttrFromKey(key)); w.writeAttribute(keyAttribute, xmlAttrFromKey(key));
const Store varMap = storeFromVariant(variant); const Store varMap = storeFromVariant(variant);
const Store::const_iterator cend = varMap.constEnd(); const Store::const_iterator cend = varMap.constEnd();
for (Store::const_iterator i = varMap.constBegin(); i != cend; ++i) for (Store::const_iterator i = varMap.constBegin(); i != cend; ++i)
writeVariantValue(w, ctx, i.value(), i.key()); writeVariantValue(w, i.value(), i.key());
w.writeEndElement(); w.writeEndElement();
} else if (variantType == QMetaType::QObjectStar) { } else if (variantType == QMetaType::QObjectStar) {
// ignore QObjects // ignore QObjects
} else if (variantType == QMetaType::VoidStar) { } else if (variantType == QMetaType::VoidStar) {
// ignore void pointers // ignore void pointers
} else { } else {
w.writeStartElement(ctx.valueElement); w.writeStartElement(valueElement);
w.writeAttribute(ctx.typeAttribute, QLatin1String(variant.typeName())); w.writeAttribute(typeAttribute, QLatin1String(variant.typeName()));
if (!key.isEmpty()) if (!key.isEmpty())
w.writeAttribute(ctx.keyAttribute, xmlAttrFromKey(key)); w.writeAttribute(keyAttribute, xmlAttrFromKey(key));
switch (variant.type()) { switch (variant.type()) {
case QVariant::Rect: case QVariant::Rect:
w.writeCharacters(rectangleToString(variant.toRect())); w.writeCharacters(rectangleToString(variant.toRect()));
@@ -445,7 +417,6 @@ bool PersistentSettingsWriter::write(const Store &data, QString *errorString) co
m_fileName.parentDir().ensureWritableDir(); m_fileName.parentDir().ensureWritableDir();
FileSaver saver(m_fileName, QIODevice::Text); FileSaver saver(m_fileName, QIODevice::Text);
if (!saver.hasError()) { if (!saver.hasError()) {
const Context ctx;
QXmlStreamWriter w(saver.file()); QXmlStreamWriter w(saver.file());
w.setAutoFormatting(true); w.setAutoFormatting(true);
w.setAutoFormattingIndent(1); // Historical, used to be QDom. w.setAutoFormattingIndent(1); // Historical, used to be QDom.
@@ -455,13 +426,13 @@ bool PersistentSettingsWriter::write(const Store &data, QString *errorString) co
arg(QCoreApplication::applicationName(), arg(QCoreApplication::applicationName(),
QCoreApplication::applicationVersion(), QCoreApplication::applicationVersion(),
QDateTime::currentDateTime().toString(Qt::ISODate))); QDateTime::currentDateTime().toString(Qt::ISODate)));
w.writeStartElement(ctx.qtCreatorElement); w.writeStartElement(qtCreatorElement);
const Store::const_iterator cend = data.constEnd(); const Store::const_iterator cend = data.constEnd();
for (Store::const_iterator it = data.constBegin(); it != cend; ++it) { for (Store::const_iterator it = data.constBegin(); it != cend; ++it) {
w.writeStartElement(ctx.dataElement); w.writeStartElement(dataElement);
// FIXME: stringFromKey() not needed from Qt 6.5 onward. // FIXME: stringFromKey() not needed from Qt 6.5 onward.
w.writeTextElement(ctx.variableElement, stringFromKey(it.key())); w.writeTextElement(variableElement, stringFromKey(it.key()));
writeVariantValue(w, ctx, it.value()); writeVariantValue(w, it.value());
w.writeEndElement(); w.writeEndElement();
} }
w.writeEndDocument(); w.writeEndDocument();