From 2f37267312390a9d2930f90ddfe5934f072f3e5f Mon Sep 17 00:00:00 2001 From: Hans Leidekker Date: Fri, 29 Jan 2016 13:27:26 +0100 Subject: [PATCH] webservices: Implement WsWriteElement. Signed-off-by: Hans Leidekker Signed-off-by: Alexandre Julliard --- 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 fdddceb2dd6..37f62c69f26 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, "test", __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, "test", __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, "", __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 e8462514706..a6656ab4f44 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 5efd62e689c..20a76de4010 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: @@ -1311,6 +1348,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.@] */