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>
This commit is contained in:
parent
5650300786
commit
b807964ec9
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue