[2/4] webservices: Add support for optional and nillable fields in the reader.

Hans Leidekker hans at codeweavers.com
Tue Sep 13 07:31:35 CDT 2016


Signed-off-by: Hans Leidekker <hans at codeweavers.com>
---
 dlls/webservices/reader.c              | 144 +++++++++++++++---------
 dlls/webservices/tests/reader.c        | 197 +++++++++++++++++++++++++--------
 dlls/webservices/webservices_private.h |   7 ++
 dlls/webservices/writer.c              |   7 --
 4 files changed, 251 insertions(+), 104 deletions(-)

diff --git a/dlls/webservices/reader.c b/dlls/webservices/reader.c
index b562c00..eb4bb7b 100644
--- a/dlls/webservices/reader.c
+++ b/dlls/webservices/reader.c
@@ -2806,6 +2806,9 @@ static HRESULT read_type_bool( struct reader *reader, WS_TYPE_MAPPING mapping,
     {
     case WS_READ_REQUIRED_VALUE:
         if (!found) return WS_E_INVALID_FORMAT;
+        /* fall through */
+
+    case WS_READ_NILLABLE_VALUE:
         if (size != sizeof(BOOL)) return E_INVALIDARG;
         *(BOOL *)ret = val;
         break;
@@ -2815,6 +2818,7 @@ static HRESULT read_type_bool( struct reader *reader, WS_TYPE_MAPPING mapping,
         /* fall through */
 
     case WS_READ_OPTIONAL_POINTER:
+    case WS_READ_NILLABLE_POINTER:
     {
         BOOL *heap_val = NULL;
         if (size != sizeof(heap_val)) return E_INVALIDARG;
@@ -2841,7 +2845,7 @@ static HRESULT read_type_int8( struct reader *reader, WS_TYPE_MAPPING mapping,
 {
     WS_XML_UTF8_TEXT *utf8;
     HRESULT hr;
-    INT64 val;
+    INT64 val = 0;
     BOOL found;
 
     if (desc)
@@ -2857,6 +2861,9 @@ static HRESULT read_type_int8( struct reader *reader, WS_TYPE_MAPPING mapping,
     {
     case WS_READ_REQUIRED_VALUE:
         if (!found) return WS_E_INVALID_FORMAT;
+        /* fall through */
+
+    case WS_READ_NILLABLE_VALUE:
         if (size != sizeof(INT8)) return E_INVALIDARG;
         *(INT8 *)ret = val;
         break;
@@ -2866,6 +2873,7 @@ static HRESULT read_type_int8( struct reader *reader, WS_TYPE_MAPPING mapping,
         /* fall through */
 
     case WS_READ_OPTIONAL_POINTER:
+    case WS_READ_NILLABLE_POINTER:
     {
         INT8 *heap_val = NULL;
         if (size != sizeof(heap_val)) return E_INVALIDARG;
@@ -2892,7 +2900,7 @@ static HRESULT read_type_int16( struct reader *reader, WS_TYPE_MAPPING mapping,
 {
     WS_XML_UTF8_TEXT *utf8;
     HRESULT hr;
-    INT64 val;
+    INT64 val = 0;
     BOOL found;
 
     if (desc)
@@ -2908,6 +2916,9 @@ static HRESULT read_type_int16( struct reader *reader, WS_TYPE_MAPPING mapping,
     {
     case WS_READ_REQUIRED_VALUE:
         if (!found) return WS_E_INVALID_FORMAT;
+        /* fall through */
+
+    case WS_READ_NILLABLE_VALUE:
         if (size != sizeof(INT16)) return E_INVALIDARG;
         *(INT16 *)ret = val;
         break;
@@ -2917,6 +2928,7 @@ static HRESULT read_type_int16( struct reader *reader, WS_TYPE_MAPPING mapping,
         /* fall through */
 
     case WS_READ_OPTIONAL_POINTER:
+    case WS_READ_NILLABLE_POINTER:
     {
         INT16 *heap_val = NULL;
         if (size != sizeof(heap_val)) return E_INVALIDARG;
@@ -2943,7 +2955,7 @@ static HRESULT read_type_int32( struct reader *reader, WS_TYPE_MAPPING mapping,
 {
     WS_XML_UTF8_TEXT *utf8;
     HRESULT hr;
-    INT64 val;
+    INT64 val = 0;
     BOOL found;
 
     if (desc)
@@ -2959,6 +2971,9 @@ static HRESULT read_type_int32( struct reader *reader, WS_TYPE_MAPPING mapping,
     {
     case WS_READ_REQUIRED_VALUE:
         if (!found) return WS_E_INVALID_FORMAT;
+        /* fall through */
+
+    case WS_READ_NILLABLE_VALUE:
         if (size != sizeof(INT32)) return E_INVALIDARG;
         *(INT32 *)ret = val;
         break;
@@ -2968,6 +2983,7 @@ static HRESULT read_type_int32( struct reader *reader, WS_TYPE_MAPPING mapping,
         /* fall through */
 
     case WS_READ_OPTIONAL_POINTER:
+    case WS_READ_NILLABLE_POINTER:
     {
         INT32 *heap_val = NULL;
         if (size != sizeof(heap_val)) return E_INVALIDARG;
@@ -2994,7 +3010,7 @@ static HRESULT read_type_int64( struct reader *reader, WS_TYPE_MAPPING mapping,
 {
     WS_XML_UTF8_TEXT *utf8;
     HRESULT hr;
-    INT64 val;
+    INT64 val = 0;
     BOOL found;
 
     if (desc)
@@ -3010,6 +3026,9 @@ static HRESULT read_type_int64( struct reader *reader, WS_TYPE_MAPPING mapping,
     {
     case WS_READ_REQUIRED_VALUE:
         if (!found) return WS_E_INVALID_FORMAT;
+        /* fall through */
+
+    case WS_READ_NILLABLE_VALUE:
         if (size != sizeof(INT64)) return E_INVALIDARG;
         *(INT64 *)ret = val;
         break;
@@ -3019,6 +3038,7 @@ static HRESULT read_type_int64( struct reader *reader, WS_TYPE_MAPPING mapping,
         /* fall through */
 
     case WS_READ_OPTIONAL_POINTER:
+    case WS_READ_NILLABLE_POINTER:
     {
         INT64 *heap_val = NULL;
         if (size != sizeof(heap_val)) return E_INVALIDARG;
@@ -3045,7 +3065,7 @@ static HRESULT read_type_uint8( struct reader *reader, WS_TYPE_MAPPING mapping,
 {
     WS_XML_UTF8_TEXT *utf8;
     HRESULT hr;
-    UINT64 val;
+    UINT64 val = 0;
     BOOL found;
 
     if (desc)
@@ -3061,6 +3081,9 @@ static HRESULT read_type_uint8( struct reader *reader, WS_TYPE_MAPPING mapping,
     {
     case WS_READ_REQUIRED_VALUE:
         if (!found) return WS_E_INVALID_FORMAT;
+        /* fall through */
+
+    case WS_READ_NILLABLE_VALUE:
         if (size != sizeof(UINT8)) return E_INVALIDARG;
         *(UINT8 *)ret = val;
         break;
@@ -3070,6 +3093,7 @@ static HRESULT read_type_uint8( struct reader *reader, WS_TYPE_MAPPING mapping,
         /* fall through */
 
     case WS_READ_OPTIONAL_POINTER:
+    case WS_READ_NILLABLE_POINTER:
     {
         UINT8 *heap_val = NULL;
         if (size != sizeof(heap_val)) return E_INVALIDARG;
@@ -3096,7 +3120,7 @@ static HRESULT read_type_uint16( struct reader *reader, WS_TYPE_MAPPING mapping,
 {
     WS_XML_UTF8_TEXT *utf8;
     HRESULT hr;
-    UINT64 val;
+    UINT64 val = 0;
     BOOL found;
 
     if (desc)
@@ -3112,6 +3136,9 @@ static HRESULT read_type_uint16( struct reader *reader, WS_TYPE_MAPPING mapping,
     {
     case WS_READ_REQUIRED_VALUE:
         if (!found) return WS_E_INVALID_FORMAT;
+        /* fall through */
+
+    case WS_READ_NILLABLE_VALUE:
         if (size != sizeof(UINT16)) return E_INVALIDARG;
         *(UINT16 *)ret = val;
         break;
@@ -3121,6 +3148,7 @@ static HRESULT read_type_uint16( struct reader *reader, WS_TYPE_MAPPING mapping,
         /* fall through */
 
     case WS_READ_OPTIONAL_POINTER:
+    case WS_READ_NILLABLE_POINTER:
     {
         UINT16 *heap_val = NULL;
         if (size != sizeof(heap_val)) return E_INVALIDARG;
@@ -3147,7 +3175,7 @@ static HRESULT read_type_uint32( struct reader *reader, WS_TYPE_MAPPING mapping,
 {
     WS_XML_UTF8_TEXT *utf8;
     HRESULT hr;
-    UINT64 val;
+    UINT64 val = 0;
     BOOL found;
 
     if (desc)
@@ -3163,6 +3191,9 @@ static HRESULT read_type_uint32( struct reader *reader, WS_TYPE_MAPPING mapping,
     {
     case WS_READ_REQUIRED_VALUE:
         if (!found) return WS_E_INVALID_FORMAT;
+        /* fall through */
+
+    case WS_READ_NILLABLE_VALUE:
         if (size != sizeof(UINT32)) return E_INVALIDARG;
         *(UINT32 *)ret = val;
         break;
@@ -3172,6 +3203,7 @@ static HRESULT read_type_uint32( struct reader *reader, WS_TYPE_MAPPING mapping,
         /* fall through */
 
     case WS_READ_OPTIONAL_POINTER:
+    case WS_READ_NILLABLE_POINTER:
     {
         UINT32 *heap_val = NULL;
         if (size != sizeof(heap_val)) return E_INVALIDARG;
@@ -3198,7 +3230,7 @@ static HRESULT read_type_uint64( struct reader *reader, WS_TYPE_MAPPING mapping,
 {
     WS_XML_UTF8_TEXT *utf8;
     HRESULT hr;
-    UINT64 val;
+    UINT64 val = 0;
     BOOL found;
 
     if (desc)
@@ -3214,6 +3246,9 @@ static HRESULT read_type_uint64( struct reader *reader, WS_TYPE_MAPPING mapping,
     {
     case WS_READ_REQUIRED_VALUE:
         if (!found) return WS_E_INVALID_FORMAT;
+        /* fall through */
+
+    case WS_READ_NILLABLE_VALUE:
         if (size != sizeof(UINT64)) return E_INVALIDARG;
         *(UINT64 *)ret = val;
         break;
@@ -3223,6 +3258,7 @@ static HRESULT read_type_uint64( struct reader *reader, WS_TYPE_MAPPING mapping,
         /* fall through */
 
     case WS_READ_OPTIONAL_POINTER:
+    case WS_READ_NILLABLE_POINTER:
     {
         UINT64 *heap_val = NULL;
         if (size != sizeof(heap_val)) return E_INVALIDARG;
@@ -3261,6 +3297,9 @@ static HRESULT read_type_double( struct reader *reader, WS_TYPE_MAPPING mapping,
     {
     case WS_READ_REQUIRED_VALUE:
         if (!found) return WS_E_INVALID_FORMAT;
+        /* fall through */
+
+    case WS_READ_NILLABLE_VALUE:
         if (size != sizeof(double)) return E_INVALIDARG;
         *(double *)ret = val;
         break;
@@ -3270,6 +3309,7 @@ static HRESULT read_type_double( struct reader *reader, WS_TYPE_MAPPING mapping,
         /* fall through */
 
     case WS_READ_OPTIONAL_POINTER:
+    case WS_READ_NILLABLE_POINTER:
     {
         double *heap_val = NULL;
         if (size != sizeof(heap_val)) return E_INVALIDARG;
@@ -3314,6 +3354,7 @@ static HRESULT read_type_wsz( struct reader *reader, WS_TYPE_MAPPING mapping,
         /* fall through */
 
     case WS_READ_OPTIONAL_POINTER:
+    case WS_READ_NILLABLE_POINTER:
         if (size != sizeof(str)) return E_INVALIDARG;
         *ret = str;
         break;
@@ -3359,6 +3400,9 @@ static HRESULT read_type_enum( struct reader *reader, WS_TYPE_MAPPING mapping,
     {
     case WS_READ_REQUIRED_VALUE:
         if (!found) return WS_E_INVALID_FORMAT;
+        /* fall through */
+
+    case WS_READ_NILLABLE_VALUE:
         if (size != sizeof(int)) return E_INVALIDARG;
         *(int *)ret = val;
         break;
@@ -3368,6 +3412,7 @@ static HRESULT read_type_enum( struct reader *reader, WS_TYPE_MAPPING mapping,
         /* fall through */
 
     case WS_READ_OPTIONAL_POINTER:
+    case WS_READ_NILLABLE_POINTER:
     {
         int *heap_val = NULL;
         if (size != sizeof(heap_val)) return E_INVALIDARG;
@@ -3406,6 +3451,9 @@ static HRESULT read_type_datetime( struct reader *reader, WS_TYPE_MAPPING mappin
     {
     case WS_READ_REQUIRED_VALUE:
         if (!found) return WS_E_INVALID_FORMAT;
+        /* fall through */
+
+    case WS_READ_NILLABLE_VALUE:
         if (size != sizeof(WS_DATETIME)) return E_INVALIDARG;
         *(WS_DATETIME *)ret = val;
         break;
@@ -3415,6 +3463,7 @@ static HRESULT read_type_datetime( struct reader *reader, WS_TYPE_MAPPING mappin
         /* fall through */
 
     case WS_READ_OPTIONAL_POINTER:
+    case WS_READ_NILLABLE_POINTER:
     {
         WS_DATETIME *heap_val = NULL;
         if (size != sizeof(heap_val)) return E_INVALIDARG;
@@ -3440,7 +3489,7 @@ static HRESULT read_type_guid( struct reader *reader, WS_TYPE_MAPPING mapping,
                                WS_HEAP *heap, void *ret, ULONG size )
 {
     WS_XML_UTF8_TEXT *utf8;
-    GUID val;
+    GUID val = {0};
     HRESULT hr;
     BOOL found;
 
@@ -3453,6 +3502,9 @@ static HRESULT read_type_guid( struct reader *reader, WS_TYPE_MAPPING mapping,
     {
     case WS_READ_REQUIRED_VALUE:
         if (!found) return WS_E_INVALID_FORMAT;
+        /* fall through */
+
+    case WS_READ_NILLABLE_VALUE:
         if (size != sizeof(GUID)) return E_INVALIDARG;
         *(GUID *)ret = val;
         break;
@@ -3462,6 +3514,7 @@ static HRESULT read_type_guid( struct reader *reader, WS_TYPE_MAPPING mapping,
         /* fall through */
 
     case WS_READ_OPTIONAL_POINTER:
+    case WS_READ_NILLABLE_POINTER:
     {
         GUID *heap_val = NULL;
         if (size != sizeof(heap_val)) return E_INVALIDARG;
@@ -3604,8 +3657,15 @@ ULONG get_type_size( WS_TYPE type, const WS_STRUCT_DESCRIPTION *desc )
     }
 }
 
-static WS_READ_OPTION get_array_read_option( WS_TYPE type )
+static WS_READ_OPTION get_field_read_option( WS_TYPE type, ULONG options )
 {
+    if (options & WS_FIELD_POINTER)
+    {
+        if (options & WS_FIELD_NILLABLE) return WS_READ_NILLABLE_POINTER;
+        if (options & WS_FIELD_OPTIONAL) return WS_READ_OPTIONAL_POINTER;
+        return WS_READ_REQUIRED_POINTER;
+    }
+
     switch (type)
     {
     case WS_BOOL_TYPE:
@@ -3619,12 +3679,15 @@ static WS_READ_OPTION get_array_read_option( WS_TYPE type )
     case WS_UINT64_TYPE:
     case WS_DOUBLE_TYPE:
     case WS_ENUM_TYPE:
-    case WS_STRUCT_TYPE:
     case WS_DATETIME_TYPE:
     case WS_GUID_TYPE:
+    case WS_STRUCT_TYPE:
+        if (options & (WS_FIELD_OPTIONAL|WS_FIELD_NILLABLE)) return WS_READ_NILLABLE_VALUE;
         return WS_READ_REQUIRED_VALUE;
 
     case WS_WSZ_TYPE:
+        if (options & WS_FIELD_NILLABLE) return WS_READ_NILLABLE_POINTER;
+        if (options & WS_FIELD_OPTIONAL) return WS_READ_OPTIONAL_POINTER;
         return WS_READ_REQUIRED_POINTER;
 
     default:
@@ -3638,20 +3701,20 @@ static HRESULT read_type( struct reader *, WS_TYPE_MAPPING, WS_TYPE, const WS_XM
                           void *, ULONG );
 
 static HRESULT read_type_repeating_element( struct reader *reader, const WS_FIELD_DESCRIPTION *desc,
-                                            WS_HEAP *heap, void **ret, ULONG size, ULONG *count )
+                                            WS_HEAP *heap, void **ret, ULONG *count )
 {
     HRESULT hr;
     ULONG item_size, nb_items = 0, nb_allocated = 1, offset = 0;
     WS_READ_OPTION option;
     char *buf;
 
-    if (size != sizeof(void *) || !(option = get_array_read_option( desc->type ))) return E_INVALIDARG;
+    if (!(option = get_field_read_option( desc->type, desc->options ))) return E_INVALIDARG;
 
     /* wrapper element */
     if (desc->localName && ((hr = read_type_next_element_node( reader, desc->localName, desc->ns )) != S_OK))
         return hr;
 
-    if (option == WS_READ_REQUIRED_VALUE)
+    if (option == WS_READ_REQUIRED_VALUE || option == WS_READ_NILLABLE_VALUE)
         item_size = get_type_size( desc->type, desc->typeDescription );
     else
         item_size = sizeof(void *);
@@ -3710,35 +3773,6 @@ static HRESULT read_type_text( struct reader *reader, const WS_FIELD_DESCRIPTION
                       desc->typeDescription, option, heap, ret, size );
 }
 
-static WS_READ_OPTION get_field_read_option( WS_TYPE type )
-{
-    switch (type)
-    {
-    case WS_BOOL_TYPE:
-    case WS_INT8_TYPE:
-    case WS_INT16_TYPE:
-    case WS_INT32_TYPE:
-    case WS_INT64_TYPE:
-    case WS_UINT8_TYPE:
-    case WS_UINT16_TYPE:
-    case WS_UINT32_TYPE:
-    case WS_UINT64_TYPE:
-    case WS_DOUBLE_TYPE:
-    case WS_ENUM_TYPE:
-    case WS_DATETIME_TYPE:
-    case WS_GUID_TYPE:
-        return WS_READ_REQUIRED_VALUE;
-
-    case WS_WSZ_TYPE:
-    case WS_STRUCT_TYPE:
-        return WS_READ_REQUIRED_POINTER;
-
-    default:
-        FIXME( "unhandled type %u\n", type );
-        return 0;
-    }
-}
-
 static HRESULT read_type_struct_field( struct reader *reader, const WS_FIELD_DESCRIPTION *desc,
                                        WS_HEAP *heap, char *buf )
 {
@@ -3748,14 +3782,14 @@ static HRESULT read_type_struct_field( struct reader *reader, const WS_FIELD_DES
     HRESULT hr;
 
     if (!desc) return E_INVALIDARG;
-    if (desc->options & ~(WS_FIELD_POINTER | WS_FIELD_OPTIONAL))
+    if (desc->options & ~(WS_FIELD_POINTER|WS_FIELD_OPTIONAL|WS_FIELD_NILLABLE|WS_FIELD_NILLABLE_ITEM))
     {
         FIXME( "options %08x not supported\n", desc->options );
         return E_NOTIMPL;
     }
-    if (!(option = get_field_read_option( desc->type ))) return E_INVALIDARG;
+    if (!(option = get_field_read_option( desc->type, desc->options ))) return E_INVALIDARG;
 
-    if (option == WS_READ_REQUIRED_VALUE)
+    if (option == WS_READ_REQUIRED_VALUE || option == WS_READ_NILLABLE_VALUE)
         size = get_type_size( desc->type, desc->typeDescription );
     else
         size = sizeof(void *);
@@ -3776,7 +3810,7 @@ static HRESULT read_type_struct_field( struct reader *reader, const WS_FIELD_DES
     case WS_REPEATING_ELEMENT_FIELD_MAPPING:
     {
         ULONG count;
-        hr = read_type_repeating_element( reader, desc, heap, (void **)ptr, size, &count );
+        hr = read_type_repeating_element( reader, desc, heap, (void **)ptr, &count );
         if (hr == S_OK) *(ULONG *)(buf + desc->countOffset) = count;
         break;
     }
@@ -3789,16 +3823,20 @@ static HRESULT read_type_struct_field( struct reader *reader, const WS_FIELD_DES
         return E_NOTIMPL;
     }
 
-    if (hr == WS_E_INVALID_FORMAT && desc->options & WS_FIELD_OPTIONAL)
+    if (hr == WS_E_INVALID_FORMAT)
     {
         switch (option)
         {
         case WS_READ_REQUIRED_VALUE:
+        case WS_READ_REQUIRED_POINTER:
+            return WS_E_INVALID_FORMAT;
+
+        case WS_READ_NILLABLE_VALUE:
             if (desc->defaultValue) memcpy( ptr, desc->defaultValue->value, desc->defaultValue->valueSize );
-            else memset( ptr, 0, size );
             return S_OK;
 
-        case WS_READ_REQUIRED_POINTER:
+        case WS_READ_OPTIONAL_POINTER:
+        case WS_READ_NILLABLE_POINTER:
             *(void **)ptr = NULL;
             return S_OK;
 
@@ -3827,11 +3865,13 @@ static HRESULT read_type_struct( struct reader *reader, WS_TYPE_MAPPING mapping,
     {
     case WS_READ_REQUIRED_POINTER:
     case WS_READ_OPTIONAL_POINTER:
+    case WS_READ_NILLABLE_POINTER:
         if (size != sizeof(void *)) return E_INVALIDARG;
         if (!(buf = ws_alloc_zero( heap, desc->size ))) return WS_E_QUOTA_EXCEEDED;
         break;
 
     case WS_READ_REQUIRED_VALUE:
+    case WS_READ_NILLABLE_VALUE:
         if (size != desc->size) return E_INVALIDARG;
         buf = ret;
         break;
@@ -3859,7 +3899,8 @@ static HRESULT read_type_struct( struct reader *reader, WS_TYPE_MAPPING mapping,
         return S_OK;
 
     case WS_READ_OPTIONAL_POINTER:
-        if (hr != S_OK)
+    case WS_READ_NILLABLE_POINTER:
+        if (is_nil_value( buf, desc->size ))
         {
             ws_free( heap, buf );
             buf = NULL;
@@ -3868,6 +3909,7 @@ static HRESULT read_type_struct( struct reader *reader, WS_TYPE_MAPPING mapping,
         return S_OK;
 
     case WS_READ_REQUIRED_VALUE:
+    case WS_READ_NILLABLE_VALUE:
         return hr;
 
     default:
diff --git a/dlls/webservices/tests/reader.c b/dlls/webservices/tests/reader.c
index e57fc0c..e8ac6b8 100644
--- a/dlls/webservices/tests/reader.c
+++ b/dlls/webservices/tests/reader.c
@@ -268,17 +268,13 @@ static void test_WsCreateHeap(void)
 
 static HRESULT set_input( WS_XML_READER *reader, const char *data, ULONG size )
 {
-    WS_XML_READER_TEXT_ENCODING encoding;
-    WS_XML_READER_BUFFER_INPUT input;
-
-    encoding.encoding.encodingType = WS_XML_READER_ENCODING_TYPE_TEXT;
-    encoding.charSet               = WS_CHARSET_AUTO;
-
-    input.input.inputType = WS_XML_READER_INPUT_TYPE_BUFFER;
-    input.encodedData     = (void *)data;
-    input.encodedDataSize = size;
+    WS_XML_READER_TEXT_ENCODING text = {{WS_XML_READER_ENCODING_TYPE_TEXT}, WS_CHARSET_AUTO};
+    WS_XML_READER_BUFFER_INPUT buf;
 
-    return WsSetInput( reader, &encoding.encoding, &input.input, NULL, 0, NULL );
+    buf.input.inputType = WS_XML_READER_INPUT_TYPE_BUFFER;
+    buf.encodedData     = (void *)data;
+    buf.encodedDataSize = size;
+    return WsSetInput( reader, &text.encoding, &buf.input, NULL, 0, NULL );
 }
 
 static void test_WsCreateReader(void)
@@ -291,11 +287,11 @@ static void test_WsCreateReader(void)
     ULONGLONG row, column;
     WS_CHARSET charset;
 
-    hr = WsCreateReader( NULL, 0, NULL, NULL ) ;
+    hr = WsCreateReader( NULL, 0, NULL, NULL );
     ok( hr == E_INVALIDARG, "got %08x\n", hr );
 
     reader = NULL;
-    hr = WsCreateReader( NULL, 0, &reader, NULL ) ;
+    hr = WsCreateReader( NULL, 0, &reader, NULL );
     ok( hr == S_OK, "got %08x\n", hr );
     ok( reader != NULL, "reader not set\n" );
 
@@ -345,7 +341,7 @@ static void test_WsCreateReader(void)
     todo_wine ok( hr == E_INVALIDARG, "got %08x\n", hr );
     WsFreeReader( reader );
 
-    hr = WsCreateReader( NULL, 0, &reader, NULL ) ;
+    hr = WsCreateReader( NULL, 0, &reader, NULL );
     ok( hr == S_OK, "got %08x\n", hr );
 
     hr = set_input( reader, data1, sizeof(data1) - 1 );
@@ -356,7 +352,7 @@ static void test_WsCreateReader(void)
     todo_wine ok( hr == E_INVALIDARG, "got %08x\n", hr );
     WsFreeReader( reader );
 
-    hr = WsCreateReader( NULL, 0, &reader, NULL ) ;
+    hr = WsCreateReader( NULL, 0, &reader, NULL );
     ok( hr == S_OK, "got %08x\n", hr );
 
     hr = set_input( reader, data1, sizeof(data1) - 1 );
@@ -374,7 +370,7 @@ static void test_WsCreateReader(void)
     prop.id = WS_XML_READER_PROPERTY_MAX_DEPTH;
     prop.value = &max_depth;
     prop.valueSize = sizeof(max_depth);
-    hr = WsCreateReader( &prop, 1, &reader, NULL ) ;
+    hr = WsCreateReader( &prop, 1, &reader, NULL );
     ok( hr == S_OK, "got %08x\n", hr );
 
     hr = set_input( reader, data1, sizeof(data1) - 1 );
@@ -392,21 +388,21 @@ static void test_WsCreateReader(void)
     prop.id = WS_XML_READER_PROPERTY_ROW;
     prop.value = &row;
     prop.valueSize = sizeof(row);
-    hr = WsCreateReader( &prop, 1, &reader, NULL ) ;
+    hr = WsCreateReader( &prop, 1, &reader, NULL );
     ok( hr == E_INVALIDARG, "got %08x\n", hr );
 
     column = 1;
     prop.id = WS_XML_READER_PROPERTY_COLUMN;
     prop.value = &column;
     prop.valueSize = sizeof(column);
-    hr = WsCreateReader( &prop, 1, &reader, NULL ) ;
+    hr = WsCreateReader( &prop, 1, &reader, NULL );
     ok( hr == E_INVALIDARG, "got %08x\n", hr );
 
     in_attr = TRUE;
     prop.id = WS_XML_READER_PROPERTY_IN_ATTRIBUTE;
     prop.value = &in_attr;
     prop.valueSize = sizeof(in_attr);
-    hr = WsCreateReader( &prop, 1, &reader, NULL ) ;
+    hr = WsCreateReader( &prop, 1, &reader, NULL );
     ok( hr == E_INVALIDARG, "got %08x\n", hr );
 }
 
@@ -480,7 +476,7 @@ static void test_WsSetInput(void)
         { test23, sizeof(test23), WS_E_INVALID_FORMAT, 0, 1 },
     };
 
-    hr = WsCreateReader( NULL, 0, &reader, NULL ) ;
+    hr = WsCreateReader( NULL, 0, &reader, NULL );
     ok( hr == S_OK, "got %08x\n", hr );
 
     hr = WsSetInput( NULL, NULL, NULL, NULL, 0, NULL );
@@ -563,7 +559,7 @@ static void test_WsSetInputToBuffer(void)
     const WS_XML_NODE *node;
     ULONG size, max_depth;
 
-    hr = WsCreateReader( NULL, 0, &reader, NULL ) ;
+    hr = WsCreateReader( NULL, 0, &reader, NULL );
     ok( hr == S_OK, "got %08x\n", hr );
 
     hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
@@ -622,7 +618,7 @@ static void test_WsFillReader(void)
     const WS_XML_NODE *node;
 
     /* what happens of we don't call WsFillReader? */
-    hr = WsCreateReader( NULL, 0, &reader, NULL ) ;
+    hr = WsCreateReader( NULL, 0, &reader, NULL );
     ok( hr == S_OK, "got %08x\n", hr );
 
     node = NULL;
@@ -647,7 +643,7 @@ static void test_WsFillReader(void)
     if (node) ok( node->nodeType == WS_XML_NODE_TYPE_EOF, "got %u\n", node->nodeType );
     WsFreeReader( reader );
 
-    hr = WsCreateReader( NULL, 0, &reader, NULL ) ;
+    hr = WsCreateReader( NULL, 0, &reader, NULL );
     ok( hr == S_OK, "got %08x\n", hr );
 
     hr = set_input( reader, data1, sizeof(data1) - 1 );
@@ -693,7 +689,7 @@ static void test_WsReadToStartElement(void)
     const WS_XML_NODE *node, *node2;
     int found;
 
-    hr = WsCreateReader( NULL, 0, &reader, NULL ) ;
+    hr = WsCreateReader( NULL, 0, &reader, NULL );
     ok( hr == S_OK, "got %08x\n", hr );
 
     hr = set_input( reader, data1, sizeof(data1) - 1 );
@@ -820,7 +816,7 @@ static void test_WsReadStartElement(void)
     const WS_XML_NODE *node, *node2;
     int found;
 
-    hr = WsCreateReader( NULL, 0, &reader, NULL ) ;
+    hr = WsCreateReader( NULL, 0, &reader, NULL );
     ok( hr == S_OK, "got %08x\n", hr );
 
     hr = set_input( reader, data2, sizeof(data2) - 1 );
@@ -946,7 +942,7 @@ static void test_WsReadEndElement(void)
     const WS_XML_NODE *node;
     int found;
 
-    hr = WsCreateReader( NULL, 0, &reader, NULL ) ;
+    hr = WsCreateReader( NULL, 0, &reader, NULL );
     ok( hr == S_OK, "got %08x\n", hr );
 
     hr = set_input( reader, data2, sizeof(data2) - 1 );
@@ -1178,7 +1174,7 @@ static void test_WsReadNode(void)
         { str17, S_OK, WS_XML_NODE_TYPE_COMMENT },
     };
 
-    hr = WsCreateReader( NULL, 0, &reader, NULL ) ;
+    hr = WsCreateReader( NULL, 0, &reader, NULL );
     ok( hr == S_OK, "got %08x\n", hr );
 
     for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
@@ -1347,7 +1343,7 @@ static void test_WsReadType(void)
     hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
     ok( hr == S_OK, "got %08x\n", hr );
 
-    hr = WsCreateReader( NULL, 0, &reader, NULL ) ;
+    hr = WsCreateReader( NULL, 0, &reader, NULL );
     ok( hr == S_OK, "got %08x\n", hr );
 
     prepare_type_test( reader, data2, sizeof(data2) - 1 );
@@ -1630,7 +1626,7 @@ static void test_WsGetXmlAttribute(void)
     hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
     ok( hr == S_OK, "got %08x\n", hr );
 
-    hr = WsCreateReader( NULL, 0, &reader, NULL ) ;
+    hr = WsCreateReader( NULL, 0, &reader, NULL );
     ok( hr == S_OK, "got %08x\n", hr );
 
     hr = set_input( reader, data9, sizeof(data9) - 1 );
@@ -1757,7 +1753,7 @@ static void test_WsMoveReader(void)
     WS_XML_ELEMENT_NODE *elem;
     WS_XML_UTF8_TEXT utf8;
 
-    hr = WsCreateReader( NULL, 0, &reader, NULL ) ;
+    hr = WsCreateReader( NULL, 0, &reader, NULL );
     ok( hr == S_OK, "got %08x\n", hr );
 
     hr = WsMoveReader( NULL, WS_MOVE_TO_EOF, NULL, NULL );
@@ -1780,7 +1776,7 @@ static void test_WsMoveReader(void)
     hr = WsCreateXmlBuffer( heap, NULL, 0, &buffer, NULL );
     ok( hr == S_OK, "got %08x\n", hr );
 
-    hr = WsCreateWriter( NULL, 0, &writer, NULL ) ;
+    hr = WsCreateWriter( NULL, 0, &writer, NULL );
     ok( hr == S_OK, "got %08x\n", hr );
 
     hr = WsSetOutputToBuffer( writer, buffer, NULL, 0, NULL );
@@ -1799,7 +1795,7 @@ static void test_WsMoveReader(void)
     hr = WsWriteEndElement( writer, NULL );
     ok( hr == S_OK, "got %08x\n", hr );
 
-    hr = WsCreateReader( NULL, 0, &reader, NULL ) ;
+    hr = WsCreateReader( NULL, 0, &reader, NULL );
     ok( hr == S_OK, "got %08x\n", hr );
 
     hr = WsMoveReader( reader, WS_MOVE_TO_EOF, NULL, NULL );
@@ -1923,7 +1919,7 @@ static void test_WsMoveReader(void)
     hr = WsCreateXmlBuffer( heap, NULL, 0, &buffer, NULL );
     ok( hr == S_OK, "got %08x\n", hr );
 
-    hr = WsCreateWriter( NULL, 0, &writer, NULL ) ;
+    hr = WsCreateWriter( NULL, 0, &writer, NULL );
     ok( hr == S_OK, "got %08x\n", hr );
 
     hr = WsSetOutputToBuffer( writer, buffer, NULL, 0, NULL );
@@ -2023,7 +2019,7 @@ static void test_simple_struct_type(void)
     hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
     ok( hr == S_OK, "got %08x\n", hr );
 
-    hr = WsCreateReader( NULL, 0, &reader, NULL ) ;
+    hr = WsCreateReader( NULL, 0, &reader, NULL );
     ok( hr == S_OK, "got %08x\n", hr );
 
     prepare_struct_type_test( reader, "<str>test</str>" );
@@ -2164,7 +2160,7 @@ static void test_cdata(void)
     WS_XML_READER *reader;
     const WS_XML_NODE *node;
 
-    hr = WsCreateReader( NULL, 0, &reader, NULL ) ;
+    hr = WsCreateReader( NULL, 0, &reader, NULL );
     ok( hr == S_OK, "got %08x\n", hr );
 
     hr = set_input( reader, test, sizeof(test) - 1 );
@@ -2232,7 +2228,7 @@ static void test_WsFindAttribute(void)
     ULONG index;
     HRESULT hr;
 
-    hr = WsCreateReader( NULL, 0, &reader, NULL ) ;
+    hr = WsCreateReader( NULL, 0, &reader, NULL );
     ok( hr == S_OK, "got %08x\n", hr );
 
     hr = set_input( reader, test, sizeof(test) - 1 );
@@ -2331,7 +2327,7 @@ static void test_WsGetNamespaceFromPrefix(void)
     WS_XML_READER *reader;
     HRESULT hr;
 
-    hr = WsCreateReader( NULL, 0, &reader, NULL ) ;
+    hr = WsCreateReader( NULL, 0, &reader, NULL );
     ok( hr == S_OK, "got %08x\n", hr );
 
     hr = WsGetNamespaceFromPrefix( NULL, NULL, FALSE, NULL, NULL );
@@ -2629,7 +2625,7 @@ static void test_text_field_mapping(void)
     hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
     ok( hr == S_OK, "got %08x\n", hr );
 
-    hr = WsCreateReader( NULL, 0, &reader, NULL ) ;
+    hr = WsCreateReader( NULL, 0, &reader, NULL );
     ok( hr == S_OK, "got %08x\n", hr );
 
     prepare_struct_type_test( reader, "<a>test</a>" );
@@ -2693,7 +2689,7 @@ static void test_complex_struct_type(void)
     hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
     ok( hr == S_OK, "got %08x\n", hr );
 
-    hr = WsCreateReader( NULL, 0, &reader, NULL ) ;
+    hr = WsCreateReader( NULL, 0, &reader, NULL );
     ok( hr == S_OK, "got %08x\n", hr );
 
     /* element content type mapping */
@@ -2839,7 +2835,7 @@ static void test_repeating_element(void)
     hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
     ok( hr == S_OK, "got %08x\n", hr );
 
-    hr = WsCreateReader( NULL, 0, &reader, NULL ) ;
+    hr = WsCreateReader( NULL, 0, &reader, NULL );
     ok( hr == S_OK, "got %08x\n", hr );
 
     prepare_struct_type_test( reader, data12 );
@@ -3098,7 +3094,7 @@ static void test_datetime(void)
     hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
     ok( hr == S_OK, "got %08x\n", hr );
 
-    hr = WsCreateReader( NULL, 0, &reader, NULL ) ;
+    hr = WsCreateReader( NULL, 0, &reader, NULL );
     ok( hr == S_OK, "got %08x\n", hr );
     for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
     {
@@ -3287,7 +3283,7 @@ static void test_double(void)
     hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
     ok( hr == S_OK, "got %08x\n", hr );
 
-    hr = WsCreateReader( NULL, 0, &reader, NULL ) ;
+    hr = WsCreateReader( NULL, 0, &reader, NULL );
     ok( hr == S_OK, "got %08x\n", hr );
 
     for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
@@ -3312,7 +3308,7 @@ static void test_WsReadElement(void)
     WS_ELEMENT_DESCRIPTION desc;
     UINT32 val;
 
-    hr = WsCreateReader( NULL, 0, &reader, NULL ) ;
+    hr = WsCreateReader( NULL, 0, &reader, NULL );
     ok( hr == S_OK, "got %08x\n", hr );
 
     desc.elementLocalName = &localname;
@@ -3347,7 +3343,7 @@ static void test_WsReadValue(void)
     WS_XML_READER *reader;
     UINT32 val;
 
-    hr = WsCreateReader( NULL, 0, &reader, NULL ) ;
+    hr = WsCreateReader( NULL, 0, &reader, NULL );
     ok( hr == S_OK, "got %08x\n", hr );
 
     prepare_struct_type_test( reader, "<t>1</t>" );
@@ -3463,7 +3459,7 @@ static void test_WsGetReaderPosition(void)
     hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
     ok( hr == S_OK, "got %08x\n", hr );
 
-    hr = WsCreateReader( NULL, 0, &reader, NULL ) ;
+    hr = WsCreateReader( NULL, 0, &reader, NULL );
     ok( hr == S_OK, "got %08x\n", hr );
 
     /* reader must be set to an XML buffer */
@@ -3509,7 +3505,7 @@ static void test_WsSetReaderPosition(void)
     hr = WsSetReaderPosition( NULL, NULL, NULL );
     ok( hr == E_INVALIDARG, "got %08x\n", hr );
 
-    hr = WsCreateReader( NULL, 0, &reader, NULL ) ;
+    hr = WsCreateReader( NULL, 0, &reader, NULL );
     ok( hr == S_OK, "got %08x\n", hr );
 
     hr = WsCreateXmlBuffer( heap, NULL, 0, &buf1, NULL );
@@ -3617,7 +3613,7 @@ static void test_entities(void)
     const WS_XML_UTF8_TEXT *utf8;
     ULONG i;
 
-    hr = WsCreateReader( NULL, 0, &reader, NULL ) ;
+    hr = WsCreateReader( NULL, 0, &reader, NULL );
     ok( hr == S_OK, "got %08x\n", hr );
 
     for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
@@ -3656,6 +3652,114 @@ static void test_entities(void)
     WsFreeReader( reader );
 }
 
+static void test_field_options(void)
+{
+    static const char xml[] =
+        "<t xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\"><wsz i:nil=\"true\"/>"
+        "<s i:nil=\"true\"/></t>";
+    static const GUID guid_null = {0};
+    HRESULT hr;
+    WS_HEAP *heap;
+    WS_XML_READER *reader;
+    WS_STRUCT_DESCRIPTION s, s2;
+    WS_FIELD_DESCRIPTION f, f2, f3, f4, f5, *fields[4], *fields2[1];
+    WS_XML_STRING ns = {0, NULL}, str_wsz = {3, (BYTE *)"wsz"}, str_s = {1, (BYTE *)"s"};
+    WS_XML_STRING str_int32 = {5, (BYTE *)"int32"}, str_guid = {4, (BYTE *)"guid"};
+    WS_DEFAULT_VALUE def_val;
+    INT32 val_int32;
+    struct s
+    {
+        INT32 int32;
+    };
+    struct test
+    {
+        WCHAR    *wsz;
+        struct s *s;
+        INT32     int32;
+        GUID      guid;
+    } *test;
+
+    hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
+
+    hr = WsCreateReader( NULL, 0, &reader, NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
+
+    hr = set_input( reader, xml, sizeof(xml) - 1 );
+    ok( hr == S_OK, "got %08x\n", hr );
+
+    memset( &f, 0, sizeof(f) );
+    f.mapping   = WS_ELEMENT_FIELD_MAPPING;
+    f.localName = &str_wsz;
+    f.ns        = &ns;
+    f.type      = WS_WSZ_TYPE;
+    f.options   = WS_FIELD_OPTIONAL|WS_FIELD_NILLABLE;
+    fields[0] = &f;
+
+    memset( &f3, 0, sizeof(f3) );
+    f3.mapping   = WS_ELEMENT_FIELD_MAPPING;
+    f3.localName = &str_int32;
+    f3.ns        = &ns;
+    f3.type      = WS_INT32_TYPE;
+    fields2[0] = &f3;
+
+    memset( &s2, 0, sizeof(s2) );
+    s2.size       = sizeof(struct s);
+    s2.alignment  = TYPE_ALIGNMENT(struct s);
+    s2.fields     = fields2;
+    s2.fieldCount = 1;
+
+    memset( &f2, 0, sizeof(f2) );
+    f2.mapping         = WS_ELEMENT_FIELD_MAPPING;
+    f2.localName       = &str_s;
+    f2.ns              = &ns;
+    f2.type            = WS_STRUCT_TYPE;
+    f2.typeDescription = &s2;
+    f2.offset          = FIELD_OFFSET(struct test, s);
+    f2.options         = WS_FIELD_POINTER|WS_FIELD_OPTIONAL|WS_FIELD_NILLABLE;
+    fields[1] = &f2;
+
+    val_int32 = -1;
+    def_val.value     = &val_int32;
+    def_val.valueSize = sizeof(val_int32);
+
+    memset( &f4, 0, sizeof(f4) );
+    f4.mapping      = WS_ELEMENT_FIELD_MAPPING;
+    f4.localName    = &str_int32;
+    f4.ns           = &ns;
+    f4.type         = WS_INT32_TYPE;
+    f4.offset       = FIELD_OFFSET(struct test, int32);
+    f4.options      = WS_FIELD_OPTIONAL;
+    f4.defaultValue = &def_val;
+    fields[2] = &f4;
+
+    memset( &f5, 0, sizeof(f5) );
+    f5.mapping      = WS_ELEMENT_FIELD_MAPPING;
+    f5.localName    = &str_guid;
+    f5.ns           = &ns;
+    f5.type         = WS_GUID_TYPE;
+    f5.offset       = FIELD_OFFSET(struct test, guid);
+    f5.options      = WS_FIELD_OPTIONAL;
+    fields[3] = &f5;
+
+    memset( &s, 0, sizeof(s) );
+    s.size       = sizeof(struct test);
+    s.alignment  = TYPE_ALIGNMENT(struct test);
+    s.fields     = fields;
+    s.fieldCount = 4;
+
+    hr = WsReadType( reader, WS_ELEMENT_CONTENT_TYPE_MAPPING, WS_STRUCT_TYPE, &s,
+                     WS_READ_REQUIRED_POINTER, heap, &test, sizeof(test), NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
+    ok( !test->wsz, "wsz is set\n" );
+    ok( !test->s, "s is set\n" );
+    ok( test->int32 == -1, "got %d\n", test->int32 );
+    ok( IsEqualGUID( &test->guid, &guid_null ), "wrong guid\n" );
+
+    WsFreeReader( reader );
+    WsFreeHeap( heap );
+}
+
 START_TEST(reader)
 {
     test_WsCreateError();
@@ -3691,4 +3795,5 @@ START_TEST(reader)
     test_WsGetReaderPosition();
     test_WsSetReaderPosition();
     test_entities();
+    test_field_options();
 }
diff --git a/dlls/webservices/webservices_private.h b/dlls/webservices/webservices_private.h
index a4d08f4..9da0e1f 100644
--- a/dlls/webservices/webservices_private.h
+++ b/dlls/webservices/webservices_private.h
@@ -105,6 +105,13 @@ void free_channel( struct channel * ) DECLSPEC_HIDDEN;
 HRESULT open_channel( struct channel *, const WS_ENDPOINT_ADDRESS * ) DECLSPEC_HIDDEN;
 HRESULT close_channel( struct channel * ) DECLSPEC_HIDDEN;
 
+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 inline void *heap_alloc( SIZE_T size )
 {
     return HeapAlloc( GetProcessHeap(), 0, size );
diff --git a/dlls/webservices/writer.c b/dlls/webservices/writer.c
index 8fe764e..3665613 100644
--- a/dlls/webservices/writer.c
+++ b/dlls/webservices/writer.c
@@ -1564,13 +1564,6 @@ 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"};
-- 
2.1.4




More information about the wine-patches mailing list