Commit 0dce2e6d authored by Nikolay Sivov's avatar Nikolay Sivov Committed by Alexandre Julliard

xmllite: Initial support for attribute list.

parent bd1e261b
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include "xmllite_private.h" #include "xmllite_private.h"
#include "wine/debug.h" #include "wine/debug.h"
#include "wine/list.h"
#include "wine/unicode.h" #include "wine/unicode.h"
WINE_DEFAULT_DEBUG_CHANNEL(xmllite); WINE_DEFAULT_DEBUG_CHANNEL(xmllite);
...@@ -88,6 +89,19 @@ typedef struct _xmlreaderinput ...@@ -88,6 +89,19 @@ typedef struct _xmlreaderinput
input_buffer *buffer; input_buffer *buffer;
} xmlreaderinput; } xmlreaderinput;
typedef struct
{
const WCHAR *str;
UINT len;
} strval;
struct attribute
{
struct list entry;
strval localname;
strval value;
};
typedef struct _xmlreader typedef struct _xmlreader
{ {
IXmlReader IXmlReader_iface; IXmlReader IXmlReader_iface;
...@@ -98,6 +112,8 @@ typedef struct _xmlreader ...@@ -98,6 +112,8 @@ typedef struct _xmlreader
XmlNodeType nodetype; XmlNodeType nodetype;
DtdProcessing dtdmode; DtdProcessing dtdmode;
UINT line, pos; /* reader position in XML stream */ UINT line, pos; /* reader position in XML stream */
struct list attrs; /* attributes list for current node */
UINT attr_count;
} xmlreader; } xmlreader;
struct input_buffer struct input_buffer
...@@ -184,6 +200,34 @@ static inline WCHAR *readerinput_strdupW(xmlreaderinput *input, const WCHAR *str ...@@ -184,6 +200,34 @@ static inline WCHAR *readerinput_strdupW(xmlreaderinput *input, const WCHAR *str
return ret; return ret;
} }
static void reader_clear_attrs(xmlreader *reader)
{
struct attribute *attr, *attr2;
LIST_FOR_EACH_ENTRY_SAFE(attr, attr2, &reader->attrs, struct attribute, entry)
{
reader_free(reader, attr);
}
list_init(&reader->attrs);
reader->attr_count = 0;
}
/* attribute data holds pointers to buffer data, so buffer shrink is not possible
while we are on a node with attributes */
static HRESULT reader_add_attr(xmlreader *reader, strval *localname, strval *value)
{
struct attribute *attr;
attr = reader_alloc(reader, sizeof(*attr));
if (!attr) return E_OUTOFMEMORY;
attr->localname = *localname;
attr->value = *value;
list_add_tail(&reader->attrs, &attr->entry);
reader->attr_count++;
return S_OK;
}
static HRESULT init_encoded_buffer(xmlreaderinput *input, encoded_buffer *buffer) static HRESULT init_encoded_buffer(xmlreaderinput *input, encoded_buffer *buffer)
{ {
const int initial_len = 0x2000; const int initial_len = 0x2000;
...@@ -495,7 +539,7 @@ static int reader_skipspaces(xmlreader *reader) ...@@ -495,7 +539,7 @@ static int reader_skipspaces(xmlreader *reader)
} }
/* [26] VersionNum ::= '1.' [0-9]+ */ /* [26] VersionNum ::= '1.' [0-9]+ */
static HRESULT reader_parse_versionnum(xmlreader *reader) static HRESULT reader_parse_versionnum(xmlreader *reader, strval *val)
{ {
const WCHAR *ptr, *ptr2, *start = reader_get_cur(reader); const WCHAR *ptr, *ptr2, *start = reader_get_cur(reader);
static const WCHAR onedotW[] = {'1','.',0}; static const WCHAR onedotW[] = {'1','.',0};
...@@ -510,6 +554,8 @@ static HRESULT reader_parse_versionnum(xmlreader *reader) ...@@ -510,6 +554,8 @@ static HRESULT reader_parse_versionnum(xmlreader *reader)
if (ptr2 == ptr) return WC_E_DIGIT; if (ptr2 == ptr) return WC_E_DIGIT;
TRACE("version=%s\n", debugstr_wn(start, ptr-start)); TRACE("version=%s\n", debugstr_wn(start, ptr-start));
val->str = start;
val->len = ptr-start;
reader_skipn(reader, ptr-ptr2); reader_skipn(reader, ptr-ptr2);
return S_OK; return S_OK;
} }
...@@ -530,11 +576,14 @@ static HRESULT reader_parse_eq(xmlreader *reader) ...@@ -530,11 +576,14 @@ static HRESULT reader_parse_eq(xmlreader *reader)
static HRESULT reader_parse_versioninfo(xmlreader *reader) static HRESULT reader_parse_versioninfo(xmlreader *reader)
{ {
static const WCHAR versionW[] = {'v','e','r','s','i','o','n',0}; static const WCHAR versionW[] = {'v','e','r','s','i','o','n',0};
strval val, name;
HRESULT hr; HRESULT hr;
if (!reader_skipspaces(reader)) return WC_E_WHITESPACE; if (!reader_skipspaces(reader)) return WC_E_WHITESPACE;
if (reader_cmp(reader, versionW)) return WC_E_XMLDECL; if (reader_cmp(reader, versionW)) return WC_E_XMLDECL;
name.str = reader_get_cur(reader);
name.len = 7;
/* skip 'version' */ /* skip 'version' */
reader_skipn(reader, 7); reader_skipn(reader, 7);
...@@ -546,7 +595,7 @@ static HRESULT reader_parse_versioninfo(xmlreader *reader) ...@@ -546,7 +595,7 @@ static HRESULT reader_parse_versioninfo(xmlreader *reader)
/* skip "'"|'"' */ /* skip "'"|'"' */
reader_skipn(reader, 1); reader_skipn(reader, 1);
hr = reader_parse_versionnum(reader); hr = reader_parse_versionnum(reader, &val);
if (FAILED(hr)) return hr; if (FAILED(hr)) return hr;
if (reader_cmp(reader, quoteW) && reader_cmp(reader, dblquoteW)) if (reader_cmp(reader, quoteW) && reader_cmp(reader, dblquoteW))
...@@ -555,7 +604,7 @@ static HRESULT reader_parse_versioninfo(xmlreader *reader) ...@@ -555,7 +604,7 @@ static HRESULT reader_parse_versioninfo(xmlreader *reader)
/* skip "'"|'"' */ /* skip "'"|'"' */
reader_skipn(reader, 1); reader_skipn(reader, 1);
return S_OK; return reader_add_attr(reader, &name, &val);
} }
/* ([A-Za-z0-9._] | '-') */ /* ([A-Za-z0-9._] | '-') */
...@@ -569,7 +618,7 @@ static inline int is_wchar_encname(WCHAR ch) ...@@ -569,7 +618,7 @@ static inline int is_wchar_encname(WCHAR ch)
} }
/* [81] EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')* */ /* [81] EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')* */
static HRESULT reader_parse_encname(xmlreader *reader) static HRESULT reader_parse_encname(xmlreader *reader, strval *val)
{ {
const WCHAR *start = reader_get_cur(reader), *ptr; const WCHAR *start = reader_get_cur(reader), *ptr;
xml_encoding enc; xml_encoding enc;
...@@ -585,6 +634,8 @@ static HRESULT reader_parse_encname(xmlreader *reader) ...@@ -585,6 +634,8 @@ static HRESULT reader_parse_encname(xmlreader *reader)
len = ptr - start; len = ptr - start;
enc = parse_encoding_name(start, len); enc = parse_encoding_name(start, len);
TRACE("encoding name %s\n", debugstr_wn(start, len)); TRACE("encoding name %s\n", debugstr_wn(start, len));
val->str = start;
val->len = len;
if (enc == XmlEncoding_Unknown) if (enc == XmlEncoding_Unknown)
return WC_E_ENCNAME; return WC_E_ENCNAME;
...@@ -598,11 +649,14 @@ static HRESULT reader_parse_encname(xmlreader *reader) ...@@ -598,11 +649,14 @@ static HRESULT reader_parse_encname(xmlreader *reader)
static HRESULT reader_parse_encdecl(xmlreader *reader) static HRESULT reader_parse_encdecl(xmlreader *reader)
{ {
static const WCHAR encodingW[] = {'e','n','c','o','d','i','n','g',0}; static const WCHAR encodingW[] = {'e','n','c','o','d','i','n','g',0};
strval name, val;
HRESULT hr; HRESULT hr;
if (!reader_skipspaces(reader)) return WC_E_WHITESPACE; if (!reader_skipspaces(reader)) return WC_E_WHITESPACE;
if (reader_cmp(reader, encodingW)) return S_FALSE; if (reader_cmp(reader, encodingW)) return S_FALSE;
name.str = reader_get_cur(reader);
name.len = 8;
/* skip 'encoding' */ /* skip 'encoding' */
reader_skipn(reader, 8); reader_skipn(reader, 8);
...@@ -614,7 +668,7 @@ static HRESULT reader_parse_encdecl(xmlreader *reader) ...@@ -614,7 +668,7 @@ static HRESULT reader_parse_encdecl(xmlreader *reader)
/* skip "'"|'"' */ /* skip "'"|'"' */
reader_skipn(reader, 1); reader_skipn(reader, 1);
hr = reader_parse_encname(reader); hr = reader_parse_encname(reader, &val);
if (FAILED(hr)) return hr; if (FAILED(hr)) return hr;
if (reader_cmp(reader, quoteW) && reader_cmp(reader, dblquoteW)) if (reader_cmp(reader, quoteW) && reader_cmp(reader, dblquoteW))
...@@ -623,7 +677,7 @@ static HRESULT reader_parse_encdecl(xmlreader *reader) ...@@ -623,7 +677,7 @@ static HRESULT reader_parse_encdecl(xmlreader *reader)
/* skip "'"|'"' */ /* skip "'"|'"' */
reader_skipn(reader, 1); reader_skipn(reader, 1);
return S_OK; return reader_add_attr(reader, &name, &val);
} }
/* [32] SDDecl ::= S 'standalone' Eq (("'" ('yes' | 'no') "'") | ('"' ('yes' | 'no') '"')) */ /* [32] SDDecl ::= S 'standalone' Eq (("'" ('yes' | 'no') "'") | ('"' ('yes' | 'no') '"')) */
...@@ -633,11 +687,14 @@ static HRESULT reader_parse_sddecl(xmlreader *reader) ...@@ -633,11 +687,14 @@ static HRESULT reader_parse_sddecl(xmlreader *reader)
static const WCHAR yesW[] = {'y','e','s',0}; static const WCHAR yesW[] = {'y','e','s',0};
static const WCHAR noW[] = {'n','o',0}; static const WCHAR noW[] = {'n','o',0};
const WCHAR *start, *ptr; const WCHAR *start, *ptr;
strval name, val;
HRESULT hr; HRESULT hr;
if (!reader_skipspaces(reader)) return WC_E_WHITESPACE; if (!reader_skipspaces(reader)) return WC_E_WHITESPACE;
if (reader_cmp(reader, standaloneW)) return S_FALSE; if (reader_cmp(reader, standaloneW)) return S_FALSE;
name.str = reader_get_cur(reader);
name.len = 10;
/* skip 'standalone' */ /* skip 'standalone' */
reader_skipn(reader, 10); reader_skipn(reader, 10);
...@@ -657,13 +714,15 @@ static HRESULT reader_parse_sddecl(xmlreader *reader) ...@@ -657,13 +714,15 @@ static HRESULT reader_parse_sddecl(xmlreader *reader)
reader_skipn(reader, reader_cmp(reader, yesW) ? 2 : 3); reader_skipn(reader, reader_cmp(reader, yesW) ? 2 : 3);
ptr = reader_get_cur(reader); ptr = reader_get_cur(reader);
TRACE("standalone=%s\n", debugstr_wn(start, ptr-start)); TRACE("standalone=%s\n", debugstr_wn(start, ptr-start));
val.str = start;
val.len = ptr-start;
if (reader_cmp(reader, quoteW) && reader_cmp(reader, dblquoteW)) if (reader_cmp(reader, quoteW) && reader_cmp(reader, dblquoteW))
return WC_E_QUOTE; return WC_E_QUOTE;
/* skip "'"|'"' */ /* skip "'"|'"' */
reader_skipn(reader, 1); reader_skipn(reader, 1);
return S_OK; return reader_add_attr(reader, &name, &val);
} }
/* [23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>' */ /* [23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>' */
...@@ -737,6 +796,7 @@ static ULONG WINAPI xmlreader_Release(IXmlReader *iface) ...@@ -737,6 +796,7 @@ static ULONG WINAPI xmlreader_Release(IXmlReader *iface)
{ {
IMalloc *imalloc = This->imalloc; IMalloc *imalloc = This->imalloc;
if (This->input) IUnknown_Release(&This->input->IXmlReaderInput_iface); if (This->input) IUnknown_Release(&This->input->IXmlReaderInput_iface);
reader_clear_attrs(This);
reader_free(This, This); reader_free(This, This);
if (imalloc) IMalloc_Release(imalloc); if (imalloc) IMalloc_Release(imalloc);
} }
...@@ -1000,10 +1060,16 @@ static HRESULT WINAPI xmlreader_GetLinePosition(IXmlReader* iface, UINT *linePos ...@@ -1000,10 +1060,16 @@ static HRESULT WINAPI xmlreader_GetLinePosition(IXmlReader* iface, UINT *linePos
return S_OK; return S_OK;
} }
static HRESULT WINAPI xmlreader_GetAttributeCount(IXmlReader* iface, UINT *attributeCount) static HRESULT WINAPI xmlreader_GetAttributeCount(IXmlReader* iface, UINT *count)
{ {
FIXME("(%p %p): stub\n", iface, attributeCount); xmlreader *This = impl_from_IXmlReader(iface);
return E_NOTIMPL;
TRACE("(%p)->(%p)\n", This, count);
if (!count) return E_INVALIDARG;
*count = This->attr_count;
return S_OK;
} }
static HRESULT WINAPI xmlreader_GetDepth(IXmlReader* iface, UINT *depth) static HRESULT WINAPI xmlreader_GetDepth(IXmlReader* iface, UINT *depth)
...@@ -1134,6 +1200,8 @@ HRESULT WINAPI CreateXmlReader(REFIID riid, void **obj, IMalloc *imalloc) ...@@ -1134,6 +1200,8 @@ HRESULT WINAPI CreateXmlReader(REFIID riid, void **obj, IMalloc *imalloc)
reader->imalloc = imalloc; reader->imalloc = imalloc;
if (imalloc) IMalloc_AddRef(imalloc); if (imalloc) IMalloc_AddRef(imalloc);
reader->nodetype = XmlNodeType_None; reader->nodetype = XmlNodeType_None;
list_init(&reader->attrs);
reader->attr_count = 0;
*obj = &reader->IXmlReader_iface; *obj = &reader->IXmlReader_iface;
......
...@@ -607,6 +607,10 @@ static void test_read_xmldeclaration(void) ...@@ -607,6 +607,10 @@ static void test_read_xmldeclaration(void)
hr = IXmlReader_SetInput(reader, (IUnknown*)stream); hr = IXmlReader_SetInput(reader, (IUnknown*)stream);
ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
hr = IXmlReader_GetAttributeCount(reader, &count);
ok(hr == S_OK, "got %08x\n", hr);
ok(count == 0, "got %d\n", count);
ok_pos(reader, 0, 0, -1, -1, FALSE); ok_pos(reader, 0, 0, -1, -1, FALSE);
type = -1; type = -1;
...@@ -627,11 +631,13 @@ static void test_read_xmldeclaration(void) ...@@ -627,11 +631,13 @@ static void test_read_xmldeclaration(void)
todo_wine ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); todo_wine ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
ok_pos(reader, 1, 7, -1, 55, TRUE); ok_pos(reader, 1, 7, -1, 55, TRUE);
hr = IXmlReader_GetAttributeCount(reader, NULL);
ok(hr == E_INVALIDARG, "got %08x\n", hr);
hr = IXmlReader_GetAttributeCount(reader, &count); hr = IXmlReader_GetAttributeCount(reader, &count);
todo_wine { ok(hr == S_OK, "got %08x\n", hr);
ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
ok(count == 3, "Expected 3, got %d\n", count); ok(count == 3, "Expected 3, got %d\n", count);
}
hr = IXmlReader_GetDepth(reader, &count); hr = IXmlReader_GetDepth(reader, &count);
todo_wine { todo_wine {
ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment