[7/8] webservices: Add support for optional and nillable fields in the writer.

Hans Leidekker hans at codeweavers.com
Thu Aug 25 13:02:49 CDT 2016


Signed-off-by: Hans Leidekker <hans at codeweavers.com>
---
 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\"/><int32>-1</int32>"
+        "<xmlstr a:nil=\"true\" xmlns:a=\"http://www.w3.org/2001/XMLSchema-instance\"/></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"};
+    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;
 
-- 
2.1.4




More information about the wine-patches mailing list