xmllite: Support resuming for start tag.

This commit is contained in:
Nikolay Sivov 2013-03-10 13:28:38 +04:00 committed by Alexandre Julliard
parent d1c52fe168
commit c87a85cce3
2 changed files with 121 additions and 47 deletions

View File

@ -62,14 +62,16 @@ typedef enum
{ {
XmlReadResumeState_Initial, XmlReadResumeState_Initial,
XmlReadResumeState_PITarget, XmlReadResumeState_PITarget,
XmlReadResumeState_PIBody XmlReadResumeState_PIBody,
XmlReadResumeState_STag
} XmlReaderResumeState; } XmlReaderResumeState;
/* saved pointer index to resume from particular input position */ /* saved pointer index to resume from particular input position */
typedef enum typedef enum
{ {
XmlReadResume_Name, /* PITarget */ XmlReadResume_Name, /* PITarget, name for NCName, prefix for QName */
XmlReadResume_Body, /* PI body, comment text */ XmlReadResume_Local, /* local for QName */
XmlReadResume_Body, /* PI body, comment text */
XmlReadResume_Last XmlReadResume_Last
} XmlReaderResume; } XmlReaderResume;
@ -1525,17 +1527,20 @@ static HRESULT reader_parse_dtd(xmlreader *reader)
return S_OK; return S_OK;
} }
/* [7 NS] QName ::= PrefixedName | UnprefixedName /* [11 NS] LocalPart ::= NCName */
[8 NS] PrefixedName ::= Prefix ':' LocalPart static HRESULT reader_parse_local(xmlreader *reader, strval *local)
[9 NS] UnprefixedName ::= LocalPart
[10 NS] Prefix ::= NCName
[11 NS] LocalPart ::= NCName */
static HRESULT reader_parse_qname(xmlreader *reader, strval *prefix, strval *local, strval *qname)
{ {
WCHAR *ptr, *start = reader_get_cur(reader); WCHAR *ptr, *start;
ptr = start; if (reader->resume[XmlReadResume_Local])
if (!is_ncnamechar(*ptr)) return NC_E_QNAMECHARACTER; {
start = reader->resume[XmlReadResume_Local];
ptr = reader_get_cur(reader);
}
else
{
ptr = start = reader_get_cur(reader);
}
while (is_ncnamechar(*ptr)) while (is_ncnamechar(*ptr))
{ {
@ -1543,25 +1548,79 @@ static HRESULT reader_parse_qname(xmlreader *reader, strval *prefix, strval *loc
ptr = reader_get_cur(reader); ptr = reader_get_cur(reader);
} }
/* got a qualified name */ if (is_reader_pending(reader))
if (*ptr == ':')
{ {
prefix->str = start; reader->resume[XmlReadResume_Local] = start;
prefix->len = ptr-start; return E_PENDING;
}
else
reader->resume[XmlReadResume_Local] = NULL;
reader_skipn(reader, 1); local->str = start;
start = ptr = reader_get_cur(reader); local->len = ptr-start;
return S_OK;
}
/* [7 NS] QName ::= PrefixedName | UnprefixedName
[8 NS] PrefixedName ::= Prefix ':' LocalPart
[9 NS] UnprefixedName ::= LocalPart
[10 NS] Prefix ::= NCName */
static HRESULT reader_parse_qname(xmlreader *reader, strval *prefix, strval *local, strval *qname)
{
WCHAR *ptr, *start;
HRESULT hr;
if (reader->resume[XmlReadResume_Name])
{
start = reader->resume[XmlReadResume_Name];
ptr = reader_get_cur(reader);
}
else
{
ptr = start = reader_get_cur(reader);
reader->resume[XmlReadResume_Name] = start;
if (!is_ncnamechar(*ptr)) return NC_E_QNAMECHARACTER;
}
if (reader->resume[XmlReadResume_Local])
{
hr = reader_parse_local(reader, local);
if (FAILED(hr)) return hr;
prefix->str = reader->resume[XmlReadResume_Name];
prefix->len = local->str - prefix->str - 1;
}
else
{
/* skip prefix part */
while (is_ncnamechar(*ptr)) while (is_ncnamechar(*ptr))
{ {
reader_skipn(reader, 1); reader_skipn(reader, 1);
ptr = reader_get_cur(reader); ptr = reader_get_cur(reader);
} }
}
else if (is_reader_pending(reader)) return E_PENDING;
{
prefix->str = NULL; /* got a qualified name */
prefix->len = 0; if (*ptr == ':')
{
prefix->str = start;
prefix->len = ptr-start;
/* skip ':' */
reader_skipn(reader, 1);
hr = reader_parse_local(reader, local);
if (FAILED(hr)) return hr;
}
else
{
local->str = reader->resume[XmlReadResume_Name];
local->len = ptr-local->str;
prefix->str = NULL;
prefix->len = 0;
}
} }
local->str = start; local->str = start;
@ -1576,6 +1635,9 @@ static HRESULT reader_parse_qname(xmlreader *reader, strval *prefix, strval *loc
/* count ':' too */ /* count ':' too */
qname->len = (prefix->len ? prefix->len + 1 : 0) + local->len; qname->len = (prefix->len ? prefix->len + 1 : 0) + local->len;
reader->resume[XmlReadResume_Name] = NULL;
reader->resume[XmlReadResume_Local] = NULL;
return S_OK; return S_OK;
} }
@ -1586,9 +1648,6 @@ static HRESULT reader_parse_stag(xmlreader *reader, strval *prefix, strval *loca
static const WCHAR endW[] = {'/','>',0}; static const WCHAR endW[] = {'/','>',0};
HRESULT hr; HRESULT hr;
/* skip '<' */
reader_skipn(reader, 1);
hr = reader_parse_qname(reader, prefix, local, qname); hr = reader_parse_qname(reader, prefix, local, qname);
if (FAILED(hr)) return hr; if (FAILED(hr)) return hr;
@ -1617,32 +1676,47 @@ static HRESULT reader_parse_stag(xmlreader *reader, strval *prefix, strval *loca
/* [39] element ::= EmptyElemTag | STag content ETag */ /* [39] element ::= EmptyElemTag | STag content ETag */
static HRESULT reader_parse_element(xmlreader *reader) static HRESULT reader_parse_element(xmlreader *reader)
{ {
strval qname, prefix, local;
HRESULT hr; HRESULT hr;
int empty;
/* check if we are really on element */ switch (reader->resumestate)
if (reader_cmp(reader, ltW)) return S_FALSE; {
reader_shrink(reader); case XmlReadResumeState_Initial:
/* check if we are really on element */
if (reader_cmp(reader, ltW)) return S_FALSE;
/* this handles empty elements too */ /* skip '<' */
empty = 0; reader_skipn(reader, 1);
hr = reader_parse_stag(reader, &prefix, &local, &qname, &empty);
if (FAILED(hr)) return hr;
/* FIXME: need to check for defined namespace to reject invalid prefix, reader_shrink(reader);
currently reject all prefixes */ reader->resumestate = XmlReadResumeState_STag;
if (prefix.len) return NC_E_UNDECLAREDPREFIX; case XmlReadResumeState_STag:
{
strval qname, prefix, local;
int empty = 0;
/* if we got empty element and stack is empty go straight to Misc */ /* this handles empty elements too */
if (empty && list_empty(&reader->elements)) hr = reader_parse_stag(reader, &prefix, &local, &qname, &empty);
reader->instate = XmlReadInState_MiscEnd; if (FAILED(hr)) return hr;
else
reader->instate = XmlReadInState_Content;
reader->nodetype = XmlNodeType_Element; /* FIXME: need to check for defined namespace to reject invalid prefix,
reader_set_strvalue(reader, StringValue_LocalName, &local); currently reject all prefixes */
reader_set_strvalue(reader, StringValue_QualifiedName, &qname); if (prefix.len) return NC_E_UNDECLAREDPREFIX;
/* if we got empty element and stack is empty go straight to Misc */
if (empty && list_empty(&reader->elements))
reader->instate = XmlReadInState_MiscEnd;
else
reader->instate = XmlReadInState_Content;
reader->nodetype = XmlNodeType_Element;
reader->resumestate = XmlReadResumeState_Initial;
reader_set_strvalue(reader, StringValue_LocalName, &local);
reader_set_strvalue(reader, StringValue_QualifiedName, &qname);
break;
}
default:
hr = E_FAIL;
}
return hr; return hr;
} }

View File

@ -994,7 +994,7 @@ static void test_read_full(void)
hr = IXmlReader_Read(reader, &type); hr = IXmlReader_Read(reader, &type);
i++; i++;
} }
ok(test->types[i] == XmlNodeType_None, "incomplete sequence\n"); ok(test->types[i] == XmlNodeType_None, "incomplete sequence, got %d\n", test->types[i]);
IStream_Release(stream); IStream_Release(stream);
IXmlReader_Release(reader); IXmlReader_Release(reader);