forked from qt-creator/qt-creator
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:
@@ -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();
|
||||||
|
Reference in New Issue
Block a user