webservices: Add support for union types in the reader.
Signed-off-by: Hans Leidekker <hans@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
c51ab4cd14
commit
c41e66fe01
|
@ -5168,6 +5168,7 @@ static WS_READ_OPTION get_field_read_option( WS_TYPE type, ULONG options )
|
|||
case WS_XML_QNAME_TYPE:
|
||||
case WS_STRUCT_TYPE:
|
||||
case WS_ENUM_TYPE:
|
||||
case WS_UNION_TYPE:
|
||||
if (options & (WS_FIELD_OPTIONAL|WS_FIELD_NILLABLE)) return WS_READ_NILLABLE_VALUE;
|
||||
return WS_READ_REQUIRED_VALUE;
|
||||
|
||||
|
@ -5261,8 +5262,63 @@ static HRESULT read_type_text( struct reader *reader, const WS_FIELD_DESCRIPTION
|
|||
desc->typeDescription, option, heap, ret, size );
|
||||
}
|
||||
|
||||
static HRESULT read_type_struct_field( struct reader *reader, const WS_FIELD_DESCRIPTION *desc,
|
||||
WS_HEAP *heap, char *buf, ULONG offset )
|
||||
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 )
|
||||
{
|
||||
char *ptr;
|
||||
WS_READ_OPTION option;
|
||||
|
@ -5299,6 +5355,12 @@ static HRESULT read_type_struct_field( struct reader *reader, const WS_FIELD_DES
|
|||
desc->typeDescription, option, heap, ptr, size );
|
||||
break;
|
||||
|
||||
case WS_ELEMENT_CHOICE_FIELD_MAPPING:
|
||||
if (desc->type != WS_UNION_TYPE || !desc->typeDescription ||
|
||||
(desc->options & (WS_FIELD_POINTER|WS_FIELD_NILLABLE))) return E_INVALIDARG;
|
||||
hr = read_type_union( reader, desc->typeDescription, option, heap, ptr, size );
|
||||
break;
|
||||
|
||||
case WS_REPEATING_ELEMENT_FIELD_MAPPING:
|
||||
{
|
||||
ULONG count;
|
||||
|
@ -5341,9 +5403,8 @@ static HRESULT read_type_struct_field( struct reader *reader, const WS_FIELD_DES
|
|||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT read_type_struct( struct reader *reader, WS_TYPE_MAPPING mapping,
|
||||
const WS_XML_STRING *localname, const WS_XML_STRING *ns,
|
||||
const WS_STRUCT_DESCRIPTION *desc, WS_READ_OPTION option,
|
||||
static HRESULT read_type_struct( struct reader *reader, WS_TYPE_MAPPING mapping, const WS_XML_STRING *localname,
|
||||
const WS_XML_STRING *ns, const WS_STRUCT_DESCRIPTION *desc, WS_READ_OPTION option,
|
||||
WS_HEAP *heap, void *ret, ULONG size )
|
||||
{
|
||||
ULONG i, offset;
|
||||
|
@ -5380,8 +5441,7 @@ static HRESULT read_type_struct( struct reader *reader, WS_TYPE_MAPPING mapping,
|
|||
for (i = 0; i < desc->fieldCount; i++)
|
||||
{
|
||||
offset = desc->fields[i]->offset;
|
||||
if ((hr = read_type_struct_field( reader, desc->fields[i], heap, buf, offset )) != S_OK)
|
||||
break;
|
||||
if ((hr = read_type_field( reader, desc->fields[i], heap, buf, offset )) != S_OK) break;
|
||||
}
|
||||
|
||||
switch (option)
|
||||
|
@ -6334,7 +6394,7 @@ static ULONG get_field_size( const WS_FIELD_DESCRIPTION *desc )
|
|||
static HRESULT read_param( struct reader *reader, const WS_FIELD_DESCRIPTION *desc, WS_HEAP *heap, void *ret )
|
||||
{
|
||||
if (!ret && !(ret = ws_alloc_zero( heap, get_field_size(desc) ))) return WS_E_QUOTA_EXCEEDED;
|
||||
return read_type_struct_field( reader, desc, heap, ret, 0 );
|
||||
return read_type_field( reader, desc, heap, ret, 0 );
|
||||
}
|
||||
|
||||
static HRESULT read_param_array( struct reader *reader, const WS_FIELD_DESCRIPTION *desc, WS_HEAP *heap,
|
||||
|
|
|
@ -2331,9 +2331,6 @@ static void prepare_struct_type_test( WS_XML_READER *reader, const char *data )
|
|||
|
||||
hr = set_input( reader, data, size );
|
||||
ok( hr == S_OK, "got %08x\n", hr );
|
||||
|
||||
hr = WsFillReader( reader, size, NULL, NULL );
|
||||
ok( hr == S_OK, "got %08x\n", hr );
|
||||
}
|
||||
|
||||
static void test_simple_struct_type(void)
|
||||
|
@ -5758,6 +5755,130 @@ static void test_WsReadXmlBuffer(void)
|
|||
WsFreeHeap( heap );
|
||||
}
|
||||
|
||||
static void test_union_type(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"};
|
||||
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_struct, *fields_struct[1];
|
||||
WS_STRUCT_DESCRIPTION s;
|
||||
const WS_XML_NODE *node;
|
||||
enum choice {CHOICE_A, CHOICE_B, CHOICE_NONE};
|
||||
struct test
|
||||
{
|
||||
enum choice choice;
|
||||
union
|
||||
{
|
||||
WCHAR *a;
|
||||
UINT32 b;
|
||||
} value;
|
||||
} *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 test, 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 test, value.b);
|
||||
fields[1] = &f2;
|
||||
|
||||
memset( &u, 0, sizeof(u) );
|
||||
u.size = sizeof(struct test);
|
||||
u.alignment = TYPE_ALIGNMENT(struct test);
|
||||
u.fields = fields;
|
||||
u.fieldCount = 2;
|
||||
u.enumOffset = FIELD_OFFSET(struct test, choice);
|
||||
u.noneEnumValue = CHOICE_NONE;
|
||||
|
||||
memset( &f_struct, 0, sizeof(f_struct) );
|
||||
f_struct.mapping = WS_ELEMENT_CHOICE_FIELD_MAPPING;
|
||||
f_struct.type = WS_UNION_TYPE;
|
||||
f_struct.typeDescription = &u;
|
||||
fields_struct[0] = &f_struct;
|
||||
|
||||
memset( &s, 0, sizeof(s) );
|
||||
s.size = sizeof(struct test);
|
||||
s.alignment = TYPE_ALIGNMENT(struct test);
|
||||
s.fields = fields_struct;
|
||||
s.fieldCount = 1;
|
||||
s.typeLocalName = &str_s;
|
||||
s.typeNs = &str_ns;
|
||||
|
||||
test = NULL;
|
||||
prepare_struct_type_test( reader, "<a>test</a>" );
|
||||
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->choice == CHOICE_A, "got %d\n", test->choice );
|
||||
ok( !lstrcmpW(test->value.a, testW), "got %s\n", wine_dbgstr_w(test->value.a) );
|
||||
|
||||
test = NULL;
|
||||
prepare_struct_type_test( reader, "<b>123</b>" );
|
||||
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->choice == CHOICE_B, "got %d\n", test->choice );
|
||||
ok( test->value.b == 123, "got %u\n", test->value.b );
|
||||
|
||||
prepare_struct_type_test( reader, "<c>456</c>" );
|
||||
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 );
|
||||
|
||||
f_struct.options = WS_FIELD_NILLABLE;
|
||||
hr = WsReadType( reader, WS_ELEMENT_CONTENT_TYPE_MAPPING, WS_STRUCT_TYPE, &s,
|
||||
WS_READ_REQUIRED_POINTER, heap, &test, sizeof(test), NULL );
|
||||
ok( hr == E_INVALIDARG, "got %08x\n", hr );
|
||||
|
||||
f_struct.options = WS_FIELD_POINTER|WS_FIELD_NILLABLE;
|
||||
hr = WsReadType( reader, WS_ELEMENT_CONTENT_TYPE_MAPPING, WS_STRUCT_TYPE, &s,
|
||||
WS_READ_REQUIRED_POINTER, heap, &test, sizeof(test), NULL );
|
||||
ok( hr == E_INVALIDARG, "got %08x\n", hr );
|
||||
|
||||
f_struct.options = WS_FIELD_POINTER;
|
||||
hr = WsReadType( reader, WS_ELEMENT_CONTENT_TYPE_MAPPING, WS_STRUCT_TYPE, &s,
|
||||
WS_READ_REQUIRED_POINTER, heap, &test, sizeof(test), NULL );
|
||||
ok( hr == E_INVALIDARG, "got %08x\n", hr );
|
||||
|
||||
test = NULL;
|
||||
f_struct.options = WS_FIELD_OPTIONAL;
|
||||
prepare_struct_type_test( reader, "<c>456</c>" );
|
||||
hr = WsReadType( reader, WS_ELEMENT_CONTENT_TYPE_MAPPING, WS_STRUCT_TYPE, &s,
|
||||
WS_READ_REQUIRED_POINTER, heap, &test, sizeof(test), NULL );
|
||||
todo_wine ok( hr == S_OK, "got %08x\n", hr );
|
||||
ok( test != NULL, "test not set\n" );
|
||||
ok( test->choice == CHOICE_NONE, "got %d\n", test->choice );
|
||||
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 );
|
||||
|
||||
WsFreeReader( reader );
|
||||
WsFreeHeap( heap );
|
||||
}
|
||||
|
||||
START_TEST(reader)
|
||||
{
|
||||
test_WsCreateError();
|
||||
|
@ -5803,4 +5924,5 @@ START_TEST(reader)
|
|||
test_binary_encoding();
|
||||
test_dictionary();
|
||||
test_WsReadXmlBuffer();
|
||||
test_union_type();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue