xmllite/writer: Initial support for starting a document.

This commit is contained in:
Nikolay Sivov 2014-05-15 18:49:37 +04:00 committed by Alexandre Julliard
parent 71ab66efa0
commit a0f67c3695
4 changed files with 175 additions and 21 deletions

View File

@ -155,6 +155,11 @@ static const struct xml_encoding_data xml_encoding_map[] = {
{ utf8W, XmlEncoding_UTF8, CP_UTF8 }
};
const WCHAR *get_encoding_name(xml_encoding encoding)
{
return xml_encoding_map[encoding].name;
}
typedef struct
{
char *data;
@ -258,14 +263,6 @@ static inline xmlreaderinput *impl_from_IXmlReaderInput(IXmlReaderInput *iface)
return CONTAINING_RECORD(iface, xmlreaderinput, IXmlReaderInput_iface);
}
static inline void *m_realloc(IMalloc *imalloc, void *mem, size_t len)
{
if (imalloc)
return IMalloc_Realloc(imalloc, mem, len);
else
return heap_realloc(mem, len);
}
/* reader memory allocation functions */
static inline void *reader_alloc(xmlreader *reader, size_t len)
{

View File

@ -133,6 +133,11 @@ static void test_writeroutput(void)
IUnknown *unk;
HRESULT hr;
output = NULL;
hr = pCreateXmlWriterOutputWithEncodingName(&testoutput, NULL, NULL, &output);
ok(hr == S_OK, "got %08x\n", hr);
IUnknown_Release(output);
hr = pCreateXmlWriterOutputWithEncodingName(&testoutput, NULL, utf16W, &output);
ok(hr == S_OK, "got %08x\n", hr);
unk = NULL;
@ -160,12 +165,10 @@ static void test_writestartdocument(void)
/* output not set */
hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
todo_wine
ok(hr == E_UNEXPECTED, "got 0x%08x\n", hr);
if (hr == E_NOTIMPL) {
IXmlWriter_Release(writer);
return;
}
hr = IXmlWriter_WriteProcessingInstruction(writer, xmlW, versionW);
ok(hr == E_UNEXPECTED, "got 0x%08x\n", hr);
hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
ok(hr == S_OK, "got 0x%08x\n", hr);
@ -177,7 +180,14 @@ todo_wine
ok(hr == S_OK, "got 0x%08x\n", hr);
hr = IXmlWriter_Flush(writer);
todo_wine
ok(hr == S_OK, "got 0x%08x\n", hr);
if (hr == E_NOTIMPL)
{
IStream_Release(stream);
IXmlWriter_Release(writer);
return;
}
hr = GetHGlobalFromStream(stream, &hglobal);
ok(hr == S_OK, "got 0x%08x\n", hr);

View File

@ -28,12 +28,15 @@
#include "initguid.h"
#include "wine/debug.h"
#include "wine/unicode.h"
WINE_DEFAULT_DEBUG_CHANNEL(xmllite);
/* not defined in public headers */
DEFINE_GUID(IID_IXmlWriterOutput, 0xc1131708, 0x0f59, 0x477f, 0x93, 0x59, 0x7d, 0x33, 0x24, 0x51, 0xbc, 0x1a);
static const WCHAR closepiW[] = {'?','>'};
struct output_buffer
{
char *data;
@ -42,6 +45,14 @@ struct output_buffer
UINT codepage;
};
typedef enum
{
XmlWriterState_Initial, /* output is not set yet */
XmlWriterState_Ready, /* SetOutput() was called, ready to start */
XmlWriterState_PIDocStarted, /* document was started with manually added 'xml' PI */
XmlWriterState_DocStarted /* document was started with WriteStartDocument() */
} XmlWriterState;
typedef struct
{
IXmlWriterOutput IXmlWriterOutput_iface;
@ -65,6 +76,7 @@ typedef struct _xmlwriter
BOOL bom;
BOOL omitxmldecl;
XmlConformanceLevel conformance;
XmlWriterState state;
} xmlwriter;
static inline xmlwriter *impl_from_IXmlWriter(IXmlWriter *iface)
@ -105,6 +117,11 @@ static inline void writeroutput_free(xmlwriteroutput *output, void *mem)
m_free(output->imalloc, mem);
}
static inline void *writeroutput_realloc(xmlwriteroutput *output, void *mem, size_t len)
{
return m_realloc(output->imalloc, mem, len);
}
/* writer memory allocation functions */
static inline void *writer_alloc(xmlwriter *writer, size_t len)
{
@ -146,6 +163,66 @@ static void free_output_buffer(xmlwriteroutput *output)
buffer->written = 0;
}
static HRESULT grow_output_buffer(xmlwriteroutput *output, int length)
{
struct output_buffer *buffer = &output->buffer;
/* grow if needed, plus 4 bytes to be sure null terminator will fit in */
if (buffer->allocated < buffer->written + length + 4) {
int grown_size = max(2*buffer->allocated, buffer->allocated + length);
char *ptr = writeroutput_realloc(output, buffer->data, grown_size);
if (!ptr) return E_OUTOFMEMORY;
buffer->data = ptr;
buffer->allocated = grown_size;
}
return S_OK;
}
static HRESULT write_output_buffer(xmlwriteroutput *output, const WCHAR *data, int len)
{
struct output_buffer *buffer = &output->buffer;
int length;
HRESULT hr;
char *ptr;
if (buffer->codepage != ~0) {
length = WideCharToMultiByte(buffer->codepage, 0, data, len, NULL, 0, NULL, NULL);
hr = grow_output_buffer(output, length);
if (FAILED(hr)) return hr;
ptr = buffer->data + buffer->written;
length = WideCharToMultiByte(buffer->codepage, 0, data, len, ptr, length, NULL, NULL);
buffer->written += len == -1 ? length-1 : length;
}
else {
/* WCHAR data just copied */
length = len == -1 ? strlenW(data) : len;
if (length) {
length *= sizeof(WCHAR);
hr = grow_output_buffer(output, length);
if (FAILED(hr)) return hr;
ptr = buffer->data + buffer->written;
memcpy(ptr, data, length);
buffer->written += length;
ptr += length;
/* null termination */
*(WCHAR*)ptr = 0;
}
}
return S_OK;
}
static HRESULT write_output_buffer_quoted(xmlwriteroutput *output, const WCHAR *data, int len)
{
static const WCHAR quotW[] = {'"'};
write_output_buffer(output, quotW, 1);
write_output_buffer(output, data, len);
write_output_buffer(output, quotW, 1);
return S_OK;
}
static void writeroutput_release_stream(xmlwriteroutput *writeroutput)
{
if (writeroutput->stream) {
@ -224,8 +301,10 @@ static HRESULT WINAPI xmlwriter_SetOutput(IXmlWriter *iface, IUnknown *output)
}
/* just reset current output */
if (!output)
if (!output) {
This->state = XmlWriterState_Initial;
return S_OK;
}
/* now try IXmlWriterOutput, ISequentialStream, IStream */
hr = IUnknown_QueryInterface(output, &IID_IXmlWriterOutput, (void**)&writeroutput);
@ -248,6 +327,7 @@ static HRESULT WINAPI xmlwriter_SetOutput(IXmlWriter *iface, IUnknown *output)
This->output = impl_from_IXmlWriterOutput(writeroutput);
}
This->state = XmlWriterState_Ready;
return writeroutput_query_for_stream(This->output);
}
@ -437,14 +517,32 @@ static HRESULT WINAPI xmlwriter_WriteNodeShallow(IXmlWriter *iface, IXmlReader *
return E_NOTIMPL;
}
static HRESULT WINAPI xmlwriter_WriteProcessingInstruction(IXmlWriter *iface, LPCWSTR pwszName,
LPCWSTR pwszText)
static HRESULT WINAPI xmlwriter_WriteProcessingInstruction(IXmlWriter *iface, LPCWSTR name,
LPCWSTR text)
{
xmlwriter *This = impl_from_IXmlWriter(iface);
static const WCHAR xmlW[] = {'x','m','l',0};
static const WCHAR openpiW[] = {'<','?'};
static const WCHAR spaceW[] = {' '};
FIXME("%p %s %s\n", This, wine_dbgstr_w(pwszName), wine_dbgstr_w(pwszText));
TRACE("(%p)->(%s %s)\n", This, wine_dbgstr_w(name), wine_dbgstr_w(text));
return E_NOTIMPL;
if (This->state == XmlWriterState_Initial)
return E_UNEXPECTED;
if (This->state == XmlWriterState_DocStarted && !strcmpW(name, xmlW))
return WR_E_INVALIDACTION;
write_output_buffer(This->output, openpiW, sizeof(openpiW)/sizeof(WCHAR));
write_output_buffer(This->output, name, -1);
write_output_buffer(This->output, spaceW, 1);
write_output_buffer(This->output, text, -1);
write_output_buffer(This->output, closepiW, sizeof(closepiW)/sizeof(WCHAR));
if (!strcmpW(name, xmlW))
This->state = XmlWriterState_PIDocStarted;
return S_OK;
}
static HRESULT WINAPI xmlwriter_WriteQualifiedName(IXmlWriter *iface, LPCWSTR pwszLocalName,
@ -477,11 +575,49 @@ static HRESULT WINAPI xmlwriter_WriteRawChars(IXmlWriter *iface, const WCHAR *p
static HRESULT WINAPI xmlwriter_WriteStartDocument(IXmlWriter *iface, XmlStandalone standalone)
{
static const WCHAR versionW[] = {'<','?','x','m','l',' ','v','e','r','s','i','o','n','=','"','1','.','0','"'};
static const WCHAR encodingW[] = {' ','e','n','c','o','d','i','n','g','='};
xmlwriter *This = impl_from_IXmlWriter(iface);
FIXME("%p\n", This);
TRACE("(%p)->(%d)\n", This, standalone);
return E_NOTIMPL;
switch (This->state)
{
case XmlWriterState_Initial:
return E_UNEXPECTED;
case XmlWriterState_PIDocStarted:
This->state = XmlWriterState_DocStarted;
return S_OK;
case XmlWriterState_DocStarted:
return WR_E_INVALIDACTION;
default:
;
}
/* version */
write_output_buffer(This->output, versionW, sizeof(versionW)/sizeof(WCHAR));
/* encoding */
write_output_buffer(This->output, encodingW, sizeof(encodingW)/sizeof(WCHAR));
write_output_buffer_quoted(This->output, get_encoding_name(This->output->encoding), -1);
/* standalone */
if (standalone == XmlStandalone_Omit)
write_output_buffer(This->output, closepiW, sizeof(closepiW)/sizeof(WCHAR));
else {
static const WCHAR standaloneW[] = {' ','s','t','a','n','d','a','l','o','n','e','=','\"'};
static const WCHAR yesW[] = {'y','e','s','\"','?','>'};
static const WCHAR noW[] = {'n','o','\"','?','>'};
write_output_buffer(This->output, standaloneW, sizeof(standaloneW)/sizeof(WCHAR));
if (standalone == XmlStandalone_Yes)
write_output_buffer(This->output, yesW, sizeof(yesW)/sizeof(WCHAR));
else
write_output_buffer(This->output, noW, sizeof(noW)/sizeof(WCHAR));
}
This->state = XmlWriterState_DocStarted;
return S_OK;
}
static HRESULT WINAPI xmlwriter_WriteStartElement(IXmlWriter *iface, LPCWSTR pwszPrefix,
@ -653,6 +789,7 @@ HRESULT WINAPI CreateXmlWriter(REFIID riid, void **obj, IMalloc *imalloc)
writer->bom = TRUE;
writer->omitxmldecl = FALSE;
writer->conformance = XmlConformanceLevel_Document;
writer->state = XmlWriterState_Initial;
*obj = &writer->IXmlWriter_iface;
@ -666,6 +803,7 @@ HRESULT WINAPI CreateXmlWriterOutputWithEncodingName(IUnknown *stream,
LPCWSTR encoding,
IXmlWriterOutput **output)
{
static const WCHAR utf8W[] = {'U','T','F','-','8',0};
xmlwriteroutput *writeroutput;
HRESULT hr;
@ -685,7 +823,7 @@ HRESULT WINAPI CreateXmlWriterOutputWithEncodingName(IUnknown *stream,
writeroutput->ref = 1;
writeroutput->imalloc = imalloc;
if (imalloc) IMalloc_AddRef(imalloc);
writeroutput->encoding = parse_encoding_name(encoding, -1);
writeroutput->encoding = parse_encoding_name(encoding ? encoding : utf8W, -1);
writeroutput->stream = NULL;
hr = init_output_buffer(writeroutput);
if (FAILED(hr)) {

View File

@ -45,6 +45,14 @@ static inline void *m_alloc(IMalloc *imalloc, size_t len)
return heap_alloc(len);
}
static inline void *m_realloc(IMalloc *imalloc, void *mem, size_t len)
{
if (imalloc)
return IMalloc_Realloc(imalloc, mem, len);
else
return heap_realloc(mem, len);
}
static inline void m_free(IMalloc *imalloc, void *mem)
{
if (imalloc)
@ -62,5 +70,6 @@ typedef enum
xml_encoding parse_encoding_name(const WCHAR*,int) DECLSPEC_HIDDEN;
HRESULT get_code_page(xml_encoding,UINT*) DECLSPEC_HIDDEN;
const WCHAR *get_encoding_name(xml_encoding) DECLSPEC_HIDDEN;
#endif /* __XMLLITE_PRIVATE__ */