297 return s; |
297 return s; |
298 } |
298 } |
299 |
299 |
300 Q_GLOBAL_STATIC(QThreadStorage<QIconvCodec::IconvState *>, fromUnicodeState) |
300 Q_GLOBAL_STATIC(QThreadStorage<QIconvCodec::IconvState *>, fromUnicodeState) |
301 |
301 |
|
302 static bool setByteOrder(iconv_t cd) |
|
303 { |
|
304 #if !defined(NO_BOM) |
|
305 // give iconv() a BOM |
|
306 char buf[4]; |
|
307 ushort bom[] = { QChar::ByteOrderMark }; |
|
308 |
|
309 char *outBytes = buf; |
|
310 char *inBytes = reinterpret_cast<char *>(bom); |
|
311 size_t outBytesLeft = sizeof buf; |
|
312 size_t inBytesLeft = sizeof bom; |
|
313 |
|
314 #if defined(GNU_LIBICONV) |
|
315 const char **inBytesPtr = const_cast<const char **>(&inBytes); |
|
316 #else |
|
317 char **inBytesPtr = &inBytes; |
|
318 #endif |
|
319 |
|
320 if (iconv(cd, inBytesPtr, &inBytesLeft, &outBytes, &outBytesLeft) == (size_t) -1) { |
|
321 return false; |
|
322 } |
|
323 #endif // NO_BOM |
|
324 |
|
325 return true; |
|
326 } |
|
327 |
302 QByteArray QIconvCodec::convertFromUnicode(const QChar *uc, int len, ConverterState *convState) const |
328 QByteArray QIconvCodec::convertFromUnicode(const QChar *uc, int len, ConverterState *convState) const |
303 { |
329 { |
304 char *inBytes; |
330 char *inBytes; |
305 char *outBytes; |
331 char *outBytes; |
306 size_t inBytesLeft; |
332 size_t inBytesLeft; |
323 return QString::fromRawData(uc, len).toLatin1(); |
349 return QString::fromRawData(uc, len).toLatin1(); |
324 } |
350 } |
325 IconvState *&state = ts->localData(); |
351 IconvState *&state = ts->localData(); |
326 if (!state) { |
352 if (!state) { |
327 state = new IconvState(QIconvCodec::createIconv_t(0, UTF16)); |
353 state = new IconvState(QIconvCodec::createIconv_t(0, UTF16)); |
328 if (state->cd != reinterpret_cast<iconv_t>(-1)) { |
354 if (state->cd == reinterpret_cast<iconv_t>(-1)) { |
329 size_t outBytesLeft = len + 3; // +3 for the BOM |
355 if (!setByteOrder(state->cd)) { |
330 QByteArray ba(outBytesLeft, Qt::Uninitialized); |
|
331 outBytes = ba.data(); |
|
332 |
|
333 #if !defined(NO_BOM) |
|
334 // give iconv() a BOM |
|
335 QChar bom[] = { QChar(QChar::ByteOrderMark) }; |
|
336 inBytes = reinterpret_cast<char *>(bom); |
|
337 inBytesLeft = sizeof(bom); |
|
338 if (iconv(state->cd, inBytesPtr, &inBytesLeft, &outBytes, &outBytesLeft) == (size_t) -1) { |
|
339 perror("QIconvCodec::convertFromUnicode: using ASCII for conversion, iconv failed for BOM"); |
356 perror("QIconvCodec::convertFromUnicode: using ASCII for conversion, iconv failed for BOM"); |
340 |
357 |
341 iconv_close(state->cd); |
358 iconv_close(state->cd); |
342 state->cd = reinterpret_cast<iconv_t>(-1); |
359 state->cd = reinterpret_cast<iconv_t>(-1); |
343 |
360 |
344 return QString(uc, len).toAscii(); |
361 return QString(uc, len).toAscii(); |
345 } |
362 } |
346 #endif // NO_BOM |
|
347 } |
363 } |
348 } |
364 } |
349 if (state->cd == reinterpret_cast<iconv_t>(-1)) { |
365 if (state->cd == reinterpret_cast<iconv_t>(-1)) { |
350 static int reported = 0; |
366 static int reported = 0; |
351 if (!reported++) { |
367 if (!reported++) { |
420 } |
436 } |
421 } |
437 } |
422 |
438 |
423 // reset to initial state |
439 // reset to initial state |
424 iconv(state->cd, 0, &inBytesLeft, 0, &outBytesLeft); |
440 iconv(state->cd, 0, &inBytesLeft, 0, &outBytesLeft); |
|
441 setByteOrder(state->cd); |
425 |
442 |
426 ba.resize(ba.size() - outBytesLeft); |
443 ba.resize(ba.size() - outBytesLeft); |
427 |
444 |
428 if (convState) |
445 if (convState) |
429 convState->invalidChars = invalidCount; |
446 convState->invalidChars = invalidCount; |