[Telepathy-commits] [telepathy-qt4/master] Fixed KeyFile/ManagerFile to proper parse list of strings.

Andre Moreira Magalhaes (andrunko) andre.magalhaes at collabora.co.uk
Tue Jan 6 05:09:54 PST 2009


---
 TelepathyQt4/key-file.cpp     |  139 ++++++++++++++++++++++++++++++++++-------
 TelepathyQt4/key-file.h       |    2 +
 TelepathyQt4/manager-file.cpp |   82 +++++++++++-------------
 3 files changed, 157 insertions(+), 66 deletions(-)

diff --git a/TelepathyQt4/key-file.cpp b/TelepathyQt4/key-file.cpp
index 3fc498e..bad2a44 100644
--- a/TelepathyQt4/key-file.cpp
+++ b/TelepathyQt4/key-file.cpp
@@ -35,7 +35,7 @@ struct KeyFile::Private
 {
     QString fileName;
     KeyFile::Status status;
-    QHash<QString, QHash<QString, QString> > groups;
+    QHash<QString, QHash<QString, QByteArray> > groups;
     QString currentGroup;
 
     Private();
@@ -46,13 +46,16 @@ struct KeyFile::Private
     bool read();
 
     bool validateKey(const QByteArray &data, int from, int to, QString &result);
-    bool unescapeString(const QByteArray &data, int from, int to, QString &result);
+    bool unescapeString(const QByteArray &data, int from, int to, QString &result) const;
+    bool unescapeStringList(const QByteArray &data, int from, int to, QStringList &result) const;
 
     QStringList allGroups() const;
     QStringList allKeys() const;
     QStringList keys() const;
     bool contains(const QString &key) const;
+    QString rawValue(const QString &key) const;
     QString value(const QString &key) const;
+    QStringList valueAsStringList(const QString &key) const;
 };
 
 KeyFile::Private::Private()
@@ -102,7 +105,8 @@ bool KeyFile::Private::read()
     QByteArray data;
     QByteArray group;
     QString currentGroup;
-    QHash<QString, QString> groupMap;
+    QHash<QString, QByteArray> groupMap;
+    QByteArray rawValue;
     int line = 0;
     int idx;
     while (!file.atEnd()) {
@@ -174,22 +178,16 @@ bool KeyFile::Private::read()
                 return false;
             }
 
-            data = data.mid(idx + 1).trimmed();
-            QString value;
-            if (!unescapeString(data, 0, data.size(), value)) {
-                setError(KeyFile::FormatError,
-                         QString("invalid key value for key '%2' at line %3")
-                                 .arg(key).arg(line));
-                return false;
-            }
-
             if (groupMap.contains(key)) {
                 setError(KeyFile::FormatError,
                          QString("duplicated key '%1' on group '%2' at line %3")
                                  .arg(key).arg(currentGroup).arg(line));
                 return false;
             }
-            groupMap[key] = value;
+
+            data = data.mid(idx + 1).trimmed();
+            rawValue = data.mid(0, data.size());
+            groupMap[key] = rawValue;
         }
     }
 
@@ -218,13 +216,18 @@ bool KeyFile::Private::validateKey(const QByteArray &data, int from, int to, QSt
     return ret;
 }
 
