[5/5] webservices: Add support for element and text field mappings in the writer.

Hans Leidekker hans at codeweavers.com
Wed Mar 2 07:06:29 CST 2016


Signed-off-by: Hans Leidekker <hans at codeweavers.com>
---
 dlls/webservices/tests/writer.c |  96 +++++++++++++++++++++++++++
 dlls/webservices/writer.c       | 142 ++++++++++++++++------------------------
 2 files changed, 152 insertions(+), 86 deletions(-)

diff --git a/dlls/webservices/tests/writer.c b/dlls/webservices/tests/writer.c
index e76eb1b..4f6b1b1 100644
--- a/dlls/webservices/tests/writer.c
+++ b/dlls/webservices/tests/writer.c
@@ -1306,6 +1306,101 @@ static void test_WsGetPrefixFromNamespace(void)
     WsFreeWriter( writer );
 }
 
+static void test_complex_struct_type(void)
+{
+    static const char expected[] =
+        "<o:OfficeConfig xmlns:o=\"urn:schemas-microsoft-com:office:office\">"
+        "<o:services o:GenerationTime=\"2015-09-03T18:47:54\"/>"
+        "</o:OfficeConfig>";
+    static const WCHAR timestampW[] =
+        {'2','0','1','5','-','0','9','-','0','3','T','1','8',':','4','7',':','5','4',0};
+    WS_XML_STRING str_officeconfig = {12, (BYTE *)"OfficeConfig"};
+    WS_XML_STRING str_services = {8, (BYTE *)"services"};
+    WS_XML_STRING str_generationtime = {14, (BYTE *)"GenerationTime"};
+    WS_XML_STRING ns = {39, (BYTE *)"urn:schemas-microsoft-com:office:office"};
+    WS_XML_STRING prefix = {1, (BYTE *)"o"};
+    DWORD size;
+    HRESULT hr;
+    WS_HEAP *heap;
+    WS_XML_BUFFER *buffer;
+    WS_XML_WRITER *writer;
+    WS_STRUCT_DESCRIPTION s, s2;
+    WS_FIELD_DESCRIPTION f, f2, *fields[1], *fields2[1];
+    struct services
+    {
+        const WCHAR *generationtime;
+    };
+    struct officeconfig
+    {
+        struct services *services;
+    } *test;
+
+    hr = WsCreateWriter( NULL, 0, &writer, NULL ) ;
+    ok( hr == S_OK, "got %08x\n", hr );
+
+    hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
+
+    hr = WsCreateXmlBuffer( heap, NULL, 0, &buffer, NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
+
+    hr = WsSetOutputToBuffer( writer, buffer, NULL, 0, NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
+
+    hr = WsWriteStartElement( writer, &prefix, &str_officeconfig, &ns, NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
+
+    memset( &f2, 0, sizeof(f2) );
+    f2.mapping         = WS_ATTRIBUTE_FIELD_MAPPING;
+    f2.localName       = &str_generationtime;
+    f2.ns              = &ns;
+    f2.type            = WS_WSZ_TYPE;
+    f2.options         = WS_FIELD_OPTIONAL;
+    fields2[0] = &f2;
+
+    memset( &s2, 0, sizeof(s2) );
+    s2.size          = sizeof(*test->services);
+    s2.alignment     = 4;
+    s2.fields        = fields2;
+    s2.fieldCount    = 1;
+    s2.typeLocalName = &str_services;
+    s2.typeNs        = &ns;
+
+    memset( &f, 0, sizeof(f) );
+    f.mapping         = WS_ELEMENT_FIELD_MAPPING;
+    f.localName       = &str_services;
+    f.ns              = &ns;
+    f.type            = WS_STRUCT_TYPE;
+    f.typeDescription = &s2;
+    f.options         = WS_FIELD_POINTER;
+    fields[0] = &f;
+
+    memset( &s, 0, sizeof(s) );
+    s.size          = sizeof(*test);
+    s.alignment     = 4;
+    s.fields        = fields;
+    s.fieldCount    = 1;
+    s.typeLocalName = &str_officeconfig;
+    s.typeNs        = &ns;
+
+    size = sizeof(struct officeconfig) + sizeof(struct services);
+    test = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size );
+    test->services = (struct services *)(test + 1);
+    test->services->generationtime = timestampW;
+    hr = WsWriteType( writer, WS_ELEMENT_CONTENT_TYPE_MAPPING, WS_STRUCT_TYPE, &s,
+                      WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
+
+    hr = WsWriteEndElement( writer, NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
+    check_output_buffer( buffer, expected, __LINE__ );
+
+    HeapFree( GetProcessHeap(), 0, test );
+    WsFreeWriter( writer );
+    WsFreeHeap( heap );
+}
+
+
 START_TEST(writer)
 {
     test_WsCreateWriter();
@@ -1323,4 +1418,5 @@ START_TEST(writer)
     test_WsWriteStartCData();
     test_WsWriteXmlnsAttribute();
     test_WsGetPrefixFromNamespace();
+    test_complex_struct_type();
 }
diff --git a/dlls/webservices/writer.c b/dlls/webservices/writer.c
index 8dbe9c2..858c9d0 100644
--- a/dlls/webservices/writer.c
+++ b/dlls/webservices/writer.c
@@ -714,7 +714,6 @@ HRESULT WINAPI WsWriteEndAttribute( WS_XML_WRITER *handle, WS_ERROR *error )
     if (error) FIXME( "ignoring error parameter\n" );
 
     if (!writer) return E_INVALIDARG;
-    if (writer->state != WRITER_STATE_STARTATTRIBUTE) return WS_E_INVALID_OPERATION;
 
     writer->state = WRITER_STATE_STARTELEMENT;
     return S_OK;
@@ -1115,7 +1114,6 @@ static HRESULT write_type_text( struct writer *writer, WS_TYPE_MAPPING mapping,
         {
         case WRITER_STATE_STARTATTRIBUTE:
             write_set_attribute_value( writer, text );
-            writer->state = WRITER_STATE_STARTELEMENT;
             return S_OK;
 
         case WRITER_STATE_STARTELEMENT:
@@ -1304,17 +1302,19 @@ static HRESULT write_type_wsz( struct writer *writer, WS_TYPE_MAPPING mapping,
     return hr;
 }
 
-static HRESULT write_type_struct( struct writer *, WS_TYPE_MAPPING, const WS_STRUCT_DESCRIPTION *,
-                                  const void * );
+static HRESULT write_type( struct writer *, WS_TYPE_MAPPING, WS_TYPE, const void *, WS_WRITE_OPTION,
+                           const void *, ULONG );
 
-static HRESULT write_type_struct_field( struct writer *writer, WS_TYPE_MAPPING mapping,
-                                        const WS_FIELD_DESCRIPTION *desc, const void *value )
+static HRESULT write_type_struct_field( struct writer *writer, const WS_FIELD_DESCRIPTION *desc,
+                                        const void *value, ULONG size )
 {
     HRESULT hr;
+    WS_TYPE_MAPPING mapping;
+    WS_WRITE_OPTION option;
 
-    if (desc->options && desc->options != WS_FIELD_POINTER &&
-        desc->options != WS_FIELD_OPTIONAL &&
-        desc->options != (WS_FIELD_POINTER | WS_FIELD_OPTIONAL))
+    if (!desc->options || desc->options == WS_FIELD_OPTIONAL) option = 0;
+    else if (desc->options == WS_FIELD_POINTER) option = WS_WRITE_REQUIRED_POINTER;
+    else
     {
         FIXME( "options 0x%x not supported\n", desc->options );
         return E_NOTIMPL;
@@ -1326,9 +1326,32 @@ static HRESULT write_type_struct_field( struct writer *writer, WS_TYPE_MAPPING m
         if (!desc->localName || !desc->ns) return E_INVALIDARG;
         if ((hr = write_add_attribute( writer, NULL, desc->localName, desc->ns, FALSE )) != S_OK)
             return hr;
+
+        mapping = WS_ATTRIBUTE_TYPE_MAPPING;
+        break;
+
+    case WS_ELEMENT_FIELD_MAPPING:
+        if ((hr = write_add_element_node( writer, NULL, desc->localName, desc->ns )) != S_OK)
+            return hr;
+
+        mapping = WS_ELEMENT_TYPE_MAPPING;
         break;
 
     case WS_TEXT_FIELD_MAPPING:
+        switch (writer->state)
+        {
+        case WRITER_STATE_STARTELEMENT:
+            mapping = WS_ELEMENT_CONTENT_TYPE_MAPPING;
+            break;
+
+        case WRITER_STATE_STARTATTRIBUTE:
+            mapping = WS_ATTRIBUTE_TYPE_MAPPING;
+            break;
+
+        default:
+            FIXME( "unhandled writer state %u\n", writer->state );
+            return E_NOTIMPL;
+        }
         break;
 
     default:
@@ -1336,86 +1359,35 @@ static HRESULT write_type_struct_field( struct writer *writer, WS_TYPE_MAPPING m
         return E_NOTIMPL;
     }
 
-    switch (desc->type)
-    {
-    case WS_STRUCT_TYPE:
-    {
-        const void * const *ptr = value;
-        if ((hr = write_type_struct( writer, mapping, desc->typeDescription, *ptr )) != S_OK) return hr;
-        break;
-    }
-    case WS_BOOL_TYPE:
-    {
-        const BOOL *ptr = value;
-        if ((hr = write_type_bool( writer, mapping, desc->typeDescription, ptr )) != S_OK) return hr;
-        break;
-    }
-    case WS_INT8_TYPE:
-    {
-        const INT8 *ptr = value;
-        if ((hr = write_type_int8( writer, mapping, desc->typeDescription, ptr )) != S_OK) return hr;
-        break;
-    }
-    case WS_INT16_TYPE:
-    {
-        const INT16 *ptr = value;
-        if ((hr = write_type_int16( writer, mapping, desc->typeDescription, ptr )) != S_OK) return hr;
-        break;
-    }
-    case WS_INT32_TYPE:
-    {
-        const INT32 *ptr = value;
-        if ((hr = write_type_int32( writer, mapping, desc->typeDescription, ptr )) != S_OK) return hr;
-        break;
-    }
-    case WS_INT64_TYPE:
-    {
-        const INT64 *ptr = value;
-        if ((hr = write_type_int64( writer, mapping, desc->typeDescription, ptr )) != S_OK) return hr;
-        break;
-    }
-    case WS_UINT8_TYPE:
-    {
-        const UINT8 *ptr = value;
-        if ((hr = write_type_uint8( writer, mapping, desc->typeDescription, ptr )) != S_OK) return hr;
-        break;
-    }
-    case WS_UINT16_TYPE:
-    {
-        const UINT16 *ptr = value;
-        if ((hr = write_type_uint16( writer, mapping, desc->typeDescription, ptr )) != S_OK) return hr;
-        break;
-    }
-    case WS_UINT32_TYPE:
-    {
-        const UINT32 *ptr = value;
-        if ((hr = write_type_uint32( writer, mapping, desc->typeDescription, ptr )) != S_OK) return hr;
-        break;
-    }
-    case WS_UINT64_TYPE:
+    if ((hr = write_type( writer, mapping, desc->type, desc->typeDescription, option, value, size )) != S_OK)
+        return hr;
+
+    switch (mapping)
     {
-        const UINT64 *ptr = value;
-        if ((hr = write_type_uint64( writer, mapping, desc->typeDescription, ptr )) != S_OK) return hr;
+    case WS_ATTRIBUTE_TYPE_MAPPING:
+        writer->state = WRITER_STATE_STARTELEMENT;
         break;
-    }
-    case WS_WSZ_TYPE:
-    {
-        const WCHAR * const *ptr = value;
-        if ((hr = write_type_wsz( writer, mapping, desc->typeDescription, *ptr )) != S_OK) return hr;
+
+    case WS_ELEMENT_TYPE_MAPPING:
+        if ((hr = write_close_element( writer )) != S_OK) return hr;
         break;
-    }
-    default:
-        FIXME( "type %u not implemented\n", desc->type );
-        return E_NOTIMPL;
+
+    default: break;
     }
 
     return S_OK;
 }
 
+static ULONG get_field_size( const WS_STRUCT_DESCRIPTION *desc, ULONG index )
+{
+    if (index < desc->fieldCount - 1) return desc->fields[index + 1]->offset - desc->fields[index]->offset;
+    return desc->size - desc->fields[index]->offset;
+}
+
 static HRESULT write_type_struct( struct writer *writer, WS_TYPE_MAPPING mapping,
                                   const WS_STRUCT_DESCRIPTION *desc, const void *value )
 {
-    ULONG i;
+    ULONG i, size;
     HRESULT hr;
     const char *ptr;
 
@@ -1430,7 +1402,8 @@ static HRESULT write_type_struct( struct writer *writer, WS_TYPE_MAPPING mapping
     for (i = 0; i < desc->fieldCount; i++)
     {
         ptr = (const char *)value + desc->fields[i]->offset;
-        if ((hr = write_type_struct_field( writer, mapping, desc->fields[i], ptr )) != S_OK)
+        size = get_field_size( desc, i );
+        if ((hr = write_type_struct_field( writer, desc->fields[i], ptr, size )) != S_OK)
             return hr;
     }
 
@@ -1447,7 +1420,7 @@ static HRESULT write_type( struct writer *writer, WS_TYPE_MAPPING mapping, WS_TY
     {
         const void * const *ptr = value;
 
-        if (!desc || option != WS_WRITE_REQUIRED_POINTER || size != sizeof(*ptr))
+        if (!desc || (option && option != WS_WRITE_REQUIRED_POINTER) || size != sizeof(*ptr))
             return E_INVALIDARG;
 
         return write_type_struct( writer, mapping, desc, *ptr );
@@ -1509,7 +1482,7 @@ static HRESULT write_type( struct writer *writer, WS_TYPE_MAPPING mapping, WS_TY
     case WS_WSZ_TYPE:
     {
         const WCHAR * const *ptr = value;
-        if (option != WS_WRITE_REQUIRED_POINTER || size != sizeof(*ptr)) return E_INVALIDARG;
+        if ((option && option != WS_WRITE_REQUIRED_POINTER) || size != sizeof(*ptr)) return E_INVALIDARG;
         return write_type_wsz( writer, mapping, desc, *ptr );
     }
     default:
@@ -1539,11 +1512,8 @@ HRESULT WINAPI WsWriteAttribute( WS_XML_WRITER *handle, const WS_ATTRIBUTE_DESCR
     if ((hr = write_add_attribute( writer, NULL, desc->attributeLocalName, desc->attributeNs,
                                    FALSE )) != S_OK) return hr;
 
-    if ((hr = write_type( writer, WS_ATTRIBUTE_TYPE_MAPPING, desc->type, desc->typeDescription,
-                          option, value, size )) != S_OK) return hr;
-
-    writer->state = WRITER_STATE_STARTELEMENT;
-    return S_OK;
+    return write_type( writer, WS_ATTRIBUTE_TYPE_MAPPING, desc->type, desc->typeDescription,
+                       option, value, size );
 }
 
 /**************************************************************************
-- 
2.7.0




More information about the wine-patches mailing list