[PATCH 5/5] xmllite/reader: Improve the way nesting level returned by GetDepth() is updated

Nikolay Sivov nsivov at codeweavers.com
Mon Mar 6 03:35:59 CST 2017


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 dlls/xmllite/reader.c       |  69 +++++++++++++++++-------------
 dlls/xmllite/tests/reader.c | 100 +++++++++++++++++++++++++-------------------
 2 files changed, 98 insertions(+), 71 deletions(-)

diff --git a/dlls/xmllite/reader.c b/dlls/xmllite/reader.c
index 8e975b329c..5f53d3f1f2 100644
--- a/dlls/xmllite/reader.c
+++ b/dlls/xmllite/reader.c
@@ -477,7 +477,8 @@ static HRESULT reader_inc_depth(xmlreader *reader)
 
 static void reader_dec_depth(xmlreader *reader)
 {
-    if (reader->depth > 1) reader->depth--;
+    if (reader->depth)
+        reader->depth--;
 }
 
 static HRESULT reader_push_ns(xmlreader *reader, const strval *prefix, const strval *uri, BOOL def)
@@ -541,33 +542,21 @@ static HRESULT reader_push_element(xmlreader *reader, strval *prefix, strval *lo
     struct element *element;
     HRESULT hr;
 
-    if (!list_empty(&reader->elements))
-    {
-        hr = reader_inc_depth(reader);
-        if (FAILED(hr))
-             return hr;
-    }
-
     element = reader_alloc_zero(reader, sizeof(*element));
-    if (!element) {
-        hr = E_OUTOFMEMORY;
-        goto failed;
-    }
+    if (!element)
+        return E_OUTOFMEMORY;
 
-    if ((hr = reader_strvaldup(reader, prefix, &element->prefix)) != S_OK ||
-            (hr = reader_strvaldup(reader, localname, &element->localname)) != S_OK ||
-            (hr = reader_strvaldup(reader, qname, &element->qname)) != S_OK)
+    if ((hr = reader_strvaldup(reader, prefix, &element->prefix)) == S_OK &&
+            (hr = reader_strvaldup(reader, localname, &element->localname)) == S_OK &&
+            (hr = reader_strvaldup(reader, qname, &element->qname)) == S_OK)
     {
-        reader_free_element(reader, element);
-        goto failed;
+        list_add_head(&reader->elements, &element->entry);
+        reader_mark_ns_nodes(reader, element);
+        reader->is_empty_element = FALSE;
     }
+    else
+        reader_free_element(reader, element);
 
-    list_add_head(&reader->elements, &element->entry);
-    reader_mark_ns_nodes(reader, element);
-    reader->is_empty_element = FALSE;
-
-failed:
-    reader_dec_depth(reader);
     return hr;
 }
 
@@ -608,7 +597,6 @@ static void reader_pop_element(xmlreader *reader)
 
     reader_pop_ns_nodes(reader, element);
     reader_free_element(reader, element);
-    reader_dec_depth(reader);
 
     /* It was a root element, the rest is expected as Misc */
     if (list_empty(&reader->elements))
@@ -1310,7 +1298,6 @@ static HRESULT reader_parse_xmldecl(xmlreader *reader)
     if (reader_cmp(reader, declcloseW)) return WC_E_XMLDECL;
     reader_skipn(reader, 2);
 
-    reader_inc_depth(reader);
     reader->nodetype = XmlNodeType_XmlDeclaration;
     reader_set_strvalue(reader, StringValue_LocalName, &strval_empty);
     reader_set_strvalue(reader, StringValue_QualifiedName, &strval_empty);
@@ -2478,10 +2465,23 @@ static HRESULT reader_parse_nextnode(xmlreader *reader)
         reader_clear_attrs(reader);
 
     /* When moving from EndElement or empty element, pop its own namespace definitions */
