make QProcessEnvironment on Unix cache converted variable names
authorOswald Buddenhagen <oswald.buddenhagen@nokia.com>
Thu, 28 Apr 2011 08:53:14 +0000 (10:53 +0200)
committerOlivier Goffart <olivier.goffart@nokia.com>
Tue, 10 May 2011 10:54:52 +0000 (12:54 +0200)
the converted keys also cache their hash, as they are used only for the
purpose of looking up in a qhash.

Reviewed-by: thiago
Reviewed-by: dt
(cherry picked from commit 18f1613aa8ece72d24ac10e28f06e3db1d8ce400)

src/corelib/io/qprocess.cpp
src/corelib/io/qprocess_p.h
src/corelib/io/qprocess_unix.cpp

index ffd5ff0..80e0b0f 100644 (file)
@@ -202,12 +202,19 @@ QStringList QProcessEnvironmentPrivate::keys() const
     return result;
 }
 
-void QProcessEnvironmentPrivate::insert(const Hash &h)
+void QProcessEnvironmentPrivate::insert(const QProcessEnvironmentPrivate &other)
 {
-    Hash::ConstIterator it = h.constBegin(),
-                       end = h.constEnd();
+    Hash::ConstIterator it = other.hash.constBegin(),
+                       end = other.hash.constEnd();
     for ( ; it != end; ++it)
         hash.insert(it.key(), it.value());
+
+#ifdef Q_OS_UNIX
+    QHash<QString, Key>::ConstIterator nit = other.nameMap.constBegin(),
+                                      nend = other.nameMap.constEnd();
+    for ( ; nit != nend; ++nit)
+        nameMap.insert(nit.key(), nit.value());
+#endif
 }
 
 /*!
@@ -288,6 +295,8 @@ void QProcessEnvironment::clear()
 {
     if (d)
         d->hash.clear();
+    // Unix: Don't clear d->nameMap, as the environment is likely to be
+    // re-populated with the same keys again.
 }
 
 /*!
@@ -409,7 +418,7 @@ void QProcessEnvironment::insert(const QProcessEnvironment &e)
         return;
 
     // d detaches from null
-    d->insert(e.d->hash);
+    d->insert(*e.d);
 }
 
 void QProcessPrivate::Channel::clear()
index 14fc9f3..9a9981e 100644 (file)
@@ -101,11 +101,33 @@ public:
     inline Value prepareValue(const QString &value) const { return value; }
     inline QString valueToString(const Value &value) const { return value; }
 #else
-    typedef QByteArray Key;
+    class Key
+    {
+    public:
+        Key() : hash(0) {}
+        explicit Key(const QByteArray &other) : key(other), hash(qHash(key)) {}
+        Key(const Key &other) { *this = other; }
+        bool operator==(const Key &other) const { return key == other.key; }
+
+        QByteArray key;
+        uint hash;
+    };
+
     typedef QByteArray Value;
 
-    inline Key prepareName(const QString &name) const { return name.toLocal8Bit(); }
-    inline QString nameToString(const Key &name) const { return QString::fromLocal8Bit(name); }
+    inline Key prepareName(const QString &name) const
+    {
+        Key &ent = nameMap[name];
+        if (ent.key.isEmpty())
+            ent = Key(name.toLocal8Bit());
+        return ent;
+    }
+    inline QString nameToString(const Key &name) const
+    {
+        const QString sname = QString::fromLocal8Bit(name.key);
+        nameMap[sname] = name;
+        return sname;
+    }
     inline Value prepareValue(const QString &value) const { return value.toLocal8Bit(); }
     inline QString valueToString(const Value &value) const { return QString::fromLocal8Bit(value); }
 #endif
@@ -113,14 +135,22 @@ public:
     typedef QHash<Key, Value> Hash;
     Hash hash;
 
+#ifdef Q_OS_UNIX
+    typedef QHash<QString, Key> NameHash;
+    mutable NameHash nameMap;
+#endif
+
     static QProcessEnvironment fromList(const QStringList &list);
     QStringList toList() const;
     QStringList keys() const;
-    void insert(const Hash &hash);
+    void insert(const QProcessEnvironmentPrivate &other);
 };
-#ifdef Q_OS_WIN
 Q_DECLARE_TYPEINFO(QProcessEnvironmentPrivate::Key, Q_MOVABLE_TYPE);
+
+#ifdef Q_OS_WIN
 inline uint qHash(const QProcessEnvironmentPrivate::Key &key) { return qHash(key.toCaseFolded()); }
+#else
+inline uint qHash(const QProcessEnvironmentPrivate::Key &key) { return key.hash; }
 #endif
 
 class QProcessPrivate : public QIODevicePrivate
index 7ee66ec..7edefd3 100644 (file)
@@ -483,7 +483,7 @@ static char **_q_dupEnvironment(const QProcessEnvironmentPrivate::Hash &environm
 #endif
     const QByteArray envLibraryPath = qgetenv(libraryPath);
     bool needToAddLibraryPath = !envLibraryPath.isEmpty() &&
-                                !environment.contains(libraryPath);
+                                !environment.contains(QProcessEnvironmentPrivate::Key(QByteArray(libraryPath)));
 
     char **envp = new char *[environment.count() + 2];
     envp[environment.count()] = 0;
@@ -492,7 +492,7 @@ static char **_q_dupEnvironment(const QProcessEnvironmentPrivate::Hash &environm
     QProcessEnvironmentPrivate::Hash::ConstIterator it = environment.constBegin();
     const QProcessEnvironmentPrivate::Hash::ConstIterator end = environment.constEnd();
     for ( ; it != end; ++it) {
-        QByteArray key = it.key();
+        QByteArray key = it.key().key;
         QByteArray value = it.value();
         key.reserve(key.length() + 1 + value.length());
         key.append('=');