Hans Leidekker : webservices: Properly restore the reader position when the next element doesn't match.

Alexandre Julliard julliard at winehq.org
Wed Apr 18 15:13:20 CDT 2018


Module: wine
Branch: master
Commit: 079f84d9181185ce80e24f01650a428acef4d263
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=079f84d9181185ce80e24f01650a428acef4d263

Author: Hans Leidekker <hans at codeweavers.com>
Date:   Wed Apr 18 12:53:33 2018 +0200

webservices: Properly restore the reader position when the next element doesn't match.

Signed-off-by: Hans Leidekker <hans at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/webservices/reader.c | 113 +++++++++++++++++++++++++---------------------
 1 file changed, 62 insertions(+), 51 deletions(-)

diff --git a/dlls/webservices/reader.c b/dlls/webservices/reader.c
index a56bb7e..79a1af6 100644
--- a/dlls/webservices/reader.c
+++ b/dlls/webservices/reader.c
@@ -4346,6 +4346,24 @@ static HRESULT read_next_node( struct reader *reader )
     return WS_E_INVALID_FORMAT;
 }
 
+struct reader_pos
+{
+    struct node *node;
+    ULONG        attr;
+};
+
+static void save_reader_position( const struct reader *reader, struct reader_pos *pos )
+{
+    pos->node = reader->current;
+    pos->attr = reader->current_attr;
+}
+
+static void restore_reader_position( struct reader *reader, const struct reader_pos *pos )
+{
+    reader->current      = pos->node;
+    reader->current_attr = pos->attr;
+}
+
 static HRESULT get_text( struct reader *reader, WS_TYPE_MAPPING mapping, const WS_XML_STRING *localname,
                          const WS_XML_STRING *ns, const WS_XML_TEXT **ret, BOOL *found )
 {
@@ -4364,16 +4382,19 @@ static HRESULT get_text( struct reader *reader, WS_TYPE_MAPPING mapping, const W
         *found = TRUE;
         if (localname)
         {
+            struct reader_pos pos;
             HRESULT hr;
+
             if (!match_element( reader->current, localname, ns ))
             {
                 *found = FALSE;
                 return S_OK;
             }
+            save_reader_position( reader, &pos );
             if ((hr = read_next_node( reader )) != S_OK) return hr;
             if (node_type( reader->current ) != WS_XML_NODE_TYPE_TEXT)
             {
-                if (!move_to_parent_element( &reader->current )) return WS_E_INVALID_FORMAT;
+                restore_reader_position( reader, &pos );
                 *found = FALSE;
                 return S_OK;
             }
@@ -6021,8 +6042,7 @@ static HRESULT read_type_next_node( struct reader *reader )
 static HRESULT read_type_next_element_node( struct reader *reader, const WS_XML_STRING *localname,
                                             const WS_XML_STRING *ns )
 {
-    struct node *node;
-    ULONG attr;
+    struct reader_pos pos;
     HRESULT hr;
 
     if (!localname) return S_OK; /* assume reader is already correctly positioned */
@@ -6034,14 +6054,10 @@ static HRESULT read_type_next_element_node( struct reader *reader, const WS_XML_
     }
     if (match_element( reader->current, localname, ns )) return S_OK;
 
-    node = reader->current;
-    attr = reader->current_attr;
-
+    save_reader_position( reader, &pos );
     if ((hr = read_type_next_node( reader )) != S_OK) return hr;
     if (match_element( reader->current, localname, ns )) return S_OK;
-
-    reader->current = node;
-    reader->current_attr = attr;
+    restore_reader_position( reader, &pos );
 
     return WS_E_INVALID_FORMAT;
 }
@@ -6166,55 +6182,37 @@ static WS_READ_OPTION get_field_read_option( WS_TYPE type, ULONG options )
 
 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 )
+static HRESULT read_type_union( struct reader *reader, const WS_UNION_DESCRIPTION *desc, WS_HEAP *heap, void *ret,
+                                ULONG size, BOOL *found )
 {
-    BOOL found = FALSE;
+    struct reader_pos pos;
     HRESULT hr;
     ULONG i;
 
-    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 (size != desc->size) return E_INVALIDARG;
 
+    save_reader_position( reader, &pos );
     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 ((found = match_element( reader->current, desc->fields[i]->field.localName, desc->fields[i]->field.ns )))
+        if ((*found = match_element( reader->current, desc->fields[i]->field.localName, desc->fields[i]->field.ns )))
             break;
     }
 
-    if (!found) *(int *)((char *)ret + desc->enumOffset) = desc->noneEnumValue;
-    else
+    if (!*found)
     {
-        ULONG 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;
+        *(int *)((char *)ret + desc->enumOffset) = desc->noneEnumValue;
+        restore_reader_position( reader, &pos );
     }
-
-    switch (option)
+    else
     {
-    case WS_READ_NILLABLE_VALUE:
-        if (!found) move_to_parent_element( &reader->current );
-        break;
-
-    case WS_READ_REQUIRED_VALUE:
-        if (!found) hr = WS_E_INVALID_FORMAT;
-        break;
-
-    default:
-        return E_INVALIDARG;
+        ULONG offset = desc->fields[i]->field.offset;
+        if ((hr = read_type_field( reader, &desc->fields[i]->field, heap, ret, offset )) != S_OK) return hr;
+        *(int *)((char *)ret + desc->enumOffset) = desc->fields[i]->value;
     }
 
-    return hr;
+    return S_OK;
 }
 
 static HRESULT read_type( struct reader *, WS_TYPE_MAPPING, WS_TYPE, const WS_XML_STRING *,
@@ -6251,17 +6249,28 @@ static HRESULT read_type_array( struct reader *reader, const WS_FIELD_DESCRIPTIO
         }
 
         if (desc->type == WS_UNION_TYPE)
-            hr = read_type_union( reader, desc->typeDescription, option, heap, buf + offset, item_size );
+        {
+            BOOL found;
+            hr = read_type_union( reader, desc->typeDescription, heap, buf + offset, item_size, &found );
+            if (hr != S_OK)
+            {
+                ws_free( heap, buf, nb_allocated * item_size );
+                return hr;
+            }
+            if (!found) break;
+        }
         else
+        {
             hr = read_type( reader, WS_ELEMENT_TYPE_MAPPING, desc->type, desc->itemLocalName, desc->itemNs,
                             desc->typeDescription, option, heap, buf + offset, item_size );
-
-        if (hr == WS_E_INVALID_FORMAT) break;
-        if (hr != S_OK)
-        {
-            ws_free( heap, buf, nb_allocated * item_size );
-            return hr;
+            if (hr == WS_E_INVALID_FORMAT) break;
+            if (hr != S_OK)
+            {
+                ws_free( heap, buf, nb_allocated * item_size );
+                return hr;
+            }
         }
+
         offset += item_size;
         nb_items++;
     }
@@ -6338,11 +6347,13 @@ static HRESULT read_type_field( struct reader *reader, const WS_FIELD_DESCRIPTIO
         break;
 
     case WS_ELEMENT_CHOICE_FIELD_MAPPING:
+    {
+        BOOL found;
         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 );
+        hr = read_type_union( reader, desc->typeDescription, heap, ptr, size, &found );
         break;
-
+    }
     case WS_REPEATING_ELEMENT_FIELD_MAPPING:
     case WS_REPEATING_ELEMENT_CHOICE_FIELD_MAPPING:
     {




More information about the wine-cvs mailing list