webservices: Implement WsWriteStartElement.

Signed-off-by: Hans Leidekker <hans@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Hans Leidekker 2015-11-10 10:46:40 +01:00 committed by Alexandre Julliard
parent 2bfcd98c30
commit 1e3b84a75e
4 changed files with 236 additions and 14 deletions

View File

@ -29,7 +29,7 @@
WINE_DEFAULT_DEBUG_CHANNEL(webservices);
static const char *debugstr_xmlstr( const WS_XML_STRING *str )
const char *debugstr_xmlstr( const WS_XML_STRING *str )
{
if (!str) return "(null)";
return debugstr_an( (const char *)str->bytes, str->length );
@ -164,6 +164,12 @@ void *ws_alloc( WS_HEAP *handle, SIZE_T size )
return HeapAlloc( heap->handle, 0, size );
}
void *ws_realloc( WS_HEAP *handle, void *ptr, SIZE_T size )
{
struct heap *heap = (struct heap *)handle;
return HeapReAlloc( heap->handle, 0, ptr, size );
}
void ws_free( WS_HEAP *handle, void *ptr )
{
struct heap *heap = (struct heap *)handle;
@ -267,15 +273,7 @@ void WINAPI WsFreeHeap( WS_HEAP *handle )
heap_free( heap );
}
struct node
{
WS_XML_ELEMENT_NODE hdr;
struct list entry;
struct node *parent;
struct list children;
};
static struct node *alloc_node( WS_XML_NODE_TYPE type )
struct node *alloc_node( WS_XML_NODE_TYPE type )
{
struct node *ret;
@ -296,7 +294,7 @@ static void free_attribute( WS_XML_ATTRIBUTE *attr )
heap_free( attr );
}
static void free_node( struct node *node )
void free_node( struct node *node )
{
if (!node) return;
switch (node->hdr.node.nodeType)
@ -336,7 +334,7 @@ static void free_node( struct node *node )
heap_free( node );
}
static void destroy_nodes( struct node *node )
void destroy_nodes( struct node *node )
{
struct list *ptr;
@ -648,7 +646,7 @@ HRESULT WINAPI WsGetXmlAttribute( WS_XML_READER *handle, const WS_XML_STRING *at
return E_NOTIMPL;
}
static WS_XML_STRING *alloc_xml_string( const char *data, ULONG len )
WS_XML_STRING *alloc_xml_string( const char *data, ULONG len )
{
WS_XML_STRING *ret;

View File

@ -183,7 +183,7 @@
@ stub WsWriteQualifiedName
@ stub WsWriteStartAttribute
@ stub WsWriteStartCData
@ stub WsWriteStartElement
@ stdcall WsWriteStartElement(ptr ptr ptr ptr ptr)
@ stub WsWriteText
@ stub WsWriteType
@ stub WsWriteValue

View File

@ -25,7 +25,22 @@ struct xmlbuf
};
void *ws_alloc( WS_HEAP *, SIZE_T ) DECLSPEC_HIDDEN;
void *ws_realloc( WS_HEAP *, void *, SIZE_T ) DECLSPEC_HIDDEN;
void ws_free( WS_HEAP *, void * ) DECLSPEC_HIDDEN;
const char *debugstr_xmlstr( const WS_XML_STRING * ) DECLSPEC_HIDDEN;
WS_XML_STRING *alloc_xml_string( const char *, ULONG ) DECLSPEC_HIDDEN;
struct node
{
WS_XML_ELEMENT_NODE hdr;
struct list entry;
struct node *parent;
struct list children;
};
struct node *alloc_node( WS_XML_NODE_TYPE ) DECLSPEC_HIDDEN;
void free_node( struct node * ) DECLSPEC_HIDDEN;
void destroy_nodes( struct node * ) DECLSPEC_HIDDEN;
static inline void *heap_alloc( SIZE_T size )
{

View File

@ -23,6 +23,7 @@
#include "webservices.h"
#include "wine/debug.h"
#include "wine/list.h"
#include "webservices_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(webservices);
@ -55,10 +56,23 @@ writer_props[] =
{ sizeof(BOOL), FALSE } /* WS_XML_WRITER_PROPERTY_EMIT_UNCOMPRESSED_EMPTY_ELEMENTS */
};
enum writer_state
{
WRITER_STATE_INITIAL,
WRITER_STATE_STARTELEMENT,
WRITER_STATE_STARTENDELEMENT,
WRITER_STATE_STARTATTRIBUTE,
WRITER_STATE_ENDSTARTELEMENT,
WRITER_STATE_ENDELEMENT
};
struct writer
{
ULONG write_pos;
char *write_bufptr;
enum writer_state state;
struct node *root;
struct node *current;
WS_XML_WRITER_OUTPUT_TYPE output_type;
struct xmlbuf *output_buf;
WS_HEAP *output_heap;
@ -108,10 +122,46 @@ static HRESULT get_writer_prop( struct writer *writer, WS_XML_WRITER_PROPERTY_ID
static void free_writer( struct writer *writer )
{
destroy_nodes( writer->root );
WsFreeHeap( writer->output_heap );
heap_free( writer );
}
static void write_insert_eof( struct writer *writer, struct node *eof )
{
if (!writer->root) writer->root = eof;
else
{
eof->parent = writer->root;
list_add_tail( &writer->root->children, &eof->entry );
}
writer->current = eof;
}
static void write_insert_node( struct writer *writer, struct node *node )
{
node->parent = writer->current;
if (writer->current == writer->root)
{
struct list *eof = list_tail( &writer->root->children );
list_add_before( eof, &node->entry );
}
else list_add_tail( &writer->current->children, &node->entry );
writer->current = node;
}
static HRESULT write_init_state( struct writer *writer )
{
struct node *node;
destroy_nodes( writer->root );
writer->root = NULL;
if (!(node = alloc_node( WS_XML_NODE_TYPE_EOF ))) return E_OUTOFMEMORY;
write_insert_eof( writer, node );
writer->state = WRITER_STATE_INITIAL;
return S_OK;
}
/**************************************************************************
* WsCreateWriter [webservices.@]
*/
@ -161,6 +211,13 @@ HRESULT WINAPI WsCreateWriter( const WS_XML_WRITER_PROPERTY *properties, ULONG c
return hr;
}
hr = write_init_state( writer );
if (hr != S_OK)
{
free_writer( writer );
return hr;
}
*handle = (WS_XML_WRITER *)writer;
return S_OK;
}
@ -327,3 +384,155 @@ HRESULT WINAPI WsSetOutputToBuffer( WS_XML_WRITER *handle, WS_XML_BUFFER *buffer
set_output_buffer( writer, xmlbuf );
return S_OK;
}
static HRESULT write_grow_buffer( struct writer *writer, ULONG size )
{
struct xmlbuf *buf = writer->output_buf;
SIZE_T new_size;
void *tmp;
if (buf->size_allocated >= writer->write_pos + size)
{
buf->size = writer->write_pos + size;
return S_OK;
}
new_size = max( buf->size_allocated * 2, writer->write_pos + size );
if (!(tmp = ws_realloc( buf->heap, buf->ptr, new_size ))) return E_OUTOFMEMORY;
writer->write_bufptr = buf->ptr = tmp;
buf->size_allocated = new_size;
buf->size = writer->write_pos + size;
return S_OK;
}
static inline void write_char( struct writer *writer, char ch )
{
writer->write_bufptr[writer->write_pos++] = ch;
}
static inline void write_bytes( struct writer *writer, const BYTE *bytes, ULONG len )
{
memcpy( writer->write_bufptr + writer->write_pos, bytes, len );
writer->write_pos += len;
}
static HRESULT write_attribute( struct writer *writer, WS_XML_ATTRIBUTE *attr )
{
WS_XML_UTF8_TEXT *text = (WS_XML_UTF8_TEXT *)attr->value;
ULONG size;
HRESULT hr;
/* ' prefix:attr="value"' */
size = attr->localName->length + 4 /* ' =""' */;
if (attr->prefix) size += attr->prefix->length + 1 /* ':' */;
if (text) size += text->value.length;
if ((hr = write_grow_buffer( writer, size )) != S_OK) return hr;
write_char( writer, ' ' );
if (attr->prefix)
{
write_bytes( writer, attr->prefix->bytes, attr->prefix->length );
write_char( writer, ':' );
}
write_bytes( writer, attr->localName->bytes, attr->localName->length );
write_char( writer, '=' );
if (attr->singleQuote) write_char( writer, '\'' );
else write_char( writer, '"' );
if (text) write_bytes( writer, text->value.bytes, text->value.length );
if (attr->singleQuote) write_char( writer, '\'' );
else write_char( writer, '"' );
/* FIXME: ignoring namespace */
return S_OK;
}
static HRESULT write_startelement( struct writer *writer )
{
WS_XML_ELEMENT_NODE *elem = (WS_XML_ELEMENT_NODE *)writer->current;
ULONG size, i;
HRESULT hr;
/* '<prefix:localname prefix:attr="value"... xmlns:prefix="ns"' */
size = elem->localName->length + 1 /* '<' */;
if (elem->prefix) size += elem->prefix->length + 1 /* ':' */;
if (elem->ns->length)
{
size += strlen(" xmlns") + elem->ns->length + 3 /* '=""' */;
if (elem->prefix) size += elem->prefix->length + 1 /* ':' */;
}
if ((hr = write_grow_buffer( writer, size )) != S_OK) return hr;
write_char( writer, '<' );
if (elem->prefix)
{
write_bytes( writer, elem->prefix->bytes, elem->prefix->length );
write_char( writer, ':' );
}
write_bytes( writer, elem->localName->bytes, elem->localName->length );
for (i = 0; i < elem->attributeCount; i++)
{
if ((hr = write_attribute( writer, elem->attributes[i] )) != S_OK) return hr;
}
if (elem->ns->length)
{
write_bytes( writer, (const BYTE *)" xmlns", 6 );
if (elem->prefix)
{
write_char( writer, ':' );
write_bytes( writer, elem->prefix->bytes, elem->prefix->length );
}
write_char( writer, '=' );
write_char( writer, '"' );
write_bytes( writer, elem->ns->bytes, elem->ns->length );
write_char( writer, '"' );
}
return S_OK;
}
/**************************************************************************
* WsWriteStartElement [webservices.@]
*/
HRESULT WINAPI WsWriteStartElement( WS_XML_WRITER *handle, const WS_XML_STRING *prefix,
const WS_XML_STRING *localname, const WS_XML_STRING *ns,
WS_ERROR *error )
{
struct writer *writer = (struct writer *)handle;
struct node *node;
WS_XML_ELEMENT_NODE *elem;
HRESULT hr = E_OUTOFMEMORY;
TRACE( "%p %s %s %s %p\n", handle, debugstr_xmlstr(prefix), debugstr_xmlstr(localname),
debugstr_xmlstr(ns), error );
if (error) FIXME( "ignoring error parameter\n" );
if (!writer || !localname || !ns) return E_INVALIDARG;
/* flush current start element */
if (writer->state == WRITER_STATE_STARTELEMENT)
{
if ((hr = write_startelement( writer )) != S_OK) return hr;
if ((hr = write_grow_buffer( writer, 1 )) != S_OK) return hr;
write_char( writer, '>' );
}
if (!(node = alloc_node( WS_XML_NODE_TYPE_ELEMENT ))) return E_OUTOFMEMORY;
elem = (WS_XML_ELEMENT_NODE *)node;
if (prefix && !(elem->prefix = alloc_xml_string( (const char *)prefix->bytes, prefix->length )))
goto error;
if (!(elem->localName = alloc_xml_string( (const char *)localname->bytes, localname->length )))
goto error;
if (!(elem->ns = alloc_xml_string( (const char *)ns->bytes, ns->length )))
goto error;
write_insert_node( writer, node );
writer->state = WRITER_STATE_STARTELEMENT;
return S_OK;
error:
free_node( node );
return hr;
}