Module: wine Branch: master Commit: b807964ec99728e3d0058fdf0872b97838abeb33 URL: http://source.winehq.org/git/wine.git/?a=commit;h=b807964ec99728e3d0058fdf08...
Author: Hans Leidekker hans@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@codeweavers.com Signed-off-by: Alexandre Julliard julliard@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(); }