[2/6] webservices: Implement WsWriteElement.

Hans Leidekker hans at codeweavers.com
Fri Jan 29 06:27:26 CST 2016


Signed-off-by: Hans Leidekker <hans at codeweavers.com>
---
 dlls/webservices/tests/writer.c   |  80 +++++++++++++++++++
 dlls/webservices/webservices.spec |   2 +-
 dlls/webservices/writer.c         | 158 ++++++++++++++++++++++++++------------
 3 files changed, 191 insertions(+), 49 deletions(-)

diff --git a/dlls/webservices/tests/writer.c b/dlls/webservices/tests/writer.c
index fdddceb..37f62c6 100644
--- a/dlls/webservices/tests/writer.c
+++ b/dlls/webservices/tests/writer.c
@@ -721,6 +721,85 @@ static void test_simple_struct_type(void)
     WsFreeWriter( writer );
 }
 
+static void test_WsWriteElement(void)
+{
+    static const WCHAR testW[] = {'t','e','s','t',0};
+    HRESULT hr;
+    WS_XML_WRITER *writer;
+    WS_STRUCT_DESCRIPTION s;
+    WS_FIELD_DESCRIPTION f, *fields[1];
+    WS_ELEMENT_DESCRIPTION desc;
+    WS_XML_STRING localname = {3, (BYTE *)"str"}, ns = {0, NULL};
+    struct test { const WCHAR *str; } *test;
+
+    hr = WsCreateWriter( NULL, 0, &writer, NULL ) ;
+    ok( hr == S_OK, "got %08x\n", hr );
+
+    hr = set_output( writer );
+    ok( hr == S_OK, "got %08x\n", hr );
+
+    /* text field mapping */
+    memset( &f, 0, sizeof(f) );
+    f.mapping = WS_TEXT_FIELD_MAPPING;
+    f.type    = WS_WSZ_TYPE;
+    fields[0] = &f;
+
+    memset( &s, 0, sizeof(s) );
+    s.size       = sizeof(struct test);
+    s.alignment  = TYPE_ALIGNMENT(struct test);
+    s.fields     = fields;
+    s.fieldCount = 1;
+
+    desc.elementLocalName = &localname;
+    desc.elementNs        = &ns;
+    desc.type             = WS_STRUCT_TYPE;
+    desc.typeDescription  = &s;
+
+    test = HeapAlloc( GetProcessHeap(), 0, sizeof(*test) );
+    test->str = testW;
+    hr = WsWriteElement( NULL, &desc, WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
+    ok( hr == E_INVALIDARG, "got %08x\n", hr );
+
+    hr = WsWriteElement( writer, NULL, WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
+    ok( hr == E_INVALIDARG, "got %08x\n", hr );
+
+    hr = WsWriteElement( writer, &desc, WS_WRITE_REQUIRED_POINTER, NULL, 0, NULL );
+    ok( hr == E_INVALIDARG, "got %08x\n", hr );
+
+    hr = WsWriteElement( writer, &desc, WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
+    check_output( writer, "<str>test</str>", __LINE__ );
+
+    hr = set_output( writer );
+    ok( hr == S_OK, "got %08x\n", hr );
+
+    hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
+
+    hr = WsWriteElement( writer, &desc, WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
+    check_output( writer, "<str><str>test</str>", __LINE__ );
+
+    hr = set_output( writer );
+    ok( hr == S_OK, "got %08x\n", hr );
+
+    /* attribute field mapping */
+    f.mapping = WS_ATTRIBUTE_FIELD_MAPPING;
+
+    /* requires localName and ns to be set */
+    hr = WsWriteElement( writer, &desc, WS_WRITE_REQUIRED_POINTER, NULL, 0, NULL );
+    ok( hr == E_INVALIDARG, "got %08x\n", hr );
+
+    f.localName = &localname;
+    f.ns        = &ns;
+    hr = WsWriteElement( writer, &desc, WS_WRITE_REQUIRED_POINTER, &test, sizeof(test), NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
+    check_output( writer, "<str str=\"test\"/>", __LINE__ );
+
+    HeapFree( GetProcessHeap(), 0, test );
+    WsFreeWriter( writer );
+}
+
 START_TEST(writer)
 {
     test_WsCreateWriter();
@@ -730,6 +809,7 @@ START_TEST(writer)
     test_WsWriteStartElement();
     test_WsWriteStartAttribute();
     test_WsWriteType();
+    test_WsWriteElement();
     test_basic_type();
     test_simple_struct_type();
 }
diff --git a/dlls/webservices/webservices.spec b/dlls/webservices/webservices.spec
index e846251..a6656ab 100644
--- a/dlls/webservices/webservices.spec
+++ b/dlls/webservices/webservices.spec
@@ -170,7 +170,7 @@
 @ stub WsWriteBytes
 @ stub WsWriteChars
 @ stub WsWriteCharsUtf8
-@ stub WsWriteElement
+@ stdcall WsWriteElement(ptr ptr long ptr long ptr)
 @ stdcall WsWriteEndAttribute(ptr ptr)
 @ stub WsWriteEndCData
 @ stdcall WsWriteEndElement(ptr ptr)
diff --git a/dlls/webservices/writer.c b/dlls/webservices/writer.c
index 5efd62e..20a76de 100644
--- a/dlls/webservices/writer.c
+++ b/dlls/webservices/writer.c
@@ -670,6 +670,43 @@ HRESULT WINAPI WsWriteEndStartElement( WS_XML_WRITER *handle, WS_ERROR *error )
     return S_OK;
 }
 
+static HRESULT write_add_attribute( struct writer *writer, const WS_XML_STRING *prefix,
+                                    const WS_XML_STRING *localname, const WS_XML_STRING *ns,
+                                    BOOL single )
+{
+    WS_XML_ATTRIBUTE *attr;
+    WS_XML_ELEMENT_NODE *elem = &writer->current->hdr;
+    HRESULT hr;
+
+    if (!(attr = heap_alloc_zero( sizeof(*attr) ))) return E_OUTOFMEMORY;
+
+    if (!prefix) prefix = elem->prefix;
+
+    attr->singleQuote = !!single;
+    if (prefix && !(attr->prefix = alloc_xml_string( prefix->bytes, prefix->length )))
+    {
+        free_attribute( attr );
+        return E_OUTOFMEMORY;
+    }
+    if (!(attr->localName = alloc_xml_string( localname->bytes, localname->length )))
+    {
+        free_attribute( attr );
+        return E_OUTOFMEMORY;
+    }
+    if (!(attr->ns = alloc_xml_string( ns->bytes, ns->length )))
+    {
+        free_attribute( attr );
+        return E_OUTOFMEMORY;
+    }
+    if ((hr = append_attribute( elem, attr )) != S_OK)
+    {
+        free_attribute( attr );
+        return hr;
+    }
+    writer->state = WRITER_STATE_STARTATTRIBUTE;
+    return S_OK;
+}
+
 /**************************************************************************
  *          WsWriteStartAttribute		[webservices.@]
  */
@@ -678,9 +715,6 @@ HRESULT WINAPI WsWriteStartAttribute( WS_XML_WRITER *handle, const WS_XML_STRING
                                       BOOL single, WS_ERROR *error )
 {
     struct writer *writer = (struct writer *)handle;
-    WS_XML_ELEMENT_NODE *elem;
-    WS_XML_ATTRIBUTE *attr;
-    HRESULT hr = E_OUTOFMEMORY;
 
     TRACE( "%p %s %s %s %d %p\n", handle, debugstr_xmlstr(prefix), debugstr_xmlstr(localname),
            debugstr_xmlstr(ns), single, error );
@@ -689,28 +723,45 @@ HRESULT WINAPI WsWriteStartAttribute( WS_XML_WRITER *handle, const WS_XML_STRING
     if (!writer || !localname || !ns) return E_INVALIDARG;
 
     if (writer->state != WRITER_STATE_STARTELEMENT) return WS_E_INVALID_OPERATION;
-    elem = (WS_XML_ELEMENT_NODE *)writer->current;
 
-    if (!(attr = heap_alloc_zero( sizeof(*attr) ))) return E_OUTOFMEMORY;
-    attr->singleQuote = !!single;
+    return write_add_attribute( writer, prefix, localname, ns, single );
+}
 
-    if (prefix && !(attr->prefix = alloc_xml_string( prefix->bytes, prefix->length )))
-        goto error;
+static HRESULT write_add_element_node( struct writer *writer, const WS_XML_STRING *prefix,
+                                       const WS_XML_STRING *localname, const WS_XML_STRING *ns )
+{
+    struct node *node;
+    WS_XML_ELEMENT_NODE *elem, *current = &writer->current->hdr;
+    HRESULT hr;
 
-    if (!(attr->localName = alloc_xml_string( localname->bytes, localname->length )))
-        goto error;
+    /* flush current start element if necessary */
+    if (writer->state == WRITER_STATE_STARTELEMENT && ((hr = write_endstartelement( writer )) != S_OK))
+        return hr;
 
-    if (!(attr->ns = alloc_xml_string( ns->bytes, ns->length )))
-        goto error;
+    if (!prefix && current->node.nodeType == WS_XML_NODE_TYPE_ELEMENT)
+        prefix = current->prefix;
 
-    if ((hr = append_attribute( elem, attr )) != S_OK) goto error;
+    if (!(node = alloc_node( WS_XML_NODE_TYPE_ELEMENT ))) return E_OUTOFMEMORY;
+    elem = &node->hdr;
 
-    writer->state = WRITER_STATE_STARTATTRIBUTE;
+    if (prefix && !(elem->prefix = alloc_xml_string( prefix->bytes, prefix->length )))
+    {
+        free_node( node );
+        return E_OUTOFMEMORY;
+    }
+    if (!(elem->localName = alloc_xml_string( localname->bytes, localname->length )))
+    {
+        free_node( node );
+        return E_OUTOFMEMORY;
+    }
+    if (!(elem->ns = alloc_xml_string( ns->bytes, ns->length )))
+    {
+        free_node( node );
+        return E_OUTOFMEMORY;
+    }
+    write_insert_node( writer, node );
+    writer->state = WRITER_STATE_STARTELEMENT;
     return S_OK;
-
-error:
-    free_attribute( attr );
-    return hr;
 }
 
 /**************************************************************************
@@ -721,9 +772,6 @@ HRESULT WINAPI WsWriteStartElement( WS_XML_WRITER *handle, const WS_XML_STRING *
                                     WS_ERROR *error )
 {
     struct writer *writer = (struct writer *)handle;
-    struct node *node;
-    WS_XML_ELEMENT_NODE *elem;
-    HRESULT hr = E_OUTOFMEMORY;
 
     TRACE( "%p %s %s %s %p\n", handle, debugstr_xmlstr(prefix), debugstr_xmlstr(localname),
            debugstr_xmlstr(ns), error );
@@ -731,33 +779,7 @@ HRESULT WINAPI WsWriteStartElement( WS_XML_WRITER *handle, const WS_XML_STRING *
 
     if (!writer || !localname || !ns) return E_INVALIDARG;
 
-    /* flush current start element */
-    if (writer->state == WRITER_STATE_STARTELEMENT)
-    {
-        if ((hr = write_startelement( writer )) != S_OK) return hr;
-        if ((hr = write_grow_buffer( writer, 1 )) != S_OK) return hr;
-        write_char( writer, '>' );
-    }
-
-    if (!(node = alloc_node( WS_XML_NODE_TYPE_ELEMENT ))) return E_OUTOFMEMORY;
-    elem = (WS_XML_ELEMENT_NODE *)node;
-
-    if (prefix && !(elem->prefix = alloc_xml_string( prefix->bytes, prefix->length )))
-        goto error;
-
-    if (!(elem->localName = alloc_xml_string( localname->bytes, localname->length )))
-        goto error;
-
-    if (!(elem->ns = alloc_xml_string( ns->bytes, ns->length )))
-        goto error;
-
-    write_insert_node( writer, node );
-    writer->state = WRITER_STATE_STARTELEMENT;
-    return S_OK;
-
-error:
-    free_node( node );
-    return hr;
+    return write_add_element_node( writer, prefix, localname, ns );
 }
 
 static inline void write_set_attribute_value( struct writer *writer, WS_XML_TEXT *text )
@@ -1129,6 +1151,21 @@ static HRESULT write_type_struct_field( struct writer *writer, WS_TYPE_MAPPING m
         return E_NOTIMPL;
     }
 
+    switch (desc->mapping)
+    {
+    case WS_ATTRIBUTE_FIELD_MAPPING:
+        if ((hr = write_add_attribute( writer, NULL, desc->localName, desc->ns, FALSE )) != S_OK)
+            return hr;
+        break;
+
+    case WS_TEXT_FIELD_MAPPING:
+        break;
+
+    default:
+        FIXME( "field mapping %u not supported\n", desc->mapping );
+        return E_NOTIMPL;
+    }
+
     switch (desc->type)
     {
     case WS_STRUCT_TYPE:
@@ -1312,6 +1349,31 @@ static HRESULT write_type( struct writer *writer, WS_TYPE_MAPPING mapping, WS_TY
 }
 
 /**************************************************************************
+ *          WsWriteElement		[webservices.@]
+ */
+HRESULT WINAPI WsWriteElement( WS_XML_WRITER *handle, const WS_ELEMENT_DESCRIPTION *desc,
+                               WS_WRITE_OPTION option, const void *value, ULONG size,
+                               WS_ERROR *error )
+{
+    struct writer *writer = (struct writer *)handle;
+    HRESULT hr;
+
+    TRACE( "%p %p %u %p %u %p\n", handle, desc, option, value, size, error );
+    if (error) FIXME( "ignoring error parameter\n" );
+
+    if (!writer || !desc || !desc->elementLocalName || !desc->elementNs || !value)
+        return E_INVALIDARG;
+
+    if ((hr = write_add_element_node( writer, NULL, desc->elementLocalName, desc->elementNs )) != S_OK)
+        return hr;
+
+    if ((hr = write_type( writer, WS_ANY_ELEMENT_TYPE_MAPPING, desc->type, desc->typeDescription,
+                          option, value, size )) != S_OK) return hr;
+
+    return write_close_element( writer );
+}
+
+/**************************************************************************
  *          WsWriteType		[webservices.@]
  */
 HRESULT WINAPI WsWriteType( WS_XML_WRITER *handle, WS_TYPE_MAPPING mapping, WS_TYPE type,
-- 
2.7.0.rc3




More information about the wine-patches mailing list