Nikolay Sivov : xmllite: Initial support for CharData (or Text) nodes.

Alexandre Julliard julliard at winehq.org
Mon Jul 22 14:22:45 CDT 2013


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

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Sat Jun 15 20:45:21 2013 +0400

xmllite: Initial support for CharData (or Text) nodes.

---

 dlls/xmllite/reader.c       |   67 ++++++++++++++++++++++++++--
 dlls/xmllite/tests/reader.c |  101 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 163 insertions(+), 5 deletions(-)

diff --git a/dlls/xmllite/reader.c b/dlls/xmllite/reader.c
index 9193d2f..ec2a071 100644
--- a/dlls/xmllite/reader.c
+++ b/dlls/xmllite/reader.c
@@ -53,7 +53,8 @@ typedef enum
     XmlReadInState_DTD_Misc,
     XmlReadInState_Element,
     XmlReadInState_Content,
-    XmlReadInState_MiscEnd
+    XmlReadInState_MiscEnd, /* optional Misc at the end of a document */
+    XmlReadInState_Eof
 } XmlReaderInternalState;
 
 /* This state denotes where parsing was interrupted by input problem.
@@ -65,7 +66,8 @@ typedef enum
     XmlReadResumeState_PIBody,
     XmlReadResumeState_CDATA,
     XmlReadResumeState_Comment,
-    XmlReadResumeState_STag
+    XmlReadResumeState_STag,
+    XmlReadResumeState_CharData
 } XmlReaderResumeState;
 
 /* saved pointer index to resume from particular input position */
@@ -73,7 +75,7 @@ typedef enum
 {
     XmlReadResume_Name,  /* PITarget, name for NCName, prefix for QName */
     XmlReadResume_Local, /* local for QName */
-    XmlReadResume_Body,  /* PI body, comment text, CDATA text */
+    XmlReadResume_Body,  /* PI body, comment text, CDATA text, CharData text */
     XmlReadResume_Last
 } XmlReaderResume;
 
@@ -1788,6 +1790,10 @@ static HRESULT reader_parse_endtag(xmlreader *reader)
 
     reader_pop_element(reader);
 
+    /* It was a root element, the rest is expected as Misc */
+    if (list_empty(&reader->elements))
+        reader->instate = XmlReadInState_MiscEnd;
+
     reader->nodetype = XmlNodeType_EndElement;
     reader_set_strvalue(reader, StringValue_LocalName, &local);
     reader_set_strvalue(reader, StringValue_QualifiedName, &qname);
@@ -1867,8 +1873,48 @@ static HRESULT reader_parse_reference(xmlreader *reader)
 /* [14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*) */
 static HRESULT reader_parse_chardata(xmlreader *reader)
 {
-    FIXME("CharData not supported\n");
-    return E_NOTIMPL;
+    WCHAR *start, *ptr;
+
+    if (reader->resume[XmlReadResume_Body])
+    {
+        start = reader->resume[XmlReadResume_Body];
+        ptr = reader_get_cur(reader);
+    }
+    else
+    {
+        reader_shrink(reader);
+        ptr = start = reader_get_cur(reader);
+        /* There's no text */
+        if (!*ptr || *ptr == '<') return S_OK;
+        reader->nodetype = XmlNodeType_Text;
+        reader->resume[XmlReadResume_Body] = start;
+        reader->resumestate = XmlReadResumeState_CharData;
+        reader_set_strvalue(reader, StringValue_LocalName, &strval_empty);
+        reader_set_strvalue(reader, StringValue_QualifiedName, &strval_empty);
+        reader_set_strvalue(reader, StringValue_Value, NULL);
+    }
+
+    while (*ptr)
+    {
+        /* CDATA closing sequence ']]>' is not allowed */
+        if (ptr[0] == ']' && ptr[1] == ']' && ptr[2] == '>')
+            return WC_E_CDSECTEND;
+
+        /* Found next markup part */
+        if (ptr[0] == '<')
+        {
+            strval value;
+
+            reader_init_strvalue(start, ptr-start, &value);
+            reader_set_strvalue(reader, StringValue_Value, &value);
+            return S_OK;
+        }
+
+        reader_skipn(reader, 1);
+        ptr++;
+    }
+
+    return S_OK;
 }
 
 /* [43] content ::= CharData? ((element | Reference | CDSect | PI | Comment) CharData?)* */
@@ -1889,6 +1935,8 @@ static HRESULT reader_parse_content(xmlreader *reader)
         case XmlReadResumeState_PIBody:
         case XmlReadResumeState_PITarget:
             return reader_parse_pi(reader);
