Commit b807964e authored by Hans Leidekker's avatar Hans Leidekker Committed by Alexandre Julliard

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

parent 56503007
...@@ -176,6 +176,12 @@ void *ws_realloc( WS_HEAP *handle, void *ptr, SIZE_T size ) ...@@ -176,6 +176,12 @@ void *ws_realloc( WS_HEAP *handle, void *ptr, SIZE_T size )
return HeapReAlloc( heap->handle, 0, ptr, 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 ) void ws_free( WS_HEAP *handle, void *ptr )
{ {
struct heap *heap = (struct heap *)handle; struct heap *heap = (struct heap *)handle;
...@@ -2528,10 +2534,112 @@ static HRESULT read_type_wsz( struct reader *reader, WS_TYPE_MAPPING mapping, ...@@ -2528,10 +2534,112 @@ static HRESULT read_type_wsz( struct reader *reader, WS_TYPE_MAPPING mapping,
return S_OK; 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 *, 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 *, const WS_XML_STRING *, const void *, WS_READ_OPTION, WS_HEAP *,
void *, ULONG ); 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, static HRESULT read_type_text( struct reader *reader, const WS_FIELD_DESCRIPTION *desc,
WS_READ_OPTION option, WS_HEAP *heap, void *ret, ULONG size ) 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 ...@@ -2598,6 +2706,13 @@ static HRESULT read_type_struct_field( struct reader *reader, const WS_FIELD_DES
desc->typeDescription, option, heap, ptr, size ); desc->typeDescription, option, heap, ptr, size );
break; 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: case WS_TEXT_FIELD_MAPPING:
hr = read_type_text( reader, desc, option, heap, ptr, size ); hr = read_type_text( reader, desc, option, heap, ptr, size );
break; break;
......
...@@ -71,6 +71,12 @@ static const char data11[] = ...@@ -71,6 +71,12 @@ static const char data11[] =
"</o:services>" "</o:services>"
"</o:OfficeConfig>"; "</o:OfficeConfig>";
static const char data12[] =
"<services>"
"<service><id>1</id></service>"
"<service><id>2</id></service>"
"</services>";
static void test_WsCreateError(void) static void test_WsCreateError(void)
{ {
HRESULT hr; HRESULT hr;
...@@ -2642,6 +2648,79 @@ static void test_complex_struct_type(void) ...@@ -2642,6 +2648,79 @@ static void test_complex_struct_type(void)
WsFreeError( error ); 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) START_TEST(reader)
{ {
test_WsCreateError(); test_WsCreateError();
...@@ -2665,4 +2744,5 @@ START_TEST(reader) ...@@ -2665,4 +2744,5 @@ START_TEST(reader)
test_WsGetNamespaceFromPrefix(); test_WsGetNamespaceFromPrefix();
test_text_field_mapping(); test_text_field_mapping();
test_complex_struct_type(); test_complex_struct_type();
test_repeating_element();
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment