Jacek Caban : xmllite: Allow reading from allocated strings in ReadValueChunk.
Alexandre Julliard
julliard at winehq.org
Fri Mar 31 14:26:29 CDT 2017
Module: wine
Branch: master
Commit: daf0504570c74f54641bb6c0afd87d979d82fca8
URL: http://source.winehq.org/git/wine.git/?a=commit;h=daf0504570c74f54641bb6c0afd87d979d82fca8
Author: Jacek Caban <jacek at 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 at codeweavers.com>
Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at 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>");
More information about the wine-cvs
mailing list