Module: wine Branch: master Commit: 81d978902d26fc3f60004dad63b52bf0b5f33694 URL: http://source.winehq.org/git/wine.git/?a=commit;h=81d978902d26fc3f60004dad63...
Author: Hans Leidekker hans@codeweavers.com Date: Thu Aug 25 20:02:49 2016 +0200
webservices: Add support for optional and nillable fields in the writer.
Signed-off-by: Hans Leidekker hans@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/webservices/tests/writer.c | 85 +++++++++++++++++++++++++++++++++++++++++ dlls/webservices/writer.c | 58 +++++++++++++++++++++++++--- 2 files changed, 138 insertions(+), 5 deletions(-)
diff --git a/dlls/webservices/tests/writer.c b/dlls/webservices/tests/writer.c index 8888c69..d2573e3 100644 --- a/dlls/webservices/tests/writer.c +++ b/dlls/webservices/tests/writer.c @@ -2111,6 +2111,90 @@ static void test_double(void) WsFreeWriter( writer ); }
+static void test_field_flags(void) +{ + static const char expected[] = + "<t><bool a:nil="true" xmlns:a="http://www.w3.org/2001/XMLSchema-instance%5C%22/%3E<int32>-1</int32>" + "<xmlstr a:nil="true" xmlns:a="http://www.w3.org/2001/XMLSchema-instance%5C%22/%3E</t>"; + HRESULT hr; + WS_XML_WRITER *writer; + WS_STRUCT_DESCRIPTION s; + WS_FIELD_DESCRIPTION f, f2, f3, f4, *fields[4]; + WS_XML_STRING localname = {1, (BYTE *)"t"}, ns = {0, NULL}, str_guid = {4, (BYTE *)"guid"}; + WS_XML_STRING str_int32 = {5, (BYTE *)"int32"}, str_bool = {4, (BYTE *)"bool"}; + WS_XML_STRING str_xmlstr = {6, (BYTE *)"xmlstr"}; + INT32 val = -1; + struct test + { + GUID guid; + BOOL *bool_ptr; + INT32 *int32_ptr; + WS_XML_STRING xmlstr; + } 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 ); + + hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + + memset( &f, 0, sizeof(f) ); + f.mapping = WS_ELEMENT_FIELD_MAPPING; + f.localName = &str_guid; + f.ns = &ns; + f.type = WS_GUID_TYPE; + f.options = WS_FIELD_OPTIONAL; + fields[0] = &f; + + memset( &f2, 0, sizeof(f2) ); + f2.mapping = WS_ELEMENT_FIELD_MAPPING; + f2.localName = &str_bool; + f2.offset = FIELD_OFFSET(struct test, bool_ptr); + f2.ns = &ns; + f2.type = WS_BOOL_TYPE; + f2.options = WS_FIELD_POINTER|WS_FIELD_NILLABLE; + fields[1] = &f2; + + memset( &f3, 0, sizeof(f3) ); + f3.mapping = WS_ELEMENT_FIELD_MAPPING; + f3.localName = &str_int32; + f3.offset = FIELD_OFFSET(struct test, int32_ptr); + f3.ns = &ns; + f3.type = WS_INT32_TYPE; + f3.options = WS_FIELD_POINTER|WS_FIELD_NILLABLE; + fields[2] = &f3; + + memset( &f4, 0, sizeof(f4) ); + f4.mapping = WS_ELEMENT_FIELD_MAPPING; + f4.localName = &str_xmlstr; + f4.offset = FIELD_OFFSET(struct test, xmlstr); + f4.ns = &ns; + f4.type = WS_XML_STRING_TYPE; + f4.options = WS_FIELD_NILLABLE; + fields[3] = &f4; + + memset( &s, 0, sizeof(s) ); + s.size = sizeof(struct test); + s.alignment = TYPE_ALIGNMENT(struct test); + s.fields = fields; + s.fieldCount = 4; + + memset( &test, 0, sizeof(test) ); + test.int32_ptr = &val; + hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_STRUCT_TYPE, &s, WS_WRITE_REQUIRED_VALUE, + &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( writer, expected, __LINE__ ); + + WsFreeWriter( writer ); +} + START_TEST(writer) { test_WsCreateWriter(); @@ -2137,4 +2221,5 @@ START_TEST(writer) test_WsCopyNode(); test_text_types(); test_double(); + test_field_flags(); } diff --git a/dlls/webservices/writer.c b/dlls/webservices/writer.c index 8872a37..7f732f0 100644 --- a/dlls/webservices/writer.c +++ b/dlls/webservices/writer.c @@ -1564,6 +1564,26 @@ static HRESULT write_type_xml_string( struct writer *writer, WS_TYPE_MAPPING map return write_type_text( writer, mapping, &utf8.text ); }
+static inline BOOL is_nil_value( const char *value, ULONG size ) +{ + ULONG i; + for (i = 0; i < size; i++) if (value[i]) return FALSE; + return TRUE; +} + +static HRESULT write_add_nil_attribute( struct writer *writer ) +{ + static const WS_XML_STRING prefix = {1, (BYTE *)"a"}; + static const WS_XML_STRING localname = {3, (BYTE *)"nil"}; + static const WS_XML_STRING ns = {41, (BYTE *)"http://www.w3.org/2001/XMLSchema-instance%22%7D; + static const WS_XML_UTF8_TEXT value = {{WS_XML_TEXT_TYPE_UTF8}, {4, (BYTE *)"true"}}; + HRESULT hr; + + if ((hr = write_add_attribute( writer, &prefix, &localname, &ns, FALSE )) != S_OK) return hr; + if ((hr = write_set_attribute_value( writer, &value.text )) != S_OK) return hr; + return write_add_namespace_attribute( writer, &prefix, &ns, FALSE ); +} + static HRESULT write_type( struct writer *, WS_TYPE_MAPPING, WS_TYPE, const void *, WS_WRITE_OPTION, const void *, ULONG );
@@ -1574,14 +1594,33 @@ static HRESULT write_type_struct_field( struct writer *writer, const WS_FIELD_DE WS_TYPE_MAPPING mapping; WS_WRITE_OPTION option;
- if (!desc->options || desc->options == WS_FIELD_OPTIONAL) option = 0; - else if (desc->options == WS_FIELD_POINTER) option = WS_WRITE_REQUIRED_POINTER; - else + if (desc->options & ~(WS_FIELD_POINTER|WS_FIELD_OPTIONAL|WS_FIELD_NILLABLE)) { FIXME( "options 0x%x not supported\n", desc->options ); return E_NOTIMPL; }
+ if (is_nil_value( value, size )) + { + if (desc->options & WS_FIELD_NILLABLE) + { + if (desc->options & WS_FIELD_POINTER) + option = WS_WRITE_NILLABLE_POINTER; + else + option = WS_WRITE_NILLABLE_VALUE; + } + else + { + if (desc->options & WS_FIELD_OPTIONAL) return S_OK; + return E_INVALIDARG; + } + } + else + { + if (desc->options & WS_FIELD_POINTER) option = WS_WRITE_REQUIRED_POINTER; + else option = 0; + } + switch (desc->mapping) { case WS_ATTRIBUTE_FIELD_MAPPING: @@ -1595,6 +1634,10 @@ static HRESULT write_type_struct_field( struct writer *writer, const WS_FIELD_DE
case WS_ELEMENT_FIELD_MAPPING: if ((hr = write_element_node( writer, NULL, desc->localName, desc->ns )) != S_OK) return hr; + if (option == WS_WRITE_NILLABLE_VALUE || option == WS_WRITE_NILLABLE_POINTER) + { + if ((hr = write_add_nil_attribute( writer )) != S_OK) return hr; + } mapping = WS_ELEMENT_TYPE_MAPPING; break;
@@ -1620,8 +1663,11 @@ static HRESULT write_type_struct_field( struct writer *writer, const WS_FIELD_DE return E_NOTIMPL; }
- if ((hr = write_type( writer, mapping, desc->type, desc->typeDescription, option, value, size )) != S_OK) - return hr; + if (option != WS_WRITE_NILLABLE_VALUE && option != WS_WRITE_NILLABLE_POINTER) + { + if ((hr = write_type( writer, mapping, desc->type, desc->typeDescription, option, value, size )) != S_OK) + return hr; + }
switch (mapping) { @@ -1670,11 +1716,13 @@ static HRESULT get_value_ptr( WS_WRITE_OPTION option, const void *value, ULONG s switch (option) { case WS_WRITE_REQUIRED_VALUE: + case WS_WRITE_NILLABLE_VALUE: if (!value || !size) return E_INVALIDARG; *ptr = value; return S_OK;
case WS_WRITE_REQUIRED_POINTER: + case WS_WRITE_NILLABLE_POINTER: if (size != sizeof(const void *) || !(*ptr = *(const void **)value)) return E_INVALIDARG; return S_OK;