-    if (nodetype == XmlNodeType_Element && reader->is_empty_element)
-        reader_pop_ns_nodes(reader, &reader->empty_element);
-    else if (nodetype == XmlNodeType_EndElement)
+    switch (nodetype)
+    {
+    case XmlNodeType_Element:
+        if (reader->is_empty_element)
+            reader_pop_ns_nodes(reader, &reader->empty_element);
+        else
+            reader_inc_depth(reader);
+        break;
+    case XmlNodeType_EndElement:
         reader_pop_element(reader);
+        /* fallthrough */
+    case XmlNodeType_Attribute:
+        reader_dec_depth(reader);
+        break;
+    default:
+        ;
+    }
 
     while (1)
     {
@@ -2658,6 +2658,7 @@ static HRESULT WINAPI xmlreader_SetInput(IXmlReader* iface, IUnknown *input)
     This->line = This->pos = 0;
     reader_clear_elements(This);
     This->depth = 0;
+    This->nodetype = XmlNodeType_None;
     This->resumestate = XmlReadResumeState_Initial;
     memset(This->resume, 0, sizeof(This->resume));
 
@@ -2816,6 +2817,14 @@ static HRESULT reader_move_to_first_attribute(xmlreader *reader)
     if (!reader->attr_count)
         return S_FALSE;
 
+    if (!reader->attr)
+    {
+        HRESULT hr;
+
+        if (FAILED(hr = reader_inc_depth(reader)))
+            return hr;
+    }
+
     reader->attr = LIST_ENTRY(list_head(&reader->attrs), struct attribute, entry);
     reader_set_strvalue(reader, StringValue_Prefix, &reader->attr->prefix);
     reader_set_strvalue(reader, StringValue_LocalName, &reader->attr->localname);
@@ -2872,6 +2881,10 @@ static HRESULT WINAPI xmlreader_MoveToElement(IXmlReader* iface)
     TRACE("(%p)\n", This);
 
     if (!This->attr_count) return S_FALSE;
+
+    if (This->attr)
+        reader_dec_depth(This);
+
     This->attr = NULL;
 
     /* FIXME: support other node types with 'attributes' like DTD */
diff --git a/dlls/xmllite/tests/reader.c b/dlls/xmllite/tests/reader.c
index 6389019702..07e149f631 100644
--- a/dlls/xmllite/tests/reader.c
+++ b/dlls/xmllite/tests/reader.c
@@ -755,6 +755,11 @@ static void test_read_xmldeclaration(void)
     ok_pos(reader, 1, 3, -1, 55, TRUE);
     test_read_state(reader, XmlReadState_Interactive, -1, FALSE);
 
+    count = 1;
+    hr = IXmlReader_GetDepth(reader, &count);
+    ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
+    ok(count == 0, "Expected 1, got %d\n", count);
+
     hr = IXmlReader_GetValue(reader, &val, NULL);
     ok(hr == S_OK, "got %08x\n", hr);
     ok(*val == 0, "got %s\n", wine_dbgstr_w(val));
@@ -763,6 +768,11 @@ static void test_read_xmldeclaration(void)
     hr = IXmlReader_MoveToNextAttribute(reader);
     ok(hr == S_OK, "got %08x\n", hr);
 
+    count = 0;
+    hr = IXmlReader_GetDepth(reader, &count);
+    ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
+    ok(count == 1, "Expected 1, got %d\n", count);
+
     type = XmlNodeType_None;
     hr = IXmlReader_GetNodeType(reader, &type);
     ok(hr == S_OK, "got %08x\n", hr);
@@ -812,6 +822,7 @@ static void test_read_xmldeclaration(void)
         ok(hr == ((i < count - 1) ? S_OK : S_FALSE), "got %08x\n", hr);
     }
 
+    count = 0;
     hr = IXmlReader_GetDepth(reader, &count);
     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
     ok(count == 1, "Expected 1, got %d\n", count);
@@ -845,7 +856,7 @@ todo_wine {
     ok(hr == S_OK, "expected S_OK, got %08x\n", hr);
     ok(type == XmlNodeType_XmlDeclaration, "expected XmlDeclaration, got %s\n", type_to_str(type));
     ok_pos(reader, 1, 3, 1, 21, TRUE);
-    test_read_state(reader, XmlReadState_Interactive, -1, TRUE);
+    test_read_state(reader, XmlReadState_Interactive, -1, FALSE);
 
     hr = IXmlReader_GetAttributeCount(reader, &count);
     ok(hr == S_OK, "expected S_OK, got %08x\n", hr);
@@ -882,7 +893,7 @@ todo_wine
     ok(hr == S_OK, "expected S_OK, got %08x\n", hr);
     ok(type == XmlNodeType_Element, "expected Element, got %s\n", type_to_str(type));
     ok_pos(reader, 1, 23, 1, 40, TRUE);
-    test_read_state(reader, XmlReadState_Interactive, -1, TRUE);
+    test_read_state(reader, XmlReadState_Interactive, -1, FALSE);
 
     hr = IXmlReader_GetAttributeCount(reader, &count);
     ok(hr == S_OK, "expected S_OK, got %08x\n", hr);
@@ -1368,11 +1379,20 @@ static struct test_entry element_tests[] = {
 static void test_read_element(void)
 {
     struct test_entry *test = element_tests;
-    static const char stag[] = "<a><b></b></a>";
+    static const char stag[] =
+         "<a attr1=\"_a\">"
+             "<b attr2=\"_b\">"
+                 "text"
+                 "<c attr3=\"_c\"/>"
+                 "<d attr4=\"_d\"></d>"
+             "</b>"
+         "</a>";
+    static const UINT depths[] = { 0, 1, 2, 2, 2, 3, 2, 1 };
     static const char mismatch[] = "<a></b>";
     IXmlReader *reader;
     XmlNodeType type;
     IStream *stream;
+    unsigned int i;
     UINT depth;
     HRESULT hr;
 
@@ -1424,56 +1444,50 @@ static void test_read_element(void)
 
     /* test reader depth increment */
     stream = create_stream_on_data(stag, sizeof(stag));
-    hr = IXmlReader_SetInput(reader, (IUnknown*)stream);
+    hr = IXmlReader_SetInput(reader, (IUnknown *)stream);
     ok(hr == S_OK, "got %08x\n", hr);
 
-    depth = 1;
-    hr = IXmlReader_GetDepth(reader, &depth);
-    ok(hr == S_OK, "got %08x\n", hr);
-    ok(depth == 0, "got %d\n", depth);
+    i = 0;
+    while (IXmlReader_Read(reader, &type) == S_OK)
+    {
+        ok(type == XmlNodeType_Element || type == XmlNodeType_EndElement ||
+                type == XmlNodeType_Text, "Unexpected node type %d\n", type);
 
-    type = XmlNodeType_None;
-    hr = IXmlReader_Read(reader, &type);
-    ok(hr == S_OK, "got %08x\n", hr);
-    ok(type == XmlNodeType_Element, "got %d\n", type);
+        depth = 123;
+        hr = IXmlReader_GetDepth(reader, &depth);
+        ok(hr == S_OK, "got %08x\n", hr);
+        ok(depth == depths[i], "%u: got depth %u, expected %u\n", i, depth, depths[i]);
 
-    depth = 1;
-    hr = IXmlReader_GetDepth(reader, &depth);
-    ok(hr == S_OK, "got %08x\n", hr);
-    ok(depth == 0, "got %d\n", depth);
+        if (type == XmlNodeType_Element)
+        {
+            UINT count = 0;
 
-    type = XmlNodeType_None;
-    hr = IXmlReader_Read(reader, &type);
-    ok(hr == S_OK, "got %08x\n", hr);
-    ok(type == XmlNodeType_Element, "got %d\n", type);
+            hr = IXmlReader_GetAttributeCount(reader, &count);
+            ok(hr == S_OK, "got %08x\n", hr);
 
-    depth = 0;
-    hr = IXmlReader_GetDepth(reader, &depth);
-    ok(hr == S_OK, "got %08x\n", hr);
-    ok(depth == 1, "got %d\n", depth);
+            /* moving to attributes increases depth */
+            if (count)
+            {
+                hr = IXmlReader_MoveToFirstAttribute(reader);
+                ok(hr == S_OK, "got %08x\n", hr);
 
-    /* read end tag for inner element */
-    type = XmlNodeType_None;
-    hr = IXmlReader_Read(reader, &type);
-    ok(hr == S_OK, "got %08x\n", hr);
-    ok(type == XmlNodeType_EndElement, "got %d\n", type);
+                depth = 123;
+                hr = IXmlReader_GetDepth(reader, &depth);
+                ok(hr == S_OK, "got %08x\n", hr);
+                ok(depth == depths[i] + 1, "%u: got depth %u, expected %u\n", i, depth, depths[i] + 1);
 
-    depth = 0;
-    hr = IXmlReader_GetDepth(reader, &depth);
-    ok(hr == S_OK, "got %08x\n", hr);
-todo_wine
-    ok(depth == 2, "got %d\n", depth);
+                hr = IXmlReader_MoveToElement(reader);
+                ok(hr == S_OK, "got %08x\n", hr);
 
-    /* read end tag for container element */
-    type = XmlNodeType_None;
-    hr = IXmlReader_Read(reader, &type);
-    ok(hr == S_OK, "got %08x\n", hr);
-    ok(type == XmlNodeType_EndElement, "got %d\n", type);
+                depth = 123;
+                hr = IXmlReader_GetDepth(reader, &depth);
+                ok(hr == S_OK, "got %08x\n", hr);
+                ok(depth == depths[i], "%u: got depth %u, expected %u\n", i, depth, depths[i]);
+            }
+        }
 
-    depth = 0;
-    hr = IXmlReader_GetDepth(reader, &depth);
-    ok(hr == S_OK, "got %08x\n", hr);
-    ok(depth == 1, "got %d\n", depth);
+        i++;
+    }
 
     IStream_Release(stream);
 
-- 
2.11.0




More information about the wine-patches mailing list