From ca0b46a10c80c56bfaf7007476fa9f5f31f60cb4 Mon Sep 17 00:00:00 2001 From: Hans Leidekker Date: Fri, 8 Dec 2017 15:49:39 +0100 Subject: [PATCH] webservices: Implement WS_REPEATING_ELEMENT_CHOICE_FIELD_MAPPING in the writer. Signed-off-by: Hans Leidekker Signed-off-by: Alexandre Julliard --- dlls/webservices/tests/writer.c | 106 ++++++++++++++++++++++++++++++++++++++++ dlls/webservices/writer.c | 80 +++++++++++++++++------------- 2 files changed, 151 insertions(+), 35 deletions(-) diff --git a/dlls/webservices/tests/writer.c b/dlls/webservices/tests/writer.c index 79b60d19ca8..15d4569662c 100644 --- a/dlls/webservices/tests/writer.c +++ b/dlls/webservices/tests/writer.c @@ -4544,6 +4544,111 @@ static void test_text_types_binary(void) WsFreeWriter( writer ); } +static void test_repeating_element_choice(void) +{ + static const WCHAR testW[] = {'t','e','s','t',0}; + static WS_XML_STRING str_ns = {0, NULL}, str_a = {1, (BYTE *)"a"}, str_b = {1, (BYTE *)"b"}; + static WS_XML_STRING str_s = {1, (BYTE *)"s"}, str_t = {1, (BYTE *)"t"}; + HRESULT hr; + WS_XML_WRITER *writer; + WS_UNION_DESCRIPTION u; + WS_UNION_FIELD_DESCRIPTION f, f2, *fields[2]; + WS_FIELD_DESCRIPTION f_items, *fields_items[1]; + WS_STRUCT_DESCRIPTION s; + enum choice {CHOICE_A, CHOICE_B, CHOICE_NONE}; + struct item + { + enum choice choice; + union + { + const WCHAR *a; + UINT32 b; + } value; + } items[2]; + struct test + { + struct item *items; + ULONG count; + } test; + + hr = WsCreateWriter( NULL, 0, &writer, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + + memset( &f, 0, sizeof(f) ); + f.value = CHOICE_A; + f.field.mapping = WS_ELEMENT_FIELD_MAPPING; + f.field.localName = &str_a; + f.field.ns = &str_ns; + f.field.type = WS_WSZ_TYPE; + f.field.offset = FIELD_OFFSET(struct item, value.a); + fields[0] = &f; + + memset( &f2, 0, sizeof(f2) ); + f2.value = CHOICE_B; + f2.field.mapping = WS_ELEMENT_FIELD_MAPPING; + f2.field.localName = &str_b; + f2.field.ns = &str_ns; + f2.field.type = WS_UINT32_TYPE; + f2.field.offset = FIELD_OFFSET(struct item, value.b); + fields[1] = &f2; + + memset( &u, 0, sizeof(u) ); + u.size = sizeof(struct item); + u.alignment = TYPE_ALIGNMENT(struct item); + u.fields = fields; + u.fieldCount = 2; + u.enumOffset = FIELD_OFFSET(struct item, choice); + u.noneEnumValue = CHOICE_NONE; + + memset( &f_items, 0, sizeof(f_items) ); + f_items.mapping = WS_REPEATING_ELEMENT_CHOICE_FIELD_MAPPING; + f_items.localName = &str_t; + f_items.ns = &str_ns; + f_items.type = WS_UNION_TYPE; + f_items.typeDescription = &u; + f_items.countOffset = FIELD_OFFSET(struct test, count); + fields_items[0] = &f_items; + + memset( &s, 0, sizeof(s) ); + s.size = sizeof(struct test); + s.alignment = TYPE_ALIGNMENT(struct test); + s.fields = fields_items; + s.fieldCount = 1; + s.typeLocalName = &str_s; + s.typeNs = &str_ns; + + items[0].choice = CHOICE_A; + items[0].value.a = testW; + items[1].choice = CHOICE_B; + items[1].value.b = 1; + test.items = items; + test.count = 2; + + hr = set_output( writer ); + ok( hr == S_OK, "got %08x\n", hr ); + hr = WsWriteType( writer, WS_ELEMENT_CONTENT_TYPE_MAPPING, WS_STRUCT_TYPE, &s, + WS_WRITE_REQUIRED_VALUE, &test, sizeof(test), NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + check_output( writer, "test1", __LINE__ ); + + items[0].choice = CHOICE_NONE; + hr = set_output( writer ); + ok( hr == S_OK, "got %08x\n", hr ); + hr = WsWriteType( writer, WS_ELEMENT_CONTENT_TYPE_MAPPING, WS_STRUCT_TYPE, &s, + WS_WRITE_REQUIRED_VALUE, &test, sizeof(test), NULL ); + ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr ); + + test.count = 0; + hr = set_output( writer ); + ok( hr == S_OK, "got %08x\n", hr ); + hr = WsWriteType( writer, WS_ELEMENT_CONTENT_TYPE_MAPPING, WS_STRUCT_TYPE, &s, + WS_WRITE_REQUIRED_VALUE, &test, sizeof(test), NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + check_output( writer, "", __LINE__ ); + + WsFreeWriter( writer ); +} + START_TEST(writer) { test_WsCreateWriter(); @@ -4586,4 +4691,5 @@ START_TEST(writer) test_dictionary(); test_union_type(); test_text_types_binary(); + test_repeating_element_choice(); } diff --git a/dlls/webservices/writer.c b/dlls/webservices/writer.c index 8738f4c9dd7..4b2466390cc 100644 --- a/dlls/webservices/writer.c +++ b/dlls/webservices/writer.c @@ -3492,6 +3492,7 @@ static WS_WRITE_OPTION get_field_write_option( WS_TYPE type, ULONG options ) case WS_XML_QNAME_TYPE: case WS_STRUCT_TYPE: case WS_ENUM_TYPE: + case WS_UNION_TYPE: if (options & (WS_FIELD_OPTIONAL|WS_FIELD_NILLABLE)) return WS_WRITE_NILLABLE_VALUE; return WS_WRITE_REQUIRED_VALUE; @@ -3506,42 +3507,11 @@ static WS_WRITE_OPTION get_field_write_option( WS_TYPE type, ULONG options ) } } +static HRESULT write_type_field( struct writer *, const WS_FIELD_DESCRIPTION *, const char *, ULONG ); + static HRESULT write_type( struct writer *, WS_TYPE_MAPPING, WS_TYPE, const void *, WS_WRITE_OPTION, const void *, ULONG ); -static HRESULT write_type_repeating_element( struct writer *writer, const WS_FIELD_DESCRIPTION *desc, - const char *buf, ULONG count ) -{ - HRESULT hr = S_OK; - ULONG i, size, offset = 0; - WS_WRITE_OPTION option; - - if (!(option = get_field_write_option( desc->type, desc->options ))) return E_INVALIDARG; - - /* wrapper element */ - if (desc->localName && ((hr = write_element_node( writer, NULL, desc->localName, desc->ns )) != S_OK)) - return hr; - - if (option == WS_WRITE_REQUIRED_VALUE || option == WS_WRITE_NILLABLE_VALUE) - size = get_type_size( desc->type, desc->typeDescription ); - else - size = sizeof(const void *); - - for (i = 0; i < count; i++) - { - if ((hr = write_element_node( writer, NULL, desc->itemLocalName, desc->itemNs )) != S_OK) return hr; - if ((hr = write_type( writer, WS_ELEMENT_TYPE_MAPPING, desc->type, desc->typeDescription, option, - buf + offset, size )) != S_OK) return hr; - if ((hr = write_endelement_node( writer )) != S_OK) return hr; - offset += size; - } - - if (desc->localName) hr = write_endelement_node( writer ); - return hr; -} - -static HRESULT write_type_field( struct writer *, const WS_FIELD_DESCRIPTION *, const char *, ULONG ); - static HRESULT write_type_union( struct writer *writer, const WS_UNION_DESCRIPTION *desc, WS_WRITE_OPTION option, const void *value, ULONG size ) { @@ -3581,6 +3551,45 @@ static HRESULT write_type_union( struct writer *writer, const WS_UNION_DESCRIPTI return E_INVALIDARG; } +static HRESULT write_type_array( struct writer *writer, const WS_FIELD_DESCRIPTION *desc, const char *buf, + ULONG count ) +{ + HRESULT hr = S_OK; + ULONG i, size, offset = 0; + WS_WRITE_OPTION option; + + if (!(option = get_field_write_option( desc->type, desc->options ))) return E_INVALIDARG; + + /* wrapper element */ + if (desc->localName && ((hr = write_element_node( writer, NULL, desc->localName, desc->ns )) != S_OK)) + return hr; + + if (option == WS_WRITE_REQUIRED_VALUE || option == WS_WRITE_NILLABLE_VALUE) + size = get_type_size( desc->type, desc->typeDescription ); + else + size = sizeof(const void *); + + for (i = 0; i < count; i++) + { + if (desc->type == WS_UNION_TYPE) + { + if ((hr = write_type_union( writer, desc->typeDescription, option, buf + offset, size )) != S_OK) + return hr; + } + else + { + if ((hr = write_element_node( writer, NULL, desc->itemLocalName, desc->itemNs )) != S_OK) return hr; + if ((hr = write_type( writer, WS_ELEMENT_TYPE_MAPPING, desc->type, desc->typeDescription, option, + buf + offset, size )) != S_OK) return hr; + if ((hr = write_endelement_node( writer )) != S_OK) return hr; + } + offset += size; + } + + if (desc->localName) hr = write_endelement_node( writer ); + return hr; +} + static HRESULT write_type_field( struct writer *writer, const WS_FIELD_DESCRIPTION *desc, const char *buf, ULONG offset ) { @@ -3646,8 +3655,9 @@ static HRESULT write_type_field( struct writer *writer, const WS_FIELD_DESCRIPTI return write_type_union( writer, desc->typeDescription, option, ptr, size ); case WS_REPEATING_ELEMENT_FIELD_MAPPING: + case WS_REPEATING_ELEMENT_CHOICE_FIELD_MAPPING: count = *(const ULONG *)(buf + desc->countOffset); - return write_type_repeating_element( writer, desc, *(const char **)ptr, count ); + return write_type_array( writer, desc, *(const char **)ptr, count ); case WS_TEXT_FIELD_MAPPING: switch (writer->state) @@ -4713,7 +4723,7 @@ static ULONG get_array_len( const WS_PARAMETER_DESCRIPTION *params, ULONG count, static HRESULT write_param_array( struct writer *writer, const WS_FIELD_DESCRIPTION *desc, const void *value, ULONG len ) { - return write_type_repeating_element( writer, desc, value, len ); + return write_type_array( writer, desc, value, len ); } HRESULT write_input_params( WS_XML_WRITER *handle, const WS_ELEMENT_DESCRIPTION *desc, -- 2.11.4.GIT