[7/7] webservices: Implement WS_REPEATING_ELEMENT_CHOICE_FIELD_MAPPING in the reader.

Hans Leidekker hans at codeweavers.com
Thu Sep 21 04:26:17 CDT 2017


Signed-off-by: Hans Leidekker <hans at codeweavers.com>
---
 dlls/webservices/reader.c       | 128 +++++++++++++++++-----------------
 dlls/webservices/tests/reader.c | 148 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 214 insertions(+), 62 deletions(-)

diff --git a/dlls/webservices/reader.c b/dlls/webservices/reader.c
index c2dbdb0298..d767d5ce1b 100644
--- a/dlls/webservices/reader.c
+++ b/dlls/webservices/reader.c
@@ -6091,12 +6091,65 @@ static WS_READ_OPTION get_field_read_option( WS_TYPE type, ULONG options )
     }
 }
 
+static HRESULT read_type_field( struct reader *, const WS_FIELD_DESCRIPTION *, WS_HEAP *, char *, ULONG );
+
+static HRESULT read_type_union( struct reader *reader, const WS_UNION_DESCRIPTION *desc, WS_READ_OPTION option,
+                                WS_HEAP *heap, void *ret, ULONG size )
+{
+    BOOL found = FALSE;
+    HRESULT hr;
+    ULONG i;
+
+    switch (option)
+    {
+    case WS_READ_REQUIRED_VALUE:
+    case WS_READ_NILLABLE_VALUE:
+        if (size != desc->size) return E_INVALIDARG;
+        break;
+
+    default:
+        return E_INVALIDARG;
+    }
+
+    if ((hr = read_type_next_node( reader )) != S_OK) return hr;
+    if (node_type( reader->current ) != WS_XML_NODE_TYPE_ELEMENT) return WS_E_INVALID_FORMAT;
+    for (i = 0; i < desc->fieldCount; i++)
+    {
+        if ((found = match_element( reader->current, desc->fields[i]->field.localName, desc->fields[i]->field.ns )))
+            break;
+    }
+
+    if (!found) *(int *)((char *)ret + desc->enumOffset) = desc->noneEnumValue;
+    else
+    {
+        ULONG offset = desc->fields[i]->field.offset;
+        if ((hr = read_type_field( reader, &desc->fields[i]->field, heap, ret, offset )) == S_OK)
+            *(int *)((char *)ret + desc->enumOffset) = desc->fields[i]->value;
+    }
+
+    switch (option)
+    {
+    case WS_READ_NILLABLE_VALUE:
+        if (!found) move_to_parent_element( &reader->current );
+        break;
+
+    case WS_READ_REQUIRED_VALUE:
+        if (!found) hr = WS_E_INVALID_FORMAT;
+        break;
+
+    default:
+        return E_INVALIDARG;
+    }
+
+    return hr;
+}
+
 static HRESULT read_type( struct reader *, WS_TYPE_MAPPING, WS_TYPE, const WS_XML_STRING *,
                           const WS_XML_STRING *, const void *, WS_READ_OPTION, WS_HEAP *,
                           void *, ULONG );
 