+        case XmlReadResumeState_CharData:
+            return reader_parse_chardata(reader);
         default:
             ERR("unknown resume state %d\n", reader->resumestate);
         }
@@ -1986,6 +2034,15 @@ static HRESULT reader_parse_nextnode(xmlreader *reader)
             return reader_parse_element(reader);
         case XmlReadInState_Content:
             return reader_parse_content(reader);
+        case XmlReadInState_MiscEnd:
+            hr = reader_parse_misc(reader);
+            if (FAILED(hr)) return hr;
+
+            if (hr == S_FALSE)
+                reader->instate = XmlReadInState_Eof;
+            return hr;
+        case XmlReadInState_Eof:
+            return S_FALSE;
         default:
             FIXME("internal state %d not handled\n", reader->instate);
             return E_NOTIMPL;
diff --git a/dlls/xmllite/tests/reader.c b/dlls/xmllite/tests/reader.c
index 46c6edd..c666712 100644
--- a/dlls/xmllite/tests/reader.c
+++ b/dlls/xmllite/tests/reader.c
@@ -1418,6 +1418,106 @@ static void test_read_cdata(void)
     IXmlReader_Release(reader);
 }
 
+static struct test_entry text_tests[] = {
+    { "<a>simple text</a>", "", "simple text", S_OK },
+    { "<a>text ]]> text</a>", "", "", WC_E_CDSECTEND },
+    { NULL }
+};
+
+static void test_read_text(void)
+{
+    struct test_entry *test = text_tests;
+    IXmlReader *reader;
+    HRESULT hr;
+
+    hr = pCreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
+    ok(hr == S_OK, "S_OK, got %08x\n", hr);
+
+    while (test->xml)
+    {
+        XmlNodeType type;
+        IStream *stream;
+
+        stream = create_stream_on_data(test->xml, strlen(test->xml)+1);
+        hr = IXmlReader_SetInput(reader, (IUnknown*)stream);
+        ok(hr == S_OK, "got %08x\n", hr);
+
+        type = XmlNodeType_None;
+        hr = IXmlReader_Read(reader, &type);
+
+        /* read one more to get to CDATA */
+        if (type == XmlNodeType_Element)
+        {
+            type = XmlNodeType_None;
+            hr = IXmlReader_Read(reader, &type);
+        }
+
+        if (test->hr_broken)
+            ok(hr == test->hr || broken(hr == test->hr_broken), "got %08x for %s\n", hr, test->xml);
+        else
+            ok(hr == test->hr, "got %08x for %s\n", hr, test->xml);
+        if (hr == S_OK)
+        {
+            const WCHAR *str;
+            WCHAR *str_exp;
+            UINT len;
+
+            ok(type == XmlNodeType_Text, "got %d for %s\n", type, test->xml);
+
+            str_exp = a2w(test->name);
+
+            len = 1;
+            str = NULL;
+            hr = IXmlReader_GetLocalName(reader, &str, &len);
+            ok(hr == S_OK, "got 0x%08x\n", hr);
+            ok(len == strlen(test->name), "got %u\n", len);
+            ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str));
+
+            str = NULL;
+            hr = IXmlReader_GetLocalName(reader, &str, NULL);
+            ok(hr == S_OK, "got 0x%08x\n", hr);
+            ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str));
+
+            free_str(str_exp);
+
+            len = 1;
+            str = NULL;
+            hr = IXmlReader_GetQualifiedName(reader, &str, &len);
+            ok(hr == S_OK, "got 0x%08x\n", hr);
+            ok(len == strlen(test->name), "got %u\n", len);
+            str_exp = a2w(test->name);
+            ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str));
+            free_str(str_exp);
+
+            /* value */
+            len = 1;
+            str = NULL;
+            hr = IXmlReader_GetValue(reader, &str, &len);
+            ok(hr == S_OK, "got 0x%08x\n", hr);
+
+            str_exp = a2w(test->value);
+            if (test->todo)
+            {
+            todo_wine {
+                ok(len == strlen(test->value), "got %u\n", len);
+                ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str));
+            }
+            }
+            else
+            {
+                ok(len == strlen(test->value), "got %u\n", len);
+                ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str));
+            }
+            free_str(str_exp);
+        }
+
+        IStream_Release(stream);
+        test++;
+    }
+
+    IXmlReader_Release(reader);
+}
+
 START_TEST(reader)
 {
     HRESULT r;
@@ -1439,6 +1539,7 @@ START_TEST(reader)
     test_read_pi();
     test_read_dtd();
     test_read_element();
+    test_read_text();
     test_read_full();
     test_read_pending();
     test_readvaluechunk();




More information about the wine-cvs mailing list