Nikolay Sivov : xmllite: Support predefined xml entities.

Alexandre Julliard julliard at winehq.org
Tue Aug 20 14:38:38 CDT 2013


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

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Tue Aug 20 14:07:32 2013 +0400

xmllite: Support predefined xml entities.

---

 dlls/xmllite/reader.c       |   79 ++++++++++++++++++++++++++++++++++++++-----
 dlls/xmllite/tests/reader.c |    3 ++
 2 files changed, 73 insertions(+), 9 deletions(-)

diff --git a/dlls/xmllite/reader.c b/dlls/xmllite/reader.c
index efdc6ff..e193e9d 100644
--- a/dlls/xmllite/reader.c
+++ b/dlls/xmllite/reader.c
@@ -207,9 +207,9 @@ static const struct IUnknownVtbl xmlreaderinputvtbl;
  */
 typedef struct
 {
-    WCHAR *start; /* input position where value starts */
-    UINT len;     /* length in WCHARs, altered after ReadValueChunk */
     WCHAR *str;   /* allocated null-terminated string */
+    UINT   len;   /* length in WCHARs, altered after ReadValueChunk */
+    WCHAR *start; /* input position where value starts */
 } strval;
 
 static WCHAR emptyW[] = {0};
@@ -1788,11 +1788,50 @@ static void reader_normalize_space(xmlreader *reader, WCHAR *ptr)
     *ptr = ' ';
 }
 
+static WCHAR get_predefined_entity(const strval *name)
+{
+    static const WCHAR entltW[]   = {'l','t'};
+    static const WCHAR entgtW[]   = {'g','t'};
+    static const WCHAR entampW[]  = {'a','m','p'};
+    static const WCHAR entaposW[] = {'a','p','o','s'};
+    static const WCHAR entquotW[] = {'q','u','o','t'};
+
+    static const strval lt   = { (WCHAR*)entltW,   2 };
+    static const strval gt   = { (WCHAR*)entgtW,   2 };
+    static const strval amp  = { (WCHAR*)entampW,  3 };
+    static const strval apos = { (WCHAR*)entaposW, 4 };
+    static const strval quot = { (WCHAR*)entquotW, 4 };
+
+    switch (name->str[0])
+    {
+    case 'l':
+        if (strval_eq(name, &lt)) return '<';
+        break;
+    case 'g':
+        if (strval_eq(name, &gt)) return '>';
+        break;
+    case 'a':
+        if (strval_eq(name, &amp))
+            return '&';
+        else if (strval_eq(name, &apos))
+            return '\'';
+        break;
+    case 'q':
+        if (strval_eq(name, &quot)) return '\"';
+        break;
+    default:
+        ;
+    }
+
+    return 0;
+}
+
 /* [66] CharRef ::= '&#' [0-9]+ ';' | '&#x' [0-9a-fA-F]+ ';'
    [67] Reference ::= EntityRef | CharRef
    [68] EntityRef ::= '&' Name ';' */
 static HRESULT reader_parse_reference(xmlreader *reader)
 {
+    encoded_buffer *buffer = &reader->input->buffer->utf16;
     WCHAR *start = reader_get_cur(reader), *ptr;
     WCHAR ch = 0;
     int len;
@@ -1803,8 +1842,6 @@ static HRESULT reader_parse_reference(xmlreader *reader)
 
     if (*ptr == '#')
     {
-        encoded_buffer *buffer = &reader->input->buffer->utf16;
-
         reader_skipn(reader, 1);
         ptr = reader_get_cur(reader);
 
@@ -1850,16 +1887,40 @@ static HRESULT reader_parse_reference(xmlreader *reader)
 
         len = buffer->written - ((char*)ptr - buffer->data) - sizeof(WCHAR);
         memmove(start+1, ptr+1, len);
-        buffer->cur = (char*)start;
+        buffer->cur = (char*)(start+1);
 
         *start = ch;
-
-        return S_OK;
     }
     else
-        FIXME("Entity references not supported\n");
+    {
+        strval name;
+        HRESULT hr;
 
-    return E_NOTIMPL;
+        hr = reader_parse_name(reader, &name);
+        if (FAILED(hr)) return hr;
+
+        ptr = reader_get_cur(reader);
+        if (*ptr != ';') return WC_E_SEMICOLON;
+
+        /* predefined entities resolve to a single character */
+        ch = get_predefined_entity(&name);
+        if (ch)
+        {
+            len = buffer->written - ((char*)ptr - buffer->data) - sizeof(WCHAR);
+            memmove(start+1, ptr+1, len);
+            buffer->cur = (char*)(start+1);
+
+            *start = ch;
+        }
+        else
+        {
+            FIXME("undeclared entity %s\n", debugstr_wn(name.str, name.len));
+            return WC_E_UNDECLAREDENTITY;
+        }
+
+    }
+
+    return S_OK;
 }
 
 /* [10 NS] AttValue ::= '"' ([^<&"] | Reference)* '"' | "'" ([^<&'] | Reference)* "'" */
diff --git a/dlls/xmllite/tests/reader.c b/dlls/xmllite/tests/reader.c
index b53c044..d7400bc 100644
--- a/dlls/xmllite/tests/reader.c
+++ b/dlls/xmllite/tests/reader.c
@@ -1576,6 +1576,8 @@ static struct test_entry attributes_tests[] = {
     { "<a attr1=\"\r\n\tval\n\"/>", "attr1", "  val ", S_OK },
     { "<a attr1=\"val \"/>", "attr1", "val ", S_OK },
     { "<a attr1=\"val&#x20;\"/>", "attr1", "val ", S_OK },
+    { "<a attr1=\"<>&'"\"/>", "attr1", "<>&\'\"", S_OK },
+    { "<a attr1=\"&entname;\"/>", NULL, NULL, WC_E_UNDECLAREDENTITY },
     { "<a attr1=\"val&#xfffe;\"/>", NULL, NULL, WC_E_XMLCHARACTER },
     { "<a attr1=\"val &#a;\"/>", NULL, NULL, WC_E_DIGIT, WC_E_SEMICOLON },
     { "<a attr1=\"val &#12a;\"/>", NULL, NULL, WC_E_SEMICOLON },
@@ -1583,6 +1585,7 @@ static struct test_entry attributes_tests[] = {
     { "<a attr1=\"val &#xg;\"/>", NULL, NULL, WC_E_HEXDIGIT, WC_E_SEMICOLON },
     { "<a attr1=attrvalue/>", NULL, NULL, WC_E_QUOTE },
     { "<a attr1=\"attr<value\"/>", NULL, NULL, WC_E_LESSTHAN },
+    { "<a attr1=\"&entname\"/>", NULL, NULL, WC_E_SEMICOLON },
     { NULL }
 };
 




More information about the wine-cvs mailing list