-static HRESULT read_type_repeating_element( struct reader *reader, const WS_FIELD_DESCRIPTION *desc,
-                                            WS_HEAP *heap, void **ret, ULONG *count )
+static HRESULT read_type_array( struct reader *reader, const WS_FIELD_DESCRIPTION *desc, WS_HEAP *heap,
+                                void **ret, ULONG *count )
 {
     HRESULT hr;
     ULONG item_size, nb_items = 0, nb_allocated = 1, offset = 0;
@@ -6120,12 +6173,16 @@ static HRESULT read_type_repeating_element( struct reader *reader, const WS_FIEL
         if (nb_items >= nb_allocated)
         {
             SIZE_T old_size = nb_allocated * item_size, new_size = old_size * 2;
-            if (!(buf = ws_realloc_zero( heap, buf, old_size, new_size )))
-                return WS_E_QUOTA_EXCEEDED;
+            if (!(buf = ws_realloc_zero( heap, buf, old_size, new_size ))) return WS_E_QUOTA_EXCEEDED;
             nb_allocated *= 2;
         }
-        hr = read_type( reader, WS_ELEMENT_TYPE_MAPPING, desc->type, desc->itemLocalName, desc->itemNs,
-                        desc->typeDescription, option, heap, buf + offset, item_size );
+
+        if (desc->type == WS_UNION_TYPE)
+            hr = read_type_union( reader, desc->typeDescription, option, heap, buf + offset, item_size );
+        else
+            hr = read_type( reader, WS_ELEMENT_TYPE_MAPPING, desc->type, desc->itemLocalName, desc->itemNs,
+                            desc->typeDescription, option, heap, buf + offset, item_size );
+
         if (hr == WS_E_INVALID_FORMAT) break;
         if (hr != S_OK)
         {
@@ -6169,60 +6226,6 @@ static HRESULT read_type_text( struct reader *reader, const WS_FIELD_DESCRIPTION
                       desc->typeDescription, option, heap, ret, size );
 }
 
-static HRESULT read_type_field( struct reader *, const WS_FIELD_DESCRIPTION *, WS_HEAP *, char *, ULONG );
-
-static HRESULT read_type_union( struct reader *reader, const WS_UNION_DESCRIPTION *desc, WS_READ_OPTION option,
-                                WS_HEAP *heap, void *ret, ULONG size )
-{
-    ULONG offset, i;
-    HRESULT hr = WS_E_INVALID_FORMAT;
-
-    switch (option)
-    {
-    case WS_READ_REQUIRED_VALUE:
-    case WS_READ_NILLABLE_VALUE:
-        if (size != desc->size) return E_INVALIDARG;
-        break;
-
-    default:
-        return E_INVALIDARG;
-    }
-
-    if ((hr = read_type_next_node( reader )) != S_OK) return hr;
-    if (node_type( reader->current ) != WS_XML_NODE_TYPE_ELEMENT) return WS_E_INVALID_FORMAT;
-    for (i = 0; i < desc->fieldCount; i++)
-    {
-        if (match_element( reader->current, desc->fields[i]->field.localName, desc->fields[i]->field.ns ))
-            break;
-    }
-    if (i == desc->fieldCount)
-    {
-        if (!move_to_parent_element( &reader->current )) return WS_E_INVALID_FORMAT;
-        *(int *)((char *)ret + desc->enumOffset) = desc->noneEnumValue;
-    }
-    else
-    {
-        offset = desc->fields[i]->field.offset;
-        if ((hr = read_type_field( reader, &desc->fields[i]->field, heap, ret, offset )) == S_OK)
-            *(int *)((char *)ret + desc->enumOffset) = desc->fields[i]->value;
-    }
-
-    switch (option)
-    {
-    case WS_READ_NILLABLE_VALUE:
-        break;
-
-    case WS_READ_REQUIRED_VALUE:
-        if (hr != S_OK) return hr;
-        break;
-
-    default:
-        return E_INVALIDARG;
-    }
-
-    return S_OK;
-}
-
 static HRESULT read_type_field( struct reader *reader, const WS_FIELD_DESCRIPTION *desc, WS_HEAP *heap, char *buf,
                                 ULONG offset )
 {
@@ -6268,9 +6271,10 @@ static HRESULT read_type_field( struct reader *reader, const WS_FIELD_DESCRIPTIO
         break;
 
     case WS_REPEATING_ELEMENT_FIELD_MAPPING:
+    case WS_REPEATING_ELEMENT_CHOICE_FIELD_MAPPING:
     {
         ULONG count;
-        hr = read_type_repeating_element( reader, desc, heap, (void **)ptr, &count );
+        hr = read_type_array( reader, desc, heap, (void **)ptr, &count );
         if (hr == S_OK) *(ULONG *)(buf + desc->countOffset) = count;
         break;
     }
@@ -7341,7 +7345,7 @@ static HRESULT read_param_array( struct reader *reader, const WS_FIELD_DESCRIPTI
                                  void **ret, ULONG *count )
 {
     if (!ret && !(ret = ws_alloc_zero( heap, sizeof(void **) ))) return WS_E_QUOTA_EXCEEDED;
-    return read_type_repeating_element( reader, desc, heap, ret, count );
+    return read_type_array( reader, desc, heap, ret, count );
 }
 
 static void set_array_len( const WS_PARAMETER_DESCRIPTION *params, ULONG count, ULONG index, ULONG len,
diff --git a/dlls/webservices/tests/reader.c b/dlls/webservices/tests/reader.c
index 0eaf350c13..fce34ed037 100644
--- a/dlls/webservices/tests/reader.c
+++ b/dlls/webservices/tests/reader.c
@@ -6128,6 +6128,9 @@ static void test_union_type(void)
     ok( test != NULL, "test not set\n" );
     ok( test->choice == CHOICE_A, "got %d\n", test->choice );
     ok( !lstrcmpW(test->value.a, testW), "got %s\n", wine_dbgstr_w(test->value.a) );
+    hr = WsGetReaderNode( reader, &node, NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
+    ok( node->nodeType == WS_XML_NODE_TYPE_EOF, "got %u\n", node->nodeType );
 
     test = NULL;
     prepare_struct_type_test( reader, "<b>123</b>" );
@@ -6142,6 +6145,9 @@ static void test_union_type(void)
     hr = WsReadType( reader, WS_ELEMENT_CONTENT_TYPE_MAPPING, WS_STRUCT_TYPE, &s,
                      WS_READ_REQUIRED_POINTER, heap, &test, sizeof(test), NULL );
     ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
+    hr = WsGetReaderNode( reader, &node, NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
+    ok( node->nodeType == WS_XML_NODE_TYPE_ELEMENT, "got %u\n", node->nodeType );
 
     f_struct.options = WS_FIELD_NILLABLE;
     hr = WsReadType( reader, WS_ELEMENT_CONTENT_TYPE_MAPPING, WS_STRUCT_TYPE, &s,
@@ -6262,6 +6268,147 @@ static void test_float(void)
     WsFreeHeap( heap );
 }
 
+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_READER *reader;
+    WS_HEAP *heap;
+    WS_UNION_DESCRIPTION u;
+    WS_UNION_FIELD_DESCRIPTION f, f2, *fields[2];
+    WS_FIELD_DESCRIPTION f_items, *fields_items[1];
+    WS_STRUCT_DESCRIPTION s;
+    const WS_XML_NODE *node;
+    enum choice {CHOICE_A, CHOICE_B, CHOICE_NONE};
+    struct item
+    {
+        enum choice choice;
+        union
+        {
+            WCHAR  *a;
+            UINT32  b;
+        } value;
+    };
+    struct test
+    {
+        struct item *items;
+        ULONG        count;
+    } *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 );
+
+    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;
+
+    test = NULL;
+    prepare_struct_type_test( reader, "<t><a>test</a></t>" );
+    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 != NULL, "test not set\n" );
+    ok( test->count == 1, "got %u\n", test->count );
+    ok( test->items[0].choice == CHOICE_A, "got %d\n", test->items[0].choice );
+    ok( !lstrcmpW(test->items[0].value.a, testW), "got %s\n", wine_dbgstr_w(test->items[0].value.a) );
+
+    test = NULL;
+    prepare_struct_type_test( reader, "<t><b>123</b></t>" );
+    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 != NULL, "test not set\n" );
+    ok( test->count == 1, "got %u\n", test->count );
+    ok( test->items[0].choice == CHOICE_B, "got %d\n", test->items[0].choice );
+    ok( test->items[0].value.b == 123, "got %u\n", test->items[0].value.b );
+
+    test = NULL;
+    prepare_struct_type_test( reader, "<t><a>test</a><b>123</b></t>" );
+    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 != NULL, "test not set\n" );
+    ok( test->count == 2, "got %u\n", test->count );
+    ok( test->items[0].choice == CHOICE_A, "got %d\n", test->items[0].choice );
+    ok( !lstrcmpW(test->items[0].value.a, testW), "got %s\n", wine_dbgstr_w(test->items[0].value.a) );
+    ok( test->items[1].choice == CHOICE_B, "got %d\n", test->items[1].choice );
+    ok( test->items[1].value.b == 123, "got %u\n", test->items[1].value.b );
+
+    prepare_struct_type_test( reader, "<t><c>123</c></t>" );
+    hr = WsReadType( reader, WS_ELEMENT_CONTENT_TYPE_MAPPING, WS_STRUCT_TYPE, &s,
+                     WS_READ_REQUIRED_POINTER, heap, &test, sizeof(test), NULL );
+    ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
+
+    hr = WsGetReaderNode( reader, &node, NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
+    todo_wine ok( node->nodeType == WS_XML_NODE_TYPE_ELEMENT, "got %u\n", node->nodeType );
+    if (node->nodeType == WS_XML_NODE_TYPE_ELEMENT)
+    {
+        const WS_XML_ELEMENT_NODE *elem = (const WS_XML_ELEMENT_NODE *)node;
+        ok( elem->localName->length == 1, "got %u\n", elem->localName->length );
+        ok( elem->localName->bytes[0] == 'c', "got '%c'\n", elem->localName->bytes[0] );
+    }
+
+    prepare_struct_type_test( reader, "<t></t>" );
+    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 != NULL, "test not set\n" );
+    ok( !test->count, "got %u\n", test->count );
+
+    hr = WsGetReaderNode( reader, &node, NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
+    ok( node->nodeType == WS_XML_NODE_TYPE_EOF, "got %u\n", node->nodeType );
+
+    WsFreeReader( reader );
+    WsFreeHeap( heap );
+}
+
+
 START_TEST(reader)
 {
     test_WsCreateError();
@@ -6309,4 +6456,5 @@ START_TEST(reader)
     test_WsReadXmlBuffer();
     test_union_type();
     test_float();
+    test_repeating_element_choice();
 }
-- 
2.11.0




More information about the wine-patches mailing list