Do not preload any codecs anymore when using ICU
authorLars Knoll <lars.knoll@nokia.com>
Wed, 25 Jul 2012 10:57:15 +0000 (12:57 +0200)
committerQt by Nokia <qt-info@nokia.com>
Tue, 31 Jul 2012 09:12:58 +0000 (11:12 +0200)
When using ICU we can now avoid pre loading any codecs
at startup. Instead QTextCodecs will always be created
lazily when first asked for.

Change-Id: Ic668f2824700896d2eca7d0de54f978404826163
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
src/corelib/codecs/qicucodec.cpp
src/corelib/codecs/qisciicodec.cpp
src/corelib/codecs/qtextcodec.cpp
src/corelib/codecs/qtextcodec_p.h

index 56efcad..221d130 100644 (file)
 
 #include "qicucodec_p.h"
 #include "qtextcodec_p.h"
+#include "qutfcodec_p.h"
+#include "qlatincodec_p.h"
+#include "qtsciicodec_p.h"
+#include "qisciicodec_p.h"
 #include "private/qcoreglobaldata_p.h"
 #include "qdebug.h"
 
@@ -55,6 +59,11 @@ static void qIcuCodecStateFree(QTextCodec::ConverterState *state)
     ucnv_close(static_cast<UConverter *>(state->d));
 }
 
