Nikolay Sivov : xmllite: Initial support for attribute list.

Alexandre Julliard julliard at winehq.org
Tue Dec 4 13:48:54 CST 2012


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

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Tue Dec  4 13:31:25 2012 +0400

xmllite: Initial support for attribute list.

---

 dlls/xmllite/reader.c       |   88 ++++++++++++++++++++++++++++++++++++++-----
 dlls/xmllite/tests/reader.c |   12 ++++-
 2 files changed, 87 insertions(+), 13 deletions(-)

diff --git a/dlls/xmllite/reader.c b/dlls/xmllite/reader.c
index 11b5eb8..0d33296 100644
--- a/dlls/xmllite/reader.c
+++ b/dlls/xmllite/reader.c
@@ -29,6 +29,7 @@
 #include "xmllite_private.h"
 
 #include "wine/debug.h"
+#include "wine/list.h"
 #include "wine/unicode.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(xmllite);
@@ -88,6 +89,19 @@ typedef struct _xmlreaderinput
     input_buffer *buffer;
 } xmlreaderinput;
 
+typedef struct
+{
+    const WCHAR *str;
+    UINT len;
+} strval;
+
+struct attribute
+{
+    struct list entry;
+    strval localname;
+    strval value;
+};
+
 typedef struct _xmlreader
 {
     IXmlReader IXmlReader_iface;
@@ -98,6 +112,8 @@ typedef struct _xmlreader
     XmlNodeType nodetype;
     DtdProcessing dtdmode;
     UINT line, pos;           /* reader position in XML stream */
+    struct list attrs; /* attributes list for current node */
+    UINT attr_count;
 } xmlreader;
 
 struct input_buffer
@@ -184,6 +200,34 @@ static inline WCHAR *readerinput_strdupW(xmlreaderinput *input, const WCHAR *str
     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)
 {
     const int initial_len = 0x2000;
@@ -495,7 +539,7 @@ static int reader_skipspaces(xmlreader *reader)
 }
 
 /* [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);
     static const WCHAR onedotW[] = {'1','.',0};
@@ -510,6 +554,8 @@ static HRESULT reader_parse_versionnum(xmlreader *reader)
 
     if (ptr2 == ptr) return WC_E_DIGIT;
     TRACE("version=%s\n", debugstr_wn(start, ptr-start));
+    val->str = start;
+    val->len = ptr-start;
     reader_skipn(reader, ptr-ptr2);
     return S_OK;
 }
@@ -530,11 +576,14 @@ static HRESULT reader_parse_eq(xmlreader *reader)
 static HRESULT reader_parse_versioninfo(xmlreader *reader)
 {
     static const WCHAR versionW[] = {'v','e','r','s','i','o','n',0};
+    strval val, name;
     HRESULT hr;
 
     if (!reader_skipspaces(reader)) return WC_E_WHITESPACE;
 
     if (reader_cmp(reader, versionW)) return WC_E_XMLDECL;
+    name.str = reader_get_cur(reader);
+    name.len = 7;
     /* skip 'version' */
     reader_skipn(reader, 7);
 
@@ -546,7 +595,7 @@ static HRESULT reader_parse_versioninfo(xmlreader *reader)
     /* skip "'"|'"' */
     reader_skipn(reader, 1);
 
-    hr = reader_parse_versionnum(reader);
+    hr = reader_parse_versionnum(reader, &val);
     if (FAILED(hr)) return hr;
 
     if (reader_cmp(reader, quoteW) && reader_cmp(reader, dblquoteW))
@@ -555,7 +604,7 @@ static HRESULT reader_parse_versioninfo(xmlreader *reader)
     /* skip "'"|'"' */
     reader_skipn(reader, 1);
 
-    return S_OK;
+    return reader_add_attr(reader, &name, &val);
 }
 
 /* ([A-Za-z0-9._] | '-') */
@@ -569,7 +618,7 @@ static inline int is_wchar_encname(WCHAR ch)
 }
 
 /* [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;
     xml_encoding enc;
@@ -585,6 +634,8 @@ static HRESULT reader_parse_encname(xmlreader *reader)
     len = ptr - start;
     enc = parse_encoding_name(start, len);
     TRACE("encoding name %s\n", debugstr_wn(start, len));
+    val->str = start;
+    val->len = len;
 
     if (enc == XmlEncoding_Unknown)
         return WC_E_ENCNAME;
@@ -598,11 +649,14 @@ static HRESULT reader_parse_encname(xmlreader *reader)
 static HRESULT reader_parse_encdecl(xmlreader *reader)
 {
     static const WCHAR encodingW[] = {'e','n','c','o','d','i','n','g',0};
+    strval name, val;
     HRESULT hr;
 
     if (!reader_skipspaces(reader)) return WC_E_WHITESPACE;
 
     if (reader_cmp(reader, encodingW)) return S_FALSE;
+    name.str = reader_get_cur(reader);
+    name.len = 8;
     /* skip 'encoding' */
     reader_skipn(reader, 8);
 
