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) 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) 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; struct element *element;
HRESULT hr; HRESULT hr;
if (!list_empty(&reader->elements))
{
hr = reader_inc_depth(reader);
if (FAILED(hr))
return hr;
}
element = reader_alloc_zero(reader, sizeof(*element)); element = reader_alloc_zero(reader, sizeof(*element));
if (!element) { if (!element)
hr = E_OUTOFMEMORY; return E_OUTOFMEMORY;
goto failed;
}
if ((hr = reader_strvaldup(reader, prefix, &element->prefix)) != 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, localname, &element->localname)) == S_OK &&
(hr = reader_strvaldup(reader, qname, &element->qname)) != S_OK) (hr = reader_strvaldup(reader, qname, &element->qname)) == S_OK)
{ {
reader_free_element(reader, element); list_add_head(&reader->elements, &element->entry);
goto failed; 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; return hr;
} }
@ -608,7 +597,6 @@ static void reader_pop_element(xmlreader *reader)
reader_pop_ns_nodes(reader, element); reader_pop_ns_nodes(reader, element);
reader_free_element(reader, element); reader_free_element(reader, element);
reader_dec_depth(reader);
/* It was a root element, the rest is expected as Misc */ /* It was a root element, the rest is expected as Misc */
if (list_empty(&reader->elements)) 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; if (reader_cmp(reader, declcloseW)) return WC_E_XMLDECL;
reader_skipn(reader, 2); reader_skipn(reader, 2);
reader_inc_depth(reader);
reader->nodetype = XmlNodeType_XmlDeclaration; reader->nodetype = XmlNodeType_XmlDeclaration;
reader_set_strvalue(reader, StringValue_LocalName, &strval_empty); reader_set_strvalue(reader, StringValue_LocalName, &strval_empty);
reader_set_strvalue(reader, StringValue_QualifiedName, &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); reader_clear_attrs(reader);
/* When moving from EndElement or empty element, pop its own namespace definitions */ /* When moving from EndElement or empty element, pop its own namespace definitions */
if (nodetype == XmlNodeType_Element && reader->is_empty_element) switch (nodetype)
reader_pop_ns_nodes(reader, &reader->empty_element); {
else if (nodetype == XmlNodeType_EndElement) 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); reader_pop_element(reader);
/* fallthrough */
case XmlNodeType_Attribute:
reader_dec_depth(reader);
break;
default:
;
}
while (1) while (1)
{ {
@ -2658,6 +2658,7 @@ static HRESULT WINAPI xmlreader_SetInput(IXmlReader* iface, IUnknown *input)
This->line = This->pos = 0; This->line = This->pos = 0;
reader_clear_elements(This); reader_clear_elements(This);
This->depth = 0; This->depth = 0;
This->nodetype = XmlNodeType_None;
This->resumestate = XmlReadResumeState_Initial; This->resumestate = XmlReadResumeState_Initial;
memset(This->resume, 0, sizeof(This->resume)); memset(This->resume, 0, sizeof(This->resume));
@ -2816,6 +2817,14 @@ static HRESULT reader_move_to_first_attribute(xmlreader *reader)
if (!reader->attr_count) if (!reader->attr_count)
return S_FALSE; 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->attr = LIST_ENTRY(list_head(&reader->attrs), struct attribute, entry);
reader_set_strvalue(reader, StringValue_Prefix, &reader->attr->prefix); reader_set_strvalue(reader, StringValue_Prefix, &reader->attr->prefix);
reader_set_strvalue(reader, StringValue_LocalName, &reader->attr->localname); reader_set_strvalue(reader, StringValue_LocalName, &reader->attr->localname);
@ -2872,6 +2881,10 @@ static HRESULT WINAPI xmlreader_MoveToElement(IXmlReader* iface)
TRACE("(%p)\n", This); TRACE("(%p)\n", This);
if (!This->attr_count) return S_FALSE; if (!This->attr_count) return S_FALSE;
if (This->attr)
reader_dec_depth(This);
This->attr = NULL; This->attr = NULL;
/* FIXME: support other node types with 'attributes' like DTD */ /* 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); ok_pos(reader, 1, 3, -1, 55, TRUE);
test_read_state(reader, XmlReadState_Interactive, -1, FALSE); 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); hr = IXmlReader_GetValue(reader, &val, NULL);
ok(hr == S_OK, "got %08x\n", hr); ok(hr == S_OK, "got %08x\n", hr);
ok(*val == 0, "got %s\n", wine_dbgstr_w(val)); ok(*val == 0, "got %s\n", wine_dbgstr_w(val));
@ -763,6 +768,11 @@ static void test_read_xmldeclaration(void)
hr = IXmlReader_MoveToNextAttribute(reader); hr = IXmlReader_MoveToNextAttribute(reader);
ok(hr == S_OK, "got %08x\n", hr); 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; type = XmlNodeType_None;
hr = IXmlReader_GetNodeType(reader, &type); hr = IXmlReader_GetNodeType(reader, &type);
ok(hr == S_OK, "got %08x\n", hr); 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); ok(hr == ((i < count - 1) ? S_OK : S_FALSE), "got %08x\n", hr);
} }
count = 0;
hr = IXmlReader_GetDepth(reader, &count); hr = IXmlReader_GetDepth(reader, &count);
ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
ok(count == 1, "Expected 1, got %d\n", count); 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(hr == S_OK, "expected S_OK, got %08x\n", hr);
ok(type == XmlNodeType_XmlDeclaration, "expected XmlDeclaration, got %s\n", type_to_str(type)); ok(type == XmlNodeType_XmlDeclaration, "expected XmlDeclaration, got %s\n", type_to_str(type));
ok_pos(reader, 1, 3, 1, 21, TRUE); 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); hr = IXmlReader_GetAttributeCount(reader, &count);
ok(hr == S_OK, "expected S_OK, got %08x\n", hr); 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(hr == S_OK, "expected S_OK, got %08x\n", hr);
ok(type == XmlNodeType_Element, "expected Element, got %s\n", type_to_str(type)); ok(type == XmlNodeType_Element, "expected Element, got %s\n", type_to_str(type));
ok_pos(reader, 1, 23, 1, 40, TRUE); 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); hr = IXmlReader_GetAttributeCount(reader, &count);
ok(hr == S_OK, "expected S_OK, got %08x\n", hr); 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) static void test_read_element(void)
{ {
struct test_entry *test = element_tests; 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>"; static const char mismatch[] = "<a></b>";
IXmlReader *reader; IXmlReader *reader;
XmlNodeType type; XmlNodeType type;
IStream *stream; IStream *stream;
unsigned int i;
UINT depth; UINT depth;
HRESULT hr; HRESULT hr;
@ -1424,56 +1444,50 @@ static void test_read_element(void)
/* test reader depth increment */ /* test reader depth increment */
stream = create_stream_on_data(stag, sizeof(stag)); 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); ok(hr == S_OK, "got %08x\n", hr);
depth = 1; i = 0;
hr = IXmlReader_GetDepth(reader, &depth); while (IXmlReader_Read(reader, &type) == S_OK)
ok(hr == S_OK, "got %08x\n", hr); {
ok(depth == 0, "got %d\n", depth); ok(type == XmlNodeType_Element || type == XmlNodeType_EndElement ||
type == XmlNodeType_Text, "Unexpected node type %d\n", type);
type = XmlNodeType_None; depth = 123;
hr = IXmlReader_Read(reader, &type); hr = IXmlReader_GetDepth(reader, &depth);
ok(hr == S_OK, "got %08x\n", hr); ok(hr == S_OK, "got %08x\n", hr);
ok(type == XmlNodeType_Element, "got %d\n", type); ok(depth == depths[i], "%u: got depth %u, expected %u\n", i, depth, depths[i]);
depth = 1; if (type == XmlNodeType_Element)
hr = IXmlReader_GetDepth(reader, &depth); {
ok(hr == S_OK, "got %08x\n", hr); UINT count = 0;
ok(depth == 0, "got %d\n", depth);
type = XmlNodeType_None; hr = IXmlReader_GetAttributeCount(reader, &count);
hr = IXmlReader_Read(reader, &type); ok(hr == S_OK, "got %08x\n", hr);
ok(hr == S_OK, "got %08x\n", hr);
ok(type == XmlNodeType_Element, "got %d\n", type);
depth = 0; /* moving to attributes increases depth */
hr = IXmlReader_GetDepth(reader, &depth); if (count)
ok(hr == S_OK, "got %08x\n", hr); {
ok(depth == 1, "got %d\n", depth); hr = IXmlReader_MoveToFirstAttribute(reader);
ok(hr == S_OK, "got %08x\n", hr);
/* read end tag for inner element */ depth = 123;
type = XmlNodeType_None; hr = IXmlReader_GetDepth(reader, &depth);
hr = IXmlReader_Read(reader, &type); ok(hr == S_OK, "got %08x\n", hr);
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);
ok(type == XmlNodeType_EndElement, "got %d\n", type);
depth = 0; hr = IXmlReader_MoveToElement(reader);
hr = IXmlReader_GetDepth(reader, &depth); ok(hr == S_OK, "got %08x\n", hr);
ok(hr == S_OK, "got %08x\n", hr);
todo_wine
ok(depth == 2, "got %d\n", depth);
/* read end tag for container element */ depth = 123;
type = XmlNodeType_None; hr = IXmlReader_GetDepth(reader, &depth);
hr = IXmlReader_Read(reader, &type); ok(hr == S_OK, "got %08x\n", hr);
ok(hr == S_OK, "got %08x\n", hr); ok(depth == depths[i], "%u: got depth %u, expected %u\n", i, depth, depths[i]);
ok(type == XmlNodeType_EndElement, "got %d\n", type); }
}
depth = 0; i++;
hr = IXmlReader_GetDepth(reader, &depth); }
ok(hr == S_OK, "got %08x\n", hr);
ok(depth == 1, "got %d\n", depth);
IStream_Release(stream); IStream_Release(stream);