Commit d1c52fe1 authored by Nikolay Sivov's avatar Nikolay Sivov Committed by Alexandre Julliard

xmllite: Support pending input reads for PI nodes.

parent 3826193f
...@@ -56,6 +56,23 @@ typedef enum ...@@ -56,6 +56,23 @@ typedef enum
XmlReadInState_MiscEnd XmlReadInState_MiscEnd
} XmlReaderInternalState; } XmlReaderInternalState;
/* This state denotes where parsing was interrupted by input problem.
Reader resumes parsing using this information. */
typedef enum
{
XmlReadResumeState_Initial,
XmlReadResumeState_PITarget,
XmlReadResumeState_PIBody
} XmlReaderResumeState;
/* saved pointer index to resume from particular input position */
typedef enum
{
XmlReadResume_Name, /* PITarget */
XmlReadResume_Body, /* PI body, comment text */
XmlReadResume_Last
} XmlReaderResume;
typedef enum typedef enum
{ {
StringValue_LocalName, StringValue_LocalName,
...@@ -146,6 +163,7 @@ typedef struct ...@@ -146,6 +163,7 @@ typedef struct
IMalloc *imalloc; IMalloc *imalloc;
XmlReadState state; XmlReadState state;
XmlReaderInternalState instate; XmlReaderInternalState instate;
XmlReaderResumeState resumestate;
XmlNodeType nodetype; XmlNodeType nodetype;
DtdProcessing dtdmode; DtdProcessing dtdmode;
UINT line, pos; /* reader position in XML stream */ UINT line, pos; /* reader position in XML stream */
...@@ -155,7 +173,7 @@ typedef struct ...@@ -155,7 +173,7 @@ typedef struct
struct list elements; struct list elements;
strval strvalues[StringValue_Last]; strval strvalues[StringValue_Last];
UINT depth; UINT depth;
WCHAR *save; WCHAR *resume[XmlReadResume_Last]; /* pointers used to resume reader */
} xmlreader; } xmlreader;
struct input_buffer struct input_buffer
...@@ -1031,9 +1049,9 @@ static HRESULT reader_parse_comment(xmlreader *reader) ...@@ -1031,9 +1049,9 @@ static HRESULT reader_parse_comment(xmlreader *reader)
{ {
WCHAR *start, *ptr; WCHAR *start, *ptr;
if (reader->save) if (reader->resume[XmlReadResume_Body])
{ {
start = reader->save; start = reader->resume[XmlReadResume_Body];
ptr = reader_get_cur(reader); ptr = reader_get_cur(reader);
} }
else else
...@@ -1043,7 +1061,7 @@ static HRESULT reader_parse_comment(xmlreader *reader) ...@@ -1043,7 +1061,7 @@ static HRESULT reader_parse_comment(xmlreader *reader)
reader_shrink(reader); reader_shrink(reader);
ptr = start = reader_get_cur(reader); ptr = start = reader_get_cur(reader);
reader->nodetype = XmlNodeType_Comment; reader->nodetype = XmlNodeType_Comment;
reader->save = start; reader->resume[XmlReadResume_Body] = start;
reader_set_strvalue(reader, StringValue_LocalName, NULL); reader_set_strvalue(reader, StringValue_LocalName, NULL);
reader_set_strvalue(reader, StringValue_QualifiedName, NULL); reader_set_strvalue(reader, StringValue_QualifiedName, NULL);
reader_set_strvalue(reader, StringValue_Value, NULL); reader_set_strvalue(reader, StringValue_Value, NULL);
...@@ -1067,7 +1085,7 @@ static HRESULT reader_parse_comment(xmlreader *reader) ...@@ -1067,7 +1085,7 @@ static HRESULT reader_parse_comment(xmlreader *reader)
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);
reader_set_strvalue(reader, StringValue_Value, &value); reader_set_strvalue(reader, StringValue_Value, &value);
reader->save = NULL; reader->resume[XmlReadResume_Body] = NULL;
return S_OK; return S_OK;
} }
else else
...@@ -1166,10 +1184,18 @@ static inline int is_namechar(WCHAR ch) ...@@ -1166,10 +1184,18 @@ static inline int is_namechar(WCHAR ch)
[5] Name ::= NameStartChar (NameChar)* */ [5] Name ::= NameStartChar (NameChar)* */
static HRESULT reader_parse_name(xmlreader *reader, strval *name) static HRESULT reader_parse_name(xmlreader *reader, strval *name)
{ {
WCHAR *ptr, *start = reader_get_cur(reader); WCHAR *ptr, *start;
ptr = start; if (reader->resume[XmlReadResume_Name])
if (!is_namestartchar(*ptr)) return WC_E_NAMECHARACTER; {
start = reader->resume[XmlReadResume_Name];
ptr = reader_get_cur(reader);
}
else
{
ptr = start = reader_get_cur(reader);
if (!is_namestartchar(*ptr)) return WC_E_NAMECHARACTER;
}
while (is_namechar(*ptr)) while (is_namechar(*ptr))
{ {
...@@ -1177,6 +1203,14 @@ static HRESULT reader_parse_name(xmlreader *reader, strval *name) ...@@ -1177,6 +1203,14 @@ static HRESULT reader_parse_name(xmlreader *reader, strval *name)
ptr = reader_get_cur(reader); ptr = reader_get_cur(reader);
} }
if (is_reader_pending(reader))
{
reader->resume[XmlReadResume_Name] = start;
return E_PENDING;
}
else
reader->resume[XmlReadResume_Name] = NULL;
TRACE("name %s:%d\n", debugstr_wn(start, ptr-start), (int)(ptr-start)); TRACE("name %s:%d\n", debugstr_wn(start, ptr-start), (int)(ptr-start));
name->str = start; name->str = start;
name->len = ptr-start; name->len = ptr-start;
...@@ -1193,7 +1227,7 @@ static HRESULT reader_parse_pitarget(xmlreader *reader, strval *target) ...@@ -1193,7 +1227,7 @@ static HRESULT reader_parse_pitarget(xmlreader *reader, strval *target)
UINT i; UINT i;
hr = reader_parse_name(reader, &name); hr = reader_parse_name(reader, &name);
if (FAILED(hr)) return WC_E_PI; if (FAILED(hr)) return is_reader_pending(reader) ? E_PENDING : WC_E_PI;
/* now that we got name check for illegal content */ /* now that we got name check for illegal content */
if (name.len == 3 && !strncmpiW(name.str, xmlW, 3)) if (name.len == 3 && !strncmpiW(name.str, xmlW, 3))
...@@ -1216,12 +1250,20 @@ static HRESULT reader_parse_pi(xmlreader *reader) ...@@ -1216,12 +1250,20 @@ static HRESULT reader_parse_pi(xmlreader *reader)
strval target; strval target;
HRESULT hr; HRESULT hr;
/* skip '<?' */ switch (reader->resumestate)
reader_skipn(reader, 2); {
reader_shrink(reader); case XmlReadResumeState_Initial:
/* skip '<?' */
hr = reader_parse_pitarget(reader, &target); reader_skipn(reader, 2);
if (FAILED(hr)) return hr; reader_shrink(reader);
reader->resumestate = XmlReadResumeState_PITarget;
case XmlReadResumeState_PITarget:
hr = reader_parse_pitarget(reader, &target);
if (FAILED(hr)) return hr;
reader->resumestate = XmlReadResumeState_PIBody;
default:
;
}
ptr = reader_get_cur(reader); ptr = reader_get_cur(reader);
/* exit earlier if there's no content */ /* exit earlier if there's no content */
...@@ -1230,17 +1272,26 @@ static HRESULT reader_parse_pi(xmlreader *reader) ...@@ -1230,17 +1272,26 @@ static HRESULT reader_parse_pi(xmlreader *reader)
/* skip '?>' */ /* skip '?>' */
reader_skipn(reader, 2); reader_skipn(reader, 2);
reader->nodetype = XmlNodeType_ProcessingInstruction; reader->nodetype = XmlNodeType_ProcessingInstruction;
reader->resumestate = XmlReadResumeState_Initial;
reader_set_strvalue(reader, StringValue_LocalName, &target); reader_set_strvalue(reader, StringValue_LocalName, &target);
reader_set_strvalue(reader, StringValue_QualifiedName, &target); reader_set_strvalue(reader, StringValue_QualifiedName, &target);
reader_set_strvalue(reader, StringValue_Value, &strval_empty); reader_set_strvalue(reader, StringValue_Value, &strval_empty);
return S_OK; return S_OK;
} }
/* now at least a single space char should be there */ if (!reader->resume[XmlReadResume_Body])
if (!is_wchar_space(*ptr)) return WC_E_WHITESPACE; {
reader_skipspaces(reader); /* now at least a single space char should be there */
if (!is_wchar_space(*ptr)) return WC_E_WHITESPACE;
ptr = start = reader_get_cur(reader); reader_skipspaces(reader);
ptr = start = reader_get_cur(reader);
reader->resume[XmlReadResume_Body] = start;
}
else
{
start = reader->resume[XmlReadResume_Body];
ptr = reader_get_cur(reader);
}
while (*ptr) while (*ptr)
{ {
...@@ -1254,6 +1305,8 @@ static HRESULT reader_parse_pi(xmlreader *reader) ...@@ -1254,6 +1305,8 @@ static HRESULT reader_parse_pi(xmlreader *reader)
/* skip '?>' */ /* skip '?>' */
reader_skipn(reader, 2); reader_skipn(reader, 2);
reader->nodetype = XmlNodeType_ProcessingInstruction; reader->nodetype = XmlNodeType_ProcessingInstruction;
reader->resumestate = XmlReadResumeState_Initial;
reader->resume[XmlReadResume_Body] = NULL;
reader_set_strvalue(reader, StringValue_LocalName, &target); reader_set_strvalue(reader, StringValue_LocalName, &target);
reader_set_strvalue(reader, StringValue_QualifiedName, &target); reader_set_strvalue(reader, StringValue_QualifiedName, &target);
reader_set_strvalue(reader, StringValue_Value, &value); reader_set_strvalue(reader, StringValue_Value, &value);
...@@ -1832,7 +1885,8 @@ static HRESULT WINAPI xmlreader_SetInput(IXmlReader* iface, IUnknown *input) ...@@ -1832,7 +1885,8 @@ 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->save = NULL; This->resumestate = XmlReadResumeState_Initial;
memset(This->resume, 0, sizeof(This->resume));
/* just reset current input */ /* just reset current input */
if (!input) if (!input)
...@@ -2255,6 +2309,7 @@ HRESULT WINAPI CreateXmlReader(REFIID riid, void **obj, IMalloc *imalloc) ...@@ -2255,6 +2309,7 @@ HRESULT WINAPI CreateXmlReader(REFIID riid, void **obj, IMalloc *imalloc)
reader->input = NULL; reader->input = NULL;
reader->state = XmlReadState_Closed; reader->state = XmlReadState_Closed;
reader->instate = XmlReadInState_Initial; reader->instate = XmlReadInState_Initial;
reader->resumestate = XmlReadResumeState_Initial;
reader->dtdmode = DtdProcessing_Prohibit; reader->dtdmode = DtdProcessing_Prohibit;
reader->line = reader->pos = 0; reader->line = reader->pos = 0;
reader->imalloc = imalloc; reader->imalloc = imalloc;
...@@ -2265,7 +2320,7 @@ HRESULT WINAPI CreateXmlReader(REFIID riid, void **obj, IMalloc *imalloc) ...@@ -2265,7 +2320,7 @@ HRESULT WINAPI CreateXmlReader(REFIID riid, void **obj, IMalloc *imalloc)
reader->attr = NULL; reader->attr = NULL;
list_init(&reader->elements); list_init(&reader->elements);
reader->depth = 0; reader->depth = 0;
reader->save = NULL; memset(reader->resume, 0, sizeof(reader->resume));
for (i = 0; i < StringValue_Last; i++) for (i = 0; i < StringValue_Last; i++)
reader->strvalues[i] = strval_empty; reader->strvalues[i] = strval_empty;
......
...@@ -852,6 +852,7 @@ static void test_read_comment(void) ...@@ -852,6 +852,7 @@ static void test_read_comment(void)
static struct test_entry pi_tests[] = { static struct test_entry pi_tests[] = {
{ "<?pi?>", "pi", "", S_OK }, { "<?pi?>", "pi", "", S_OK },
{ "<?pi ?>", "pi", "", S_OK }, { "<?pi ?>", "pi", "", S_OK },
{ "<?pi ?>", "pi", "", S_OK },
{ "<?pi pi data?>", "pi", "pi data", S_OK }, { "<?pi pi data?>", "pi", "pi data", S_OK },
{ "<?pi pi data ?>", "pi", "pi data ", S_OK }, { "<?pi pi data ?>", "pi", "pi data ", S_OK },
{ "<?pi:pi?>", NULL, NULL, NC_E_NAMECOLON, WC_E_NAMECHARACTER }, { "<?pi:pi?>", NULL, NULL, NC_E_NAMECOLON, WC_E_NAMECHARACTER },
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment