xmllite/reader: Improve the way nesting level returned by GetDepth() is updated.

Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Nikolay Sivov 2017-03-06 12:35:59 +03:00 committed by Alexandre Julliard
parent 073c43a139
commit 8f0c235f81
2 changed files with 98 additions and 71 deletions

View File

@ -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);
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)
switch (nodetype)
{
case XmlNodeType_Element:
if (reader->is_empty_element)
reader_pop_ns_nodes(reader, &reader->empty_element);
else if (nodetype == XmlNodeType_EndElement)
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 */

View File

@ -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;
@ -1427,53 +1447,47 @@ static void test_read_element(void)
hr = IXmlReader_SetInput(reader, (IUnknown *)stream);
ok(hr == S_OK, "got %08x\n", hr);
depth = 1;
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);
depth = 123;
hr = IXmlReader_GetDepth(reader, &depth);
ok(hr == S_OK, "got %08x\n", hr);
ok(depth == 0, "got %d\n", depth);
ok(depth == depths[i], "%u: got depth %u, expected %u\n", i, depth, depths[i]);
type = XmlNodeType_None;
hr = IXmlReader_Read(reader, &type);
if (type == XmlNodeType_Element)
{
UINT count = 0;
hr = IXmlReader_GetAttributeCount(reader, &count);
ok(hr == S_OK, "got %08x\n", hr);
ok(type == XmlNodeType_Element, "got %d\n", type);
depth = 1;
/* moving to attributes increases depth */
if (count)
{
hr = IXmlReader_MoveToFirstAttribute(reader);
ok(hr == S_OK, "got %08x\n", hr);
depth = 123;
hr = IXmlReader_GetDepth(reader, &depth);
ok(hr == S_OK, "got %08x\n", hr);
ok(depth == 0, "got %d\n", depth);
ok(depth == depths[i] + 1, "%u: got depth %u, expected %u\n", i, depth, depths[i] + 1);
type = XmlNodeType_None;
hr = IXmlReader_Read(reader, &type);
hr = IXmlReader_MoveToElement(reader);
ok(hr == S_OK, "got %08x\n", hr);
ok(type == XmlNodeType_Element, "got %d\n", type);
depth = 0;
depth = 123;
hr = IXmlReader_GetDepth(reader, &depth);
ok(hr == S_OK, "got %08x\n", hr);
ok(depth == 1, "got %d\n", depth);
ok(depth == depths[i], "%u: got depth %u, expected %u\n", i, depth, depths[i]);
}
}
/* 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 = 0;
hr = IXmlReader_GetDepth(reader, &depth);
ok(hr == S_OK, "got %08x\n", hr);
todo_wine
ok(depth == 2, "got %d\n", depth);
/* 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 = 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);