[6/9] webservices: Add support for UTF-16 text values in the writer.

Hans Leidekker hans at codeweavers.com
Mon Jul 4 04:35:42 CDT 2016


Signed-off-by: Hans Leidekker <hans at codeweavers.com>
---
 dlls/webservices/writer.c | 305 ++++++++++++++++++++--------------------------
 include/webservices.h     |   6 +
 2 files changed, 141 insertions(+), 170 deletions(-)

diff --git a/dlls/webservices/writer.c b/dlls/webservices/writer.c
index 3ee5102..5070c7d 100644
--- a/dlls/webservices/writer.c
+++ b/dlls/webservices/writer.c
@@ -989,24 +989,64 @@ HRESULT WINAPI WsWriteStartElement( WS_XML_WRITER *handle, const WS_XML_STRING *
     return write_element_node( writer, prefix, localname, ns );
 }
 
-static inline void write_set_attribute_value( struct writer *writer, WS_XML_TEXT *text )
+static HRESULT text_to_utf8text( const WS_XML_TEXT *text, WS_XML_UTF8_TEXT **ret )
+{
+    switch (text->textType)
+    {
+    case WS_XML_TEXT_TYPE_UTF8:
+    {
+        const WS_XML_UTF8_TEXT *src = (const WS_XML_UTF8_TEXT *)text;
+        if (!(*ret = alloc_utf8_text( src->value.bytes, src->value.length ))) return E_OUTOFMEMORY;
+        return S_OK;
+    }
+    case WS_XML_TEXT_TYPE_UTF16:
+    {
+        const WS_XML_UTF16_TEXT *src = (const WS_XML_UTF16_TEXT *)text;
+        const WCHAR *str = (const WCHAR *)src->bytes;
+        ULONG len = src->byteCount / sizeof(WCHAR), len_utf8;
+
+        if (src->byteCount % sizeof(WCHAR)) return E_INVALIDARG;
+        len_utf8 = WideCharToMultiByte( CP_UTF8, 0, str, len, NULL, 0, NULL, NULL );
+        if (!(*ret = alloc_utf8_text( NULL, len_utf8 ))) return E_OUTOFMEMORY;
+        WideCharToMultiByte( CP_UTF8, 0, str, len, (char *)(*ret)->value.bytes, (*ret)->value.length, NULL, NULL );
+        return S_OK;
+    }
+    default:
+        FIXME( "unhandled text type %u\n", text->textType );
+        return E_NOTIMPL;
+    }
+}
+
+static HRESULT write_set_attribute_value( struct writer *writer, const WS_XML_TEXT *value )
 {
     WS_XML_ELEMENT_NODE *elem = &writer->current->hdr;
-    elem->attributes[elem->attributeCount - 1]->value = text;
+    WS_XML_UTF8_TEXT *utf8;
+    HRESULT hr;
+
+    if ((hr = text_to_utf8text( value, &utf8 )) != S_OK) return hr;
+    elem->attributes[elem->attributeCount - 1]->value = &utf8->text;
+    return S_OK;
 }
 
-static HRESULT write_add_text_node( struct writer *writer, WS_XML_TEXT *value )
+static HRESULT write_add_text_node( struct writer *writer, const WS_XML_TEXT *value )
 {
     struct node *node;
     WS_XML_TEXT_NODE *text;
+    WS_XML_UTF8_TEXT *utf8;
+    HRESULT hr;
 
     if (node_type( writer->current ) != WS_XML_NODE_TYPE_ELEMENT &&
         node_type( writer->current ) != WS_XML_NODE_TYPE_BOF &&
         node_type( writer->current ) != WS_XML_NODE_TYPE_CDATA) return WS_E_INVALID_FORMAT;
 
     if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return E_OUTOFMEMORY;
+    if ((hr = text_to_utf8text( value, &utf8 )) != S_OK)
+    {
+        heap_free( node );
+        return hr;
+    }
     text = (WS_XML_TEXT_NODE *)node;
-    text->text = value;
+    text->text = &utf8->text;
 
     write_insert_node( writer, writer->current, node );
     return S_OK;
@@ -1023,7 +1063,7 @@ static HRESULT write_text( struct writer *writer )
     return S_OK;
 }
 
