Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/xmllite/writer.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/dlls/xmllite/writer.c b/dlls/xmllite/writer.c index aa6ff7f92a..92217b8a4d 100644 --- a/dlls/xmllite/writer.c +++ b/dlls/xmllite/writer.c @@ -1221,6 +1221,7 @@ static HRESULT WINAPI xmlwriter_WriteEndElement(IXmlWriter *iface) write_output_buffer(This->output, element->qname, element->len); write_output_buffer(This->output, gtW, ARRAY_SIZE(gtW)); } + writer_free_element(This, element);
return S_OK; } @@ -1287,6 +1288,8 @@ static HRESULT WINAPI xmlwriter_WriteFullEndElement(IXmlWriter *iface) write_output_buffer(This->output, element->qname, element->len); write_output_buffer(This->output, gtW, ARRAY_SIZE(gtW));
+ writer_free_element(This, element); + return S_OK; }
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/xmllite/tests/writer.c | 88 ++++++++++++++++++++++++++++++------- dlls/xmllite/writer.c | 21 +++++---- 2 files changed, 85 insertions(+), 24 deletions(-)
diff --git a/dlls/xmllite/tests/writer.c b/dlls/xmllite/tests/writer.c index 1710462deb..42b534f269 100644 --- a/dlls/xmllite/tests/writer.c +++ b/dlls/xmllite/tests/writer.c @@ -881,6 +881,20 @@ static HRESULT write_element_string(IXmlWriter *writer, const char *prefix, cons return hr; }
+static HRESULT write_string(IXmlWriter *writer, const char *str) +{ + WCHAR *strW; + HRESULT hr; + + strW = strdupAtoW(str); + + hr = IXmlWriter_WriteString(writer, strW); + + heap_free(strW); + + return hr; +} + static void test_WriteStartElement(void) { static const struct @@ -1853,10 +1867,6 @@ static void test_WriteCharEntity(void)
static void test_WriteString(void) { - static const WCHAR markupW[] = {'<','&','"','>','=',0}; - static const WCHAR aW[] = {'a',0}; - static const WCHAR bW[] = {'b',0}; - static const WCHAR emptyW[] = {0}; IXmlWriter *writer; IStream *stream; HRESULT hr; @@ -1866,31 +1876,31 @@ static void test_WriteString(void)
writer_set_property(writer, XmlWriterProperty_OmitXmlDeclaration);
- hr = IXmlWriter_WriteString(writer, aW); + hr = write_string(writer, "a"); ok(hr == E_UNEXPECTED, "got 0x%08x\n", hr);
- hr = IXmlWriter_WriteString(writer, NULL); + hr = write_string(writer, NULL); ok(hr == S_OK, "got 0x%08x\n", hr);
- hr = IXmlWriter_WriteString(writer, emptyW); + hr = write_string(writer, ""); ok(hr == E_UNEXPECTED, "got 0x%08x\n", hr);
stream = writer_set_output(writer);
- hr = IXmlWriter_WriteStartElement(writer, NULL, bW, NULL); + hr = write_start_element(writer, NULL, "b", NULL); ok(hr == S_OK, "got 0x%08x\n", hr);
- hr = IXmlWriter_WriteString(writer, NULL); + hr = write_string(writer, NULL); ok(hr == S_OK, "got 0x%08x\n", hr);
- hr = IXmlWriter_WriteString(writer, emptyW); + hr = write_string(writer, ""); ok(hr == S_OK, "got 0x%08x\n", hr);
- hr = IXmlWriter_WriteString(writer, aW); + hr = write_string(writer, "a"); ok(hr == S_OK, "got 0x%08x\n", hr);
/* WriteString automatically escapes markup characters */ - hr = IXmlWriter_WriteString(writer, markupW); + hr = write_string(writer, "<&">="); ok(hr == S_OK, "got 0x%08x\n", hr);
hr = IXmlWriter_Flush(writer); @@ -1902,10 +1912,10 @@ static void test_WriteString(void)
stream = writer_set_output(writer);
- hr = IXmlWriter_WriteStartElement(writer, NULL, bW, NULL); + hr = write_start_element(writer, NULL, "b", NULL); ok(hr == S_OK, "got 0x%08x\n", hr);
- hr = IXmlWriter_WriteString(writer, NULL); + hr = write_string(writer, NULL); ok(hr == S_OK, "got 0x%08x\n", hr);
hr = IXmlWriter_Flush(writer); @@ -1914,7 +1924,7 @@ static void test_WriteString(void) CHECK_OUTPUT(stream, "<b");
- hr = IXmlWriter_WriteString(writer, emptyW); + hr = write_string(writer, ""); ok(hr == S_OK, "got 0x%08x\n", hr);
hr = IXmlWriter_Flush(writer); @@ -1923,6 +1933,54 @@ static void test_WriteString(void) CHECK_OUTPUT(stream, "<b>");
+ IStream_Release(stream); + IXmlWriter_Release(writer); + + /* With indentation */ + hr = CreateXmlWriter(&IID_IXmlWriter, (void **)&writer, NULL); + ok(hr == S_OK, "Failed to create a writer, hr %#x.\n", hr); + + stream = writer_set_output(writer); + + writer_set_property(writer, XmlWriterProperty_Indent); + + hr = write_start_element(writer, NULL, "a", NULL); + ok(hr == S_OK, "Failed to start element, hr %#x.\n", hr); + + hr = write_start_element(writer, NULL, "b", NULL); + ok(hr == S_OK, "Failed to start element, hr %#x.\n", hr); + + hr = write_string(writer, "text"); + ok(hr == S_OK, "Failed to write a string, hr %#x.\n", hr); + + hr = IXmlWriter_Flush(writer); + ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr); + + CHECK_OUTPUT(stream, + "<a>\r\n" + " <b>text"); + + hr = IXmlWriter_WriteFullEndElement(writer); + ok(hr == S_OK, "Failed to end element, hr %#x.\n", hr); + + hr = IXmlWriter_Flush(writer); + ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr); + + CHECK_OUTPUT(stream, + "<a>\r\n" + " <b>text</b>"); + + hr = IXmlWriter_WriteFullEndElement(writer); + ok(hr == S_OK, "Failed to end element, hr %#x.\n", hr); + + hr = IXmlWriter_Flush(writer); + ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr); + + CHECK_OUTPUT(stream, + "<a>\r\n" + " <b>text</b>\r\n" + "</a>"); + IXmlWriter_Release(writer); IStream_Release(stream); } diff --git a/dlls/xmllite/writer.c b/dlls/xmllite/writer.c index 92217b8a4d..94e1f2f8a8 100644 --- a/dlls/xmllite/writer.c +++ b/dlls/xmllite/writer.c @@ -80,6 +80,7 @@ typedef struct xml_encoding encoding; WCHAR *encoding_name; /* exactly as specified on output creation */ struct output_buffer buffer; + DWORD written : 1; } xmlwriteroutput;
static const struct IUnknownVtbl xmlwriteroutputvtbl; @@ -114,9 +115,9 @@ typedef struct _xmlwriter BOOL omitxmldecl; XmlConformanceLevel conformance; XmlWriterState state; - BOOL bomwritten; - BOOL starttagopen; struct list elements; + DWORD bomwritten : 1; + DWORD starttagopen : 1; } xmlwriter;
static inline xmlwriter *impl_from_IXmlWriter(IXmlWriter *iface) @@ -438,6 +439,7 @@ static HRESULT write_output_buffer(xmlwriteroutput *output, const WCHAR *data, i length = WideCharToMultiByte(buffer->codepage, 0, data, len, ptr, length, NULL, NULL); buffer->written += len == -1 ? length-1 : length; } + output->written = length != 0;
return S_OK; } @@ -603,7 +605,7 @@ static HRESULT writer_close_starttag(xmlwriter *writer)
writer_output_ns(writer, LIST_ENTRY(list_head(&writer->elements), struct element, entry)); hr = write_output_buffer(writer->output, gtW, ARRAY_SIZE(gtW)); - writer->starttagopen = FALSE; + writer->starttagopen = 0; return hr; }
@@ -629,7 +631,7 @@ static void write_node_indent(xmlwriter *writer)
/* Do state check to prevent newline inserted after BOM. It is assumed that state does not change between writing BOM and inserting indentation. */ - if (writer->output->buffer.written && writer->state != XmlWriterState_Ready) + if (writer->output->written && writer->state != XmlWriterState_Ready) write_output_buffer(writer->output, crlfW, ARRAY_SIZE(crlfW)); while (indent_level--) write_output_buffer(writer->output, dblspaceW, ARRAY_SIZE(dblspaceW)); @@ -701,7 +703,7 @@ static HRESULT WINAPI xmlwriter_SetOutput(IXmlWriter *iface, IUnknown *output) writeroutput_release_stream(This->output); IUnknown_Release(&This->output->IXmlWriterOutput_iface); This->output = NULL; - This->bomwritten = FALSE; + This->bomwritten = 0; This->indent_level = 0; writer_free_element_stack(This); } @@ -1211,7 +1213,7 @@ static HRESULT WINAPI xmlwriter_WriteEndElement(IXmlWriter *iface) { writer_output_ns(This, element); write_output_buffer(This->output, closetagW, ARRAY_SIZE(closetagW)); - This->starttagopen = FALSE; + This->starttagopen = 0; } else { @@ -1551,7 +1553,7 @@ static HRESULT WINAPI xmlwriter_WriteStartElement(IXmlWriter *iface, LPCWSTR pre write_node_indent(This);
This->state = XmlWriterState_ElemStarted; - This->starttagopen = TRUE; + This->starttagopen = 1;
writer_push_element(This, element);
@@ -1772,8 +1774,8 @@ HRESULT WINAPI CreateXmlWriter(REFIID riid, void **obj, IMalloc *imalloc) writer->omitxmldecl = FALSE; writer->conformance = XmlConformanceLevel_Document; writer->state = XmlWriterState_Initial; - writer->bomwritten = FALSE; - writer->starttagopen = FALSE; + writer->bomwritten = 0; + writer->starttagopen = 0; list_init(&writer->elements);
hr = IXmlWriter_QueryInterface(&writer->IXmlWriter_iface, riid, obj); @@ -1819,6 +1821,7 @@ static HRESULT create_writer_output(IUnknown *stream, IMalloc *imalloc, xml_enco } else writeroutput->encoding_name = NULL; + writeroutput->written = 0;
IUnknown_QueryInterface(stream, &IID_IUnknown, (void**)&writeroutput->output);
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/xmllite/tests/writer.c | 87 +++++++++++++++++++++++++++++++++++++ dlls/xmllite/writer.c | 24 ++++++---- 2 files changed, 103 insertions(+), 8 deletions(-)
diff --git a/dlls/xmllite/tests/writer.c b/dlls/xmllite/tests/writer.c index 42b534f269..7f731be211 100644 --- a/dlls/xmllite/tests/writer.c +++ b/dlls/xmllite/tests/writer.c @@ -1981,6 +1981,93 @@ static void test_WriteString(void) " <b>text</b>\r\n" "</a>");
+ IStream_Release(stream); + + stream = writer_set_output(writer); + + hr = write_start_element(writer, NULL, "a", NULL); + ok(hr == S_OK, "Failed to start element, hr %#x.\n", hr); + + hr = write_start_element(writer, NULL, "b", NULL); + ok(hr == S_OK, "Failed to start element, hr %#x.\n", hr); + + hr = IXmlWriter_WriteEndElement(writer); + ok(hr == S_OK, "Failed to end element, hr %#x.\n", hr); + + hr = IXmlWriter_Flush(writer); + ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr); + + CHECK_OUTPUT(stream, + "<a>\r\n" + " <b />"); + + hr = write_start_element(writer, NULL, "c", NULL); + ok(hr == S_OK, "Failed to start element, hr %#x.\n", hr); + + hr = write_attribute_string(writer, NULL, "attr", NULL, "value"); + ok(hr == S_OK, "Failed to write attribute string, hr %#x.\n", hr); + + hr = IXmlWriter_Flush(writer); + ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr); + + CHECK_OUTPUT(stream, + "<a>\r\n" + " <b />\r\n" + " <c attr="value""); + + hr = write_string(writer, "text"); + ok(hr == S_OK, "Failed to write a string, hr %#x.\n", hr); + + hr = IXmlWriter_Flush(writer); + ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr); + + CHECK_OUTPUT(stream, + "<a>\r\n" + " <b />\r\n" + " <c attr="value">text"); + + hr = IXmlWriter_WriteEndElement(writer); + ok(hr == S_OK, "Failed to end element, hr %#x.\n", hr); + + hr = IXmlWriter_Flush(writer); + ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr); + + CHECK_OUTPUT(stream, + "<a>\r\n" + " <b />\r\n" + " <c attr="value">text</c>"); + + hr = write_start_element(writer, NULL, "d", NULL); + ok(hr == S_OK, "Failed to start element, hr %#x.\n", hr); + + hr = write_string(writer, ""); + ok(hr == S_OK, "Failed to write a string, hr %#x.\n", hr); + + hr = IXmlWriter_WriteEndElement(writer); + ok(hr == S_OK, "Failed to end element, hr %#x.\n", hr); + + hr = IXmlWriter_Flush(writer); + ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr); + + CHECK_OUTPUT(stream, + "<a>\r\n" + " <b />\r\n" + " <c attr="value">text</c>\r\n" + " <d></d>"); + + hr = IXmlWriter_WriteEndElement(writer); + ok(hr == S_OK, "Failed to end element, hr %#x.\n", hr); + + hr = IXmlWriter_Flush(writer); + ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr); + + CHECK_OUTPUT(stream, + "<a>\r\n" + " <b />\r\n" + " <c attr="value">text</c>\r\n" + " <d></d>\r\n" + "</a>"); + IXmlWriter_Release(writer); IStream_Release(stream); } diff --git a/dlls/xmllite/writer.c b/dlls/xmllite/writer.c index 94e1f2f8a8..f0eac777ca 100644 --- a/dlls/xmllite/writer.c +++ b/dlls/xmllite/writer.c @@ -118,6 +118,7 @@ typedef struct _xmlwriter struct list elements; DWORD bomwritten : 1; DWORD starttagopen : 1; + DWORD textnode : 1; } xmlwriter;
static inline xmlwriter *impl_from_IXmlWriter(IXmlWriter *iface) @@ -626,8 +627,11 @@ static void write_node_indent(xmlwriter *writer) static const WCHAR crlfW[] = {'\r','\n'}; unsigned int indent_level = writer->indent_level;
- if (!writer->indent) + if (!writer->indent || writer->textnode) + { + writer->textnode = 0; return; + }
/* Do state check to prevent newline inserted after BOM. It is assumed that state does not change between writing BOM and inserting indentation. */ @@ -635,6 +639,8 @@ static void write_node_indent(xmlwriter *writer) write_output_buffer(writer->output, crlfW, ARRAY_SIZE(crlfW)); while (indent_level--) write_output_buffer(writer->output, dblspaceW, ARRAY_SIZE(dblspaceW)); + + writer->textnode = 0; }
static HRESULT WINAPI xmlwriter_QueryInterface(IXmlWriter *iface, REFIID riid, void **ppvObject) @@ -704,6 +710,7 @@ static HRESULT WINAPI xmlwriter_SetOutput(IXmlWriter *iface, IUnknown *output) IUnknown_Release(&This->output->IXmlWriterOutput_iface); This->output = NULL; This->bomwritten = 0; + This->textnode = 0; This->indent_level = 0; writer_free_element_stack(This); } @@ -1281,7 +1288,10 @@ static HRESULT WINAPI xmlwriter_WriteFullEndElement(IXmlWriter *iface)
/* don't force full end tag to the next line */ if (This->state == XmlWriterState_ElemStarted) + { This->state = XmlWriterState_Content; + This->textnode = 0; + } else write_node_indent(This);
@@ -1623,6 +1633,7 @@ static HRESULT WINAPI xmlwriter_WriteString(IXmlWriter *iface, const WCHAR *stri ; }
+ This->textnode = 1; write_escaped_string(This, string); return S_OK; } @@ -1761,21 +1772,18 @@ HRESULT WINAPI CreateXmlWriter(REFIID riid, void **obj, IMalloc *imalloc) writer = IMalloc_Alloc(imalloc, sizeof(*writer)); else writer = heap_alloc(sizeof(*writer)); - if(!writer) return E_OUTOFMEMORY; + if (!writer) + return E_OUTOFMEMORY; + + memset(writer, 0, sizeof(*writer));
writer->IXmlWriter_iface.lpVtbl = &xmlwriter_vtbl; writer->ref = 1; writer->imalloc = imalloc; if (imalloc) IMalloc_AddRef(imalloc); - writer->output = NULL; - writer->indent_level = 0; - writer->indent = FALSE; writer->bom = TRUE; - writer->omitxmldecl = FALSE; writer->conformance = XmlConformanceLevel_Document; writer->state = XmlWriterState_Initial; - writer->bomwritten = 0; - writer->starttagopen = 0; list_init(&writer->elements);
hr = IXmlWriter_QueryInterface(&writer->IXmlWriter_iface, riid, obj);
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/xmllite/writer.c | 59 +++++++++++++++++++++++++++---------------- 1 file changed, 37 insertions(+), 22 deletions(-)
diff --git a/dlls/xmllite/writer.c b/dlls/xmllite/writer.c index f0eac777ca..a359e35ee9 100644 --- a/dlls/xmllite/writer.c +++ b/dlls/xmllite/writer.c @@ -148,6 +148,9 @@ static const char *debugstr_writer_prop(XmlWriterProperty prop) return prop_names[prop]; }
+static HRESULT create_writer_output(IUnknown *stream, IMalloc *imalloc, xml_encoding encoding, + const WCHAR *encoding_name, xmlwriteroutput **out); + /* writer output memory allocation functions */ static inline void *writeroutput_alloc(xmlwriteroutput *output, size_t len) { @@ -735,10 +738,10 @@ static HRESULT WINAPI xmlwriter_SetOutput(IXmlWriter *iface, IUnknown *output) }
if (hr != S_OK || !writeroutput) { - /* create IXmlWriterOutput basing on supplied interface */ - hr = CreateXmlWriterOutputWithEncodingName(output, This->imalloc, NULL, &writeroutput); - if (hr != S_OK) return hr; - This->output = impl_from_IXmlWriterOutput(writeroutput); + /* Create output for given stream. */ + hr = create_writer_output(output, This->imalloc, XmlEncoding_UTF8, NULL, &This->output); + if (hr != S_OK) + return hr; }
if (This->output->encoding == XmlEncoding_Unknown) @@ -1795,12 +1798,12 @@ HRESULT WINAPI CreateXmlWriter(REFIID riid, void **obj, IMalloc *imalloc) }
static HRESULT create_writer_output(IUnknown *stream, IMalloc *imalloc, xml_encoding encoding, - const WCHAR *encoding_name, IXmlWriterOutput **output) + const WCHAR *encoding_name, xmlwriteroutput **out) { xmlwriteroutput *writeroutput; HRESULT hr;
- *output = NULL; + *out = NULL;
if (imalloc) writeroutput = IMalloc_Alloc(imalloc, sizeof(*writeroutput)); @@ -1833,40 +1836,52 @@ static HRESULT create_writer_output(IUnknown *stream, IMalloc *imalloc, xml_enco
IUnknown_QueryInterface(stream, &IID_IUnknown, (void**)&writeroutput->output);
- *output = &writeroutput->IXmlWriterOutput_iface; + *out = writeroutput;
- TRACE("returning iface %p\n", *output); + TRACE("Created writer output %p\n", *out);
return S_OK; }
-HRESULT WINAPI CreateXmlWriterOutputWithEncodingName(IUnknown *stream, - IMalloc *imalloc, - LPCWSTR encoding, - IXmlWriterOutput **output) +HRESULT WINAPI CreateXmlWriterOutputWithEncodingName(IUnknown *stream, IMalloc *imalloc, const WCHAR *encoding, + IXmlWriterOutput **out) { static const WCHAR utf8W[] = {'U','T','F','-','8',0}; + xmlwriteroutput *output; xml_encoding xml_enc; + HRESULT hr; + + TRACE("%p %p %s %p\n", stream, imalloc, debugstr_w(encoding), out);
- TRACE("%p %p %s %p\n", stream, imalloc, debugstr_w(encoding), output); + if (!stream || !out) + return E_INVALIDARG;
- if (!stream || !output) return E_INVALIDARG; + *out = NULL;
xml_enc = parse_encoding_name(encoding ? encoding : utf8W, -1); - return create_writer_output(stream, imalloc, xml_enc, encoding, output); + if (SUCCEEDED(hr = create_writer_output(stream, imalloc, xml_enc, encoding, &output))) + *out = &output->IXmlWriterOutput_iface; + + return hr; }
-HRESULT WINAPI CreateXmlWriterOutputWithEncodingCodePage(IUnknown *stream, - IMalloc *imalloc, - UINT codepage, - IXmlWriterOutput **output) +HRESULT WINAPI CreateXmlWriterOutputWithEncodingCodePage(IUnknown *stream, IMalloc *imalloc, UINT codepage, + IXmlWriterOutput **out) { + xmlwriteroutput *output; xml_encoding xml_enc; + HRESULT hr;
- TRACE("%p %p %u %p\n", stream, imalloc, codepage, output); + TRACE("%p %p %u %p\n", stream, imalloc, codepage, out);
- if (!stream || !output) return E_INVALIDARG; + if (!stream || !out) + return E_INVALIDARG; + + *out = NULL;
xml_enc = get_encoding_from_codepage(codepage); - return create_writer_output(stream, imalloc, xml_enc, NULL, output); + if (SUCCEEDED(hr = create_writer_output(stream, imalloc, xml_enc, NULL, &output))) + *out = &output->IXmlWriterOutput_iface; + + return hr; }
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/xmllite/writer.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/dlls/xmllite/writer.c b/dlls/xmllite/writer.c index a359e35ee9..e9ad941365 100644 --- a/dlls/xmllite/writer.c +++ b/dlls/xmllite/writer.c @@ -1846,7 +1846,6 @@ static HRESULT create_writer_output(IUnknown *stream, IMalloc *imalloc, xml_enco HRESULT WINAPI CreateXmlWriterOutputWithEncodingName(IUnknown *stream, IMalloc *imalloc, const WCHAR *encoding, IXmlWriterOutput **out) { - static const WCHAR utf8W[] = {'U','T','F','-','8',0}; xmlwriteroutput *output; xml_encoding xml_enc; HRESULT hr; @@ -1858,7 +1857,7 @@ HRESULT WINAPI CreateXmlWriterOutputWithEncodingName(IUnknown *stream, IMalloc *
*out = NULL;
- xml_enc = parse_encoding_name(encoding ? encoding : utf8W, -1); + xml_enc = encoding ? parse_encoding_name(encoding, -1) : XmlEncoding_UTF8; if (SUCCEEDED(hr = create_writer_output(stream, imalloc, xml_enc, encoding, &output))) *out = &output->IXmlWriterOutput_iface;