Changeset 70257 in webkit


Ignore:
Timestamp:
Oct 21, 2010 12:33:10 PM (14 years ago)
Author:
commit-queue@webkit.org
Message:

2010-10-21 Carlos Garcia Campos <cgarcia@igalia.com>

Reviewed by Martin Robinson.

[GTK] Use GCharsetConverter instead of g_iconv in TextCodecGtk
https://bugs.webkit.org/show_bug.cgi?id=47896

  • wtf/gobject/GTypedefs.h:

2010-10-21 Carlos Garcia Campos <cgarcia@igalia.com>

Reviewed by Martin Robinson.

[GTK] Use GCharsetConverter instead of g_iconv in TextCodecGtk
https://bugs.webkit.org/show_bug.cgi?id=47896

It makes error handling easier. Fixes tests:

fast/encoding/invalid-multi-byte-over-consumption.html
fast/encoding/invalid-xml.html
fast/encoding/japanese-encoding-mix.html

when building with glib unicode

  • platform/text/gtk/TextCodecGtk.cpp: (WebCore::TextCodecGtk::TextCodecGtk): (WebCore::TextCodecGtk::~TextCodecGtk): (WebCore::TextCodecGtk::createIConvDecoder): (WebCore::TextCodecGtk::createIConvEncoder): (WebCore::TextCodecGtk::decode): (WebCore::TextCodecGtk::encode):
  • platform/text/gtk/TextCodecGtk.h:
Location:
trunk
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/ChangeLog

    r70212 r70257  
     12010-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
    1102010-10-21  Adam Barth  <abarth@webkit.org>
    211
  • trunk/JavaScriptCore/wtf/gobject/GTypedefs.h

    r67664 r70257  
    3939typedef struct _GAsyncResult GAsyncResult;
    4040typedef struct _GCancellable GCancellable;
     41typedef struct _GCharsetConverter GCharsetConverter;
    4142typedef struct _GCond GCond;
    4243typedef struct _GDir GDir;
  • trunk/WebCore/ChangeLog

    r70256 r70257  
     12010-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
    1232010-10-21  Chris Fleizach  <cfleizach@apple.com>
    224
  • trunk/WebCore/platform/text/gtk/TextCodecGtk.cpp

    r70227 r70257  
    3030#include "TextCodecGtk.h"
    3131
     32#include <gio/gio.h>
    3233#include "GOwnPtr.h"
    3334#include "Logging.h"
     
    411412    : m_encoding(encoding)
    412413    , m_numBufferedBytes(0)
    413     , m_iconvDecoder(reinterpret_cast<GIConv>(-1))
    414     , m_iconvEncoder(reinterpret_cast<GIConv>(-1))
    415414{
    416415}
     
    418417TextCodecGtk::~TextCodecGtk()
    419418{
    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     }
    428419}
    429420
    430421void TextCodecGtk::createIConvDecoder() const
    431422{
    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));
    435426}
    436427
    437428void TextCodecGtk::createIConvEncoder() const
    438429{
    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));
    442433}
    443434
     
    445436{
    446437    // Get a converter for the passed-in encoding.
    447     if (m_iconvDecoder == reinterpret_cast<GIConv>(-1)) {
     438    if (!m_iconvDecoder)
    448439        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;
    458457    char* prefixedBytes = 0;
    459458
    460459    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));
    463462        memcpy(prefixedBytes, m_bufferedBytes, m_numBufferedBytes);
    464463        memcpy(prefixedBytes + m_numBufferedBytes, bytes, length);
    465        
    466         conversionBytes = prefixedBytes;
    467        
     464
     465        input = prefixedBytes;
     466
    468467        // all buffered bytes are consumed now
    469468        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            }
    504506        }
    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);
    507510
    508511    fastFree(prefixedBytes);
    509    
    510     Vector<UChar> result;
    511 
    512     result.append(buffer.get(), countWritten / sizeof(UChar));
    513512
    514513    return String::adopt(result);
     
    520519        return "";
    521520
    522     if (m_iconvEncoder == reinterpret_cast<GIConv>(-1))
     521    if (!m_iconvEncoder)
    523522        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.");
    525525        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);
    535553        return CString();
    536554    }
    537555
    538     return CString(buffer.get(), count);
     556    return CString(result.data(), size);
    539557}
    540558
  • trunk/WebCore/platform/text/gtk/TextCodecGtk.h

    r70211 r70257  
    3030#define TextCodecGTK_h
    3131
     32#include "GRefPtr.h"
    3233#include <glib.h>
    3334#include "TextCodec.h"
     
    5758        size_t m_numBufferedBytes;
    5859        unsigned char m_bufferedBytes[16]; // bigger than any single multi-byte character       
    59         mutable GIConv m_iconvDecoder;
    60         mutable GIConv m_iconvEncoder;
     60        mutable PlatformRefPtr<GCharsetConverter> m_iconvDecoder;
     61        mutable PlatformRefPtr<GCharsetConverter> m_iconvEncoder;
    6162    };
    6263
Note: See TracChangeset for help on using the changeset viewer.