xmllite: Add partial support for xml declaration parsing.
This commit is contained in:
parent
eddd7fcf29
commit
acb56b0796
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* IXmlReader implementation
|
* IXmlReader implementation
|
||||||
*
|
*
|
||||||
* Copyright 2010 Nikolay Sivov
|
* Copyright 2010, 2012 Nikolay Sivov
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* 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
|
struct xml_encoding_data
|
||||||
{
|
{
|
||||||
const WCHAR *encoding;
|
const WCHAR *name;
|
||||||
xml_encoding enc;
|
xml_encoding enc;
|
||||||
UINT cp;
|
UINT cp;
|
||||||
};
|
};
|
||||||
|
@ -213,11 +213,11 @@ static HRESULT get_code_page(xml_encoding encoding, UINT *cp)
|
||||||
return S_OK;
|
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;
|
int min, max, n, c;
|
||||||
|
|
||||||
if (!encoding) return XmlEncoding_Unknown;
|
if (!name) return XmlEncoding_Unknown;
|
||||||
|
|
||||||
min = 0;
|
min = 0;
|
||||||
max = sizeof(xml_encoding_map)/sizeof(struct xml_encoding_data) - 1;
|
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;
|
n = (min+max)/2;
|
||||||
|
|
||||||
c = strcmpiW(xml_encoding_map[n].encoding, encoding);
|
c = strcmpiW(xml_encoding_map[n].name, name);
|
||||||
if (!c)
|
if (!c)
|
||||||
return xml_encoding_map[n].enc;
|
return xml_encoding_map[n].enc;
|
||||||
|
|
||||||
|
@ -431,6 +431,136 @@ static void readerinput_switchencoding(xmlreaderinput *readerinput, xml_encoding
|
||||||
readerinput->buffer->code_page = cp;
|
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)
|
static HRESULT WINAPI xmlreader_QueryInterface(IXmlReader *iface, REFIID riid, void** ppvObject)
|
||||||
{
|
{
|
||||||
xmlreader *This = impl_from_IXmlReader(iface);
|
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 */
|
/* try to detect encoding by BOM or data and set input code page */
|
||||||
hr = readerinput_detectencoding(This->input, &enc);
|
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;
|
if (FAILED(hr)) return hr;
|
||||||
|
|
||||||
/* always switch first time cause we have to put something in */
|
/* always switch first time cause we have to put something in */
|
||||||
readerinput_switchencoding(This->input, enc);
|
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;
|
return E_NOTIMPL;
|
||||||
|
|
Loading…
Reference in New Issue