From a4a1cfe900ab06ff1f8dbe30d73476937a122582 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 5 Mar 2010 14:57:01 +0100 Subject: 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 --- src/corelib/codecs/qiconvcodec.cpp | 41 +++++++++++++++++++++++++++----------- 1 file 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, 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(bom); + size_t outBytesLeft = sizeof buf; + size_t inBytesLeft = sizeof bom; + +#if defined(GNU_LIBICONV) + const char **inBytesPtr = const_cast(&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(-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(bom); - inBytesLeft = sizeof(bom); - if (iconv(state->cd, inBytesPtr, &inBytesLeft, &outBytes, &outBytesLeft) == (size_t) -1) { + if (state->cd == reinterpret_cast(-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(-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); -- cgit v0.12