diff --git a/src/corelib/codecs/qtextcodec.cpp b/src/corelib/codecs/qtextcodec.cpp index 5d62095..0984d2f 100644 --- a/src/corelib/codecs/qtextcodec.cpp +++ b/src/corelib/codecs/qtextcodec.cpp @@ -97,8 +97,45 @@ QT_BEGIN_NAMESPACE +static QList *localCodecs = 0; +static QList *pluginCodecs = 0; +#ifdef Q_DEBUG_TEXTCODEC +static bool destroying_is_ok = false; +#endif +static QTextCodec *localeMapper = 0; +QTextCodec *QTextCodec::cftr = 0; + #ifndef QT_NO_TEXTCODECPLUGIN -Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader, +class QTextCodecFactoryLoader : public QFactoryLoader +{ +public: + QTextCodecFactoryLoader(const char *iid, + const QString &suffix = QString(), + Qt::CaseSensitivity caseSensitivity = Qt::CaseSensitive) + : QFactoryLoader(iid, suffix, caseSensitivity) + { + pluginCodecs = new QList; + } + ~QTextCodecFactoryLoader() + { + if (pluginCodecs) { +#ifdef Q_DEBUG_TEXTCODEC + destroying_is_ok = true; +#endif + // making sure we delete the QTextCodec before unloading the plugin. + for (QList::const_iterator it = pluginCodecs->constBegin() + ; it != pluginCodecs->constEnd(); ++it) { + delete *it; + } + delete pluginCodecs; + pluginCodecs = 0; +#ifdef Q_DEBUG_TEXTCODEC + destroying_is_ok = false; +#endif + } + } +}; +Q_GLOBAL_STATIC_WITH_ARGS(QTextCodecFactoryLoader, loader, (QTextCodecFactoryInterface_iid, QLatin1String("/codecs"))) #endif @@ -148,7 +185,9 @@ static QTextCodec *createForName(const QByteArray &name) QString realName = keys.at(i); if (QTextCodecFactoryInterface *factory = qobject_cast(l->instance(realName))) { - return factory->create(realName); + QTextCodec *codec = factory->create(realName); + pluginCodecs->append(codec); + return codec; } } } @@ -163,23 +202,17 @@ static QTextCodec *createForMib(int mib) #ifndef QT_NO_TEXTCODECPLUGIN QString name = QLatin1String("MIB: ") + QString::number(mib); if (QTextCodecFactoryInterface *factory - = qobject_cast(loader()->instance(name))) - return factory->create(name); + = qobject_cast(loader()->instance(name))) { + QTextCodec *codec = factory->create(name); + pluginCodecs->append(codec); + return codec; + } #else Q_UNUSED(mib); #endif return 0; } -static QList *all = 0; -#ifdef Q_DEBUG_TEXTCODEC -static bool destroying_is_ok = false; -#endif - -static QTextCodec *localeMapper = 0; -QTextCodec *QTextCodec::cftr = 0; - - class QTextCodecCleanup { public: @@ -187,25 +220,23 @@ public: }; /* - Deletes all the created codecs. This destructor is called just - before exiting to delete any QTextCodec objects that may be lying - around. + Deletes all local codecs, i.e. not loaded from a plugin. This destructor is + called just before exiting to delete any QTextCodec objects that may be + lying around. */ QTextCodecCleanup::~QTextCodecCleanup() { - if (!all) + if (!localCodecs) return; #ifdef Q_DEBUG_TEXTCODEC destroying_is_ok = true; #endif - for (QList::const_iterator it = all->constBegin() - ; it != all->constEnd(); ++it) { - delete *it; - } - delete all; - all = 0; + while (localCodecs->size()) + delete localCodecs->takeFirst(); + delete localCodecs; + localCodecs = 0; localeMapper = 0; #ifdef Q_DEBUG_TEXTCODEC @@ -663,78 +694,78 @@ static void setupLocaleMapper() static void setup() { #ifndef QT_NO_THREAD - QMutexLocker locker(QMutexPool::globalInstanceGet(&all)); + QMutexLocker locker(QMutexPool::globalInstanceGet(&localCodecs)); #endif - if (all) + if (localCodecs) return; #ifdef Q_DEBUG_TEXTCODEC if (destroying_is_ok) qWarning("QTextCodec: Creating new codec during codec cleanup"); #endif - all = new QList; + localCodecs = new QList; // create the cleanup object to cleanup all codecs on exit (void) createQTextCodecCleanup(); #ifndef QT_NO_CODECS # if defined(Q_WS_X11) && !defined(QT_BOOTSTRAPPED) // no font codecs when bootstrapping - (void)new QFontLaoCodec; + localCodecs->append(new QFontLaoCodec); # if defined(QT_NO_ICONV) // no iconv(3) support, must build all codecs into the library - (void)new QFontGb2312Codec; - (void)new QFontGbkCodec; - (void)new QFontGb18030_0Codec; - (void)new QFontJis0208Codec; - (void)new QFontJis0201Codec; - (void)new QFontKsc5601Codec; - (void)new QFontBig5hkscsCodec; - (void)new QFontBig5Codec; + localCodecs->append(new QFontGb2312Codec); + localCodecs->append(new QFontGbkCodec); + localCodecs->append(new QFontGb18030_0Codec); + localCodecs->append(new QFontJis0208Codec); + localCodecs->append(new QFontJis0201Codec); + localCodecs->append(new QFontKsc5601Codec); + localCodecs->append(new QFontBig5hkscsCodec); + localCodecs->append(new QFontBig5Codec); # endif // QT_NO_ICONV && !QT_BOOTSTRAPPED # endif // Q_WS_X11 - (void)new QTsciiCodec; + localCodecs->append(new QTsciiCodec); for (int i = 0; i < 9; ++i) - (void)new QIsciiCodec(i); + localCodecs->append(new QIsciiCodec(i)); # if defined(QT_NO_ICONV) && !defined(QT_BOOTSTRAPPED) // no asian codecs when bootstrapping, sorry - (void)new QGb18030Codec; - (void)new QGbkCodec; - (void)new QGb2312Codec; - (void)new QEucJpCodec; - (void)new QJisCodec; - (void)new QSjisCodec; - (void)new QEucKrCodec; - (void)new QCP949Codec; - (void)new QBig5Codec; - (void)new QBig5hkscsCodec; + localCodecs->append(new QGb18030Codec); + localCodecs->append(new QGbkCodec); + localCodecs->append(new QGb2312Codec); + localCodecs->append(new QEucJpCodec); + localCodecs->append(new QJisCodec); + localCodecs->append(new QSjisCodec); + localCodecs->append(new QEucKrCodec); + localCodecs->append(new QCP949Codec); + localCodecs->append(new QBig5Codec); + localCodecs->append(new QBig5hkscsCodec); # endif // QT_NO_ICONV && !QT_BOOTSTRAPPED #endif // QT_NO_CODECS #if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) - (void) new QWindowsLocalCodec; + localCodecs->append(new QWindowsLocalCodec); #endif // Q_OS_WIN32 - (void)new QUtf16Codec; - (void)new QUtf16BECodec; - (void)new QUtf16LECodec; - (void)new QUtf32Codec; - (void)new QUtf32BECodec; - (void)new QUtf32LECodec; - (void)new QLatin15Codec; - (void)new QLatin1Codec; - (void)new QUtf8Codec; + localCodecs->append(new QUtf16Codec); + localCodecs->append(new QUtf16BECodec); + localCodecs->append(new QUtf16LECodec); + localCodecs->append(new QUtf32Codec); + localCodecs->append(new QUtf32BECodec); + localCodecs->append(new QUtf32LECodec); + localCodecs->append(new QLatin15Codec); + localCodecs->append(new QLatin1Codec); + localCodecs->append(new QUtf8Codec); for (int i = 0; i < QSimpleTextCodec::numSimpleCodecs; ++i) - (void)new QSimpleTextCodec(i); + localCodecs->append(new QSimpleTextCodec(i)); #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(); + localCodecs->append(new QIconvCodec()); #endif if (!localeMapper) @@ -913,7 +944,6 @@ QTextCodec::ConverterState::~ConverterState() QTextCodec::QTextCodec() { setup(); - all->prepend(this); } @@ -929,8 +959,10 @@ QTextCodec::~QTextCodec() if (!destroying_is_ok) qWarning("QTextCodec::~QTextCodec: Called by application"); #endif - if (all) - all->removeAll(this); + if (localCodecs) + localCodecs->removeAll(this); + if (pluginCodecs) + pluginCodecs->removeAll(this); } /*! @@ -953,8 +985,8 @@ QTextCodec *QTextCodec::codecForName(const QByteArray &name) setup(); - for (int i = 0; i < all->size(); ++i) { - QTextCodec *cursor = all->at(i); + for (int i = 0; i < localCodecs->size(); ++i) { + QTextCodec *cursor = localCodecs->at(i); if (nameMatch(cursor->name(), name)) return cursor; QList aliases = cursor->aliases(); @@ -962,6 +994,17 @@ QTextCodec *QTextCodec::codecForName(const QByteArray &name) if (nameMatch(aliases.at(i), name)) return cursor; } + if (pluginCodecs) { + for (int i = 0; i < pluginCodecs->size(); ++i) { + QTextCodec *cursor = pluginCodecs->at(i); + if (nameMatch(cursor->name(), name)) + return cursor; + QList aliases = cursor->aliases(); + for (int i = 0; i < aliases.size(); ++i) + if (nameMatch(aliases.at(i), name)) + return cursor; + } + } return createForName(name); } @@ -980,12 +1023,18 @@ QTextCodec* QTextCodec::codecForMib(int mib) if (mib == 1000) mib = 1015; - QList::ConstIterator i; - for (int i = 0; i < all->size(); ++i) { - QTextCodec *cursor = all->at(i); + for (int i = 0; i < localCodecs->size(); ++i) { + QTextCodec *cursor = localCodecs->at(i); if (cursor->mibEnum() == mib) return cursor; } + if (pluginCodecs) { + for (int i = 0; i < pluginCodecs->size(); ++i) { + QTextCodec *cursor = pluginCodecs->at(i); + if (cursor->mibEnum() == mib) + return cursor; + } + } return createForMib(mib); } @@ -1004,9 +1053,15 @@ QList QTextCodec::availableCodecs() setup(); QList codecs; - for (int i = 0; i < all->size(); ++i) { - codecs += all->at(i)->name(); - codecs += all->at(i)->aliases(); + for (int i = 0; i < localCodecs->size(); ++i) { + codecs += localCodecs->at(i)->name(); + codecs += localCodecs->at(i)->aliases(); + } + if (pluginCodecs) { + for (int i = 0; i < pluginCodecs->size(); ++i) { + codecs += pluginCodecs->at(i)->name(); + codecs += pluginCodecs->at(i)->aliases(); + } } #ifndef QT_NO_TEXTCODECPLUGIN QFactoryLoader *l = loader(); @@ -1034,8 +1089,12 @@ QList QTextCodec::availableMibs() setup(); QList codecs; - for (int i = 0; i < all->size(); ++i) - codecs += all->at(i)->mibEnum(); + for (int i = 0; i < localCodecs->size(); ++i) + codecs += localCodecs->at(i)->mibEnum(); + if (pluginCodecs) { + for (int i = 0; i < pluginCodecs->size(); ++i) + codecs += pluginCodecs->at(i)->mibEnum(); + } #ifndef QT_NO_TEXTCODECPLUGIN QFactoryLoader *l = loader(); QStringList keys = l->keys(); diff --git a/src/corelib/codecs/qtextcodec.h b/src/corelib/codecs/qtextcodec.h index f831700..e8b89f7 100644 --- a/src/corelib/codecs/qtextcodec.h +++ b/src/corelib/codecs/qtextcodec.h @@ -144,6 +144,7 @@ public: private: friend class QTextCodecCleanup; + friend class QTextCodecFactoryLoader; static QTextCodec *cftr; }; Q_DECLARE_OPERATORS_FOR_FLAGS(QTextCodec::ConversionFlags) diff --git a/src/corelib/plugin/qfactoryloader.cpp b/src/corelib/plugin/qfactoryloader.cpp index 41d8db9..5b24cdb 100644 --- a/src/corelib/plugin/qfactoryloader.cpp +++ b/src/corelib/plugin/qfactoryloader.cpp @@ -67,7 +67,7 @@ public: ~QFactoryLoaderPrivate(); mutable QMutex mutex; QByteArray iid; - QList libraryList; + mutable QList > libraryList; QMap keyMap; QStringList keyList; QString suffix; @@ -79,8 +79,12 @@ public: QFactoryLoaderPrivate::~QFactoryLoaderPrivate() { - for (int i = 0; i < libraryList.count(); ++i) - libraryList.at(i)->release(); + for (int i = 0; i < libraryList.count(); ++i) { + if (libraryList.at(i).second) + libraryList.at(i).first->unload(); + + libraryList.at(i).first->release(); + } } QFactoryLoader::QFactoryLoader(const char *iid, @@ -135,6 +139,7 @@ void QFactoryLoader::update() library->release(); continue; } + bool did_load = false; QString regkey = QString::fromLatin1("Qt Factory Cache %1.%2/%3:/%4") .arg((QT_VERSION & 0xff0000) >> 16) .arg((QT_VERSION & 0xff00) >> 8) @@ -154,6 +159,7 @@ void QFactoryLoader::update() library->release(); continue; } + did_load = true; QObject *instance = library->instance(); if (!instance) // ignore plugins that have a valid signature but cannot be loaded. @@ -176,7 +182,7 @@ void QFactoryLoader::update() library->release(); continue; } - d->libraryList += library; + d->libraryList += QPair(library, did_load); for (int k = 0; k < keys.count(); ++k) { // first come first serve, unless the first // library was built with a future Qt version, @@ -233,13 +239,24 @@ QObject *QFactoryLoader::instance(const QString &key) const QString lowered = d->cs ? key : key.toLower(); if (QLibraryPrivate* library = d->keyMap.value(lowered)) { - if (library->instance || library->loadPlugin()) { - if (QObject *obj = library->instance()) { - if (obj && !obj->parent()) - obj->moveToThread(QCoreApplicationPrivate::mainThread()); - return obj; + if (!library->instance) { + if (!library->loadPlugin()) + return 0; + + QList >::iterator itr; + for (itr = d->libraryList.begin(); itr != d->libraryList.end(); ++itr) { + if (library == (*itr).first) { + (*itr).second = true; // mark this plugin as loaded + break; + } } } + + if (QObject *obj = library->instance()) { + if (obj && !obj->parent()) + obj->moveToThread(QCoreApplicationPrivate::mainThread()); + return obj; + } } return 0; }