diff options
author | Thiago Macieira <thiago.macieira@nokia.com> | 2011-03-29 09:58:40 (GMT) |
---|---|---|
committer | Thiago Macieira <thiago.macieira@nokia.com> | 2011-03-29 10:30:11 (GMT) |
commit | a8bf19019b3374eefaadb4e054d24089bc4fd5a4 (patch) | |
tree | b39642a80c894edf1c4447c940c84a0052792a7c | |
parent | bfc04b22d3f80f43787e86ee4cc6a39436fa039c (diff) | |
download | Qt-a8bf19019b3374eefaadb4e054d24089bc4fd5a4.zip Qt-a8bf19019b3374eefaadb4e054d24089bc4fd5a4.tar.gz Qt-a8bf19019b3374eefaadb4e054d24089bc4fd5a4.tar.bz2 |
Make the QIconvCodec on Unix not enforce the Latin1 codec.
Originally, the QIconvCodec created and disposed of the iconv_t
structure at every turn. In Qt 4.5, we started saving it for later in
a thread-local storage.
We had to introduce a fix to make sure that we didn't create the
iconv_t structure before the setlocale(LC_ALL, "") call was made,
though: otherwise, we'd keep forever an iconv_t that pointed to the
wrong encoding.
So now simply restore the Qt 4.4 behaviour: create and dispose of the
iconv_t structure if we're called before the QCoreApplication
constructor is run or after the static destructors are run.
Note: this means QIconvCodec will probably default to US-ASCII when
run before QCoreApplication, not Latin 1. Non-ASCII characters
(anything with the high bit set) will fail to convert.
Task-number: QTBUG-15229?
Reviewed-by: Denis Dzyubenko
-rw-r--r-- | src/corelib/codecs/qiconvcodec.cpp | 38 |
1 files changed, 18 insertions, 20 deletions
diff --git a/src/corelib/codecs/qiconvcodec.cpp b/src/corelib/codecs/qiconvcodec.cpp index 4497b8c..053b3d2 100644 --- a/src/corelib/codecs/qiconvcodec.cpp +++ b/src/corelib/codecs/qiconvcodec.cpp @@ -173,6 +173,7 @@ QString QIconvCodec::convertToUnicode(const char* chars, int len, ConverterState int invalidCount = 0; int remainingCount = 0; char *remainingBuffer = 0; + IconvState *temporaryState = 0; IconvState **pstate; if (convState) { @@ -193,11 +194,11 @@ QString QIconvCodec::convertToUnicode(const char* chars, int len, ConverterState // we're running after the Q_GLOBAL_STATIC has been deleted // or before the QCoreApplication initialization // bad programmer, no cookie for you - return QString::fromLatin1(chars, len); + pstate = &temporaryState; + } else { + // stateless conversion -- use thread-local data + pstate = &toUnicodeState()->localData(); } - - // stateless conversion -- use thread-local data - pstate = &toUnicodeState()->localData(); } if (!*pstate) { @@ -280,6 +281,7 @@ QString QIconvCodec::convertToUnicode(const char* chars, int len, ConverterState iconv(state->cd, 0, &inBytesLeft, 0, &outBytesLeft); } + delete temporaryState; return QString::fromLatin1(chars, len); } } while (inBytesLeft != 0); @@ -294,6 +296,7 @@ QString QIconvCodec::convertToUnicode(const char* chars, int len, ConverterState iconv(state->cd, 0, &inBytesLeft, 0, &outBytesLeft); } + delete temporaryState; return s; } @@ -337,30 +340,22 @@ QByteArray QIconvCodec::convertFromUnicode(const QChar *uc, int len, ConverterSt char **inBytesPtr = &inBytes; #endif + IconvState *temporaryState = 0; QThreadStorage<QIconvCodec::IconvState *> *ts = fromUnicodeState(); - if (!qt_locale_initialized || !ts) { - // we're running after the Q_GLOBAL_STATIC has been deleted - // or before the QCoreApplication initialization - // bad programmer, no cookie for you - if (!len) - // this is a special case - zero-sized string should be - // translated to empty but not-null QByteArray. - return QByteArray(""); - return QString::fromRawData(uc, len).toLatin1(); - } - IconvState *&state = ts->localData(); + IconvState *&state = (qt_locale_initialized && ts) ? ts->localData() : temporaryState; if (!state) { - state = new IconvState(QIconvCodec::createIconv_t(0, UTF16)); - if (state->cd == reinterpret_cast<iconv_t>(-1)) { - if (!setByteOrder(state->cd)) { + iconv_t cd = QIconvCodec::createIconv_t(0, UTF16); + if (cd != reinterpret_cast<iconv_t>(-1)) { + if (!setByteOrder(cd)) { perror("QIconvCodec::convertFromUnicode: using Latin-1 for conversion, iconv failed for BOM"); - iconv_close(state->cd); - state->cd = reinterpret_cast<iconv_t>(-1); + iconv_close(cd); + cd = reinterpret_cast<iconv_t>(-1); return QString(uc, len).toLatin1(); } } + state = new IconvState(cd); } if (state->cd == reinterpret_cast<iconv_t>(-1)) { static int reported = 0; @@ -368,6 +363,7 @@ QByteArray QIconvCodec::convertFromUnicode(const QChar *uc, int len, ConverterSt fprintf(stderr, "QIconvCodec::convertFromUnicode: using Latin-1 for conversion, iconv_open failed\n"); } + delete temporaryState; return QString(uc, len).toLatin1(); } @@ -430,6 +426,7 @@ QByteArray QIconvCodec::convertFromUnicode(const QChar *uc, int len, ConverterSt // reset to initial state iconv(state->cd, 0, &inBytesLeft, 0, &outBytesLeft); + delete temporaryState; return QString(uc, len).toLatin1(); } } @@ -445,6 +442,7 @@ QByteArray QIconvCodec::convertFromUnicode(const QChar *uc, int len, ConverterSt if (convState) convState->invalidChars = invalidCount; + delete temporaryState; return ba; } |