mirror of
git://source.winehq.org/git/wine.git
synced 2024-10-14 17:47:16 +00:00
webservices: Add support for union types in the writer.
Signed-off-by: Hans Leidekker <hans@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
95308f22d4
commit
c51ab4cd14
|
@ -5073,7 +5073,7 @@ static HRESULT read_type_next_element_node( struct reader *reader, const WS_XML_
|
|||
return WS_E_INVALID_FORMAT;
|
||||
}
|
||||
|
||||
ULONG get_type_size( WS_TYPE type, const WS_STRUCT_DESCRIPTION *desc )
|
||||
ULONG get_type_size( WS_TYPE type, const void *desc )
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
|
@ -5119,12 +5119,19 @@ ULONG get_type_size( WS_TYPE type, const WS_STRUCT_DESCRIPTION *desc )
|
|||
case WS_XML_QNAME_TYPE:
|
||||
return sizeof(WS_XML_QNAME);
|
||||
|
||||
case WS_STRUCT_TYPE:
|
||||
return desc->size;
|
||||
|
||||
case WS_DESCRIPTION_TYPE:
|
||||
return sizeof(WS_STRUCT_DESCRIPTION *);
|
||||
|
||||
case WS_STRUCT_TYPE:
|
||||
{
|
||||
const WS_STRUCT_DESCRIPTION *desc_struct = desc;
|
||||
return desc_struct->size;
|
||||
}
|
||||
case WS_UNION_TYPE:
|
||||
{
|
||||
const WS_UNION_DESCRIPTION *desc_union = desc;
|
||||
return desc_union->size;
|
||||
}
|
||||
default:
|
||||
ERR( "unhandled type %u\n", type );
|
||||
return 0;
|
||||
|
|
|
@ -3909,6 +3909,122 @@ static void test_dictionary(void)
|
|||
WsFreeWriter( writer );
|
||||
}
|
||||
|
||||
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"}, str_t = {1, (BYTE *)"t"};
|
||||
HRESULT hr;
|
||||
WS_XML_WRITER *writer;
|
||||
WS_UNION_DESCRIPTION u;
|
||||
WS_UNION_FIELD_DESCRIPTION f, f2, *fields[2];
|
||||
WS_FIELD_DESCRIPTION f_struct, *fields_struct[1];
|
||||
WS_STRUCT_DESCRIPTION s;
|
||||
enum choice {CHOICE_A, CHOICE_B, CHOICE_NONE};
|
||||
struct test
|
||||
{
|
||||
enum choice choice;
|
||||
union
|
||||
{
|
||||
const WCHAR *a;
|
||||
UINT32 b;
|
||||
} value;
|
||||
} test;
|
||||
|
||||
hr = WsCreateWriter( NULL, 0, &writer, 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;
|
||||
|
||||
hr = set_output( writer );
|
||||
ok( hr == S_OK, "got %08x\n", hr );
|
||||
hr = WsWriteStartElement( writer, NULL, &str_t, &str_ns, NULL );
|
||||
ok( hr == S_OK, "got %08x\n", hr );
|
||||
test.choice = CHOICE_A;
|
||||
test.value.a = testW;
|
||||
hr = WsWriteType( writer, WS_ELEMENT_CONTENT_TYPE_MAPPING, WS_STRUCT_TYPE, &s,
|
||||
WS_WRITE_REQUIRED_VALUE, &test, sizeof(test), NULL );
|
||||
ok( hr == S_OK, "got %08x\n", hr );
|
||||
hr = WsWriteEndElement( writer, NULL );
|
||||
ok( hr == S_OK, "got %08x\n", hr );
|
||||
check_output( writer, "<t><a>test</a></t>", __LINE__ );
|
||||
|
||||
hr = set_output( writer );
|
||||
ok( hr == S_OK, "got %08x\n", hr );
|
||||
hr = WsWriteStartElement( writer, NULL, &str_t, &str_ns, NULL );
|
||||
ok( hr == S_OK, "got %08x\n", hr );
|
||||
test.choice = CHOICE_B;
|
||||
test.value.b = 123;
|
||||
hr = WsWriteType( writer, WS_ELEMENT_CONTENT_TYPE_MAPPING, WS_STRUCT_TYPE, &s,
|
||||
WS_WRITE_REQUIRED_VALUE, &test, sizeof(test), NULL );
|
||||
ok( hr == S_OK, "got %08x\n", hr );
|
||||
hr = WsWriteEndElement( writer, NULL );
|
||||
ok( hr == S_OK, "got %08x\n", hr );
|
||||
check_output( writer, "<t><b>123</b></t>", __LINE__ );
|
||||
|
||||
hr = set_output( writer );
|
||||
ok( hr == S_OK, "got %08x\n", hr );
|
||||
hr = WsWriteStartElement( writer, NULL, &str_t, &str_ns, NULL );
|
||||
ok( hr == S_OK, "got %08x\n", hr );
|
||||
test.choice = CHOICE_NONE;
|
||||
hr = WsWriteType( writer, WS_ELEMENT_CONTENT_TYPE_MAPPING, WS_STRUCT_TYPE, &s,
|
||||
WS_WRITE_REQUIRED_VALUE, &test, sizeof(test), NULL );
|
||||
ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
|
||||
|
||||
hr = set_output( writer );
|
||||
ok( hr == S_OK, "got %08x\n", hr );
|
||||
hr = WsWriteStartElement( writer, NULL, &str_t, &str_ns, NULL );
|
||||
ok( hr == S_OK, "got %08x\n", hr );
|
||||
test.choice = CHOICE_NONE;
|
||||
f_struct.options = WS_FIELD_OPTIONAL;
|
||||
hr = WsWriteType( writer, WS_ELEMENT_CONTENT_TYPE_MAPPING, WS_STRUCT_TYPE, &s,
|
||||
WS_WRITE_REQUIRED_VALUE, &test, sizeof(test), NULL );
|
||||
ok( hr == S_OK, "got %08x\n", hr );
|
||||
hr = WsWriteEndElement( writer, NULL );
|
||||
ok( hr == S_OK, "got %08x\n", hr );
|
||||
check_output( writer, "<t/>", __LINE__ );
|
||||
|
||||
WsFreeWriter( writer );
|
||||
}
|
||||
|
||||
START_TEST(writer)
|
||||
{
|
||||
test_WsCreateWriter();
|
||||
|
@ -3949,4 +4065,5 @@ START_TEST(writer)
|
|||
test_binary_encoding();
|
||||
test_namespaces();
|
||||
test_dictionary();
|
||||
test_union_type();
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ WS_TYPE map_value_type( WS_VALUE_TYPE ) DECLSPEC_HIDDEN;
|
|||
BOOL set_fpword( unsigned short, unsigned short * ) DECLSPEC_HIDDEN;
|
||||
void restore_fpword( unsigned short ) DECLSPEC_HIDDEN;
|
||||
HRESULT set_output( WS_XML_WRITER * ) DECLSPEC_HIDDEN;
|
||||
ULONG get_type_size( WS_TYPE, const WS_STRUCT_DESCRIPTION * ) DECLSPEC_HIDDEN;
|
||||
ULONG get_type_size( WS_TYPE, const void * ) DECLSPEC_HIDDEN;
|
||||
HRESULT read_header( WS_XML_READER *, const WS_XML_STRING *, const WS_XML_STRING *, WS_TYPE,
|
||||
const void *, WS_READ_OPTION, WS_HEAP *, void *, ULONG ) DECLSPEC_HIDDEN;
|
||||
|
||||
|
|
|
@ -2923,8 +2923,49 @@ static HRESULT write_type_repeating_element( struct writer *writer, const WS_FIE
|
|||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT write_type_struct_field( struct writer *writer, const WS_FIELD_DESCRIPTION *desc,
|
||||
const char *buf, ULONG offset )
|
||||
static HRESULT write_type_field( struct writer *, const WS_FIELD_DESCRIPTION *, const char *, ULONG );
|
||||
|
||||
static HRESULT write_type_union( struct writer *writer, const WS_UNION_DESCRIPTION *desc, WS_WRITE_OPTION option,
|
||||
const void *value, ULONG size )
|
||||
{
|
||||
ULONG i, offset;
|
||||
const void *ptr;
|
||||
int enum_value;
|
||||
HRESULT hr;
|
||||
|
||||
if ((hr = get_value_ptr( option, value, size, desc->size, &ptr )) != S_OK) return hr;
|
||||
|
||||
if (size < sizeof(enum_value)) return E_INVALIDARG;
|
||||
if ((enum_value = *(int *)(char *)ptr + desc->enumOffset) == desc->noneEnumValue)
|
||||
{
|
||||
switch (option)
|
||||
{
|
||||
case WS_WRITE_REQUIRED_VALUE:
|
||||
return WS_E_INVALID_FORMAT;
|
||||
|
||||
case WS_WRITE_NILLABLE_VALUE:
|
||||
return S_OK;
|
||||
|
||||
default:
|
||||
ERR( "unhandled write option %u\n", option );
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < desc->fieldCount; i++)
|
||||
{
|
||||
if (desc->fields[i]->value == enum_value)
|
||||
{
|
||||
offset = desc->fields[i]->field.offset;
|
||||
return write_type_field( writer, &desc->fields[i]->field, ptr, offset );
|
||||
}
|
||||
}
|
||||
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
static HRESULT write_type_field( struct writer *writer, const WS_FIELD_DESCRIPTION *desc, const char *buf,
|
||||
ULONG offset )
|
||||
{
|
||||
HRESULT hr;
|
||||
WS_TYPE_MAPPING mapping;
|
||||
|
@ -2982,6 +3023,11 @@ static HRESULT write_type_struct_field( struct writer *writer, const WS_FIELD_DE
|
|||
mapping = WS_ELEMENT_TYPE_MAPPING;
|
||||
break;
|
||||
|
||||
case WS_ELEMENT_CHOICE_FIELD_MAPPING:
|
||||
if (desc->type != WS_UNION_TYPE || !desc->typeDescription) return E_INVALIDARG;
|
||||
option = (field_options & WS_FIELD_OPTIONAL) ? WS_WRITE_NILLABLE_VALUE : WS_WRITE_REQUIRED_VALUE;
|
||||
return write_type_union( writer, desc->typeDescription, option, ptr, size );
|
||||
|
||||
case WS_REPEATING_ELEMENT_FIELD_MAPPING:
|
||||
count = *(const ULONG *)(buf + desc->countOffset);
|
||||
return write_type_repeating_element( writer, desc, *(const char **)ptr, count );
|
||||
|
@ -3043,14 +3089,12 @@ static HRESULT write_type_struct( struct writer *writer, WS_TYPE_MAPPING mapping
|
|||
for (i = 0; i < desc->fieldCount; i++)
|
||||
{
|
||||
offset = desc->fields[i]->offset;
|
||||
if ((hr = write_type_struct_field( writer, desc->fields[i], ptr, offset )) != S_OK)
|
||||
return hr;
|
||||
if ((hr = write_type_field( writer, desc->fields[i], ptr, offset )) != S_OK) return hr;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
static HRESULT write_type( struct writer *writer, WS_TYPE_MAPPING mapping, WS_TYPE type,
|
||||
const void *desc, WS_WRITE_OPTION option, const void *value,
|
||||
ULONG size )
|
||||
|
@ -4023,7 +4067,7 @@ done:
|
|||
|
||||
static HRESULT write_param( struct writer *writer, const WS_FIELD_DESCRIPTION *desc, const void *value )
|
||||
{
|
||||
return write_type_struct_field( writer, desc, value, 0 );
|
||||
return write_type_field( writer, desc, value, 0 );
|
||||
}
|
||||
|
||||
static ULONG get_array_len( const WS_PARAMETER_DESCRIPTION *params, ULONG count, ULONG index, const void **args )
|
||||
|
|
|
@ -531,6 +531,21 @@ typedef struct _WS_STRUCT_DESCRIPTION {
|
|||
ULONG structOptions;
|
||||
} WS_STRUCT_DESCRIPTION;
|
||||
|
||||
typedef struct _WS_UNION_FIELD_DESCRIPTION {
|
||||
int value;
|
||||
WS_FIELD_DESCRIPTION field;
|
||||
} WS_UNION_FIELD_DESCRIPTION;
|
||||
|
||||
typedef struct _WS_UNION_DESCRIPTION {
|
||||
ULONG size;
|
||||
ULONG alignment;
|
||||
WS_UNION_FIELD_DESCRIPTION **fields;
|
||||
ULONG fieldCount;
|
||||
ULONG enumOffset;
|
||||
int noneEnumValue;
|
||||
ULONG *valueIndices;
|
||||
} WS_UNION_DESCRIPTION;
|
||||
|
||||
typedef struct _WS_ATTRIBUTE_DESCRIPTION {
|
||||
WS_XML_STRING *attributeLocalName;
|
||||
WS_XML_STRING *attributeNs;
|
||||
|
|
Loading…
Reference in a new issue