src/corelib/codecs/qtextcodec.cpp
branchRCL_3
changeset 7 3f74d0d4af4c
parent 4 3b1da2848fc7
child 8 740e5562c97f
--- a/src/corelib/codecs/qtextcodec.cpp	Mon Mar 15 12:43:09 2010 +0200
+++ b/src/corelib/codecs/qtextcodec.cpp	Thu Apr 08 14:19:33 2010 +0300
@@ -64,6 +64,7 @@
 #ifndef QT_NO_CODECS
 #  include "qtsciicodec_p.h"
 #  include "qisciicodec_p.h"
+#ifndef Q_OS_SYMBIAN
 #  if defined(QT_NO_ICONV) && !defined(QT_BOOTSTRAPPED)
 // no iconv(3) support, must build all codecs into the library
 #    include "../../plugins/codecs/cn/qgb18030codec.h"
@@ -77,9 +78,11 @@
 #    include "qfontlaocodec_p.h"
 #    include "../../plugins/codecs/jp/qfontjpcodec.h"
 #  endif
+#endif // QT_NO_SYMBIAN
 #endif // QT_NO_CODECS
 #include "qlocale.h"
-#include "private/qmutexpool_p.h"
+#include "qmutex.h"
+#include "qhash.h"
 
 #include <stdlib.h>
 #include <ctype.h>
@@ -92,6 +95,11 @@
 #  define QT_NO_SETLOCALE
 #endif
 
+#ifdef Q_OS_SYMBIAN
+#include "qtextcodec_symbian.cpp"
+#endif
+
+
 // enabling this is not exception safe!
 // #define Q_DEBUG_TEXTCODEC
 
@@ -172,6 +180,7 @@
 }
 
 static QList<QTextCodec*> *all = 0;
+static int clearCaches = 0;  // flags specifying if caches should be invalided: 0x1 codecForName, 0x2 codecForMib
 #ifdef Q_DEBUG_TEXTCODEC
 static bool destroying_is_ok = false;
 #endif
@@ -535,6 +544,12 @@
 */
 static void setupLocaleMapper()
 {
+#ifdef Q_OS_SYMBIAN
+    localeMapper = QSymbianTextCodec::localeMapper;
+    if (localeMapper)
+        return;
+#endif
+
 #if defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
     localeMapper = QTextCodec::codecForName("System");
 #else
@@ -659,13 +674,13 @@
 #endif
 }
 
+#ifndef QT_NO_THREAD
+Q_GLOBAL_STATIC_WITH_ARGS(QMutex, textCodecsMutex, (QMutex::Recursive));
+#endif
 