+bool qTextCodecNameMatch(const char *n, const char *h)
+{
+    return ucnv_compareNames(n, h) == 0;
+}
+
 /* The list below is generated from http://www.iana.org/assignments/character-sets/
    using the snippet of code below:
 
@@ -341,6 +350,33 @@ static const char mibToNameTable[] =
     "windows-1258\0"
     "TIS-620\0";
 
+static QTextCodec *loadQtCodec(const char *name)
+{
+    if (!strcmp(name, "UTF-8"))
+        return new QUtf8Codec;
+    if (!strcmp(name, "UTF-16"))
+        return new QUtf16Codec;
+    if (!strcmp(name, "ISO-8859-1"))
+        return new QLatin1Codec;
+    if (!strcmp(name, "UTF-16BE"))
+        return new QUtf16BECodec;
+    if (!strcmp(name, "UTF-16LE"))
+        return new QUtf16LECodec;
+    if (!strcmp(name, "UTF-32"))
+        return new QUtf32Codec;
+    if (!strcmp(name, "UTF-32BE"))
+        return new QUtf32BECodec;
+    if (!strcmp(name, "UTF-32LE"))
+        return new QUtf32LECodec;
+    if (!strcmp(name, "TSCII"))
+        return new QTsciiCodec;
+    if (!qstrnicmp(name, "iscii", 5))
+        return QIsciiCodec::create(name);
+
+    return 0;
+}
+
+
 QList<QByteArray> QIcuCodec::availableCodecs()
 {
     QList<QByteArray> codecs;
@@ -397,14 +433,16 @@ QTextCodec *QIcuCodec::defaultCodec()
     if (c)
         return c;
 
+#if defined(QT_LOCALE_IS_UTF8)
+    const char *name = "UTF-8";
+#else
     const char *name = ucnv_getDefaultName();
+#endif
     c = codecForName(name);
     globalData->codecForLocale.storeRelease(c);
     return c;
 }
 
-static inline bool nameMatch(const QByteArray &a, const char *b)
-{ return a == b; }
 
 QTextCodec *QIcuCodec::codecForName(const char *name)
 {
@@ -449,20 +487,24 @@ QTextCodec *QIcuCodec::codecForName(const char *name)
 
     for (int i = 0; i < globalData->allCodecs.size(); ++i) {
         QTextCodec *cursor = globalData->allCodecs.at(i);
-        if (nameMatch(cursor->name(), standardName)) {
+        if (qTextCodecNameMatch(cursor->name(), standardName)) {
             if (cache)
                 cache->insert(standardName, cursor);
             return cursor;
         }
         QList<QByteArray> aliases = cursor->aliases();
         for (int y = 0; y < aliases.size(); ++y)
-            if (nameMatch(aliases.at(y), standardName)) {
+            if (qTextCodecNameMatch(aliases.at(y), standardName)) {
                 if (cache)
                     cache->insert(standardName, cursor);
                 return cursor;
             }
     }
 
+    QTextCodec *c = loadQtCodec(standardName);
+    if (c)
+        return c;
+
     if (qt_only)
         return 0;
 
@@ -476,7 +518,7 @@ QTextCodec *QIcuCodec::codecForName(const char *name)
     ucnv_close(conv);
 
 
-    QTextCodec *c = new QIcuCodec(standardName);
+    c = new QIcuCodec(standardName);
     if (cache)
         cache->insert(standardName, c);
     return c;
@@ -628,7 +670,7 @@ QList<QByteArray> QIcuCodec::aliases() const
 int QIcuCodec::mibEnum() const
 {
     for (int i = 0; i < mibToNameSize; ++i) {
-        if (m_name == (mibToNameTable + mibToName[i].index))
+        if (qTextCodecNameMatch(m_name, (mibToNameTable + mibToName[i].index)))
             return mibToName[i].mib;
     }
 
index 1e5d512..d760d1e 100644 (file)
@@ -74,7 +74,7 @@ static const Codecs codecs [] = {
 QTextCodec *QIsciiCodec::create(const char *name)
 {
     for (int i = 0; i < 9; ++i) {
-        if (!qstricmp(name, codecs[i].name))
+        if (qTextCodecNameMatch(name, codecs[i].name))
             return new QIsciiCodec(i);
     }
     return 0;
index 6fef779..25d2d1f 100644 (file)
 
 QT_BEGIN_NAMESPACE
 
+Q_GLOBAL_STATIC_WITH_ARGS(QMutex, textCodecsMutex, (QMutex::Recursive));
+QMutex *qTextCodecsMutex() { return textCodecsMutex(); }
+
+#if !defined(QT_USE_ICU)
 static char qtolower(register char c)
 { if (c >= 'A' && c <= 'Z') return c + 0x20; return c; }
 static bool qisalnum(register char c)
 { return (c >= '0' && c <= '9') || ((c | 0x20) >= 'a' && (c | 0x20) <= 'z'); }
 
-static bool nameMatch(const QByteArray &name, const QByteArray &test)
+bool qTextCodecNameMatch(const char *n, const char *h)
 {
-    // if they're the same, return a perfect score
-    if (qstricmp(name.constData(), test.constData()) == 0)
+    if (qstricmp(n, h) == 0)
         return true;
 
-    const char *n = name.constData();
-    const char *h = test.constData();
-
     // if the letters and numbers are the same, we have a match
     while (*n != '\0') {
         if (qisalnum(*n)) {
@@ -130,6 +130,7 @@ static bool nameMatch(const QByteArray &name, const QByteArray &test)
     return (*h == '\0');
 }
 
+
 #if !defined(Q_OS_WIN32) && !defined(Q_OS_WINCE)
 static QTextCodec *checkForCodec(const QByteArray &name) {
     QTextCodec *c = QTextCodec::codecForName(name);
@@ -143,9 +144,6 @@ static QTextCodec *checkForCodec(const QByteArray &name) {
 }
 #endif
 
-Q_GLOBAL_STATIC_WITH_ARGS(QMutex, textCodecsMutex, (QMutex::Recursive));
-QMutex *qTextCodecsMutex() { return textCodecsMutex(); }
-
 static void setup();
 
 // this returns the codec the method sets up as locale codec to
@@ -155,10 +153,7 @@ static QTextCodec *setupLocaleMapper()
 {
     QCoreGlobalData *globalData = QCoreGlobalData::instance();
 
-    QTextCodec *locale = globalData->codecForLocale.loadAcquire();
-    if (locale)
-        // already setup
-        return locale;
+    QTextCodec *locale = 0;
 
     {
         QMutexLocker locker(textCodecsMutex());
@@ -170,10 +165,8 @@ static QTextCodec *setupLocaleMapper()
     QCoreApplicationPrivate::initLocale();
 #endif
 
-#if defined(Q_OS_MAC) || defined(Q_OS_IOS) || defined(Q_OS_LINUX_ANDROID) || defined(Q_OS_QNX)
+#if defined(QT_LOCALE_IS_UTF8)
     locale = QTextCodec::codecForName("UTF-8");
-#elif defined(QT_USE_ICU)
-    locale = QIcuCodec::defaultCodec();
 #elif defined(Q_OS_WIN) || defined(Q_OS_WINCE)
     locale = QTextCodec::codecForName("System");
 #else
@@ -263,14 +256,18 @@ static QTextCodec *setupLocaleMapper()
     return locale;
 }
 
+
 // textCodecsMutex need to be locked to enter this function
 static void setup()
 {
+    QCoreGlobalData *globalData = QCoreGlobalData::instance();
+    if (!globalData->allCodecs.isEmpty())
+        return;
+
 #if !defined(QT_NO_CODECS) && !defined(QT_BOOTSTRAPPED)
     (void)new QTsciiCodec;
     for (int i = 0; i < 9; ++i)
         (void)new QIsciiCodec(i);
-#if !defined(QT_USE_ICU)
     for (int i = 0; i < QSimpleTextCodec::numSimpleCodecs; ++i)
         (void)new QSimpleTextCodec(i);
 
@@ -292,7 +289,6 @@ static void setup()
 #if defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
     (void) new QWindowsLocalCodec;
 #endif // Q_OS_WIN32
-#endif // QT_USE_ICU
 #endif // !QT_NO_CODECS && !QT_BOOTSTRAPPED
 
     (void)new QUtf16Codec;
@@ -305,6 +301,9 @@ static void setup()
     (void)new QLatin1Codec;
     (void)new QUtf8Codec;
 }
+#else
+static void setup() {}
+#endif // QT_USE_ICU
 
 /*!
     \enum QTextCodec::ConversionFlag
@@ -510,7 +509,6 @@ QTextCodec *QTextCodec::codecForName(const QByteArray &name)
     QCoreGlobalData *globalData = QCoreGlobalData::instance();
     if (!globalData)
         return 0;
-    if (globalData->allCodecs.isEmpty())
         setup();
 
 #ifndef QT_USE_ICU
@@ -524,14 +522,14 @@ QTextCodec *QTextCodec::codecForName(const QByteArray &name)
 
     for (int i = 0; i < globalData->allCodecs.size(); ++i) {
         QTextCodec *cursor = globalData->allCodecs.at(i);
-        if (nameMatch(cursor->name(), name)) {
+        if (qTextCodecNameMatch(cursor->name(), name)) {
             if (cache)
                 cache->insert(name, cursor);
             return cursor;
         }
         QList<QByteArray> aliases = cursor->aliases();
         for (int y = 0; y < aliases.size(); ++y)
-            if (nameMatch(aliases.at(y), name)) {
+            if (qTextCodecNameMatch(aliases.at(y), name)) {
                 if (cache)
                     cache->insert(name, cursor);
                 return cursor;
@@ -677,8 +675,13 @@ QTextCodec* QTextCodec::codecForLocale()
         return 0;
 
     QTextCodec *codec = globalData->codecForLocale.loadAcquire();
-    if (!codec)
+    if (!codec) {
+#ifdef QT_USE_ICU
+        codec = QIcuCodec::defaultCodec();
+#else
         codec = setupLocaleMapper();
+#endif
+    }
 
     return codec;
 }
@@ -1062,7 +1065,7 @@ QTextCodec *QTextCodec::codecForHtml(const QByteArray &ba, QTextCodec *defaultCo
 */
 QTextCodec *QTextCodec::codecForHtml(const QByteArray &ba)
 {
-    return codecForHtml(ba, QTextCodec::codecForMib(/*Latin 1*/ 4));
+    return codecForHtml(ba, QTextCodec::codecForName("ISO-8859-1"));
 }
 
 /*!
index d138359..532670d 100644 (file)
@@ -60,6 +60,10 @@ QT_BEGIN_NAMESPACE
 
 #ifndef QT_NO_TEXTCODEC
 
+#if defined(Q_OS_MAC) || defined(Q_OS_IOS) || defined(Q_OS_LINUX_ANDROID) || defined(Q_OS_QNX)
+#define QT_LOCALE_IS_UTF8
+#endif
+
 typedef void (*QTextCodecStateFreeFunction)(QTextCodec::ConverterState*);
 
 struct QTextCodecUnalignedPointer
@@ -77,6 +81,8 @@ struct QTextCodecUnalignedPointer
     }
 };
 
+bool qTextCodecNameMatch(const char *a, const char *b);
+
 #else
 
 class QTextCodec