[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