Nikolay Sivov : xmllite/writer: Implement ByteOrderMark property.

Alexandre Julliard julliard at winehq.org
Tue May 20 14:36:24 CDT 2014


Module: wine
Branch: master
Commit: 086a1e370906b5cbb5df59edf96019bacd602ab9
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=086a1e370906b5cbb5df59edf96019bacd602ab9

Author: Nikolay Sivov <nsivov at 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;
 




More information about the wine-cvs mailing list