[2/2] xmllite: Add partial support for xml declaration parsing

Nikolay Sivov nsivov at codeweavers.com
Mon Nov 26 03:08:22 CST 2012


Add partial support for xml declaration parsing
-------------- next part --------------
>From 729cb63f686018c5bfe6fc4249a5c351841a9482 Mon Sep 17 00:00:00 2001
From: Nikolay Sivov <nsivov at codeweavers.com>
Date: Sun, 25 Nov 2012 21:59:49 -0500
Subject: [PATCH 2/4] Add partial support for xml declaration parsing

---
 dlls/xmllite/reader.c |  148 +++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 142 insertions(+), 6 deletions(-)

diff --git a/dlls/xmllite/reader.c b/dlls/xmllite/reader.c
index 878b3d1..62c58df 100644
--- a/dlls/xmllite/reader.c
+++ b/dlls/xmllite/reader.c
@@ -1,7 +1,7 @@
 /*
  * IXmlReader implementation
  *
- * Copyright 2010 Nikolay Sivov
+ * Copyright 2010, 2012 Nikolay Sivov
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -48,7 +48,7 @@ static const WCHAR utf8W[] = {'U','T','F','-','8',0};
 
 struct xml_encoding_data
 {
-    const WCHAR *encoding;
+    const WCHAR *name;
     xml_encoding enc;
     UINT cp;
 };
@@ -213,11 +213,11 @@ static HRESULT get_code_page(xml_encoding encoding, UINT *cp)
     return S_OK;
 }
 
-static xml_encoding parse_encoding_name(const WCHAR *encoding)
+static xml_encoding parse_encoding_name(const WCHAR *name)
 {
     int min, max, n, c;
 
-    if (!encoding) return XmlEncoding_Unknown;
+    if (!name) return XmlEncoding_Unknown;
 
     min = 0;
     max = sizeof(xml_encoding_map)/sizeof(struct xml_encoding_data) - 1;
@@ -226,7 +226,7 @@ static xml_encoding parse_encoding_name(const WCHAR *encoding)
     {
         n = (min+max)/2;
 
-        c = strcmpiW(xml_encoding_map[n].encoding, encoding);
+        c = strcmpiW(xml_encoding_map[n].name, name);
         if (!c)
             return xml_encoding_map[n].enc;
 
@@ -431,6 +431,136 @@ static void readerinput_switchencoding(xmlreaderinput *readerinput, xml_encoding
     readerinput->buffer->code_page = cp;
 }
 
+static inline const WCHAR *reader_get_cur(xmlreader *reader)
+{
+    return (WCHAR*)reader->input->buffer->utf16.cur;
+}
+
+static int reader_cmp(xmlreader *reader, const WCHAR *str)
+{
+    const WCHAR *ptr = reader_get_cur(reader);
+    int i = 0;
+
+    return strncmpW(str, ptr, strlenW(str));
+
+    while (str[i]) {
+        if (ptr[i] != str[i]) return 0;
+        i++;
+    }
+
+    return 1;
+}
+
+/* moves cursor n WCHARs forward */
+static void reader_skipn(xmlreader *reader, int n)
+{
+    encoded_buffer *buffer = &reader->input->buffer->utf16;
+    const WCHAR *ptr = reader_get_cur(reader);
+
+    while (*ptr++ && n--)
+    {
+        buffer->cur += sizeof(WCHAR);
+        reader->pos++;
+    }
+}
+
+/* [3] S ::= (#x20 | #x9 | #xD | #xA)+ */
+static int reader_skipspaces(xmlreader *reader)
+{
+    encoded_buffer *buffer = &reader->input->buffer->utf16;
+    const WCHAR *ptr = reader_get_cur(reader), *start = ptr;
+
+    while (*ptr == ' ' || *ptr == '\t' || *ptr == '\r' || *ptr == '\n')
+    {
+        buffer->cur += sizeof(WCHAR);
+        if (*ptr == '\r')
+            reader->pos = 0;
+        else if (*ptr == '\n')
+        {
+            reader->line++;
+            reader->pos = 0;
+        }
+        else
+            reader->pos++;
+        ptr++;
+    }
+
+    return ptr - start;
+}
+
+/* [26] VersionNum ::= '1.' [0-9]+ */
+static HRESULT reader_parse_versionnum(xmlreader *reader)
+{
+    const WCHAR *ptr, *start = reader_get_cur(reader);
+    static const WCHAR onedotW[] = {'1','.',0};
+
+    if (reader_cmp(reader, onedotW)) return WC_E_XMLDECL;
+    /* skip "1." */
+    reader_skipn(reader, 2);
+
+    ptr = reader_get_cur(reader);
+    while (*ptr >= '0' && *ptr <= '9')
+        ptr++;
+
+    if (ptr == start) return WC_E_DIGIT;
+    TRACE("version=%s\n", debugstr_wn(start, ptr-start));
+    reader_skipn(reader, ptr-start);
+    return S_OK;
+}
+
+/* [24] VersionInfo ::= S 'version' Eq ("'" VersionNum "'" | '"' VersionNum '"') */
+static HRESULT reader_parse_versioninfo(xmlreader *reader)
+{
+    static const WCHAR versionW[] = {'v','e','r','s','i','o','n',0};
+    static const WCHAR dblquoteW[] = {'\"',0};
+    static const WCHAR quoteW[] = {'\'',0};
+    static const WCHAR eqW[] = {'=',0};
+    HRESULT hr;
+
+    if (!reader_skipspaces(reader)) return WC_E_WHITESPACE;
+
+    if (reader_cmp(reader, versionW)) return WC_E_XMLDECL;
+    /* skip 'version' */
+    reader_skipn(reader, 7);
+
+    if (reader_cmp(reader, eqW)) return WC_E_EQUAL;
+    /* skip '=' */
+    reader_skipn(reader, 1);
+
+    if (reader_cmp(reader, quoteW) && reader_cmp(reader, dblquoteW))
+        return WC_E_QUOTE;
+    /* skip "'"|'"' */
+    reader_skipn(reader, 1);
+
+    hr = reader_parse_versionnum(reader);
+    if (FAILED(hr)) return hr;
+
+    if (reader_cmp(reader, quoteW) && reader_cmp(reader, dblquoteW))
+        return WC_E_QUOTE;
+
+    /* skip "'"|'"' */
+    reader_skipn(reader, 1);
+
+    return S_OK;
+}
+
+/* [23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>' */
+static HRESULT reader_parse_xmldecl(xmlreader *reader)
+{
+    static const WCHAR xmldeclW[] = {'<','?','x','m','l',0};
+    HRESULT hr;
+
+    /* check if we have "<?xml" */
+    if (reader_cmp(reader, xmldeclW)) return S_OK;
+
+    reader_skipn(reader, 5);
+    hr = reader_parse_versioninfo(reader);
+    if (FAILED(hr))
+        return hr;
+
+    return E_NOTIMPL;
+}
+
 static HRESULT WINAPI xmlreader_QueryInterface(IXmlReader *iface, REFIID riid, void** ppvObject)
 {
     xmlreader *This = impl_from_IXmlReader(iface);
@@ -586,11 +716,17 @@ static HRESULT WINAPI xmlreader_Read(IXmlReader* iface, XmlNodeType *node_type)
 
         /* try to detect encoding by BOM or data and set input code page */
         hr = readerinput_detectencoding(This->input, &enc);
-        TRACE("detected encoding %d, 0x%08x\n", enc, hr);
+        TRACE("detected encoding %s, 0x%08x\n", debugstr_w(xml_encoding_map[enc].name), hr);
         if (FAILED(hr)) return hr;
 
         /* always switch first time cause we have to put something in */
         readerinput_switchencoding(This->input, enc);
+
+        /* parse xml declaration */
+        hr = reader_parse_xmldecl(This);
+        if (FAILED(hr)) return hr;
+
+        This->state = XmlReadState_Interactive;
     }
 
     return E_NOTIMPL;
-- 
1.7.10.4




More information about the wine-patches mailing list