Nikolay Sivov : xmllite: Support resuming for start tag.

Alexandre Julliard julliard at winehq.org
Mon Mar 11 16:24:51 CDT 2013


Module: wine
Branch: master
Commit: c87a85cce37a239161924854042bf2c4d33923e9
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=c87a85cce37a239161924854042bf2c4d33923e9

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Sun Mar 10 13:28:38 2013 +0400

xmllite: Support resuming for start tag.

---

 dlls/xmllite/reader.c       |  166 +++++++++++++++++++++++++++++++------------
 dlls/xmllite/tests/reader.c |    2 +-
 2 files changed, 121 insertions(+), 47 deletions(-)

diff --git a/dlls/xmllite/reader.c b/dlls/xmllite/reader.c
index b4a7f33..489d346 100644
--- a/dlls/xmllite/reader.c
+++ b/dlls/xmllite/reader.c
@@ -62,14 +62,16 @@ typedef enum
 {
     XmlReadResumeState_Initial,
     XmlReadResumeState_PITarget,
-    XmlReadResumeState_PIBody
+    XmlReadResumeState_PIBody,
+    XmlReadResumeState_STag
 } XmlReaderResumeState;
 
 /* saved pointer index to resume from particular input position */
 typedef enum
 {
-    XmlReadResume_Name, /* PITarget */
-    XmlReadResume_Body, /* PI body, comment text */
+    XmlReadResume_Name,  /* PITarget, name for NCName, prefix for QName */
+    XmlReadResume_Local, /* local for QName */
+    XmlReadResume_Body,  /* PI body, comment text */
     XmlReadResume_Last
 } XmlReaderResume;
 
@@ -1525,17 +1527,20 @@ static HRESULT reader_parse_dtd(xmlreader *reader)
     return S_OK;
 }
 
-/* [7 NS]  QName ::= PrefixedName | UnprefixedName
-   [8 NS]  PrefixedName ::= Prefix ':' LocalPart
-   [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)
+/* [11 NS] LocalPart ::= NCName */
+static HRESULT reader_parse_local(xmlreader *reader, strval *local)
 {
-    WCHAR *ptr, *start = reader_get_cur(reader);
+    WCHAR *ptr, *start;
 
-    ptr = start;
-    if (!is_ncnamechar(*ptr)) return NC_E_QNAMECHARACTER;
+    if (reader->resume[XmlReadResume_Local])
+    {
+        start = reader->resume[XmlReadResume_Local];
+        ptr = reader_get_cur(reader);
+    }
+    else
+    {
+        ptr = start = reader_get_cur(reader);
+    }
 
     while (is_ncnamechar(*ptr))
     {
@@ -1543,25 +1548,79 @@ static HRESULT reader_parse_qname(xmlreader *reader, strval *prefix, strval *loc
         ptr = reader_get_cur(reader);
     }
 
-    /* got a qualified name */
-    if (*ptr == ':')
+    if (is_reader_pending(reader))
     {
-        prefix->str = start;
-        prefix->len = ptr-start;
+         reader->resume[XmlReadResume_Local] = start;
+         return E_PENDING;
+    }
+    else
+         reader->resume[XmlReadResume_Local] = NULL;
 
-        reader_skipn(reader, 1);
-        start = ptr = reader_get_cur(reader);
+    local->str = start;
+    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))
         {
             reader_skipn(reader, 1);
             ptr = reader_get_cur(reader);
         }
-    }
-    else
-    {
-        prefix->str = NULL;
-        prefix->len = 0;
+
+        if (is_reader_pending(reader)) return E_PENDING;
+
+        /* got a qualified name */
+        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;
@@ -1576,6 +1635,9 @@ static HRESULT reader_parse_qname(xmlreader *reader, strval *prefix, strval *loc
     /* count ':' too */
     qname->len = (prefix->len ? prefix->len + 1 : 0) + local->len;
 
+    reader->resume[XmlReadResume_Name] = NULL;
+    reader->resume[XmlReadResume_Local] = NULL;
+
     return S_OK;
 }
 
@@ -1586,9 +1648,6 @@ static HRESULT reader_parse_stag(xmlreader *reader, strval *prefix, strval *loca
     static const WCHAR endW[] = {'/','>',0};
     HRESULT hr;
 
-    /* skip '<' */
-    reader_skipn(reader, 1);
-
     hr = reader_parse_qname(reader, prefix, local, qname);
     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 */
 static HRESULT reader_parse_element(xmlreader *reader)
 {
-    strval qname, prefix, local;
     HRESULT hr;
-    int empty;
 
-    /* check if we are really on element */
-    if (reader_cmp(reader, ltW)) return S_FALSE;
-    reader_shrink(reader);
+    switch (reader->resumestate)
+    {
+    case XmlReadResumeState_Initial:
+        /* check if we are really on element */
+        if (reader_cmp(reader, ltW)) return S_FALSE;
 
-    /* this handles empty elements too */
-    empty = 0;
-    hr = reader_parse_stag(reader, &prefix, &local, &qname, &empty);
-    if (FAILED(hr)) return hr;
+        /* skip '<' */
+        reader_skipn(reader, 1);
 
-    /* FIXME: need to check for defined namespace to reject invalid prefix,
-       currently reject all prefixes */
-    if (prefix.len) return NC_E_UNDECLAREDPREFIX;
+        reader_shrink(reader);
+        reader->resumestate = XmlReadResumeState_STag;
+    case XmlReadResumeState_STag:
+    {
+        strval qname, prefix, local;
+        int empty = 0;
 
-    /* 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;
+        /* this handles empty elements too */
+        hr = reader_parse_stag(reader, &prefix, &local, &qname, &empty);
+        if (FAILED(hr)) return hr;
 
-    reader->nodetype = XmlNodeType_Element;
-    reader_set_strvalue(reader, StringValue_LocalName, &local);
-    reader_set_strvalue(reader, StringValue_QualifiedName, &qname);
+        /* FIXME: need to check for defined namespace to reject invalid prefix,
+           currently reject all prefixes */
+        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;
 }
diff --git a/dlls/xmllite/tests/reader.c b/dlls/xmllite/tests/reader.c
index 77e596a..9829452 100644
--- a/dlls/xmllite/tests/reader.c
+++ b/dlls/xmllite/tests/reader.c
@@ -994,7 +994,7 @@ static void test_read_full(void)
         hr = IXmlReader_Read(reader, &type);
         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);
     IXmlReader_Release(reader);




More information about the wine-cvs mailing list