Nikolay Sivov : xmllite: Support pending input reads for PI nodes.
Alexandre Julliard
julliard at winehq.org
Mon Mar 11 16:24:51 CDT 2013
Module: wine
Branch: master
Commit: d1c52fe168c24ac61223b63cc41a10c63491271a
URL: http://source.winehq.org/git/wine.git/?a=commit;h=d1c52fe168c24ac61223b63cc41a10c63491271a
Author: Nikolay Sivov <nsivov at codeweavers.com>
Date: Fri Mar 8 14:10:26 2013 +0400
xmllite: Support pending input reads for PI nodes.
---
dlls/xmllite/reader.c | 99 +++++++++++++++++++++++++++++++++----------
dlls/xmllite/tests/reader.c | 1 +
2 files changed, 78 insertions(+), 22 deletions(-)
diff --git a/dlls/xmllite/reader.c b/dlls/xmllite/reader.c
index c6f416d..b4a7f33 100644
--- a/dlls/xmllite/reader.c
+++ b/dlls/xmllite/reader.c
@@ -56,6 +56,23 @@ typedef enum
XmlReadInState_MiscEnd
} 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
{
StringValue_LocalName,
@@ -146,6 +163,7 @@ typedef struct
IMalloc *imalloc;
XmlReadState state;
XmlReaderInternalState instate;
+ XmlReaderResumeState resumestate;
XmlNodeType nodetype;
DtdProcessing dtdmode;
UINT line, pos; /* reader position in XML stream */
@@ -155,7 +173,7 @@ typedef struct
struct list elements;
strval strvalues[StringValue_Last];
UINT depth;
- WCHAR *save;
+ WCHAR *resume[XmlReadResume_Last]; /* pointers used to resume reader */
} xmlreader;
struct input_buffer
@@ -1031,9 +1049,9 @@ static HRESULT reader_parse_comment(xmlreader *reader)
{
WCHAR *start, *ptr;
- if (reader->save)
+ if (reader->resume[XmlReadResume_Body])
{
- start = reader->save;
+ start = reader->resume[XmlReadResume_Body];
ptr = reader_get_cur(reader);
}
else
@@ -1043,7 +1061,7 @@ static HRESULT reader_parse_comment(xmlreader *reader)
reader_shrink(reader);
ptr = start = reader_get_cur(reader);
reader->nodetype = XmlNodeType_Comment;
- reader->save = start;
+ reader->resume[XmlReadResume_Body] = start;
reader_set_strvalue(reader, StringValue_LocalName, NULL);
reader_set_strvalue(reader, StringValue_QualifiedName, NULL);
reader_set_strvalue(reader, StringValue_Value, NULL);
@@ -1067,7 +1085,7 @@ static HRESULT reader_parse_comment(xmlreader *reader)
reader_set_strvalue(reader, StringValue_LocalName, &strval_empty);
reader_set_strvalue(reader, StringValue_QualifiedName, &strval_empty);
reader_set_strvalue(reader, StringValue_Value, &value);
- reader->save = NULL;
+ reader->resume[XmlReadResume_Body] = NULL;
return S_OK;
}
else
@@ -1166,10 +1184,18 @@ static inline int is_namechar(WCHAR ch)
[5] Name ::= NameStartChar (NameChar)* */
static HRESULT reader_parse_name(xmlreader *reader, strval *name)
{
- WCHAR *ptr, *start = reader_get_cur(reader);
+ WCHAR *ptr, *start;
- ptr = start;
- if (!is_namestartchar(*ptr)) return WC_E_NAMECHARACTER;
+ if (reader->resume[XmlReadResume_Name])
+ {
+ 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))
{
@@ -1177,6 +1203,14 @@ static HRESULT reader_parse_name(xmlreader *reader, strval *name)
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));
name->str = start;
name->len = ptr-start;
@@ -1193,7 +1227,7 @@ static HRESULT reader_parse_pitarget(xmlreader *reader, strval *target)
UINT i;
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 */
if (name.len == 3 && !strncmpiW(name.str, xmlW, 3))
@@ -1216,12 +1250,20 @@ static HRESULT reader_parse_pi(xmlreader *reader)
strval target;
HRESULT hr;
- /* skip '<?' */
- reader_skipn(reader, 2);
- reader_shrink(reader);
-
- hr = reader_parse_pitarget(reader, &target);
- if (FAILED(hr)) return hr;
+ switch (reader->resumestate)
+ {
+ case XmlReadResumeState_Initial:
+ /* skip '<?' */
+ reader_skipn(reader, 2);
+ 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);
/* exit earlier if there's no content */
@@ -1230,17 +1272,26 @@ static HRESULT reader_parse_pi(xmlreader *reader)
/* skip '?>' */
reader_skipn(reader, 2);
reader->nodetype = XmlNodeType_ProcessingInstruction;
+ reader->resumestate = XmlReadResumeState_Initial;
reader_set_strvalue(reader, StringValue_LocalName, &target);
reader_set_strvalue(reader, StringValue_QualifiedName, &target);
reader_set_strvalue(reader, StringValue_Value, &strval_empty);
return S_OK;
}
- /* now at least a single space char should be there */
- if (!is_wchar_space(*ptr)) return WC_E_WHITESPACE;
- reader_skipspaces(reader);
-
- ptr = start = reader_get_cur(reader);
+ if (!reader->resume[XmlReadResume_Body])
+ {
+ /* now at least a single space char should be there */
+ if (!is_wchar_space(*ptr)) return WC_E_WHITESPACE;
+ 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)
{
@@ -1254,6 +1305,8 @@ static HRESULT reader_parse_pi(xmlreader *reader)
/* skip '?>' */
reader_skipn(reader, 2);
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_QualifiedName, &target);
reader_set_strvalue(reader, StringValue_Value, &value);
@@ -1832,7 +1885,8 @@ static HRESULT WINAPI xmlreader_SetInput(IXmlReader* iface, IUnknown *input)
This->line = This->pos = 0;
reader_clear_elements(This);
This->depth = 0;
- This->save = NULL;
+ This->resumestate = XmlReadResumeState_Initial;
+ memset(This->resume, 0, sizeof(This->resume));
/* just reset current input */
if (!input)
@@ -2255,6 +2309,7 @@ HRESULT WINAPI CreateXmlReader(REFIID riid, void **obj, IMalloc *imalloc)
reader->input = NULL;
reader->state = XmlReadState_Closed;
reader->instate = XmlReadInState_Initial;
+ reader->resumestate = XmlReadResumeState_Initial;
reader->dtdmode = DtdProcessing_Prohibit;
reader->line = reader->pos = 0;
reader->imalloc = imalloc;
@@ -2265,7 +2320,7 @@ HRESULT WINAPI CreateXmlReader(REFIID riid, void **obj, IMalloc *imalloc)
reader->attr = NULL;
list_init(&reader->elements);
reader->depth = 0;
- reader->save = NULL;
+ memset(reader->resume, 0, sizeof(reader->resume));
for (i = 0; i < StringValue_Last; i++)
reader->strvalues[i] = strval_empty;
diff --git a/dlls/xmllite/tests/reader.c b/dlls/xmllite/tests/reader.c
index 65c3448..77e596a 100644
--- a/dlls/xmllite/tests/reader.c
+++ b/dlls/xmllite/tests/reader.c
@@ -852,6 +852,7 @@ static void test_read_comment(void)
static struct test_entry pi_tests[] = {
{ "<?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?>", NULL, NULL, NC_E_NAMECOLON, WC_E_NAMECHARACTER },
More information about the wine-cvs
mailing list