diff options
author | Thiago Macieira <thiago.macieira@nokia.com> | 2010-03-05 13:57:01 (GMT) |
---|---|---|
committer | Thiago Macieira <thiago.macieira@nokia.com> | 2010-03-05 15:42:39 (GMT) |
commit | a4a1cfe900ab06ff1f8dbe30d73476937a122582 (patch) | |
tree | cb68a1db66b165cb136394b9d6ae96d1d8f61f29 /src/corelib/codecs | |
parent | ddaa4643c1ee96c9dfc16b1c247481a240e2e16b (diff) | |
download | Qt-a4a1cfe900ab06ff1f8dbe30d73476937a122582.zip Qt-a4a1cfe900ab06ff1f8dbe30d73476937a122582.tar.gz Qt-a4a1cfe900ab06ff1f8dbe30d73476937a122582.tar.bz2 |
Reset the byte order in the iconv codec after using it.
Otherwise, if you try run
QString(QChar(0xfffe)).toLocal8Bit()
iconv will be left in byte-swapping mode.
Reviewed-by: Denis Dzyubenko
Diffstat (limited to 'src/corelib/codecs')
-rw-r--r-- | src/corelib/codecs/qiconvcodec.cpp | 41 |
1 files changed, 29 insertions, 12 deletions
diff --git a/src/corelib/codecs/qiconvcodec.cpp b/src/corelib/codecs/qiconvcodec.cpp index 0f73d9b..0fcdf96 100644 --- a/src/corelib/codecs/qiconvcodec.cpp +++ b/src/corelib/codecs/qiconvcodec.cpp @@ -299,6 +299,32 @@ QString QIconvCodec::convertToUnicode(const char* chars, int len, ConverterState Q_GLOBAL_STATIC(QThreadStorage<QIconvCodec::IconvState *>, fromUnicodeState) +static bool setByteOrder(iconv_t cd) +{ +#if !defined(NO_BOM) + // give iconv() a BOM + char buf[4]; + ushort bom[] = { QChar::ByteOrderMark }; + + char *outBytes = buf; + char *inBytes = reinterpret_cast<char *>(bom); + size_t outBytesLeft = sizeof buf; + size_t inBytesLeft = sizeof bom; + +#if defined(GNU_LIBICONV) + const char **inBytesPtr = const_cast<const char **>(&inBytes); +#else + char **inBytesPtr = &inBytes; +#endif + + if (iconv(cd, inBytesPtr, &inBytesLeft, &outBytes, &outBytesLeft) == (size_t) -1) { + return false; + } +#endif // NO_BOM + + return true; +} + QByteArray QIconvCodec::convertFromUnicode(const QChar *uc, int len, ConverterState *convState) const { char *inBytes; @@ -325,17 +351,8 @@ QByteArray QIconvCodec::convertFromUnicode(const QChar *uc, int len, ConverterSt IconvState *&state = ts->localData(); if (!state) { state = new IconvState(QIconvCodec::createIconv_t(0, UTF16)); - if (state->cd != reinterpret_cast<iconv_t>(-1)) { - size_t outBytesLeft = len + 3; // +3 for the BOM - QByteArray ba(outBytesLeft, Qt::Uninitialized); - outBytes = ba.data(); - -#if !defined(NO_BOM) - // give iconv() a BOM - QChar bom[] = { QChar(QChar::ByteOrderMark) }; - inBytes = reinterpret_cast<char *>(bom); - inBytesLeft = sizeof(bom); - if (iconv(state->cd, inBytesPtr, &inBytesLeft, &outBytes, &outBytesLeft) == (size_t) -1) { + if (state->cd == reinterpret_cast<iconv_t>(-1)) { + if (!setByteOrder(state->cd)) { perror("QIconvCodec::convertFromUnicode: using ASCII for conversion, iconv failed for BOM"); iconv_close(state->cd); @@ -343,7 +360,6 @@ QByteArray QIconvCodec::convertFromUnicode(const QChar *uc, int len, ConverterSt return QString(uc, len).toAscii(); } -#endif // NO_BOM } } if (state->cd == reinterpret_cast<iconv_t>(-1)) { @@ -422,6 +438,7 @@ QByteArray QIconvCodec::convertFromUnicode(const QChar *uc, int len, ConverterSt // reset to initial state iconv(state->cd, 0, &inBytesLeft, 0, &outBytesLeft); + setByteOrder(state->cd); ba.resize(ba.size() - outBytesLeft); |