Commit 0a235233 authored by Hans Leidekker's avatar Hans Leidekker Committed by Alexandre Julliard

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

parent 43e213e2
......@@ -2665,6 +2665,115 @@ static void test_datetime(void)
WsFreeWriter( writer );
}
static void test_repeating_element(void)
{
static const WCHAR oneW[] = {'1',0}, twoW[] = {'2',0};
WS_XML_STRING localname = {4, (BYTE *)"test"}, ns = {0, NULL};
WS_XML_STRING val = {3, (BYTE *)"val"}, wrapper = {7, (BYTE *)"wrapper"};
HRESULT hr;
WS_XML_WRITER *writer;
WS_STRUCT_DESCRIPTION s;
WS_FIELD_DESCRIPTION f, *fields[1];
WS_ITEM_RANGE range;
struct test
{
const WCHAR **val;
ULONG count;
} *test;
struct test2
{
INT32 *val;
ULONG count;
} *test2;
hr = WsCreateWriter( NULL, 0, &writer, NULL );
ok( hr == S_OK, "got %08x\n", hr );
/* array of strings, wrapper */
hr = set_output( writer );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
ok( hr == S_OK, "got %08x\n", hr );
memset( &f, 0, sizeof(f) );
f.mapping = WS_REPEATING_ELEMENT_FIELD_MAPPING;
f.localName = &wrapper;
f.ns = &ns;
f.type = WS_WSZ_TYPE;
f.countOffset = FIELD_OFFSET(struct test, count);
f.itemLocalName = &val;
f.itemNs = &ns;
fields[0] = &f;
memset( &s, 0, sizeof(s) );
s.size = sizeof(struct test);
s.alignment = TYPE_ALIGNMENT(struct test);
s.typeLocalName = &localname;
s.typeNs = &ns;
s.fields = fields;
s.fieldCount = 1;
hr = set_output( writer );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
ok( hr == S_OK, "got %08x\n", hr );
test = HeapAlloc( GetProcessHeap(), 0, sizeof(*test) + 2 * sizeof(const WCHAR *) );
test->val = (const WCHAR **)(test + 1);
test->val[0] = oneW;
test->val[1] = twoW;
test->count = 2;
hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_STRUCT_TYPE, &s,
WS_WRITE_REQUIRED_POINTER, &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, "<test><wrapper><val>1</val><val>2</val></wrapper></test>", __LINE__ );
HeapFree( GetProcessHeap(), 0, test );
/* array of integers, no wrapper */
hr = set_output( writer );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
ok( hr == S_OK, "got %08x\n", hr );
f.type = WS_INT32_TYPE;
f.localName = NULL;
f.ns = NULL;
test2 = HeapAlloc( GetProcessHeap(), 0, sizeof(*test2) + 2 * sizeof(INT32) );
test2->val = (INT32 *)(test2 + 1);
test2->val[0] = 1;
test2->val[1] = 2;
test2->count = 2;
hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_STRUCT_TYPE, &s,
WS_WRITE_REQUIRED_POINTER, &test2, sizeof(test2), NULL );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsWriteEndElement( writer, NULL );
ok( hr == S_OK, "got %08x\n", hr );
check_output( writer, "<test><val>1</val><val>2</val></test>", __LINE__ );
/* item range has no effect */
hr = set_output( writer );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
ok( hr == S_OK, "got %08x\n", hr );
range.minItemCount = 0;
range.maxItemCount = 0;
f.itemRange = &range;
hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_STRUCT_TYPE, &s,
WS_WRITE_REQUIRED_POINTER, &test2, sizeof(test2), NULL );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsWriteEndElement( writer, NULL );
ok( hr == S_OK, "got %08x\n", hr );
check_output( writer, "<test><val>1</val><val>2</val></test>", __LINE__ );
HeapFree( GetProcessHeap(), 0, test2 );
WsFreeWriter( writer );
}
START_TEST(writer)
{
test_WsCreateWriter();
......@@ -2697,4 +2806,5 @@ START_TEST(writer)
test_escapes();
test_write_option();
test_datetime();
test_repeating_element();
}
......@@ -1937,16 +1937,89 @@ static HRESULT write_type_xml_string( struct writer *writer, WS_TYPE_MAPPING map
return write_type_text( writer, mapping, &utf8.text );
}
static WS_WRITE_OPTION get_field_write_option( WS_TYPE type, ULONG options )
{
if (options & WS_FIELD_POINTER)
{
if (options & (WS_FIELD_OPTIONAL|WS_FIELD_NILLABLE)) return WS_WRITE_NILLABLE_POINTER;
return WS_WRITE_REQUIRED_POINTER;
}
switch (type)
{
case WS_BOOL_TYPE:
case WS_INT8_TYPE:
case WS_INT16_TYPE:
case WS_INT32_TYPE:
case WS_INT64_TYPE:
case WS_UINT8_TYPE:
case WS_UINT16_TYPE:
case WS_UINT32_TYPE:
case WS_UINT64_TYPE:
case WS_DOUBLE_TYPE:
case WS_DATETIME_TYPE:
case WS_GUID_TYPE:
case WS_STRING_TYPE:
case WS_BYTES_TYPE:
case WS_XML_STRING_TYPE:
case WS_STRUCT_TYPE:
case WS_ENUM_TYPE:
if (options & (WS_FIELD_OPTIONAL|WS_FIELD_NILLABLE)) return WS_WRITE_NILLABLE_VALUE;
return WS_WRITE_REQUIRED_VALUE;
case WS_WSZ_TYPE:
case WS_DESCRIPTION_TYPE:
if (options & (WS_FIELD_OPTIONAL|WS_FIELD_NILLABLE)) return WS_WRITE_NILLABLE_POINTER;
return WS_WRITE_REQUIRED_POINTER;
default:
FIXME( "unhandled type %u\n", type );
return 0;
}
}
static HRESULT write_type( struct writer *, WS_TYPE_MAPPING, WS_TYPE, const void *, WS_WRITE_OPTION,
const void *, ULONG );
static HRESULT write_type_repeating_element( struct writer *writer, const WS_FIELD_DESCRIPTION *desc,
const char *buf, ULONG count )
{
HRESULT hr = S_OK;
ULONG i, size, offset = 0;
WS_WRITE_OPTION option;
if (!(option = get_field_write_option( desc->type, desc->options ))) return E_INVALIDARG;
/* wrapper element */
if (desc->localName && ((hr = write_element_node( writer, NULL, desc->localName, desc->ns )) != S_OK))
return hr;
if (option == WS_WRITE_REQUIRED_VALUE || option == WS_WRITE_NILLABLE_VALUE)
size = get_type_size( desc->type, desc->typeDescription );
else
size = sizeof(const void *);
for (i = 0; i < count; i++)
{
if ((hr = write_element_node( writer, NULL, desc->itemLocalName, desc->itemNs )) != S_OK) return hr;
if ((hr = write_type( writer, WS_ELEMENT_TYPE_MAPPING, desc->type, desc->typeDescription, option,
buf + offset, size )) != S_OK) return hr;
if ((hr = write_endelement_node( writer )) != S_OK) return hr;
offset += size;
}
if (desc->localName) hr = write_endelement_node( writer );
return hr;
}
static HRESULT write_type_struct_field( struct writer *writer, const WS_FIELD_DESCRIPTION *desc,
const void *value, ULONG size )
const char *buf, ULONG offset )
{
HRESULT hr;
WS_TYPE_MAPPING mapping;
WS_WRITE_OPTION option;
ULONG field_options = desc->options;
ULONG count, size, field_options = desc->options;
const char *ptr = buf + offset;
if (field_options & ~(WS_FIELD_POINTER|WS_FIELD_OPTIONAL|WS_FIELD_NILLABLE))
{
......@@ -1957,7 +2030,12 @@ static HRESULT write_type_struct_field( struct writer *writer, const WS_FIELD_DE
/* zero-terminated strings are always pointers */
if (desc->type == WS_WSZ_TYPE) field_options |= WS_FIELD_POINTER;
if (is_nil_value( value, size ))
if (field_options & WS_FIELD_POINTER)
size = sizeof(const void *);
else
size = get_type_size( desc->type, desc->typeDescription );
if (is_nil_value( ptr, size ))
{
if (field_options & WS_FIELD_OPTIONAL) return S_OK;
if (field_options & WS_FIELD_NILLABLE)
......@@ -1989,6 +2067,10 @@ static HRESULT write_type_struct_field( struct writer *writer, const WS_FIELD_DE
mapping = WS_ELEMENT_TYPE_MAPPING;
break;
case WS_REPEATING_ELEMENT_FIELD_MAPPING:
count = *(const ULONG *)(buf + desc->countOffset);
return write_type_repeating_element( writer, desc, *(const char **)ptr, count );
case WS_TEXT_FIELD_MAPPING:
switch (writer->state)
{
......@@ -2011,7 +2093,7 @@ static HRESULT write_type_struct_field( struct writer *writer, const WS_FIELD_DE
return E_NOTIMPL;
}
if ((hr = write_type( writer, mapping, desc->type, desc->typeDescription, option, value, size )) != S_OK)
if ((hr = write_type( writer, mapping, desc->type, desc->typeDescription, option, ptr, size )) != S_OK)
return hr;
switch (mapping)
......@@ -2030,78 +2112,12 @@ static HRESULT write_type_struct_field( struct writer *writer, const WS_FIELD_DE
return S_OK;
}
static WS_WRITE_OPTION get_field_write_option( WS_TYPE type, ULONG options )
{
if (options & WS_FIELD_POINTER)
{
if (options & (WS_FIELD_OPTIONAL|WS_FIELD_NILLABLE)) return WS_WRITE_NILLABLE_POINTER;
return WS_WRITE_REQUIRED_POINTER;
}
switch (type)
{
case WS_BOOL_TYPE:
case WS_INT8_TYPE:
case WS_INT16_TYPE:
case WS_INT32_TYPE:
case WS_INT64_TYPE:
case WS_UINT8_TYPE:
case WS_UINT16_TYPE:
case WS_UINT32_TYPE:
case WS_UINT64_TYPE:
case WS_DOUBLE_TYPE:
case WS_DATETIME_TYPE:
case WS_GUID_TYPE:
case WS_STRING_TYPE:
case WS_BYTES_TYPE:
case WS_XML_STRING_TYPE:
case WS_STRUCT_TYPE:
case WS_ENUM_TYPE:
if (options & (WS_FIELD_OPTIONAL|WS_FIELD_NILLABLE)) return WS_WRITE_NILLABLE_VALUE;
return WS_WRITE_REQUIRED_VALUE;
case WS_WSZ_TYPE:
case WS_DESCRIPTION_TYPE:
if (options & (WS_FIELD_OPTIONAL|WS_FIELD_NILLABLE)) return WS_WRITE_NILLABLE_POINTER;
return WS_WRITE_REQUIRED_POINTER;
default:
FIXME( "unhandled type %u\n", type );
return 0;
}
}
static ULONG get_field_size( const WS_FIELD_DESCRIPTION *desc )
{
WS_WRITE_OPTION option;
ULONG size;
switch ((option = get_field_write_option( desc->type, desc->options )))
{
case WS_WRITE_REQUIRED_POINTER:
case WS_WRITE_NILLABLE_POINTER:
size = sizeof(const void *);
break;
case WS_WRITE_REQUIRED_VALUE:
case WS_WRITE_NILLABLE_VALUE:
size = get_type_size( desc->type, desc->typeDescription );
break;
default:
WARN( "unhandled option %u\n", option );
return 0;
}
return size;
}
static HRESULT write_type_struct( struct writer *writer, WS_TYPE_MAPPING mapping,
const WS_STRUCT_DESCRIPTION *desc, WS_WRITE_OPTION option,
const void *value, ULONG size )
{
ULONG i, field_size;
const void *ptr, *field_ptr;
ULONG i, offset;
const void *ptr;
HRESULT hr;
if (!desc) return E_INVALIDARG;
......@@ -2111,9 +2127,8 @@ static HRESULT write_type_struct( struct writer *writer, WS_TYPE_MAPPING mapping
for (i = 0; i < desc->fieldCount; i++)
{
field_ptr = (const char *)ptr + desc->fields[i]->offset;
field_size = get_field_size( desc->fields[i] );
if ((hr = write_type_struct_field( writer, desc->fields[i], field_ptr, field_size )) != S_OK)
offset = desc->fields[i]->offset;
if ((hr = write_type_struct_field( writer, desc->fields[i], ptr, offset )) != S_OK)
return hr;
}
......@@ -2795,7 +2810,7 @@ HRESULT WINAPI WsCopyNode( WS_XML_WRITER *handle, WS_XML_READER *reader, WS_ERRO
static HRESULT write_param( struct writer *writer, const WS_FIELD_DESCRIPTION *desc, const void *value )
{
return write_type_struct_field( writer, desc, value, get_field_size(desc) );
return write_type_struct_field( writer, desc, value, 0 );
}
HRESULT write_input_params( WS_XML_WRITER *handle, const WS_ELEMENT_DESCRIPTION *desc,
......
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