-bool KeyFile::Private::unescapeString(const QByteArray &data, int from, int to, QString &result)
+bool KeyFile::Private::unescapeString(const QByteArray &data, int from, int to, QString &result) const
 {
     int i = from;
     while (i < to) {
         uint ch = data.at(i++);
 
         if (ch == '\\') {
+            if (i == to) {
+                result += '\\';
+                return true;
+            }
+
             char nextCh = data.at(i++);
             switch (nextCh) {
                 case 's':
@@ -240,8 +243,7 @@ bool KeyFile::Private::unescapeString(const QByteArray &data, int from, int to,
                     result += '\r';
                     break;
                 case ';':
-                    // keep \; there so we can split lists properly
-                    result += "\\;";
+                    result += ";";
                     break;
                 case '\\':
                     result += '\\';
@@ -258,6 +260,46 @@ bool KeyFile::Private::unescapeString(const QByteArray &data, int from, int to,
     return true;
 }
 
+bool KeyFile::Private::unescapeStringList(const QByteArray &data, int from, int to, QStringList &result) const
+{
+    QByteArray value;
+    QList<QByteArray> valueList;
+    int i = from;
+    QChar ch;
+    while (i < to) {
+        ch = data.at(i++);
+
+        if (ch == '\\') {
+            value += ch;
+            if (i < to) {
+                value += data.at(i++);
+                continue;
+            }
+            else {
+                valueList << value;
+                break;
+            }
+        }
+        else if (ch == ';') {
+            valueList << value;
+            value = "";
+        }
+        else {
+            value += ch;
+        }
+    }
+
+    Q_FOREACH (value, valueList) {
+        QString str;
+        if (!unescapeString(value, 0, value.size(), str)) {
+            return false;
+        }
+        result << str;
+    }
+
+    return true;
+}
+
 QStringList KeyFile::Private::allGroups() const
 {
     return groups.keys();
@@ -266,7 +308,7 @@ QStringList KeyFile::Private::allGroups() const
 QStringList KeyFile::Private::allKeys() const
 {
     QStringList keys;
-    QHash<QString, QHash<QString, QString> >::const_iterator itrGroups = groups.begin();
+    QHash<QString, QHash<QString, QByteArray> >::const_iterator itrGroups = groups.begin();
     while (itrGroups != groups.end()) {
         keys << itrGroups.value().keys();
         ++itrGroups;
@@ -276,22 +318,44 @@ QStringList KeyFile::Private::allKeys() const
 
 QStringList KeyFile::Private::keys() const
 {
-    QHash<QString, QString> groupMap = groups[currentGroup];
+    QHash<QString, QByteArray> groupMap = groups[currentGroup];
     return groupMap.keys();
 }
 
 bool KeyFile::Private::contains(const QString &key) const
 {
-    QHash<QString, QString> groupMap = groups[currentGroup];
+    QHash<QString, QByteArray> groupMap = groups[currentGroup];
     return groupMap.contains(key);
 }
 
+QString KeyFile::Private::rawValue(const QString &key) const
+{
+    QHash<QString, QByteArray> groupMap = groups[currentGroup];
+    QByteArray rawValue = groupMap.value(key);
+    return QString(rawValue);
+}
+
 QString KeyFile::Private::value(const QString &key) const
 {
-    QHash<QString, QString> groupMap = groups[currentGroup];
-    return groupMap.value(key);
+    QHash<QString, QByteArray> groupMap = groups[currentGroup];
+    QString result;
+    QByteArray rawValue = groupMap.value(key);
+    if (unescapeString(rawValue, 0, rawValue.size(), result)) {
+        return result;
+    }
+    return QString();
 }
 
+QStringList KeyFile::Private::valueAsStringList(const QString &key) const
+{
+    QHash<QString, QByteArray> groupMap = groups[currentGroup];
+    QStringList result;
+    QByteArray rawValue = groupMap.value(key);
+    if (unescapeStringList(rawValue, 0, rawValue.size(), result)) {
+        return result;
+    }
+    return QStringList();
+}
 
 /**
  * \class KeyFile
@@ -441,14 +505,45 @@ bool KeyFile::contains(const QString &key) const
 }
 
 /**
- * Get the value for the key in the current group named \a key.
+ * Get the raw value for the key in the current group named \a key.
+ *
+ * The raw value is the value as is in the key file.
  *
  * \return Value of \a key, empty string if not found.
  * \sa group(), setGroup()
  */
+QString KeyFile::rawValue(const QString &key) const
+{
+    return mPriv->rawValue(key);
+}
+
+/**
+ * Get the value for the key in the current group named \a key.
+ *
+ * Escape sequences in the value are interpreted as defined in:
+ * http://standards.freedesktop.org/desktop-entry-spec/latest/
+ *
+ * \return Value of \a key, empty string if not found or an error occurred.
+ * \sa group(), setGroup()
+ */
 QString KeyFile::value(const QString &key) const
 {
     return mPriv->value(key);
 }
 
+/**
+ * Get the value for the key in the current group named \a key as a list.
+ *
+ * Return a list containing all strings on this key separated by ';'.
+ * Escape sequences in the value are interpreted as defined in:
+ * http://standards.freedesktop.org/desktop-entry-spec/latest/
+ *
+ * \return Value of \a key as a list, empty string list if not found or an error occurred.
+ * \sa group(), setGroup()
+ */
+QStringList KeyFile::valueAsStringList(const QString &key) const
+{
+    return mPriv->valueAsStringList(key);
+}
+
 }
diff --git a/TelepathyQt4/key-file.h b/TelepathyQt4/key-file.h
index 98dbb65..9374031 100644
--- a/TelepathyQt4/key-file.h
+++ b/TelepathyQt4/key-file.h
@@ -60,7 +60,9 @@ public:
     QStringList keys() const;
     bool contains(const QString &key) const;
 
+    QString rawValue(const QString &key) const;
     QString value(const QString &key) const;
+    QStringList valueAsStringList(const QString &key) const;
 
 private:
     Q_DISABLE_COPY(KeyFile);
diff --git a/TelepathyQt4/manager-file.cpp b/TelepathyQt4/manager-file.cpp
index 7ded867..9b3a97a 100644
--- a/TelepathyQt4/manager-file.cpp
+++ b/TelepathyQt4/manager-file.cpp
@@ -53,7 +53,7 @@ struct ManagerFile::Private
     QStringList protocols() const;
     ParamSpecList parameters(const QString &protocol) const;
 
-    QVariant valueForKey(const QString &value, const QString &signature);
+    QVariant valueForKey(const QString &param, const QString &signature);
 };
 
 ManagerFile::Private::Private(const QString &cmName)
@@ -162,7 +162,7 @@ bool ManagerFile::Private::parse(const QString &fileName)
 
                     /* map based on the param dbus signature, otherwise use
                      * QString */
-                    QVariant value = valueForKey(keyFile.value(param), spec->signature);
+                    QVariant value = valueForKey(param, spec->signature);
                     spec->defaultValue = QDBusVariant(value);
                 }
             }
@@ -212,7 +212,7 @@ ParamSpecList ManagerFile::Private::parameters(const QString &protocol) const
     return protocolParams.value(protocol);
 }
 
-QVariant ManagerFile::Private::valueForKey(const QString &value,
+QVariant ManagerFile::Private::valueForKey(const QString &param,
                                            const QString &signature)
 {
     QVariant::Type type = ManagerFile::variantTypeFromDBusSignature(signature);
@@ -223,58 +223,52 @@ QVariant ManagerFile::Private::valueForKey(const QString &value,
 
     switch (type) {
         case QVariant::Bool:
-            if (value.toLower() == "true" || value == "1") {
-                return QVariant(true);
-            }
-            else {
-                return QVariant(false);
+            {
+                QString value = keyFile.value(param);
+                if (value.toLower() == "true" || value == "1") {
+                    return QVariant(true);
+                }
+                else {
+                    return QVariant(false);
+                }
+                break;
             }
-            break;
         case QVariant::Int:
-            return QVariant(value.toInt());
+            {
+                QString value = keyFile.value(param);
+                return QVariant(value.toInt());
+            }
         case QVariant::UInt:
-            return QVariant(value.toUInt());
+            {
+                QString value = keyFile.value(param);
+                return QVariant(value.toUInt());
+            }
         case QVariant::LongLong:
-            return QVariant(value.toLongLong());
+            {
+                QString value = keyFile.value(param);
+                return QVariant(value.toLongLong());
+            }
         case QVariant::ULongLong:
-            return QVariant(value.toULongLong());
+            {
+                QString value = keyFile.value(param);
+                return QVariant(value.toULongLong());
+            }
         case QVariant::Double:
-            return QVariant(value.toDouble());
+            {
+                QString value = keyFile.value(param);
+                return QVariant(value.toDouble());
+            }
         case QVariant::StringList:
             {
-                // split string in a list of strings escaping \; to ;
-                QStringList result;
-                QString v;
-                int i = 0;
-                int len = value.length();
-                QChar lastch, ch;
-                while (i < len) {
-                    ch = value.at(i++);
-                    if (ch == ';') {
-                        if (lastch == '\\') {
-                            v += ';';
-                        }
-                        else {
-                            result << v;
-                            v = QString();
-                        }
-                    }
-                    else if (ch != '\\') {
-                        v += ch;
-                    }
-                    lastch = ch;
-                }
-
-                if (ch != ';') {
-                    result << v;
-                }
-
-                return QVariant(result);
+                QStringList value = keyFile.valueAsStringList(param);
+                return QVariant(value);
             }
         default:
-            break;
+            {
+                QString value = keyFile.value(param);
+                return QVariant(value);
+            }
     }
-    return QVariant(value);
 }
 
 
-- 
1.5.6.5




More information about the Telepathy-commits mailing list