src/corelib/codecs/qtextcodec.cpp
branchRCL_3
changeset 7 3f74d0d4af4c
parent 4 3b1da2848fc7
child 8 740e5562c97f
equal deleted inserted replaced
6:dee5afe5301f 7:3f74d0d4af4c
    62 #include "qsimplecodec_p.h"
    62 #include "qsimplecodec_p.h"
    63 #include "qlatincodec_p.h"
    63 #include "qlatincodec_p.h"
    64 #ifndef QT_NO_CODECS
    64 #ifndef QT_NO_CODECS
    65 #  include "qtsciicodec_p.h"
    65 #  include "qtsciicodec_p.h"
    66 #  include "qisciicodec_p.h"
    66 #  include "qisciicodec_p.h"
       
    67 #ifndef Q_OS_SYMBIAN
    67 #  if defined(QT_NO_ICONV) && !defined(QT_BOOTSTRAPPED)
    68 #  if defined(QT_NO_ICONV) && !defined(QT_BOOTSTRAPPED)
    68 // no iconv(3) support, must build all codecs into the library
    69 // no iconv(3) support, must build all codecs into the library
    69 #    include "../../plugins/codecs/cn/qgb18030codec.h"
    70 #    include "../../plugins/codecs/cn/qgb18030codec.h"
    70 #    include "../../plugins/codecs/jp/qeucjpcodec.h"
    71 #    include "../../plugins/codecs/jp/qeucjpcodec.h"
    71 #    include "../../plugins/codecs/jp/qjiscodec.h"
    72 #    include "../../plugins/codecs/jp/qjiscodec.h"
    75 #  endif // QT_NO_ICONV
    76 #  endif // QT_NO_ICONV
    76 #  if defined(Q_WS_X11) && !defined(QT_BOOTSTRAPPED)
    77 #  if defined(Q_WS_X11) && !defined(QT_BOOTSTRAPPED)
    77 #    include "qfontlaocodec_p.h"
    78 #    include "qfontlaocodec_p.h"
    78 #    include "../../plugins/codecs/jp/qfontjpcodec.h"
    79 #    include "../../plugins/codecs/jp/qfontjpcodec.h"
    79 #  endif
    80 #  endif
       
    81 #endif // QT_NO_SYMBIAN
    80 #endif // QT_NO_CODECS
    82 #endif // QT_NO_CODECS
    81 #include "qlocale.h"
    83 #include "qlocale.h"
    82 #include "private/qmutexpool_p.h"
    84 #include "qmutex.h"
       
    85 #include "qhash.h"
    83 
    86 
    84 #include <stdlib.h>
    87 #include <stdlib.h>
    85 #include <ctype.h>
    88 #include <ctype.h>
    86 #include <locale.h>
    89 #include <locale.h>
    87 #if defined (_XOPEN_UNIX) && !defined(Q_OS_QNX) && !defined(Q_OS_OSF)
    90 #if defined (_XOPEN_UNIX) && !defined(Q_OS_QNX) && !defined(Q_OS_OSF)
    89 #endif
    92 #endif
    90 
    93 
    91 #if defined(Q_OS_WINCE)
    94 #if defined(Q_OS_WINCE)
    92 #  define QT_NO_SETLOCALE
    95 #  define QT_NO_SETLOCALE
    93 #endif
    96 #endif
       
    97 
       
    98 #ifdef Q_OS_SYMBIAN
       
    99 #include "qtextcodec_symbian.cpp"
       
   100 #endif
       
   101 
    94 
   102 
    95 // enabling this is not exception safe!
   103 // enabling this is not exception safe!
    96 // #define Q_DEBUG_TEXTCODEC
   104 // #define Q_DEBUG_TEXTCODEC
    97 
   105 
    98 QT_BEGIN_NAMESPACE
   106 QT_BEGIN_NAMESPACE
   170 #endif
   178 #endif
   171     return 0;
   179     return 0;
   172 }
   180 }
   173 
   181 
   174 static QList<QTextCodec*> *all = 0;
   182 static QList<QTextCodec*> *all = 0;
       
   183 static int clearCaches = 0;  // flags specifying if caches should be invalided: 0x1 codecForName, 0x2 codecForMib
   175 #ifdef Q_DEBUG_TEXTCODEC
   184 #ifdef Q_DEBUG_TEXTCODEC
   176 static bool destroying_is_ok = false;
   185 static bool destroying_is_ok = false;
   177 #endif
   186 #endif
   178 
   187 
   179 static QTextCodec *localeMapper = 0;
   188 static QTextCodec *localeMapper = 0;
   533 /* the next two functions are implicitely thread safe,
   542 /* the next two functions are implicitely thread safe,
   534    as they are only called by setup() which uses a mutex.
   543    as they are only called by setup() which uses a mutex.
   535 */
   544 */
   536 static void setupLocaleMapper()
   545 static void setupLocaleMapper()
   537 {
   546 {
       
   547 #ifdef Q_OS_SYMBIAN
       
   548     localeMapper = QSymbianTextCodec::localeMapper;
       
   549     if (localeMapper)
       
   550         return;
       
   551 #endif
       
   552 
   538 #if defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
   553 #if defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
   539     localeMapper = QTextCodec::codecForName("System");
   554     localeMapper = QTextCodec::codecForName("System");
   540 #else
   555 #else
   541 
   556 
   542 #ifndef QT_NO_ICONV
   557 #ifndef QT_NO_ICONV
   657     if (!localeMapper)
   672     if (!localeMapper)
   658         localeMapper = QTextCodec::codecForName("ISO 8859-1");
   673         localeMapper = QTextCodec::codecForName("ISO 8859-1");
   659 #endif
   674 #endif
   660 }
   675 }
   661 
   676 
   662 
   677 #ifndef QT_NO_THREAD
       
   678 Q_GLOBAL_STATIC_WITH_ARGS(QMutex, textCodecsMutex, (QMutex::Recursive));
       
   679 #endif
       
   680 
       
   681 // textCodecsMutex need to be locked to enter this function
   663 static void setup()
   682 static void setup()
   664 {
   683 {
   665 #ifndef QT_NO_THREAD
       
   666     QMutexLocker locker(QMutexPool::globalInstanceGet(&all));
       
   667 #endif
       
   668 
       
   669     if (all)
   684     if (all)
   670         return;
   685         return;
   671 
   686 
   672 #ifdef Q_DEBUG_TEXTCODEC
   687 #ifdef Q_DEBUG_TEXTCODEC
   673     if (destroying_is_ok)
   688     if (destroying_is_ok)
   676     all = new QList<QTextCodec*>;
   691     all = new QList<QTextCodec*>;
   677     // create the cleanup object to cleanup all codecs on exit
   692     // create the cleanup object to cleanup all codecs on exit
   678     (void) createQTextCodecCleanup();
   693     (void) createQTextCodecCleanup();
   679 
   694 
   680 #ifndef QT_NO_CODECS
   695 #ifndef QT_NO_CODECS
       
   696     (void)new QTsciiCodec;
       
   697     for (int i = 0; i < 9; ++i)
       
   698         (void)new QIsciiCodec(i);
       
   699 
       
   700     for (int i = 0; i < QSimpleTextCodec::numSimpleCodecs; ++i)
       
   701         (void)new QSimpleTextCodec(i);
       
   702 
       
   703 #ifdef Q_OS_SYMBIAN
       
   704     localeMapper = QSymbianTextCodec::init();
       
   705 #endif
       
   706 
   681 #  if defined(Q_WS_X11) && !defined(QT_BOOTSTRAPPED)
   707 #  if defined(Q_WS_X11) && !defined(QT_BOOTSTRAPPED)
   682     // no font codecs when bootstrapping
   708     // no font codecs when bootstrapping
   683     (void)new QFontLaoCodec;
   709     (void)new QFontLaoCodec;
   684 #    if defined(QT_NO_ICONV)
   710 #    if defined(QT_NO_ICONV)
   685     // no iconv(3) support, must build all codecs into the library
   711     // no iconv(3) support, must build all codecs into the library
   692     (void)new QFontBig5hkscsCodec;
   718     (void)new QFontBig5hkscsCodec;
   693     (void)new QFontBig5Codec;
   719     (void)new QFontBig5Codec;
   694 #    endif // QT_NO_ICONV && !QT_BOOTSTRAPPED
   720 #    endif // QT_NO_ICONV && !QT_BOOTSTRAPPED
   695 #  endif // Q_WS_X11
   721 #  endif // Q_WS_X11
   696 
   722 
   697     (void)new QTsciiCodec;
   723 
   698 
   724 #ifndef Q_OS_SYMBIAN
   699     for (int i = 0; i < 9; ++i)
       
   700         (void)new QIsciiCodec(i);
       
   701 
       
   702 
       
   703 #  if defined(QT_NO_ICONV) && !defined(QT_BOOTSTRAPPED)
   725 #  if defined(QT_NO_ICONV) && !defined(QT_BOOTSTRAPPED)
   704     // no asian codecs when bootstrapping, sorry
   726     // no asian codecs when bootstrapping, sorry
   705     (void)new QGb18030Codec;
   727     (void)new QGb18030Codec;
   706     (void)new QGbkCodec;
   728     (void)new QGbkCodec;
   707     (void)new QGb2312Codec;
   729     (void)new QGb2312Codec;
   711     (void)new QEucKrCodec;
   733     (void)new QEucKrCodec;
   712     (void)new QCP949Codec;
   734     (void)new QCP949Codec;
   713     (void)new QBig5Codec;
   735     (void)new QBig5Codec;
   714     (void)new QBig5hkscsCodec;
   736     (void)new QBig5hkscsCodec;
   715 #  endif // QT_NO_ICONV && !QT_BOOTSTRAPPED
   737 #  endif // QT_NO_ICONV && !QT_BOOTSTRAPPED
       
   738 #endif //Q_OS_SYMBIAN
   716 #endif // QT_NO_CODECS
   739 #endif // QT_NO_CODECS
   717 
   740 
   718 #if defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
   741 #if defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
   719     (void) new QWindowsLocalCodec;
   742     (void) new QWindowsLocalCodec;
   720 #endif // Q_OS_WIN32
   743 #endif // Q_OS_WIN32
   723     (void)new QUtf16BECodec;
   746     (void)new QUtf16BECodec;
   724     (void)new QUtf16LECodec;
   747     (void)new QUtf16LECodec;
   725     (void)new QUtf32Codec;
   748     (void)new QUtf32Codec;
   726     (void)new QUtf32BECodec;
   749     (void)new QUtf32BECodec;
   727     (void)new QUtf32LECodec;
   750     (void)new QUtf32LECodec;
       
   751 #ifndef Q_OS_SYMBIAN
   728     (void)new QLatin15Codec;
   752     (void)new QLatin15Codec;
       
   753 #endif
   729     (void)new QLatin1Codec;
   754     (void)new QLatin1Codec;
   730     (void)new QUtf8Codec;
   755     (void)new QUtf8Codec;
   731 
   756 
   732     for (int i = 0; i < QSimpleTextCodec::numSimpleCodecs; ++i)
   757 #ifndef Q_OS_SYMBIAN
   733         (void)new QSimpleTextCodec(i);
       
   734 
       
   735 #if defined(Q_OS_UNIX) && !defined(QT_NO_ICONV) && !defined(QT_BOOTSTRAPPED)
   758 #if defined(Q_OS_UNIX) && !defined(QT_NO_ICONV) && !defined(QT_BOOTSTRAPPED)
   736     // QIconvCodec depends on the UTF-16 codec, so it needs to be created last
   759     // QIconvCodec depends on the UTF-16 codec, so it needs to be created last
   737     (void) new QIconvCodec();
   760     (void) new QIconvCodec();
       
   761 #endif
   738 #endif
   762 #endif
   739 
   763 
   740     if (!localeMapper)
   764     if (!localeMapper)
   741         setupLocaleMapper();
   765         setupLocaleMapper();
   742 }
   766 }
   901 
   925 
   902     \sa QTextStream, QTextDecoder, QTextEncoder, {Codecs Example}
   926     \sa QTextStream, QTextDecoder, QTextEncoder, {Codecs Example}
   903 */
   927 */
   904 
   928 
   905 /*!
   929 /*!
   906     \nonreentrant
       
   907 
       
   908     Constructs a QTextCodec, and gives it the highest precedence. The
   930     Constructs a QTextCodec, and gives it the highest precedence. The
   909     QTextCodec should always be constructed on the heap (i.e. with \c
   931     QTextCodec should always be constructed on the heap (i.e. with \c
   910     new). Qt takes ownership and will delete it when the application
   932     new). Qt takes ownership and will delete it when the application
   911     terminates.
   933     terminates.
   912 */
   934 */
   913 QTextCodec::QTextCodec()
   935 QTextCodec::QTextCodec()
   914 {
   936 {
       
   937 #ifndef QT_NO_THREAD
       
   938     QMutexLocker locker(textCodecsMutex());
       
   939 #endif
   915     setup();
   940     setup();
   916     all->prepend(this);
   941     all->prepend(this);
   917 }
   942 }
   918 
   943 
   919 
   944 
   927 {
   952 {
   928 #ifdef Q_DEBUG_TEXTCODEC
   953 #ifdef Q_DEBUG_TEXTCODEC
   929     if (!destroying_is_ok)
   954     if (!destroying_is_ok)
   930         qWarning("QTextCodec::~QTextCodec: Called by application");
   955         qWarning("QTextCodec::~QTextCodec: Called by application");
   931 #endif
   956 #endif
   932     if (all)
   957     if (all) {
       
   958 #ifndef QT_NO_THREAD
       
   959         QMutexLocker locker(textCodecsMutex());
       
   960 #endif
   933         all->removeAll(this);
   961         all->removeAll(this);
       
   962         clearCaches = 0x1 | 0x2;
       
   963     }
   934 }
   964 }
   935 
   965 
   936 /*!
   966 /*!
   937     \fn QTextCodec *QTextCodec::codecForName(const char *name)
   967     \fn QTextCodec *QTextCodec::codecForName(const char *name)
   938 
   968 
   949 QTextCodec *QTextCodec::codecForName(const QByteArray &name)
   979 QTextCodec *QTextCodec::codecForName(const QByteArray &name)
   950 {
   980 {
   951     if (name.isEmpty())
   981     if (name.isEmpty())
   952         return 0;
   982         return 0;
   953 
   983 
       
   984 #ifndef QT_NO_THREAD
       
   985     QMutexLocker locker(textCodecsMutex());
       
   986 #endif
   954     setup();
   987     setup();
       
   988 
       
   989     static QHash <QByteArray, QTextCodec *> cache;
       
   990     if (clearCaches & 0x1) {
       
   991         cache.clear();
       
   992         clearCaches &= ~0x1;
       
   993     }
       
   994     QTextCodec *codec = cache.value(name);
       
   995     if (codec)
       
   996         return codec;
   955 
   997 
   956     for (int i = 0; i < all->size(); ++i) {
   998     for (int i = 0; i < all->size(); ++i) {
   957         QTextCodec *cursor = all->at(i);
   999         QTextCodec *cursor = all->at(i);
   958         if (nameMatch(cursor->name(), name))
  1000         if (nameMatch(cursor->name(), name)) {
       
  1001             cache.insert(name, cursor);
   959             return cursor;
  1002             return cursor;
       
  1003         }
   960         QList<QByteArray> aliases = cursor->aliases();
  1004         QList<QByteArray> aliases = cursor->aliases();
   961         for (int i = 0; i < aliases.size(); ++i)
  1005         for (int y = 0; y < aliases.size(); ++y)
   962             if (nameMatch(aliases.at(i), name))
  1006             if (nameMatch(aliases.at(y), name)) {
       
  1007                 cache.insert(name, cursor);
   963                 return cursor;
  1008                 return cursor;
   964     }
  1009             }
   965 
  1010     }
   966     return createForName(name);
  1011 
       
  1012     codec = createForName(name);
       
  1013     if (codec)
       
  1014         cache.insert(name, codec);
       
  1015     return codec;
   967 }
  1016 }
   968 
  1017 
   969 
  1018 
   970 /*!
  1019 /*!
   971     Returns the QTextCodec which matches the \link
  1020     Returns the QTextCodec which matches the \link
   972     QTextCodec::mibEnum() MIBenum\endlink \a mib.
  1021     QTextCodec::mibEnum() MIBenum\endlink \a mib.
   973 */
  1022 */
   974 QTextCodec* QTextCodec::codecForMib(int mib)
  1023 QTextCodec* QTextCodec::codecForMib(int mib)
   975 {
  1024 {
       
  1025 #ifndef QT_NO_THREAD
       
  1026     QMutexLocker locker(textCodecsMutex());
       
  1027 #endif
   976     setup();
  1028     setup();
   977 
  1029 
   978     // Qt 3 used 1000 (mib for UCS2) as its identifier for the utf16 codec. Map
  1030     static QHash <int, QTextCodec *> cache;
   979     // this correctly for compatibility.
  1031     if (clearCaches & 0x2) {
   980     if (mib == 1000)
  1032         cache.clear();
   981         mib = 1015;
  1033         clearCaches &= ~0x2;
       
  1034     }
       
  1035     QTextCodec *codec = cache.value(mib);
       
  1036     if (codec)
       
  1037         return codec;
   982 
  1038 
   983     QList<QTextCodec*>::ConstIterator i;
  1039     QList<QTextCodec*>::ConstIterator i;
   984     for (int i = 0; i < all->size(); ++i) {
  1040     for (int i = 0; i < all->size(); ++i) {
   985         QTextCodec *cursor = all->at(i);
  1041         QTextCodec *cursor = all->at(i);
   986         if (cursor->mibEnum() == mib)
  1042         if (cursor->mibEnum() == mib) {
       
  1043             cache.insert(mib, cursor);
   987             return cursor;
  1044             return cursor;
   988     }
  1045         }
   989 
  1046     }
   990     return createForMib(mib);
  1047 
       
  1048     codec = createForMib(mib);
       
  1049 
       
  1050     // Qt 3 used 1000 (mib for UCS2) as its identifier for the utf16 codec. Map
       
  1051     // this correctly for compatibility.
       
  1052     if (!codec && mib == 1000)
       
  1053         return codecForMib(1015);
       
  1054 
       
  1055     if (codec)
       
  1056         cache.insert(mib, codec);
       
  1057     return codec;
   991 }
  1058 }
   992 
  1059 
   993 /*!
  1060 /*!
   994     Returns the list of all available codecs, by name. Call
  1061     Returns the list of all available codecs, by name. Call
   995     QTextCodec::codecForName() to obtain the QTextCodec for the name.
  1062     QTextCodec::codecForName() to obtain the QTextCodec for the name.
   999 
  1066 
  1000     \sa availableMibs(), name(), aliases()
  1067     \sa availableMibs(), name(), aliases()
  1001 */
  1068 */
  1002 QList<QByteArray> QTextCodec::availableCodecs()
  1069 QList<QByteArray> QTextCodec::availableCodecs()
  1003 {
  1070 {
       
  1071 #ifndef QT_NO_THREAD
       
  1072     QMutexLocker locker(textCodecsMutex());
       
  1073 #endif
  1004     setup();
  1074     setup();
  1005 
  1075 
  1006     QList<QByteArray> codecs;
  1076     QList<QByteArray> codecs;
  1007     for (int i = 0; i < all->size(); ++i) {
  1077     for (int i = 0; i < all->size(); ++i) {
  1008         codecs += all->at(i)->name();
  1078         codecs += all->at(i)->name();
  1009         codecs += all->at(i)->aliases();
  1079         codecs += all->at(i)->aliases();
  1010     }
  1080     }
       
  1081 
       
  1082 #ifndef QT_NO_THREAD
       
  1083     locker.unlock();
       
  1084 #endif
       
  1085 
  1011 #ifndef QT_NO_TEXTCODECPLUGIN
  1086 #ifndef QT_NO_TEXTCODECPLUGIN
  1012     QFactoryLoader *l = loader();
  1087     QFactoryLoader *l = loader();
  1013     QStringList keys = l->keys();
  1088     QStringList keys = l->keys();
  1014     for (int i = 0; i < keys.size(); ++i) {
  1089     for (int i = 0; i < keys.size(); ++i) {
  1015         if (!keys.at(i).startsWith(QLatin1String("MIB: "))) {
  1090         if (!keys.at(i).startsWith(QLatin1String("MIB: "))) {
  1029 
  1104 
  1030     \sa availableCodecs(), mibEnum()
  1105     \sa availableCodecs(), mibEnum()
  1031 */
  1106 */
  1032 QList<int> QTextCodec::availableMibs()
  1107 QList<int> QTextCodec::availableMibs()
  1033 {
  1108 {
       
  1109 #ifndef QT_NO_THREAD
       
  1110     QMutexLocker locker(textCodecsMutex());
       
  1111 #endif
  1034     setup();
  1112     setup();
  1035 
  1113 
  1036     QList<int> codecs;
  1114     QList<int> codecs;
  1037     for (int i = 0; i < all->size(); ++i)
  1115     for (int i = 0; i < all->size(); ++i)
  1038         codecs += all->at(i)->mibEnum();
  1116         codecs += all->at(i)->mibEnum();
       
  1117 
       
  1118 #ifndef QT_NO_THREAD
       
  1119     locker.unlock();
       
  1120 #endif
       
  1121 
  1039 #ifndef QT_NO_TEXTCODECPLUGIN
  1122 #ifndef QT_NO_TEXTCODECPLUGIN
  1040     QFactoryLoader *l = loader();
  1123     QFactoryLoader *l = loader();
  1041     QStringList keys = l->keys();
  1124     QStringList keys = l->keys();
  1042     for (int i = 0; i < keys.size(); ++i) {
  1125     for (int i = 0; i < keys.size(); ++i) {
  1043         if (keys.at(i).startsWith(QLatin1String("MIB: "))) {
  1126         if (keys.at(i).startsWith(QLatin1String("MIB: "))) {
  1061 
  1144 
  1062     \sa codecForLocale()
  1145     \sa codecForLocale()
  1063 */
  1146 */
  1064 void QTextCodec::setCodecForLocale(QTextCodec *c)
  1147 void QTextCodec::setCodecForLocale(QTextCodec *c)
  1065 {
  1148 {
       
  1149 #ifndef QT_NO_THREAD
       
  1150     QMutexLocker locker(textCodecsMutex());
       
  1151 #endif
  1066     localeMapper = c;
  1152     localeMapper = c;
  1067     if (!localeMapper)
  1153     if (!localeMapper)
  1068         setupLocaleMapper();
  1154         setupLocaleMapper();
  1069 }
  1155 }
  1070 
  1156 
  1080 QTextCodec* QTextCodec::codecForLocale()
  1166 QTextCodec* QTextCodec::codecForLocale()
  1081 {
  1167 {
  1082     if (localeMapper)
  1168     if (localeMapper)
  1083         return localeMapper;
  1169         return localeMapper;
  1084 
  1170 
       
  1171 #ifndef QT_NO_THREAD
       
  1172     QMutexLocker locker(textCodecsMutex());
       
  1173 #endif
  1085     setup();
  1174     setup();
  1086 
  1175 
  1087     return localeMapper;
  1176     return localeMapper;
  1088 }
  1177 }
  1089 
  1178