From 8a883d972da3b28d87689c4d4d9c9b5e5b1dcba1 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Wed, 25 Jul 2012 12:57:15 +0200 Subject: [PATCH] Do not preload any codecs anymore when using ICU 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 --- src/corelib/codecs/qicucodec.cpp | 54 +++++++++++++++++++++++++++++++++----- src/corelib/codecs/qisciicodec.cpp | 2 +- src/corelib/codecs/qtextcodec.cpp | 49 ++++++++++++++++++---------------- src/corelib/codecs/qtextcodec_p.h | 6 +++++ 4 files changed, 81 insertions(+), 30 deletions(-) diff --git a/src/corelib/codecs/qicucodec.cpp b/src/corelib/codecs/qicucodec.cpp index 56efcad..221d130 100644 --- a/src/corelib/codecs/qicucodec.cpp +++ b/src/corelib/codecs/qicucodec.cpp @@ -41,6 +41,10 @@ #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(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 QIcuCodec::availableCodecs() { QList 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 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 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; } diff --git a/src/corelib/codecs/qisciicodec.cpp b/src/corelib/codecs/qisciicodec.cpp index 1e5d512..d760d1e 100644 --- a/src/corelib/codecs/qisciicodec.cpp +++ b/src/corelib/codecs/qisciicodec.cpp @@ -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; diff --git a/src/corelib/codecs/qtextcodec.cpp b/src/corelib/codecs/qtextcodec.cpp index 6fef779..25d2d1f 100644 --- a/src/corelib/codecs/qtextcodec.cpp +++ b/src/corelib/codecs/qtextcodec.cpp @@ -95,20 +95,20 @@ 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 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")); } /*! diff --git a/src/corelib/codecs/qtextcodec_p.h b/src/corelib/codecs/qtextcodec_p.h index d138359..532670d 100644 --- a/src/corelib/codecs/qtextcodec_p.h +++ b/src/corelib/codecs/qtextcodec_p.h @@ -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 -- 2.7.4