[PATCH 1/2] webservices: Use the search index to look up the union field, if available.

Hans Leidekker hans at codeweavers.com
Thu Nov 8 02:54:21 CST 2018


Signed-off-by: Hans Leidekker <hans at 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 )
 {
-- 
2.11.0




More information about the wine-devel mailing list