Signed-off-by: Hans Leidekker hans@codeweavers.com --- dlls/webservices/tests/writer.c | 13 +++++++++- dlls/webservices/writer.c | 56 ++++++++++++++++++++++++++++++----------- 2 files changed, 54 insertions(+), 15 deletions(-)
diff --git a/dlls/webservices/tests/writer.c b/dlls/webservices/tests/writer.c index e33c38951e..f46578ba3b 100644 --- a/dlls/webservices/tests/writer.c +++ b/dlls/webservices/tests/writer.c @@ -3920,7 +3920,8 @@ static void test_union_type(void) 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}; + enum choice {CHOICE_A = 30, CHOICE_B = 20, CHOICE_C = 10, CHOICE_NONE = 0}; + ULONG index[2] = {1, 0}; struct test { enum choice choice; @@ -3987,6 +3988,7 @@ static void test_union_type(void) ok( hr == S_OK, "got %08x\n", hr ); check_output( writer, "<t><a>test</a></t>", __LINE__ );
+ u.valueIndices = index; hr = set_output( writer ); ok( hr == S_OK, "got %08x\n", hr ); hr = WsWriteStartElement( writer, NULL, &str_t, &str_ns, NULL ); @@ -4004,6 +4006,15 @@ static void test_union_type(void) 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_C; + 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; hr = WsWriteType( writer, WS_ELEMENT_CONTENT_TYPE_MAPPING, WS_STRUCT_TYPE, &s, WS_WRITE_REQUIRED_VALUE, &test, sizeof(test), NULL ); diff --git a/dlls/webservices/writer.c b/dlls/webservices/writer.c index ff633a656c..0f20049b7a 100644 --- a/dlls/webservices/writer.c +++ b/dlls/webservices/writer.c @@ -3580,15 +3580,48 @@ static WS_WRITE_OPTION get_field_write_option( WS_TYPE type, ULONG options ) } }
-static HRESULT write_type_field( struct writer *, const WS_FIELD_DESCRIPTION *, const char *, ULONG ); +static HRESULT find_index( const WS_UNION_DESCRIPTION *desc, int value, ULONG *idx ) +{ + ULONG i;
-static HRESULT write_type( struct writer *, WS_TYPE_MAPPING, WS_TYPE, const void *, WS_WRITE_OPTION, - const void *, ULONG ); + if (desc->valueIndices) + { + int c, min = 0, max = desc->fieldCount - 1; + while (min <= max) + { + i = (min + max) / 2; + c = value - desc->fields[desc->valueIndices[i]]->value; + if (c < 0) + max = i - 1; + else if (c > 0) + min = i + 1; + else + { + *idx = desc->valueIndices[i]; + return S_OK; + } + } + return WS_E_INVALID_FORMAT; + } + + /* fall back to linear search */ + for (i = 0; i < desc->fieldCount; i++) + { + if (desc->fields[i]->value == value) + { + *idx = i; + return S_OK; + } + } + return WS_E_INVALID_FORMAT; +} + +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; + ULONG i; const void *ptr; int enum_value; HRESULT hr; @@ -3612,18 +3645,13 @@ static HRESULT write_type_union( struct writer *writer, const WS_UNION_DESCRIPTI } }
- 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; + if ((hr = find_index( desc, enum_value, &i )) != S_OK) return hr; + return write_type_field( writer, &desc->fields[i]->field, ptr, desc->fields[i]->field.offset ); }
+static HRESULT write_type( struct writer *, WS_TYPE_MAPPING, WS_TYPE, const void *, WS_WRITE_OPTION, + const void *, ULONG ); + static HRESULT write_type_array( struct writer *writer, const WS_FIELD_DESCRIPTION *desc, const char *buf, ULONG count ) {