Changeset 70257 in webkit
- Timestamp:
- Oct 21, 2010 12:33:10 PM (14 years ago)
- Location:
- trunk
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/ChangeLog
r70212 r70257 1 2010-10-21 Carlos Garcia Campos <cgarcia@igalia.com> 2 3 Reviewed by Martin Robinson. 4 5 [GTK] Use GCharsetConverter instead of g_iconv in TextCodecGtk 6 https://bugs.webkit.org/show_bug.cgi?id=47896 7 8 * wtf/gobject/GTypedefs.h: 9 1 10 2010-10-21 Adam Barth <abarth@webkit.org> 2 11 -
trunk/JavaScriptCore/wtf/gobject/GTypedefs.h
r67664 r70257 39 39 typedef struct _GAsyncResult GAsyncResult; 40 40 typedef struct _GCancellable GCancellable; 41 typedef struct _GCharsetConverter GCharsetConverter; 41 42 typedef struct _GCond GCond; 42 43 typedef struct _GDir GDir; -
trunk/WebCore/ChangeLog
r70256 r70257 1 2010-10-21 Carlos Garcia Campos <cgarcia@igalia.com> 2 3 Reviewed by Martin Robinson. 4 5 [GTK] Use GCharsetConverter instead of g_iconv in TextCodecGtk 6 https://bugs.webkit.org/show_bug.cgi?id=47896 7 8 It makes error handling easier. Fixes tests: 9 fast/encoding/invalid-multi-byte-over-consumption.html 10 fast/encoding/invalid-xml.html 11 fast/encoding/japanese-encoding-mix.html 12 when building with glib unicode 13 14 * platform/text/gtk/TextCodecGtk.cpp: 15 (WebCore::TextCodecGtk::TextCodecGtk): 16 (WebCore::TextCodecGtk::~TextCodecGtk): 17 (WebCore::TextCodecGtk::createIConvDecoder): 18 (WebCore::TextCodecGtk::createIConvEncoder): 19 (WebCore::TextCodecGtk::decode): 20 (WebCore::TextCodecGtk::encode): 21 * platform/text/gtk/TextCodecGtk.h: 22 1 23 2010-10-21 Chris Fleizach <cfleizach@apple.com> 2 24 -
trunk/WebCore/platform/text/gtk/TextCodecGtk.cpp
r70227 r70257 30 30 #include "TextCodecGtk.h" 31 31 32 #include <gio/gio.h> 32 33 #include "GOwnPtr.h" 33 34 #include "Logging.h" … … 411 412 : m_encoding(encoding) 412 413 , m_numBufferedBytes(0) 413 , m_iconvDecoder(reinterpret_cast<GIConv>(-1))414 , m_iconvEncoder(reinterpret_cast<GIConv>(-1))415 414 { 416 415 } … … 418 417 TextCodecGtk::~TextCodecGtk() 419 418 { 420 if (m_iconvDecoder != reinterpret_cast<GIConv>(-1)) {421 g_iconv_close(m_iconvDecoder);422 m_iconvDecoder = reinterpret_cast<GIConv>(-1);423 }424 if (m_iconvEncoder != reinterpret_cast<GIConv>(-1)) {425 g_iconv_close(m_iconvEncoder);426 m_iconvEncoder = reinterpret_cast<GIConv>(-1);427 }428 419 } 429 420 430 421 void TextCodecGtk::createIConvDecoder() const 431 422 { 432 ASSERT( m_iconvDecoder == reinterpret_cast<GIConv>(-1));433 434 m_iconvDecoder = g_iconv_open(internalEncodingName, m_encoding.name());423 ASSERT(!m_iconvDecoder); 424 425 m_iconvDecoder = adoptPlatformRef(g_charset_converter_new(internalEncodingName, m_encoding.name(), 0)); 435 426 } 436 427 437 428 void TextCodecGtk::createIConvEncoder() const 438 429 { 439 ASSERT( m_iconvDecoder == reinterpret_cast<GIConv>(-1));440 441 m_iconvEncoder = g_iconv_open(m_encoding.name(), internalEncodingName);430 ASSERT(!m_iconvEncoder); 431 432 m_iconvEncoder = adoptPlatformRef(g_charset_converter_new(m_encoding.name(), internalEncodingName, 0)); 442 433 } 443 434 … … 445 436 { 446 437 // Get a converter for the passed-in encoding. 447 if ( m_iconvDecoder == reinterpret_cast<GIConv>(-1)) {438 if (!m_iconvDecoder) 448 439 createIConvDecoder(); 449 ASSERT(m_iconvDecoder != reinterpret_cast<GIConv>(-1)); 450 if (m_iconvDecoder == reinterpret_cast<GIConv>(-1)) { 451 LOG_ERROR("Error creating IConv encoder even though encoding was in table."); 452 return String(); 453 } 454 } 455 456 size_t countWritten, countRead, conversionLength; 457 const char* conversionBytes; 440 if (!m_iconvDecoder) { 441 LOG_ERROR("Error creating IConv encoder even though encoding was in table."); 442 return String(); 443 } 444 445 Vector<UChar> result; 446 447 gsize bytesRead = 0; 448 gsize bytesWritten = 0; 449 const gchar* input = bytes; 450 gsize inputLength = length; 451 gchar buffer[ConversionBufferSize]; 452 int flags = !length ? G_CONVERTER_INPUT_AT_END : G_CONVERTER_NO_FLAGS; 453 if (flush) 454 flags |= G_CONVERTER_FLUSH; 455 456 bool bufferWasFull = false; 458 457 char* prefixedBytes = 0; 459 458 460 459 if (m_numBufferedBytes) { 461 conversionLength = length + m_numBufferedBytes;462 prefixedBytes = static_cast<char*>(fastMalloc( conversionLength));460 inputLength = length + m_numBufferedBytes; 461 prefixedBytes = static_cast<char*>(fastMalloc(inputLength)); 463 462 memcpy(prefixedBytes, m_bufferedBytes, m_numBufferedBytes); 464 463 memcpy(prefixedBytes + m_numBufferedBytes, bytes, length); 465 466 conversionBytes= prefixedBytes;467 464 465 input = prefixedBytes; 466 468 467 // all buffered bytes are consumed now 469 468 m_numBufferedBytes = 0; 470 } else { 471 // no previously buffered partial data, 472 // just convert the data that was passed in 473 conversionBytes = bytes; 474 conversionLength = length; 475 } 476 477 GOwnPtr<GError> err; 478 GOwnPtr<UChar> buffer; 479 480 buffer.outPtr() = reinterpret_cast<UChar*>(g_convert_with_iconv(conversionBytes, conversionLength, m_iconvDecoder, &countRead, &countWritten, &err.outPtr())); 481 482 483 if (err) { 484 LOG_ERROR("GIConv conversion error, Code %d: \"%s\"", err->code, err->message); 485 m_numBufferedBytes = 0; // reset state for subsequent calls to decode 486 fastFree(prefixedBytes); 487 sawError = true; 488 return String(); 489 } 490 491 // Partial input at the end of the string may not result in an error being raised. 492 // From the gnome library documentation on g_convert_with_iconv: 493 // "Even if the conversion was successful, this may be less than len if there were partial characters at the end of the input." 494 // That's why we need to compare conversionLength against countRead 495 496 m_numBufferedBytes = conversionLength - countRead; 497 if (m_numBufferedBytes > 0) { 498 if (flush) { 499 LOG_ERROR("Partial bytes at end of input while flush requested."); 500 m_numBufferedBytes = 0; // reset state for subsequent calls to decode 501 fastFree(prefixedBytes); 502 sawError = true; 503 return String(); 469 } 470 471 do { 472 GOwnPtr<GError> error; 473 GConverterResult res = g_converter_convert(G_CONVERTER(m_iconvDecoder.get()), 474 input, inputLength, 475 buffer, sizeof(buffer), 476 static_cast<GConverterFlags>(flags), 477 &bytesRead, &bytesWritten, 478 &error.outPtr()); 479 input += bytesRead; 480 inputLength -= bytesRead; 481 482 if (res == G_CONVERTER_ERROR) { 483 if (g_error_matches(error.get(), G_IO_ERROR, G_IO_ERROR_PARTIAL_INPUT)) { 484 // There is not enough input to fully determine what the conversion should produce, 485 // save it to a buffer to prepend it to the next input. 486 memcpy(m_bufferedBytes, input, inputLength); 487 m_numBufferedBytes = inputLength; 488 inputLength = 0; 489 } else if (g_error_matches(error.get(), G_IO_ERROR, G_IO_ERROR_NO_SPACE)) 490 bufferWasFull = true; 491 else if (g_error_matches(error.get(), G_IO_ERROR, G_IO_ERROR_INVALID_DATA)) { 492 if (stopOnError) 493 sawError = true; 494 if (inputLength) { 495 // Ignore invalid character. 496 input += 1; 497 inputLength -= 1; 498 } 499 } else { 500 sawError = true; 501 LOG_ERROR("GIConv conversion error, Code %d: \"%s\"", error->code, error->message); 502 m_numBufferedBytes = 0; // Reset state for subsequent calls to decode. 503 fastFree(prefixedBytes); 504 return String(); 505 } 504 506 } 505 memcpy(m_bufferedBytes, conversionBytes + countRead, m_numBufferedBytes); 506 } 507 508 result.append(reinterpret_cast<UChar*>(buffer), bytesWritten / sizeof(UChar)); 509 } while ((inputLength || bufferWasFull) && !sawError); 507 510 508 511 fastFree(prefixedBytes); 509 510 Vector<UChar> result;511 512 result.append(buffer.get(), countWritten / sizeof(UChar));513 512 514 513 return String::adopt(result); … … 520 519 return ""; 521 520 522 if ( m_iconvEncoder == reinterpret_cast<GIConv>(-1))521 if (!m_iconvEncoder) 523 522 createIConvEncoder(); 524 if (m_iconvEncoder == reinterpret_cast<GIConv>(-1)) 523 if (!m_iconvEncoder) { 524 LOG_ERROR("Error creating IConv encoder even though encoding was in table."); 525 525 return CString(); 526 527 size_t count; 528 529 GOwnPtr<GError> err; 530 GOwnPtr<char> buffer; 531 532 buffer.outPtr() = g_convert_with_iconv(reinterpret_cast<const char*>(characters), length * sizeof(UChar), m_iconvEncoder, 0, &count, &err.outPtr()); 533 if (err) { 534 LOG_ERROR("GIConv conversion error, Code %d: \"%s\"", err->code, err->message); 526 } 527 528 gsize bytesRead = 0; 529 gsize bytesWritten = 0; 530 const gchar* input = reinterpret_cast<const char*>(characters); 531 gsize inputLength = length * sizeof(UChar); 532 gchar buffer[ConversionBufferSize]; 533 Vector<char> result; 534 GOwnPtr<GError> error; 535 536 size_t size = 0; 537 do { 538 g_converter_convert(G_CONVERTER(m_iconvEncoder.get()), 539 input, inputLength, 540 buffer, sizeof(buffer), 541 G_CONVERTER_INPUT_AT_END, 542 &bytesRead, &bytesWritten, 543 &error.outPtr()); 544 input += bytesRead; 545 inputLength -= bytesRead; 546 result.grow(size + bytesWritten); 547 memcpy(result.data() + size, buffer, bytesWritten); 548 size += bytesWritten; 549 } while (inputLength && !error.get()); 550 551 if (error) { 552 LOG_ERROR("GIConv conversion error, Code %d: \"%s\"", error->code, error->message); 535 553 return CString(); 536 554 } 537 555 538 return CString( buffer.get(), count);556 return CString(result.data(), size); 539 557 } 540 558 -
trunk/WebCore/platform/text/gtk/TextCodecGtk.h
r70211 r70257 30 30 #define TextCodecGTK_h 31 31 32 #include "GRefPtr.h" 32 33 #include <glib.h> 33 34 #include "TextCodec.h" … … 57 58 size_t m_numBufferedBytes; 58 59 unsigned char m_bufferedBytes[16]; // bigger than any single multi-byte character 59 mutable GIConvm_iconvDecoder;60 mutable GIConvm_iconvEncoder;60 mutable PlatformRefPtr<GCharsetConverter> m_iconvDecoder; 61 mutable PlatformRefPtr<GCharsetConverter> m_iconvEncoder; 61 62 }; 62 63
Note: See TracChangeset
for help on using the changeset viewer.