Module: wine Branch: master Commit: daf0504570c74f54641bb6c0afd87d979d82fca8 URL: http://source.winehq.org/git/wine.git/?a=commit;h=daf0504570c74f54641bb6c0af...
Author: Jacek Caban jacek@codeweavers.com Date: Fri Mar 31 15:58:06 2017 +0200
xmllite: Allow reading from allocated strings in ReadValueChunk.
Signed-off-by: Jacek Caban jacek@codeweavers.com Signed-off-by: Nikolay Sivov nsivov@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/xmllite/reader.c | 118 ++++++++++++++++++++++++++------------------ dlls/xmllite/tests/reader.c | 2 - 2 files changed, 70 insertions(+), 50 deletions(-)
diff --git a/dlls/xmllite/reader.c b/dlls/xmllite/reader.c index 660d2cd..a11ec7a 100644 --- a/dlls/xmllite/reader.c +++ b/dlls/xmllite/reader.c @@ -22,6 +22,7 @@
#include <stdio.h> #include <stdarg.h> +#include <assert.h> #include "windef.h" #include "winbase.h" #include "initguid.h" @@ -286,6 +287,7 @@ typedef struct struct list nsdef; struct list ns; struct list elements; + int chunk_read_off; strval strvalues[StringValue_Last]; UINT depth; UINT max_depth; @@ -2536,7 +2538,10 @@ static HRESULT reader_parse_nextnode(xmlreader *reader) HRESULT hr;
if (!is_reader_pending(reader)) + { + reader->chunk_read_off = 0; reader_clear_attrs(reader); + }
/* When moving from EndElement or empty element, pop its own namespace definitions */ switch (nodetype) @@ -2934,6 +2939,7 @@ static HRESULT reader_move_to_first_attribute(xmlreader *reader) reader_inc_depth(reader);
reader->attr = LIST_ENTRY(list_head(&reader->attrs), struct attribute, entry); + reader->chunk_read_off = 0; reader_set_strvalue(reader, StringValue_Prefix, &reader->attr->prefix); reader_set_strvalue(reader, StringValue_QualifiedName, &reader->attr->qname); reader_set_strvalue(reader, StringValue_Value, &reader->attr->value); @@ -2966,6 +2972,7 @@ static HRESULT WINAPI xmlreader_MoveToNextAttribute(IXmlReader* iface) if (next) { This->attr = LIST_ENTRY(next, struct attribute, entry); + This->chunk_read_off = 0; reader_set_strvalue(This, StringValue_Prefix, &This->attr->prefix); reader_set_strvalue(This, StringValue_QualifiedName, &This->attr->qname); reader_set_strvalue(This, StringValue_Value, &This->attr->value); @@ -3007,6 +3014,7 @@ static HRESULT WINAPI xmlreader_MoveToElement(IXmlReader* iface) reader_set_strvalue(This, StringValue_QualifiedName, &element->qname); } } + This->chunk_read_off = 0; reader_set_strvalue(This, StringValue_Value, &strval_empty);
return S_OK; @@ -3274,17 +3282,54 @@ static HRESULT WINAPI xmlreader_GetPrefix(IXmlReader* iface, const WCHAR **ret, return S_OK; }
+static const strval *reader_get_value(xmlreader *reader, BOOL ensure_allocated) +{ + strval *val; + + switch (reader_get_nodetype(reader)) + { + case XmlNodeType_XmlDeclaration: + case XmlNodeType_EndElement: + case XmlNodeType_None: + return &strval_empty; + case XmlNodeType_Attribute: + /* For namespace definition attributes return values from namespace list */ + if (reader->attr->flags & (ATTRIBUTE_NS_DEFINITION | ATTRIBUTE_DEFAULT_NS_DEFINITION)) + { + struct ns *ns; + + if (!(ns = reader_lookup_ns(reader, &reader->attr->localname))) + ns = reader_lookup_nsdef(reader); + + return &ns->uri; + } + break; + default: + break; + } + + val = &reader->strvalues[StringValue_Value]; + if (!val->str && ensure_allocated) + { + WCHAR *ptr = reader_alloc(reader, (val->len+1)*sizeof(WCHAR)); + if (!ptr) return NULL; + memcpy(ptr, reader_get_strptr(reader, val), val->len*sizeof(WCHAR)); + ptr[val->len] = 0; + val->str = ptr; + } + + return val; +} + static HRESULT WINAPI xmlreader_GetValue(IXmlReader* iface, const WCHAR **value, UINT *len) { xmlreader *reader = impl_from_IXmlReader(iface); - strval *val = &reader->strvalues[StringValue_Value]; - UINT length; + const strval *val = &reader->strvalues[StringValue_Value]; + UINT off;
TRACE("(%p)->(%p %p)\n", reader, value, len);
*value = NULL; - if (!len) - len = &length;
if ((reader->nodetype == XmlNodeType_Comment && !val->str && !val->len) || is_reader_pending(reader)) { @@ -3298,64 +3343,40 @@ static HRESULT WINAPI xmlreader_GetValue(IXmlReader* iface, const WCHAR **value, if (is_reader_pending(reader)) return E_PENDING; }
- switch (reader_get_nodetype(reader)) - { - case XmlNodeType_XmlDeclaration: - case XmlNodeType_EndElement: - case XmlNodeType_None: - *value = emptyW; - *len = 0; - break; - case XmlNodeType_Attribute: - { - /* For namespace definition attributes return values from namespace list */ - if (reader->attr->flags & (ATTRIBUTE_NS_DEFINITION | ATTRIBUTE_DEFAULT_NS_DEFINITION)) - { - struct ns *ns; - - if (!(ns = reader_lookup_ns(reader, &reader->attr->localname))) - ns = reader_lookup_nsdef(reader); - - *value = ns->uri.str; - *len = ns->uri.len; - break; - } - } - /* fallthrough */ - default: - if (!val->str) - { - WCHAR *ptr = reader_alloc(reader, (val->len+1)*sizeof(WCHAR)); - if (!ptr) return E_OUTOFMEMORY; - memcpy(ptr, reader_get_strptr(reader, val), val->len*sizeof(WCHAR)); - ptr[val->len] = 0; - val->str = ptr; - } - *value = val->str; - *len = val->len; - break; - } + val = reader_get_value(reader, TRUE); + if (!val) + return E_OUTOFMEMORY;
+ off = abs(reader->chunk_read_off); + assert(off <= val->len); + *value = val->str + off; + if (len) *len = val->len - off; + reader->chunk_read_off = -off; return S_OK; }
static HRESULT WINAPI xmlreader_ReadValueChunk(IXmlReader* iface, WCHAR *buffer, UINT chunk_size, UINT *read) { xmlreader *reader = impl_from_IXmlReader(iface); - strval *val = &reader->strvalues[StringValue_Value]; - UINT len; + const strval *val; + UINT len = 0;
TRACE("(%p)->(%p %u %p)\n", reader, buffer, chunk_size, read);
- /* Value is already allocated, chunked reads are not possible. */ - len = !val->str && val->len ? min(chunk_size, val->len) : 0; + val = reader_get_value(reader, FALSE); + + /* If value is already read by GetValue, chunk_read_off is negative and chunked reads are not possible. */ + if (reader->chunk_read_off >= 0) + { + assert(reader->chunk_read_off <= val->len); + len = min(val->len - reader->chunk_read_off, chunk_size); + } if (read) *read = len;
if (len) { - memcpy(buffer, reader_get_ptr2(reader, val->start), len*sizeof(WCHAR)); - val->start += len; - val->len -= len; + memcpy(buffer, reader_get_strptr(reader, val) + reader->chunk_read_off, len*sizeof(WCHAR)); + reader->chunk_read_off += len; }
return len || !chunk_size ? S_OK : S_FALSE; @@ -3601,6 +3622,7 @@ HRESULT WINAPI CreateXmlReader(REFIID riid, void **obj, IMalloc *imalloc) list_init(&reader->elements); reader->max_depth = 256;
+ reader->chunk_read_off = 0; for (i = 0; i < StringValue_Last; i++) reader->strvalues[i] = strval_empty;
diff --git a/dlls/xmllite/tests/reader.c b/dlls/xmllite/tests/reader.c index 20d8240..fd83569 100644 --- a/dlls/xmllite/tests/reader.c +++ b/dlls/xmllite/tests/reader.c @@ -2581,12 +2581,10 @@ static void test_string_pointers(void) next_attribute(reader); read_value_char(reader, 'm'); IXmlReader_GetValue(reader, &p, NULL); - todo_wine ok(!strcmp_wa(p, "yns"), "value = %s\n", wine_dbgstr_w(p));
read_node(reader, XmlNodeType_Element); ns = reader_namespace(reader, "myns"); - todo_wine ok(ns+1 == p, "ns+1 != p\n");
set_input_string(reader, "<elem attr="value"></elem>");