Nikolay Sivov : msxml3: Properly handle writer output in a form of BSTR.
Alexandre Julliard
julliard at winehq.org
Fri Dec 9 14:41:39 CST 2011
Module: wine
Branch: master
Commit: b0f704daaf633d8c713c9212a2ab5dd8a4457e7a
URL: http://source.winehq.org/git/wine.git/?a=commit;h=b0f704daaf633d8c713c9212a2ab5dd8a4457e7a
Author: Nikolay Sivov <nsivov at codeweavers.com>
Date: Fri Dec 9 21:34:27 2011 +0300
msxml3: Properly handle writer output in a form of BSTR.
---
dlls/msxml3/mxwriter.c | 87 ++++++++++++++++++++++++++---------------
dlls/msxml3/tests/saxreader.c | 13 +++++-
2 files changed, 65 insertions(+), 35 deletions(-)
diff --git a/dlls/msxml3/mxwriter.c b/dlls/msxml3/mxwriter.c
index f4e2960..febabe1 100644
--- a/dlls/msxml3/mxwriter.c
+++ b/dlls/msxml3/mxwriter.c
@@ -78,8 +78,8 @@ typedef struct _mxwriter
IStream *dest;
ULONG dest_written;
- INT decl_count; /* practically how many times startDocument was called */
- INT decl_written; /* byte length of document prolog */
+ int decl_count; /* practically how many times startDocument was called */
+ int decl_written; /* byte length of document prolog */
xmlOutputBufferPtr buffer;
} mxwriter;
@@ -385,11 +385,6 @@ static HRESULT WINAPI mxwriter_put_output(IMXWriter *iface, VARIANT dest)
{
if (This->dest) IStream_Release(This->dest);
This->dest = NULL;
-
- /* We need to reset the output buffer to UTF-16, since the only way
- * the content of the mxwriter can be accessed now is through a BSTR.
- */
- This->encoding = xmlParseCharEncoding("UTF-16");
reset_output_buffer(This);
break;
}
@@ -427,48 +422,76 @@ static HRESULT WINAPI mxwriter_get_output(IMXWriter *iface, VARIANT *dest)
if (!This->dest)
{
- BSTR output;
+ xmlOutputBufferPtr prolog;
+ BSTR output, body = NULL;
+ xmlBufferPtr buffer;
+ WCHAR *ptr;
HRESULT hr;
+ int i;
hr = flush_output_buffer(This);
if (FAILED(hr))
return hr;
- /* TODO: Windows always seems to re-encode the XML to UTF-16 (this includes
- * updating the XML decl so it says "UTF-16" instead of "UTF-8"). We don't
- * support this yet...
- */
- if (This->encoding == XML_CHAR_ENCODING_UTF8) {
- FIXME("XML re-encoding not supported yet\n");
- return E_NOTIMPL;
+ if (This->decl_count)
+ {
+ prolog = xmlAllocOutputBuffer(xmlGetCharEncodingHandler(xmlParseCharEncoding("UTF-16")));
+ write_prolog_buffer(This, xmlParseCharEncoding("UTF-16"), prolog);
}
+ else
+ prolog = NULL;
- if (This->decl_count)
+ /* optimize some paticular cases */
+ /* 1. no prolog and UTF-8 buffer */
+ if (This->encoding == XML_CHAR_ENCODING_UTF8 && !prolog)
{
- xmlOutputBufferPtr prolog;
- INT i = This->decl_count;
- WCHAR *ptr;
+ V_VT(dest) = VT_BSTR;
+ V_BSTR(dest) = bstr_from_xmlChar(This->buffer->buffer->content);
+ return S_OK;
+ }
- prolog = xmlAllocOutputBuffer(xmlGetCharEncodingHandler(xmlParseCharEncoding("UTF-16")));
+ /* 2. no prolog and UTF-16 buffer */
+ if (!prolog)
+ {
+ V_VT(dest) = VT_BSTR;
+ V_BSTR(dest) = SysAllocStringLen((const WCHAR*)This->buffer->conv->content,
+ This->buffer->conv->use/sizeof(WCHAR));
+ return S_OK;
+ }
- write_prolog_buffer(This, xmlParseCharEncoding("UTF-16"), prolog);
+ V_BSTR(dest) = NULL;
+ if (This->encoding == XML_CHAR_ENCODING_UTF8)
+ {
+ buffer = This->buffer->buffer;
+ body = bstr_from_xmlChar(buffer->content+This->decl_written);
ptr = output = SysAllocStringByteLen(NULL, prolog->conv->use*This->decl_count +
- This->buffer->conv->use-This->decl_written);
- while (i--)
- {
- memcpy(ptr, prolog->conv->content, prolog->conv->use);
- ptr += prolog->conv->use/sizeof(WCHAR);
- }
-
- memcpy(ptr, This->buffer->conv->content + This->decl_written, This->buffer->conv->use-This->decl_written);
- xmlOutputBufferClose(prolog);
+ SysStringByteLen(body));
}
else
{
- output = SysAllocStringLen((const WCHAR*)This->buffer->conv->content,
- This->buffer->conv->use/sizeof(WCHAR));
+ buffer = This->buffer->conv;
+ ptr = output = SysAllocStringByteLen(NULL, prolog->conv->use*This->decl_count +
+ buffer->use - This->decl_written);
+ }
+
+ /* write prolog part */
+ i = This->decl_count;
+ while (i--)
+ {
+ memcpy(ptr, prolog->conv->content, prolog->conv->use);
+ ptr += prolog->conv->use/sizeof(WCHAR);
+ }
+ xmlOutputBufferClose(prolog);
+
+ /* write main part */
+ if (body)
+ {
+ memcpy(ptr, body, SysStringByteLen(body));
+ SysFreeString(body);
}
+ else
+ memcpy(ptr, buffer->content + This->decl_written, buffer->use-This->decl_written);
V_VT(dest) = VT_BSTR;
V_BSTR(dest) = output;
diff --git a/dlls/msxml3/tests/saxreader.c b/dlls/msxml3/tests/saxreader.c
index 0fac3dd..d713fd3 100644
--- a/dlls/msxml3/tests/saxreader.c
+++ b/dlls/msxml3/tests/saxreader.c
@@ -2303,6 +2303,13 @@ static void test_mxwriter_startendelement(void)
hr = IMXWriter_put_output(writer, dest);
EXPECT_HR(hr, S_OK);
+ V_VT(&dest) = VT_EMPTY;
+ hr = IMXWriter_get_output(writer, &dest);
+ EXPECT_HR(hr, S_OK);
+ ok(V_VT(&dest) == VT_BSTR, "got %d\n", V_VT(&dest));
+ ok(!lstrcmpW(_bstr_(""), V_BSTR(&dest)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest)));
+ VariantClear(&dest);
+
hr = ISAXContentHandler_startDocument(content);
EXPECT_HR(hr, S_OK);
@@ -2615,9 +2622,9 @@ static void test_mxwriter_encoding(void)
*/
V_VT(&dest) = VT_EMPTY;
hr = IMXWriter_get_output(writer, &dest);
- todo_wine ok(hr == S_OK, "get_output failed: %08x\n", hr);
- todo_wine ok(V_VT(&dest) == VT_BSTR, "Expected VT_BSTR, got %d\n", V_VT(&dest));
- if (V_VT(&dest) == VT_BSTR) todo_wine ok(!lstrcmpW(_bstr_("<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"?>\r\n"), V_BSTR(&dest)),
+ EXPECT_HR(hr, S_OK);
+ ok(V_VT(&dest) == VT_BSTR, "Expected VT_BSTR, got %d\n", V_VT(&dest));
+ ok(!lstrcmpW(_bstr_("<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"?>\r\n"), V_BSTR(&dest)),
"got wrong content: %s\n", wine_dbgstr_w(V_BSTR(&dest)));
VariantClear(&dest);
More information about the wine-cvs
mailing list