Module: wine Branch: master Commit: 086a1e370906b5cbb5df59edf96019bacd602ab9 URL: http://source.winehq.org/git/wine.git/?a=commit;h=086a1e370906b5cbb5df59edf9...
Author: Nikolay Sivov nsivov@codeweavers.com Date: Tue May 20 01:37:14 2014 +0400
xmllite/writer: Implement ByteOrderMark property.
---
dlls/xmllite/tests/writer.c | 73 +++++++++++++++++++++++++++++++++++++++++++ dlls/xmllite/writer.c | 28 +++++++++++++++++ 2 files changed, 101 insertions(+)
diff --git a/dlls/xmllite/tests/writer.c b/dlls/xmllite/tests/writer.c index d617c43..6800cd2 100644 --- a/dlls/xmllite/tests/writer.c +++ b/dlls/xmllite/tests/writer.c @@ -405,6 +405,78 @@ static void test_omitxmldeclaration(void) IXmlWriter_Release(writer); }
+static void test_bom(void) +{ + static const WCHAR versionW[] = {'v','e','r','s','i','o','n','=','"','1','.','0','"',0}; + static const WCHAR utf16W[] = {'u','t','f','-','1','6',0}; + static const WCHAR xmlW[] = {'x','m','l',0}; + IXmlWriterOutput *output; + unsigned char *ptr; + IXmlWriter *writer; + IStream *stream; + HGLOBAL hglobal; + HRESULT hr; + + hr = CreateStreamOnHGlobal(NULL, TRUE, &stream); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = pCreateXmlWriterOutputWithEncodingName((IUnknown*)stream, NULL, utf16W, &output); + ok(hr == S_OK, "got %08x\n", hr); + + hr = pCreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL); + ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); + + hr = IXmlWriter_SetProperty(writer, XmlWriterProperty_OmitXmlDeclaration, TRUE); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IXmlWriter_SetOutput(writer, output); + ok(hr == S_OK, "got 0x%08x\n", hr); + + /* BOM is on by default */ + hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IXmlWriter_Flush(writer); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = GetHGlobalFromStream(stream, &hglobal); + ok(hr == S_OK, "got 0x%08x\n", hr); + + ptr = GlobalLock(hglobal); + ok(ptr[0] == 0xff && ptr[1] == 0xfe, "got %x,%x\n", ptr[0], ptr[1]); + GlobalUnlock(hglobal); + + IStream_Release(stream); + IUnknown_Release(output); + + /* start with PI */ + hr = CreateStreamOnHGlobal(NULL, TRUE, &stream); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = pCreateXmlWriterOutputWithEncodingName((IUnknown*)stream, NULL, utf16W, &output); + ok(hr == S_OK, "got %08x\n", hr); + + hr = IXmlWriter_SetOutput(writer, output); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IXmlWriter_WriteProcessingInstruction(writer, xmlW, versionW); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IXmlWriter_Flush(writer); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = GetHGlobalFromStream(stream, &hglobal); + ok(hr == S_OK, "got 0x%08x\n", hr); + + ptr = GlobalLock(hglobal); + ok(ptr[0] == 0xff && ptr[1] == 0xfe, "got %x,%x\n", ptr[0], ptr[1]); + GlobalUnlock(hglobal); + + IUnknown_Release(output); + IXmlWriter_Release(writer); + IStream_Release(stream); +} + START_TEST(writer) { if (!init_pointers()) @@ -415,4 +487,5 @@ START_TEST(writer) test_writestartdocument(); test_flush(); test_omitxmldeclaration(); + test_bom(); } diff --git a/dlls/xmllite/writer.c b/dlls/xmllite/writer.c index d1834b8..a1f409c 100644 --- a/dlls/xmllite/writer.c +++ b/dlls/xmllite/writer.c @@ -78,6 +78,7 @@ typedef struct _xmlwriter BOOL omitxmldecl; XmlConformanceLevel conformance; XmlWriterState state; + BOOL bomwritten; } xmlwriter;
static inline xmlwriter *impl_from_IXmlWriter(IXmlWriter *iface) @@ -272,6 +273,26 @@ static HRESULT writeroutput_flush_stream(xmlwriteroutput *output) return S_OK; }
+static HRESULT write_encoding_bom(xmlwriter *writer) +{ + if (!writer->bom || writer->bomwritten) return S_OK; + + if (writer->output->encoding == XmlEncoding_UTF16) { + static const char utf16bom[] = {0xff, 0xfe}; + struct output_buffer *buffer = &writer->output->buffer; + int len = sizeof(utf16bom); + HRESULT hr; + + hr = grow_output_buffer(writer->output, len); + if (FAILED(hr)) return hr; + memcpy(buffer->data + buffer->written, utf16bom, len); + buffer->written += len; + } + + writer->bomwritten = TRUE; + return S_OK; +} + static HRESULT WINAPI xmlwriter_QueryInterface(IXmlWriter *iface, REFIID riid, void **ppvObject) { xmlwriter *This = impl_from_IXmlWriter(iface); @@ -329,6 +350,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; }
/* just reset current output */ @@ -400,6 +422,9 @@ static HRESULT WINAPI xmlwriter_SetProperty(IXmlWriter *iface, UINT property, LO
switch (property) { + case XmlWriterProperty_ByteOrderMark: + This->bom = !!value; + break; case XmlWriterProperty_OmitXmlDeclaration: This->omitxmldecl = !!value; break; @@ -574,6 +599,7 @@ static HRESULT WINAPI xmlwriter_WriteProcessingInstruction(IXmlWriter *iface, LP if (This->state == XmlWriterState_DocStarted && !strcmpW(name, xmlW)) return WR_E_INVALIDACTION;
+ write_encoding_bom(This); write_output_buffer(This->output, openpiW, sizeof(openpiW)/sizeof(WCHAR)); write_output_buffer(This->output, name, -1); write_output_buffer(This->output, spaceW, 1); @@ -635,6 +661,7 @@ static HRESULT WINAPI xmlwriter_WriteStartDocument(IXmlWriter *iface, XmlStandal ; }
+ write_encoding_bom(This); This->state = XmlWriterState_DocStarted; if (This->omitxmldecl) return S_OK;
@@ -833,6 +860,7 @@ HRESULT WINAPI CreateXmlWriter(REFIID riid, void **obj, IMalloc *imalloc) writer->omitxmldecl = FALSE; writer->conformance = XmlConformanceLevel_Document; writer->state = XmlWriterState_Initial; + writer->bomwritten = FALSE;
*obj = &writer->IXmlWriter_iface;