+// textCodecsMutex need to be locked to enter this function
 static void setup()
 {
-#ifndef QT_NO_THREAD
-    QMutexLocker locker(QMutexPool::globalInstanceGet(&all));
-#endif
-
     if (all)
         return;
 
@@ -678,6 +693,17 @@
     (void) createQTextCodecCleanup();
 
 #ifndef QT_NO_CODECS
+    (void)new QTsciiCodec;
+    for (int i = 0; i < 9; ++i)
+        (void)new QIsciiCodec(i);
+
+    for (int i = 0; i < QSimpleTextCodec::numSimpleCodecs; ++i)
+        (void)new QSimpleTextCodec(i);
+
+#ifdef Q_OS_SYMBIAN
+    localeMapper = QSymbianTextCodec::init();
+#endif
+
 #  if defined(Q_WS_X11) && !defined(QT_BOOTSTRAPPED)
     // no font codecs when bootstrapping
     (void)new QFontLaoCodec;
@@ -694,12 +720,8 @@
 #    endif // QT_NO_ICONV && !QT_BOOTSTRAPPED
 #  endif // Q_WS_X11
 
-    (void)new QTsciiCodec;
 
-    for (int i = 0; i < 9; ++i)
-        (void)new QIsciiCodec(i);
-
-
+#ifndef Q_OS_SYMBIAN
 #  if defined(QT_NO_ICONV) && !defined(QT_BOOTSTRAPPED)
     // no asian codecs when bootstrapping, sorry
     (void)new QGb18030Codec;
@@ -713,6 +735,7 @@
     (void)new QBig5Codec;
     (void)new QBig5hkscsCodec;
 #  endif // QT_NO_ICONV && !QT_BOOTSTRAPPED
+#endif //Q_OS_SYMBIAN
 #endif // QT_NO_CODECS
 
 #if defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
@@ -725,17 +748,18 @@
     (void)new QUtf32Codec;
     (void)new QUtf32BECodec;
     (void)new QUtf32LECodec;
+#ifndef Q_OS_SYMBIAN
     (void)new QLatin15Codec;
+#endif
     (void)new QLatin1Codec;
     (void)new QUtf8Codec;
 
-    for (int i = 0; i < QSimpleTextCodec::numSimpleCodecs; ++i)
-        (void)new QSimpleTextCodec(i);
-
+#ifndef Q_OS_SYMBIAN
 #if defined(Q_OS_UNIX) && !defined(QT_NO_ICONV) && !defined(QT_BOOTSTRAPPED)
     // QIconvCodec depends on the UTF-16 codec, so it needs to be created last
     (void) new QIconvCodec();
 #endif
+#endif
 
     if (!localeMapper)
         setupLocaleMapper();
@@ -903,8 +927,6 @@
 */
 
 /*!
-    \nonreentrant
-
     Constructs a QTextCodec, and gives it the highest precedence. The
     QTextCodec should always be constructed on the heap (i.e. with \c
     new). Qt takes ownership and will delete it when the application
@@ -912,6 +934,9 @@
 */
 QTextCodec::QTextCodec()
 {
+#ifndef QT_NO_THREAD
+    QMutexLocker locker(textCodecsMutex());
+#endif
     setup();
     all->prepend(this);
 }
@@ -929,8 +954,13 @@
     if (!destroying_is_ok)
         qWarning("QTextCodec::~QTextCodec: Called by application");
 #endif
-    if (all)
+    if (all) {
+#ifndef QT_NO_THREAD
+        QMutexLocker locker(textCodecsMutex());
+#endif
         all->removeAll(this);
+        clearCaches = 0x1 | 0x2;
+    }
 }
 
 /*!
@@ -951,19 +981,38 @@
     if (name.isEmpty())
         return 0;
 
+#ifndef QT_NO_THREAD
+    QMutexLocker locker(textCodecsMutex());
+#endif
     setup();
 
+    static QHash <QByteArray, QTextCodec *> cache;
+    if (clearCaches & 0x1) {
+        cache.clear();
+        clearCaches &= ~0x1;
+    }
+    QTextCodec *codec = cache.value(name);
+    if (codec)
+        return codec;
+
     for (int i = 0; i < all->size(); ++i) {
         QTextCodec *cursor = all->at(i);
-        if (nameMatch(cursor->name(), name))
+        if (nameMatch(cursor->name(), name)) {
+            cache.insert(name, cursor);
             return cursor;
+        }
         QList<QByteArray> aliases = cursor->aliases();
-        for (int i = 0; i < aliases.size(); ++i)
-            if (nameMatch(aliases.at(i), name))
+        for (int y = 0; y < aliases.size(); ++y)
+            if (nameMatch(aliases.at(y), name)) {
+                cache.insert(name, cursor);
                 return cursor;
+            }
     }
 
-    return createForName(name);
+    codec = createForName(name);
+    if (codec)
+        cache.insert(name, codec);
+    return codec;
 }
 
 
@@ -973,21 +1022,39 @@
 */
 QTextCodec* QTextCodec::codecForMib(int mib)
 {
+#ifndef QT_NO_THREAD
+    QMutexLocker locker(textCodecsMutex());
+#endif
     setup();
 
-    // Qt 3 used 1000 (mib for UCS2) as its identifier for the utf16 codec. Map
-    // this correctly for compatibility.
-    if (mib == 1000)
-        mib = 1015;
+    static QHash <int, QTextCodec *> cache;
+    if (clearCaches & 0x2) {
+        cache.clear();
+        clearCaches &= ~0x2;
+    }
+    QTextCodec *codec = cache.value(mib);
+    if (codec)
+        return codec;
 
     QList<QTextCodec*>::ConstIterator i;
     for (int i = 0; i < all->size(); ++i) {
         QTextCodec *cursor = all->at(i);
-        if (cursor->mibEnum() == mib)
+        if (cursor->mibEnum() == mib) {
+            cache.insert(mib, cursor);
             return cursor;
+        }
     }
 
-    return createForMib(mib);
+    codec = createForMib(mib);
+
+    // Qt 3 used 1000 (mib for UCS2) as its identifier for the utf16 codec. Map
+    // this correctly for compatibility.
+    if (!codec && mib == 1000)
+        return codecForMib(1015);
+
+    if (codec)
+        cache.insert(mib, codec);
+    return codec;
 }
 
 /*!
@@ -1001,6 +1068,9 @@
 */
 QList<QByteArray> QTextCodec::availableCodecs()
 {
+#ifndef QT_NO_THREAD
+    QMutexLocker locker(textCodecsMutex());
+#endif
     setup();
 
     QList<QByteArray> codecs;
@@ -1008,6 +1078,11 @@
         codecs += all->at(i)->name();
         codecs += all->at(i)->aliases();
     }
+
+#ifndef QT_NO_THREAD
+    locker.unlock();
+#endif
+
 #ifndef QT_NO_TEXTCODECPLUGIN
     QFactoryLoader *l = loader();
     QStringList keys = l->keys();
@@ -1031,11 +1106,19 @@
 */
 QList<int> QTextCodec::availableMibs()
 {
+#ifndef QT_NO_THREAD
+    QMutexLocker locker(textCodecsMutex());
+#endif
     setup();
 
     QList<int> codecs;
     for (int i = 0; i < all->size(); ++i)
         codecs += all->at(i)->mibEnum();
+
+#ifndef QT_NO_THREAD
+    locker.unlock();
+#endif
+
 #ifndef QT_NO_TEXTCODECPLUGIN
     QFactoryLoader *l = loader();
     QStringList keys = l->keys();
@@ -1063,6 +1146,9 @@
 */
 void QTextCodec::setCodecForLocale(QTextCodec *c)
 {
+#ifndef QT_NO_THREAD
+    QMutexLocker locker(textCodecsMutex());
+#endif
     localeMapper = c;
     if (!localeMapper)
         setupLocaleMapper();
@@ -1082,6 +1168,9 @@
     if (localeMapper)
         return localeMapper;
 
+#ifndef QT_NO_THREAD
+    QMutexLocker locker(textCodecsMutex());
+#endif
     setup();
 
     return localeMapper;