-static HRESULT write_text_node( struct writer *writer, WS_XML_TEXT *text )
+static HRESULT write_text_node( struct writer *writer, const WS_XML_TEXT *text )
 {
     HRESULT hr;
     if ((hr = write_flush( writer )) != S_OK) return hr;
@@ -1039,114 +1079,68 @@ static HRESULT write_text_node( struct writer *writer, WS_XML_TEXT *text )
 HRESULT WINAPI WsWriteText( WS_XML_WRITER *handle, const WS_XML_TEXT *text, WS_ERROR *error )
 {
     struct writer *writer = (struct writer *)handle;
-    const WS_XML_UTF8_TEXT *src = (const WS_XML_UTF8_TEXT *)text;
-    WS_XML_UTF8_TEXT *dst;
-    HRESULT hr;
 
     TRACE( "%p %p %p\n", handle, text, error );
 
     if (!writer || !text) return E_INVALIDARG;
 
-    if (text->textType != WS_XML_TEXT_TYPE_UTF8)
-    {
-        FIXME( "text type %u not supported\n", text->textType );
-        return E_NOTIMPL;
-    }
-    if (!(dst = alloc_utf8_text( src->value.bytes, src->value.length ))) return E_OUTOFMEMORY;
-
-    if (writer->state == WRITER_STATE_STARTATTRIBUTE)
-    {
-        write_set_attribute_value( writer, &dst->text );
-        return S_OK;
-    }
-
-    if ((hr = write_text_node( writer, &dst->text )) != S_OK) heap_free( dst );
-    return hr;
+    if (writer->state == WRITER_STATE_STARTATTRIBUTE) return write_set_attribute_value( writer, text );
+    return write_text_node( writer, text );
 }
 
-static WS_XML_TEXT *widechar_to_xmltext( const WCHAR *src, WS_XML_TEXT_TYPE type )
+static ULONG format_bool( const BOOL *ptr, unsigned char *buf )
 {
-    switch (type)
-    {
-    case WS_XML_TEXT_TYPE_UTF8:
+    static const unsigned char bool_true[] = {'t','r','u','e'}, bool_false[] = {'f','a','l','s','e'};
+    if (*ptr)
     {
-        WS_XML_UTF8_TEXT *text;
-        int len = WideCharToMultiByte( CP_UTF8, 0, src, -1, NULL, 0, NULL, NULL ) - 1;
-        if (!(text = alloc_utf8_text( NULL, len ))) return NULL;
-        WideCharToMultiByte( CP_UTF8, 0, src, -1, (char *)text->value.bytes, text->value.length, NULL, NULL );
-        return &text->text;
-    }
-    default:
-        FIXME( "unhandled type %u\n", type );
-        return NULL;
+        memcpy( buf, bool_true, sizeof(bool_true) );
+        return sizeof(bool_true);
     }
+    memcpy( buf, bool_false, sizeof(bool_false) );
+    return sizeof(bool_false);
 }
 
-static WS_XML_UTF8_TEXT *format_bool( const BOOL *ptr )
-{
-    static const unsigned char bool_true[] = {'t','r','u','e'}, bool_false[] = {'f','a','l','s','e'};
-    if (*ptr) return alloc_utf8_text( bool_true, sizeof(bool_true) );
-    else return alloc_utf8_text( bool_false, sizeof(bool_false) );
-}
-
-static WS_XML_UTF8_TEXT *format_int8( const INT8 *ptr )
+static ULONG format_int8( const INT8 *ptr, unsigned char *buf )
 {
-    char buf[5]; /* "-128" */
-    int len = wsprintfA( buf, "%d", *ptr );
-    return alloc_utf8_text( (const unsigned char *)buf, len );
+    return wsprintfA( (char *)buf, "%d", *ptr );
 }
 
-static WS_XML_UTF8_TEXT *format_int16( const INT16 *ptr )
+static ULONG format_int16( const INT16 *ptr, unsigned char *buf )
 {
-    char buf[7]; /* "-32768" */
-    int len = wsprintfA( buf, "%d", *ptr );
-    return alloc_utf8_text( (const unsigned char *)buf, len );
+    return wsprintfA( (char *)buf, "%d", *ptr );
 }
 
-static WS_XML_UTF8_TEXT *format_int32( const INT32 *ptr )
+static ULONG format_int32( const INT32 *ptr, unsigned char *buf )
 {
-    char buf[12]; /* "-2147483648" */
-    int len = wsprintfA( buf, "%d", *ptr );
-    return alloc_utf8_text( (const unsigned char *)buf, len );
+    return wsprintfA( (char *)buf, "%d", *ptr );
 }
 
-static WS_XML_UTF8_TEXT *format_int64( const INT64 *ptr )
+static ULONG format_int64( const INT64 *ptr, unsigned char *buf )
 {
-    char buf[21]; /* "-9223372036854775808" */
-    int len = wsprintfA( buf, "%I64d", *ptr );
-    return alloc_utf8_text( (const unsigned char *)buf, len );
+    return wsprintfA( (char *)buf, "%I64d", *ptr );
 }
 
-static WS_XML_UTF8_TEXT *format_uint8( const UINT8 *ptr )
+static ULONG format_uint8( const UINT8 *ptr, unsigned char *buf )
 {
-    char buf[4]; /* "255" */
-    int len = wsprintfA( buf, "%u", *ptr );
-    return alloc_utf8_text( (const unsigned char *)buf, len );
+    return wsprintfA( (char *)buf, "%u", *ptr );
 }
 
-static WS_XML_UTF8_TEXT *format_uint16( const UINT16 *ptr )
+static ULONG format_uint16( const UINT16 *ptr, unsigned char *buf )
 {
-    char buf[6]; /* "65535" */
-    int len = wsprintfA( buf, "%u", *ptr );
-    return alloc_utf8_text( (const unsigned char *)buf, len );
+    return wsprintfA( (char *)buf, "%u", *ptr );
 }
 
-static WS_XML_UTF8_TEXT *format_uint32( const UINT32 *ptr )
+static ULONG format_uint32( const UINT32 *ptr, unsigned char *buf )
 {
-    char buf[11]; /* "4294967295" */
-    int len = wsprintfA( buf, "%u", *ptr );
-    return alloc_utf8_text( (const unsigned char *)buf, len );
+    return wsprintfA( (char *)buf, "%u", *ptr );
 }
 
-static WS_XML_UTF8_TEXT *format_uint64( const UINT64 *ptr )
+static ULONG format_uint64( const UINT64 *ptr, unsigned char *buf )
 {
-    char buf[21]; /* "18446744073709551615" */
-    int len = wsprintfA( buf, "%I64u", *ptr );
-    return alloc_utf8_text( (const unsigned char *)buf, len );
+    return wsprintfA( (char *)buf, "%I64u", *ptr );
 }
 
-static HRESULT write_type_text( struct writer *writer, WS_TYPE_MAPPING mapping,
-                                WS_XML_TEXT *text )
+static HRESULT write_type_text( struct writer *writer, WS_TYPE_MAPPING mapping, const WS_XML_TEXT *text )
 {
     switch (mapping)
     {
@@ -1155,15 +1149,13 @@ static HRESULT write_type_text( struct writer *writer, WS_TYPE_MAPPING mapping,
         return write_text_node( writer, text );
 
     case WS_ATTRIBUTE_TYPE_MAPPING:
-        write_set_attribute_value( writer, text );
-        return S_OK;
+        return write_set_attribute_value( writer, text );
 
     case WS_ANY_ELEMENT_TYPE_MAPPING:
         switch (writer->state)
         {
         case WRITER_STATE_STARTATTRIBUTE:
-            write_set_attribute_value( writer, text );
-            return S_OK;
+            return write_set_attribute_value( writer, text );
 
         case WRITER_STATE_STARTELEMENT:
             return write_text_node( writer, text );
@@ -1182,171 +1174,170 @@ static HRESULT write_type_text( struct writer *writer, WS_TYPE_MAPPING mapping,
 static HRESULT write_type_bool( struct writer *writer, WS_TYPE_MAPPING mapping,
                                 const WS_BOOL_DESCRIPTION *desc, const BOOL *value )
 {
-    WS_XML_UTF8_TEXT *text;
-    HRESULT hr;
+    WS_XML_UTF8_TEXT utf8;
+    unsigned char buf[6]; /* "false" */
 
     if (desc)
     {
         FIXME( "description not supported\n" );
         return E_NOTIMPL;
     }
-    if (!(text = format_bool( value ))) return E_OUTOFMEMORY;
-    if ((hr = write_type_text( writer, mapping, &text->text )) == S_OK) return S_OK;
-    heap_free( text );
-    return hr;
+    utf8.text.textType = WS_XML_TEXT_TYPE_UTF8;
+    utf8.value.bytes   = buf;
+    utf8.value.length  = format_bool( value, buf );
+    return write_type_text( writer, mapping, &utf8.text );
 }
 
 static HRESULT write_type_int8( struct writer *writer, WS_TYPE_MAPPING mapping,
                                 const WS_INT8_DESCRIPTION *desc, const INT8 *value )
 {
-    WS_XML_UTF8_TEXT *text;
-    HRESULT hr;
+    WS_XML_UTF8_TEXT utf8;
+    unsigned char buf[5]; /* "-128" */
 
     if (desc)
     {
         FIXME( "description not supported\n" );
         return E_NOTIMPL;
     }
-    if (!(text = format_int8( value ))) return E_OUTOFMEMORY;
-    if ((hr = write_type_text( writer, mapping, &text->text )) == S_OK) return S_OK;
-    heap_free( text );
-    return hr;
+    utf8.text.textType = WS_XML_TEXT_TYPE_UTF8;
+    utf8.value.bytes   = buf;
+    utf8.value.length  = format_int8( value, buf );
+    return write_type_text( writer, mapping, &utf8.text );
 }
 
 static HRESULT write_type_int16( struct writer *writer, WS_TYPE_MAPPING mapping,
                                  const WS_INT16_DESCRIPTION *desc, const INT16 *value )
 {
-    WS_XML_UTF8_TEXT *text;
-    HRESULT hr;
+    WS_XML_UTF8_TEXT utf8;
+    unsigned char buf[7]; /* "-32768" */
 
     if (desc)
     {
         FIXME( "description not supported\n" );
         return E_NOTIMPL;
     }
-    if (!(text = format_int16( value ))) return E_OUTOFMEMORY;
-    if ((hr = write_type_text( writer, mapping, &text->text )) == S_OK) return S_OK;
-    heap_free( text );
-    return hr;
+    utf8.text.textType = WS_XML_TEXT_TYPE_UTF8;
+    utf8.value.bytes   = buf;
+    utf8.value.length  = format_int16( value, buf );
+    return write_type_text( writer, mapping, &utf8.text );
 }
 
 static HRESULT write_type_int32( struct writer *writer, WS_TYPE_MAPPING mapping,
                                  const WS_INT32_DESCRIPTION *desc, const INT32 *value )
 {
-    WS_XML_UTF8_TEXT *text;
-    HRESULT hr;
+    WS_XML_UTF8_TEXT utf8;
+    unsigned char buf[12]; /* "-2147483648" */
 
     if (desc)
     {
         FIXME( "description not supported\n" );
         return E_NOTIMPL;
     }
-    if (!(text = format_int32( value ))) return E_OUTOFMEMORY;
-    if ((hr = write_type_text( writer, mapping, &text->text )) == S_OK) return S_OK;
-    heap_free( text );
-    return hr;
+    utf8.text.textType = WS_XML_TEXT_TYPE_UTF8;
+    utf8.value.bytes   = buf;
+    utf8.value.length  = format_int32( value, buf );
+    return write_type_text( writer, mapping, &utf8.text );
 }
 
 static HRESULT write_type_int64( struct writer *writer, WS_TYPE_MAPPING mapping,
                                  const WS_INT64_DESCRIPTION *desc, const INT64 *value )
 {
-    WS_XML_UTF8_TEXT *text;
-    HRESULT hr;
+    WS_XML_UTF8_TEXT utf8;
+    unsigned char buf[21]; /* "-9223372036854775808" */
 
     if (desc)
     {
         FIXME( "description not supported\n" );
         return E_NOTIMPL;
     }
-    if (!(text = format_int64( value ))) return E_OUTOFMEMORY;
-    if ((hr = write_type_text( writer, mapping, &text->text )) == S_OK) return S_OK;
-    heap_free( text );
-    return hr;
+    utf8.text.textType = WS_XML_TEXT_TYPE_UTF8;
+    utf8.value.bytes   = buf;
+    utf8.value.length  = format_int64( value, buf );
+    return write_type_text( writer, mapping, &utf8.text );
 }
 
 static HRESULT write_type_uint8( struct writer *writer, WS_TYPE_MAPPING mapping,
                                  const WS_UINT8_DESCRIPTION *desc, const UINT8 *value )
 {
-    WS_XML_UTF8_TEXT *text;
-    HRESULT hr;
+    WS_XML_UTF8_TEXT utf8;
+    unsigned char buf[4]; /* "255" */
 
     if (desc)
     {
         FIXME( "description not supported\n" );
         return E_NOTIMPL;
     }
-    if (!(text = format_uint8( value ))) return E_OUTOFMEMORY;
-    if ((hr = write_type_text( writer, mapping, &text->text )) == S_OK) return S_OK;
-    heap_free( text );
-    return hr;
+    utf8.text.textType = WS_XML_TEXT_TYPE_UTF8;
+    utf8.value.bytes   = buf;
+    utf8.value.length  = format_uint8( value, buf );
+    return write_type_text( writer, mapping, &utf8.text );
 }
 
 static HRESULT write_type_uint16( struct writer *writer, WS_TYPE_MAPPING mapping,
                                   const WS_UINT16_DESCRIPTION *desc, const UINT16 *value )
 {
-    WS_XML_UTF8_TEXT *text;
-    HRESULT hr;
+    WS_XML_UTF8_TEXT utf8;
+    unsigned char buf[6]; /* "65535" */
 
     if (desc)
     {
         FIXME( "description not supported\n" );
         return E_NOTIMPL;
     }
-    if (!(text = format_uint16( value ))) return E_OUTOFMEMORY;
-    if ((hr = write_type_text( writer, mapping, &text->text )) == S_OK) return S_OK;
-    heap_free( text );
-    return hr;
+    utf8.text.textType = WS_XML_TEXT_TYPE_UTF8;
+    utf8.value.bytes   = buf;
+    utf8.value.length  = format_uint16( value, buf );
+    return write_type_text( writer, mapping, &utf8.text );
 }
 
 static HRESULT write_type_uint32( struct writer *writer, WS_TYPE_MAPPING mapping,
                                   const WS_UINT32_DESCRIPTION *desc, const UINT32 *value )
 {
-    WS_XML_UTF8_TEXT *text;
-    HRESULT hr;
+    WS_XML_UTF8_TEXT utf8;
+    unsigned char buf[11]; /* "4294967295" */
 
     if (desc)
     {
         FIXME( "description not supported\n" );
         return E_NOTIMPL;
     }
-    if (!(text = format_uint32( value ))) return E_OUTOFMEMORY;
-    if ((hr = write_type_text( writer, mapping, &text->text )) == S_OK) return S_OK;
-    heap_free( text );
-    return hr;
+    utf8.text.textType = WS_XML_TEXT_TYPE_UTF8;
+    utf8.value.bytes   = buf;
+    utf8.value.length  = format_uint32( value, buf );
+    return write_type_text( writer, mapping, &utf8.text );
 }
 
 static HRESULT write_type_uint64( struct writer *writer, WS_TYPE_MAPPING mapping,
                                   const WS_UINT64_DESCRIPTION *desc, const UINT64 *value )
 {
-    WS_XML_UTF8_TEXT *text;
-    HRESULT hr;
+    WS_XML_UTF8_TEXT utf8;
+    unsigned char buf[21]; /* "18446744073709551615" */
 
     if (desc)
     {
         FIXME( "description not supported\n" );
         return E_NOTIMPL;
     }
-    if (!(text = format_uint64( value ))) return E_OUTOFMEMORY;
-    if ((hr = write_type_text( writer, mapping, &text->text )) == S_OK) return S_OK;
-    heap_free( text );
-    return hr;
+    utf8.text.textType = WS_XML_TEXT_TYPE_UTF8;
+    utf8.value.bytes   = buf;
+    utf8.value.length  = format_uint64( value, buf );
+    return write_type_text( writer, mapping, &utf8.text );
 }
 
 static HRESULT write_type_wsz( struct writer *writer, WS_TYPE_MAPPING mapping,
                                const WS_WSZ_DESCRIPTION *desc, const WCHAR *value )
 {
-    WS_XML_TEXT *text;
-    HRESULT hr;
+    WS_XML_UTF16_TEXT utf16;
 
     if (desc)
     {
         FIXME( "description not supported\n" );
         return E_NOTIMPL;
     }
-    if (!(text = widechar_to_xmltext( value, WS_XML_TEXT_TYPE_UTF8 ))) return E_OUTOFMEMORY;
-    if ((hr = write_type_text( writer, mapping, text )) == S_OK) return S_OK;
-    heap_free( text );
-    return hr;
+    utf16.text.textType = WS_XML_TEXT_TYPE_UTF16;
+    utf16.bytes         = (BYTE *)value;
+    utf16.byteCount     = strlenW( value ) * sizeof(WCHAR);
+    return write_type_text( writer, mapping, &utf16.text );
 }
 
 static HRESULT write_type( struct writer *, WS_TYPE_MAPPING, WS_TYPE, const void *, WS_WRITE_OPTION,
@@ -1934,25 +1925,9 @@ static HRESULT write_set_attributes( struct writer *writer, WS_XML_ATTRIBUTE **a
 
     for (i = 0; i < count; i++)
     {
-        const WS_XML_UTF8_TEXT *src = (const WS_XML_UTF8_TEXT *)attrs[i]->value;
-        WS_XML_UTF8_TEXT *dst = NULL;
-
-        if (attrs[i]->value)
-        {
-            if (attrs[i]->value->textType != WS_XML_TEXT_TYPE_UTF8)
-            {
-                FIXME( "text type %u not supported\n", attrs[i]->value->textType );
-                return E_NOTIMPL;
-            }
-            if (!(dst = alloc_utf8_text( src->value.bytes, src->value.length ))) return E_OUTOFMEMORY;
-        }
         if ((hr = write_add_attribute( writer, attrs[i]->prefix, attrs[i]->localName, attrs[i]->ns,
-                                       attrs[i]->singleQuote )) != S_OK)
-        {
-            heap_free( dst );
-            return hr;
-        }
-        if (dst) write_set_attribute_value( writer, &dst->text );
+                                       attrs[i]->singleQuote )) != S_OK) return hr;
+        if ((hr = write_set_attribute_value( writer, attrs[i]->value )) != S_OK) return hr;
     }
     return S_OK;
 }
@@ -1972,17 +1947,7 @@ static HRESULT write_node( struct writer *writer, const WS_XML_NODE *node )
     case WS_XML_NODE_TYPE_TEXT:
     {
         const WS_XML_TEXT_NODE *text = (const WS_XML_TEXT_NODE *)node;
-        const WS_XML_UTF8_TEXT *src = (const WS_XML_UTF8_TEXT *)text->text;
-        WS_XML_UTF8_TEXT *dst;
-
-        if (src->text.textType != WS_XML_TEXT_TYPE_UTF8)
-        {
-            FIXME( "text type %u not supported\n", src->text.textType );
-            return E_NOTIMPL;
-        }
-        if (!(dst = alloc_utf8_text( src->value.bytes, src->value.length ))) return E_OUTOFMEMORY;
-        if ((hr = write_text_node( writer, &dst->text )) != S_OK) heap_free( dst );
-        return hr;
+        return write_text_node( writer, text->text );
     }
     case WS_XML_NODE_TYPE_END_ELEMENT:
         return write_endelement_node( writer );
diff --git a/include/webservices.h b/include/webservices.h
index d377e47..d4a5b6b 100644
--- a/include/webservices.h
+++ b/include/webservices.h
@@ -552,6 +552,12 @@ typedef struct _WS_XML_UTF8_TEXT {
     WS_XML_STRING value;
 } WS_XML_UTF8_TEXT;
 
+typedef struct _WS_XML_UTF16_TEXT {
+    WS_XML_TEXT text;
+    BYTE *bytes;
+    ULONG byteCount;
+} WS_XML_UTF16_TEXT;
+
 typedef enum {
     WS_BOOL_VALUE_TYPE,
     WS_INT8_VALUE_TYPE,
-- 
2.8.1




More information about the wine-patches mailing list