xmllite: Support resuming for start tag.
This commit is contained in:
parent
d1c52fe168
commit
c87a85cce3
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue