Hans Leidekker : webservices: Add support for repeating element field mappings in WsReadType.

Alexandre Julliard julliard at wine.codeweavers.com
Wed Mar 30 10:00:31 CDT 2016


Module: wine
Branch: master
Commit: b807964ec99728e3d0058fdf0872b97838abeb33
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=b807964ec99728e3d0058fdf0872b97838abeb33

Author: Hans Leidekker <hans at codeweavers.com>
Date:   Wed Mar 30 14:12:19 2016 +0200

webservices: Add support for repeating element field mappings in WsReadType.

Signed-off-by: Hans Leidekker <hans at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/webservices/reader.c       | 115 ++++++++++++++++++++++++++++++++++++++++
 dlls/webservices/tests/reader.c |  80 ++++++++++++++++++++++++++++
 2 files changed, 195 insertions(+)

diff --git a/dlls/webservices/reader.c b/dlls/webservices/reader.c
index 59fe8a1..b61c50c 100644
--- a/dlls/webservices/reader.c
+++ b/dlls/webservices/reader.c
@@ -176,6 +176,12 @@ void *ws_realloc( WS_HEAP *handle, void *ptr, SIZE_T size )
     return HeapReAlloc( heap->handle, 0, ptr, size );
 }
 
+static void *ws_realloc_zero( WS_HEAP *handle, void *ptr, SIZE_T size )
+{
+    struct heap *heap = (struct heap *)handle;
+    return HeapReAlloc( heap->handle, HEAP_ZERO_MEMORY, ptr, size );
+}
+
 void ws_free( WS_HEAP *handle, void *ptr )
 {
     struct heap *heap = (struct heap *)handle;
@@ -2528,10 +2534,112 @@ static HRESULT read_type_wsz( struct reader *reader, WS_TYPE_MAPPING mapping,
     return S_OK;
 }
 
+static ULONG get_type_size( WS_TYPE type, const WS_STRUCT_DESCRIPTION *desc )
+{
+    switch (type)
+    {
+    case WS_INT8_TYPE:
+    case WS_UINT8_TYPE:
+        return sizeof(INT8);
+
+    case WS_INT16_TYPE:
+    case WS_UINT16_TYPE:
+        return sizeof(INT16);
+
+    case WS_BOOL_TYPE:
+    case WS_INT32_TYPE:
+    case WS_UINT32_TYPE:
+        return sizeof(INT32);
+
+    case WS_INT64_TYPE:
+    case WS_UINT64_TYPE:
+        return sizeof(INT64);
+
+    case WS_WSZ_TYPE:
+        return sizeof(WCHAR *);
+
+    case WS_STRUCT_TYPE:
+        return desc->size;
+
+    default:
+        ERR( "unhandled type %u\n", type );
+        return 0;
+    }
+}
+
 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_READ_OPTION option, WS_HEAP *heap, void **ret,
+                                            ULONG size, ULONG *count )
+{
+    HRESULT hr;
+    ULONG item_size, nb_items = 0, nb_allocated = 1, offset = 0;
+    char *buf;
+
+    if (desc->itemRange)
+        FIXME( "ignoring range (%u-%u)\n", desc->itemRange->minItemCount, desc->itemRange->maxItemCount );
+
+    /* wrapper element */
+    if (desc->localName && ((hr = read_node( reader )) != S_OK)) return hr;
+
+    item_size = get_type_size( desc->type, desc->typeDescription );
+    if (!(buf = ws_alloc_zero( heap, item_size ))) return WS_E_QUOTA_EXCEEDED;
+    for (;;)
+    {
+        if (nb_items >= nb_allocated)
+        {
+            if (!(buf = ws_realloc_zero( heap, buf, nb_allocated * 2 * item_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, WS_READ_REQUIRED_VALUE, heap, buf + offset, item_size );
+        if (hr == WS_E_INVALID_FORMAT) break;
+        if (hr != S_OK)
+        {
+            ws_free( heap, buf );
+            return hr;
+        }
+        if ((hr = read_node( reader )) != S_OK)
+        {
+            ws_free( heap, buf );
+            return hr;
+        }
+        offset += item_size;
+        nb_items++;
+    }
+
+    if (desc->localName && ((hr = read_node( reader )) != S_OK)) return hr;
+
+    if (!nb_items)
+    {
+        ws_free( heap, buf );
+        buf = NULL;
+    }
+
+    switch (option)
+    {
+    case WS_READ_REQUIRED_POINTER:
+        if (!nb_items) return WS_E_INVALID_FORMAT;
+        /* fall through */
+
+    case WS_READ_OPTIONAL_POINTER:
+        if (size < sizeof(void *)) return E_INVALIDARG;
+        *ret = buf;
+        break;
+
+    default:
+        FIXME( "read option %u not supported\n", option );
+        return E_NOTIMPL;
+    }
+
+    *count = nb_items;
+    return S_OK;
+}
+
 static HRESULT read_type_text( struct reader *reader, const WS_FIELD_DESCRIPTION *desc,
                                WS_READ_OPTION option, WS_HEAP *heap, void *ret, ULONG size )
 {
@@ -2598,6 +2706,13 @@ static HRESULT read_type_struct_field( struct reader *reader, const WS_FIELD_DES
                         desc->typeDescription, option, heap, ptr, size );
         break;
 
+    case WS_REPEATING_ELEMENT_FIELD_MAPPING:
+    {
+        ULONG count;
+        hr = read_type_repeating_element( reader, desc, option, heap, (void **)ptr, size, &count );
+        if (hr == S_OK) *(ULONG *)(ptr + desc->countOffset) = count;
+        break;
+    }
     case WS_TEXT_FIELD_MAPPING:
         hr = read_type_text( reader, desc, option, heap, ptr, size );
         break;
diff --git a/dlls/webservices/tests/reader.c b/dlls/webservices/tests/reader.c
index 027b6f4..755a070 100644
--- a/dlls/webservices/tests/reader.c
+++ b/dlls/webservices/tests/reader.c
@@ -71,6 +71,12 @@ static const char data11[] =
     "</o:services>"
     "</o:OfficeConfig>";
 
+static const char data12[] =
+    "<services>"
+    "<service><id>1</id></service>"
+    "<service><id>2</id></service>"
+    "</services>";
+
 static void test_WsCreateError(void)
 {
     HRESULT hr;
@@ -2642,6 +2648,79 @@ static void test_complex_struct_type(void)
     WsFreeError( error );
 }
 
+static void test_repeating_element(void)
+{
+    WS_XML_STRING str_services = {8, (BYTE *)"services"};
+    WS_XML_STRING str_service = {7, (BYTE *)"service"};
+    WS_XML_STRING str_id = {2, (BYTE *)"id"};
+    WS_XML_STRING str_ns = {0, NULL};
+    HRESULT hr;
+    WS_XML_READER *reader;
+    WS_HEAP *heap;
+    WS_STRUCT_DESCRIPTION s, s2;
+    WS_FIELD_DESCRIPTION f, f2, *fields[1], *fields2[1];
+    struct service
+    {
+        UINT32 id;
+    };
+    struct services
+    {
+        struct service *service;
+        ULONG           service_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 );
+
+    prepare_struct_type_test( reader, data12 );
+
+    memset( &f2, 0, sizeof(f2) );
+    f2.mapping   = WS_ELEMENT_FIELD_MAPPING;
+    f2.localName = &str_id;
+    f2.ns        = &str_ns;
+    f2.type      = WS_UINT32_TYPE;
+    fields2[0]   = &f2;
+
+    memset( &s2, 0, sizeof(s2) );
+    s2.size          = sizeof(struct service);
+    s2.alignment     = TYPE_ALIGNMENT(struct service);
+    s2.fields        = fields2;
+    s2.fieldCount    = 1;
+    s2.typeLocalName = &str_service;
+
+    memset( &f, 0, sizeof(f) );
+    f.mapping         = WS_REPEATING_ELEMENT_FIELD_MAPPING;
+    f.countOffset     = FIELD_OFFSET(struct services, service_count);
+    f.type            = WS_STRUCT_TYPE;
+    f.typeDescription = &s2;
+    f.itemLocalName   = &str_service;
+    f.itemNs          = &str_ns;
+    fields[0] = &f;
+
+    memset( &s, 0, sizeof(s) );
+    s.size          = sizeof(struct services);
+    s.alignment     = TYPE_ALIGNMENT(struct services);
+    s.fields        = fields;
+    s.fieldCount    = 1;
+    s.typeLocalName = &str_services;
+
+    test = NULL;
+    hr = WsReadType( reader, WS_ELEMENT_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->service != NULL, "service not set\n" );
+    ok( test->service_count == 2, "got %u\n", test->service_count );
+    ok( test->service[0].id == 1, "got %u\n", test->service[0].id );
+    ok( test->service[1].id == 2, "got %u\n", test->service[1].id );
+
+    WsFreeReader( reader );
+    WsFreeHeap( heap );
+}
+
 START_TEST(reader)
 {
     test_WsCreateError();
@@ -2665,4 +2744,5 @@ START_TEST(reader)
     test_WsGetNamespaceFromPrefix();
     test_text_field_mapping();
     test_complex_struct_type();
+    test_repeating_element();
 }




More information about the wine-cvs mailing list