Module: wine Branch: master Commit: 22c9af716270632437d2d4ea261d04aea490363c URL: https://gitlab.winehq.org/wine/wine/-/commit/22c9af716270632437d2d4ea261d04a...
Author: Nikolay Sivov nsivov@codeweavers.com Date: Wed Sep 14 23:57:10 2022 +0300
xmllite/writer: Implement WriteAttributes().
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com
---
dlls/xmllite/tests/writer.c | 105 ++++++++++++++++++++++++++++++++++++++++++++ dlls/xmllite/writer.c | 50 ++++++++++++++++++--- 2 files changed, 150 insertions(+), 5 deletions(-)
diff --git a/dlls/xmllite/tests/writer.c b/dlls/xmllite/tests/writer.c index f01f6194a4d..c65916d44e4 100644 --- a/dlls/xmllite/tests/writer.c +++ b/dlls/xmllite/tests/writer.c @@ -32,6 +32,41 @@ #include "initguid.h" DEFINE_GUID(IID_IXmlWriterOutput, 0xc1131708, 0x0f59, 0x477f, 0x93, 0x59, 0x7d, 0x33, 0x24, 0x51, 0xbc, 0x1a);
+static IStream *create_stream_on_data(const void *data, unsigned int size) +{ + IStream *stream = NULL; + HGLOBAL hglobal; + void *ptr; + HRESULT hr; + + hglobal = GlobalAlloc(GHND, size); + ptr = GlobalLock(hglobal); + + memcpy(ptr, data, size); + + hr = CreateStreamOnHGlobal(hglobal, TRUE, &stream); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(stream != NULL, "Expected non-NULL stream\n"); + + GlobalUnlock(hglobal); + + return stream; +} + +#define reader_set_input(a, b) _reader_set_input(__LINE__, a, b) +static void _reader_set_input(unsigned line, IXmlReader *reader, const char *xml) +{ + IStream *stream; + HRESULT hr; + + stream = create_stream_on_data(xml, strlen(xml)); + + hr = IXmlReader_SetInput(reader, (IUnknown *)stream); + ok_(__FILE__,line)(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + IStream_Release(stream); +} + #define EXPECT_REF(obj, ref) _expect_ref((IUnknown *)obj, ref, __LINE__) static void _expect_ref(IUnknown *obj, ULONG ref, int line) { @@ -2155,6 +2190,75 @@ static void test_WriteProcessingInstruction(void) IXmlWriter_Release(writer); }
+static void test_WriteAttributes(void) +{ + XmlNodeType node_type; + IXmlWriter *writer; + IXmlReader *reader; + const WCHAR *name; + IStream *stream; + HRESULT hr; + + hr = CreateXmlWriter(&IID_IXmlWriter, (void **)&writer, NULL); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = CreateXmlReader(&IID_IXmlReader, (void **)&reader, NULL); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + /* No attributes. */ + reader_set_input(reader, "<a/>"); + stream = writer_set_output(writer); + hr = IXmlWriter_WriteAttributes(writer, reader, FALSE); + ok(hr == E_UNEXPECTED, "Unexpected hr %#lx.\n", hr); + hr = IXmlReader_Read(reader, NULL); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IXmlWriter_WriteAttributes(writer, reader, FALSE); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IXmlWriter_Flush(writer); + ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr); + CHECK_OUTPUT(stream, ""); + IStream_Release(stream); + + /* Position on element with attributes. */ + reader_set_input(reader, "<a attr1='b' attr2='c' attr3='d' />"); + stream = writer_set_output(writer); + hr = IXmlReader_Read(reader, NULL); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IXmlWriter_WriteStartElement(writer, NULL, L"w", NULL); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IXmlWriter_WriteAttributes(writer, reader, FALSE); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IXmlReader_GetNodeType(reader, &node_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(node_type == XmlNodeType_Element, "Unexpected node type %d.\n", node_type); + hr = IXmlWriter_Flush(writer); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + CHECK_OUTPUT(stream, "<w attr1="b" attr2="c" attr3="d""); + IStream_Release(stream); + + /* Position on second attribute. */ + hr = IXmlReader_MoveToAttributeByName(reader, L"attr2", NULL); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + stream = writer_set_output(writer); + hr = IXmlWriter_WriteStartElement(writer, NULL, L"w", NULL); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IXmlWriter_WriteAttributes(writer, reader, FALSE); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IXmlReader_GetNodeType(reader, &node_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(node_type == XmlNodeType_Attribute, "Unexpected node type %d.\n", node_type); + hr = IXmlReader_GetLocalName(reader, &name, NULL); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(!wcscmp(name, L"attr3"), "Unexpected node %s.\n", debugstr_w(name)); + hr = IXmlWriter_Flush(writer); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + CHECK_OUTPUT(stream, "<w attr2="c" attr3="d""); + IStream_Release(stream); + + IXmlWriter_Release(writer); + IXmlReader_Release(reader); +} + START_TEST(writer) { test_writer_create(); @@ -2179,4 +2283,5 @@ START_TEST(writer) test_WriteDocType(); test_WriteWhitespace(); test_WriteProcessingInstruction(); + test_WriteAttributes(); } diff --git a/dlls/xmllite/writer.c b/dlls/xmllite/writer.c index 1df4c1dc922..e9a2e387126 100644 --- a/dlls/xmllite/writer.c +++ b/dlls/xmllite/writer.c @@ -845,14 +845,54 @@ static HRESULT WINAPI xmlwriter_SetProperty(IXmlWriter *iface, UINT property, LO return S_OK; }
-static HRESULT WINAPI xmlwriter_WriteAttributes(IXmlWriter *iface, IXmlReader *pReader, - BOOL fWriteDefaultAttributes) +static HRESULT writer_write_attribute(IXmlWriter *writer, IXmlReader *reader, BOOL write_default_attributes) { - xmlwriter *This = impl_from_IXmlWriter(iface); + const WCHAR *prefix, *local, *uri, *value; + HRESULT hr;
- FIXME("%p %p %d\n", This, pReader, fWriteDefaultAttributes); + if (IXmlReader_IsDefault(reader) && !write_default_attributes) + return S_OK;
- return E_NOTIMPL; + if (FAILED(hr = IXmlReader_GetPrefix(reader, &prefix, NULL))) return hr; + if (FAILED(hr = IXmlReader_GetLocalName(reader, &local, NULL))) return hr; + if (FAILED(hr = IXmlReader_GetNamespaceUri(reader, &uri, NULL))) return hr; + if (FAILED(hr = IXmlReader_GetValue(reader, &value, NULL))) return hr; + return IXmlWriter_WriteAttributeString(writer, prefix, local, uri, value); +} + +static HRESULT WINAPI xmlwriter_WriteAttributes(IXmlWriter *iface, IXmlReader *reader, BOOL write_default_attributes) +{ + XmlNodeType node_type; + HRESULT hr = S_OK; + + TRACE("%p, %p, %d.\n", iface, reader, write_default_attributes); + + if (FAILED(hr = IXmlReader_GetNodeType(reader, &node_type))) return hr; + + switch (node_type) + { + case XmlNodeType_Element: + case XmlNodeType_XmlDeclaration: + case XmlNodeType_Attribute: + if (node_type != XmlNodeType_Attribute) + { + if (FAILED(hr = IXmlReader_MoveToFirstAttribute(reader))) return hr; + if (hr == S_FALSE) return S_OK; + } + if (FAILED(hr = writer_write_attribute(iface, reader, write_default_attributes))) return hr; + while (IXmlReader_MoveToNextAttribute(reader) == S_OK) + { + if (FAILED(hr = writer_write_attribute(iface, reader, write_default_attributes))) break; + } + if (node_type != XmlNodeType_Attribute && SUCCEEDED(hr)) + hr = IXmlReader_MoveToElement(reader); + break; + default: + WARN("Unexpected node type %d.\n", node_type); + return E_UNEXPECTED; + } + + return hr; }
static void write_output_attribute(xmlwriter *writer, const WCHAR *prefix, int prefix_len,