@@ -614,7 +668,7 @@ static HRESULT reader_parse_encdecl(xmlreader *reader)
     /* skip "'"|'"' */
     reader_skipn(reader, 1);
 
-    hr = reader_parse_encname(reader);
+    hr = reader_parse_encname(reader, &val);
     if (FAILED(hr)) return hr;
 
     if (reader_cmp(reader, quoteW) && reader_cmp(reader, dblquoteW))
@@ -623,7 +677,7 @@ static HRESULT reader_parse_encdecl(xmlreader *reader)
     /* skip "'"|'"' */
     reader_skipn(reader, 1);
 
-    return S_OK;
+    return reader_add_attr(reader, &name, &val);
 }
 
 /* [32] SDDecl ::= S 'standalone' Eq (("'" ('yes' | 'no') "'") | ('"' ('yes' | 'no') '"')) */
@@ -633,11 +687,14 @@ static HRESULT reader_parse_sddecl(xmlreader *reader)
     static const WCHAR yesW[] = {'y','e','s',0};
     static const WCHAR noW[] = {'n','o',0};
     const WCHAR *start, *ptr;
+    strval name, val;
     HRESULT hr;
 
     if (!reader_skipspaces(reader)) return WC_E_WHITESPACE;
 
     if (reader_cmp(reader, standaloneW)) return S_FALSE;
+    name.str = reader_get_cur(reader);
+    name.len = 10;
     /* skip 'standalone' */
     reader_skipn(reader, 10);
 
@@ -657,13 +714,15 @@ static HRESULT reader_parse_sddecl(xmlreader *reader)
     reader_skipn(reader, reader_cmp(reader, yesW) ? 2 : 3);
     ptr = reader_get_cur(reader);
     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))
         return WC_E_QUOTE;
     /* skip "'"|'"' */
     reader_skipn(reader, 1);
 
-    return S_OK;
+    return reader_add_attr(reader, &name, &val);
 }
 
 /* [23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>' */
@@ -737,6 +796,7 @@ static ULONG WINAPI xmlreader_Release(IXmlReader *iface)
     {
         IMalloc *imalloc = This->imalloc;
         if (This->input) IUnknown_Release(&This->input->IXmlReaderInput_iface);
+        reader_clear_attrs(This);
         reader_free(This, This);
         if (imalloc) IMalloc_Release(imalloc);
     }
@@ -1000,10 +1060,16 @@ static HRESULT WINAPI xmlreader_GetLinePosition(IXmlReader* iface, UINT *linePos
     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);
-    return E_NOTIMPL;
+    xmlreader *This = impl_from_IXmlReader(iface);
+
+    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)
@@ -1134,6 +1200,8 @@ HRESULT WINAPI CreateXmlReader(REFIID riid, void **obj, IMalloc *imalloc)
     reader->imalloc = imalloc;
     if (imalloc) IMalloc_AddRef(imalloc);
     reader->nodetype = XmlNodeType_None;
+    list_init(&reader->attrs);
+    reader->attr_count = 0;
 
     *obj = &reader->IXmlReader_iface;
 
diff --git a/dlls/xmllite/tests/reader.c b/dlls/xmllite/tests/reader.c
index af0ea62..c44816c 100644
--- a/dlls/xmllite/tests/reader.c
+++ b/dlls/xmllite/tests/reader.c
@@ -607,6 +607,10 @@ static void test_read_xmldeclaration(void)
     hr = IXmlReader_SetInput(reader, (IUnknown*)stream);
     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);
 
     type = -1;
@@ -627,11 +631,13 @@ static void test_read_xmldeclaration(void)
     todo_wine ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
     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);
-todo_wine {
-    ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
+    ok(hr == S_OK, "got %08x\n", hr);
     ok(count == 3, "Expected 3, got %d\n", count);
-}
+
     hr = IXmlReader_GetDepth(reader, &count);
 todo_wine {
     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);




More information about the wine-cvs mailing list