webservices: Avoid writing redundant namespace attributes.
[wine.git] / dlls / webservices / writer.c
blobecbba37c8f99faeb1e3c6648ddda0aa0dfa9863a
1 /*
2 * Copyright 2015, 2016 Hans Leidekker for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include <stdarg.h>
21 #include "windef.h"
22 #include "winbase.h"
23 #include "winuser.h"
24 #include "webservices.h"
26 #include "wine/debug.h"
27 #include "wine/list.h"
28 #include "wine/unicode.h"
29 #include "webservices_private.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(webservices);
33 static const struct prop_desc writer_props[] =
35 { sizeof(ULONG), FALSE }, /* WS_XML_WRITER_PROPERTY_MAX_DEPTH */
36 { sizeof(BOOL), FALSE }, /* WS_XML_WRITER_PROPERTY_ALLOW_FRAGMENT */
37 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_MAX_ATTRIBUTES */
38 { sizeof(BOOL), FALSE }, /* WS_XML_WRITER_PROPERTY_WRITE_DECLARATION */
39 { sizeof(ULONG), FALSE }, /* WS_XML_WRITER_PROPERTY_INDENT */
40 { sizeof(ULONG), FALSE }, /* WS_XML_WRITER_PROPERTY_BUFFER_TRIM_SIZE */
41 { sizeof(WS_CHARSET), FALSE }, /* WS_XML_WRITER_PROPERTY_CHARSET */
42 { sizeof(WS_BUFFERS), FALSE }, /* WS_XML_WRITER_PROPERTY_BUFFERS */
43 { sizeof(ULONG), FALSE }, /* WS_XML_WRITER_PROPERTY_BUFFER_MAX_SIZE */
44 { sizeof(WS_BYTES), FALSE }, /* WS_XML_WRITER_PROPERTY_BYTES */
45 { sizeof(BOOL), TRUE }, /* WS_XML_WRITER_PROPERTY_IN_ATTRIBUTE */
46 { sizeof(ULONG), FALSE }, /* WS_XML_WRITER_PROPERTY_MAX_MIME_PARTS_BUFFER_SIZE */
47 { sizeof(WS_BYTES), FALSE }, /* WS_XML_WRITER_PROPERTY_INITIAL_BUFFER */
48 { sizeof(BOOL), FALSE }, /* WS_XML_WRITER_PROPERTY_ALLOW_INVALID_CHARACTER_REFERENCES */
49 { sizeof(ULONG), FALSE }, /* WS_XML_WRITER_PROPERTY_MAX_NAMESPACES */
50 { sizeof(ULONG), TRUE }, /* WS_XML_WRITER_PROPERTY_BYTES_WRITTEN */
51 { sizeof(ULONG), TRUE }, /* WS_XML_WRITER_PROPERTY_BYTES_TO_CLOSE */
52 { sizeof(BOOL), FALSE }, /* WS_XML_WRITER_PROPERTY_COMPRESS_EMPTY_ELEMENTS */
53 { sizeof(BOOL), FALSE } /* WS_XML_WRITER_PROPERTY_EMIT_UNCOMPRESSED_EMPTY_ELEMENTS */
56 enum writer_state
58 WRITER_STATE_INITIAL,
59 WRITER_STATE_STARTELEMENT,
60 WRITER_STATE_STARTENDELEMENT,
61 WRITER_STATE_STARTATTRIBUTE,
62 WRITER_STATE_STARTCDATA,
63 WRITER_STATE_ENDSTARTELEMENT,
64 WRITER_STATE_TEXT,
65 WRITER_STATE_ENDELEMENT,
66 WRITER_STATE_ENDCDATA
69 struct writer
71 ULONG write_pos;
72 unsigned char *write_bufptr;
73 enum writer_state state;
74 struct node *root;
75 struct node *current;
76 WS_XML_STRING *current_ns;
77 WS_XML_WRITER_OUTPUT_TYPE output_type;
78 struct xmlbuf *output_buf;
79 WS_HEAP *output_heap;
80 ULONG prop_count;
81 struct prop prop[sizeof(writer_props)/sizeof(writer_props[0])];
84 static struct writer *alloc_writer(void)
86 static const ULONG count = sizeof(writer_props)/sizeof(writer_props[0]);
87 struct writer *ret;
88 ULONG size = sizeof(*ret) + prop_size( writer_props, count );
90 if (!(ret = heap_alloc_zero( size ))) return NULL;
91 prop_init( writer_props, count, ret->prop, &ret[1] );
92 ret->prop_count = count;
93 return ret;
96 static void free_writer( struct writer *writer )
98 destroy_nodes( writer->root );
99 heap_free( writer->current_ns );
100 WsFreeHeap( writer->output_heap );
101 heap_free( writer );
104 static void write_insert_eof( struct writer *writer, struct node *eof )
106 if (!writer->root) writer->root = eof;
107 else
109 eof->parent = writer->root;
110 list_add_tail( &writer->root->children, &eof->entry );
112 writer->current = eof;
115 static void write_insert_bof( struct writer *writer, struct node *bof )
117 writer->root->parent = bof;
118 list_add_tail( &bof->children, &writer->root->entry );
119 writer->current = writer->root = bof;
122 static void write_insert_node( struct writer *writer, struct node *node )
124 node->parent = writer->current;
125 if (writer->current == writer->root)
127 struct list *eof = list_tail( &writer->root->children );
128 list_add_before( eof, &node->entry );
130 else list_add_tail( &writer->current->children, &node->entry );
131 writer->current = node;
134 static HRESULT write_init_state( struct writer *writer )
136 struct node *node;
138 heap_free( writer->current_ns );
139 writer->current_ns = NULL;
140 destroy_nodes( writer->root );
141 writer->root = NULL;
143 if (!(node = alloc_node( WS_XML_NODE_TYPE_EOF ))) return E_OUTOFMEMORY;
144 write_insert_eof( writer, node );
145 writer->state = WRITER_STATE_INITIAL;
146 return S_OK;
149 /**************************************************************************
150 * WsCreateWriter [webservices.@]
152 HRESULT WINAPI WsCreateWriter( const WS_XML_WRITER_PROPERTY *properties, ULONG count,
153 WS_XML_WRITER **handle, WS_ERROR *error )
155 struct writer *writer;
156 ULONG i, max_depth = 32, max_attrs = 128, trim_size = 4096, max_size = 65536, max_ns = 32;
157 WS_CHARSET charset = WS_CHARSET_UTF8;
158 HRESULT hr;
160 TRACE( "%p %u %p %p\n", properties, count, handle, error );
161 if (error) FIXME( "ignoring error parameter\n" );
163 if (!handle) return E_INVALIDARG;
164 if (!(writer = alloc_writer())) return E_OUTOFMEMORY;
166 prop_set( writer->prop, writer->prop_count, WS_XML_WRITER_PROPERTY_MAX_DEPTH, &max_depth, sizeof(max_depth) );
167 prop_set( writer->prop, writer->prop_count, WS_XML_WRITER_PROPERTY_MAX_ATTRIBUTES, &max_attrs, sizeof(max_attrs) );
168 prop_set( writer->prop, writer->prop_count, WS_XML_WRITER_PROPERTY_BUFFER_TRIM_SIZE, &trim_size, sizeof(trim_size) );
169 prop_set( writer->prop, writer->prop_count, WS_XML_WRITER_PROPERTY_CHARSET, &charset, sizeof(charset) );
170 prop_set( writer->prop, writer->prop_count, WS_XML_WRITER_PROPERTY_BUFFER_MAX_SIZE, &max_size, sizeof(max_size) );
171 prop_set( writer->prop, writer->prop_count, WS_XML_WRITER_PROPERTY_MAX_MIME_PARTS_BUFFER_SIZE, &max_size, sizeof(max_size) );
172 prop_set( writer->prop, writer->prop_count, WS_XML_WRITER_PROPERTY_MAX_NAMESPACES, &max_ns, sizeof(max_ns) );
174 for (i = 0; i < count; i++)
176 hr = prop_set( writer->prop, writer->prop_count, properties[i].id, properties[i].value,
177 properties[i].valueSize );
178 if (hr != S_OK)
180 free_writer( writer );
181 return hr;
185 hr = prop_get( writer->prop, writer->prop_count, WS_XML_WRITER_PROPERTY_BUFFER_MAX_SIZE,
186 &max_size, sizeof(max_size) );
187 if (hr != S_OK)
189 free_writer( writer );
190 return hr;
193 hr = WsCreateHeap( max_size, 0, NULL, 0, &writer->output_heap, NULL );
194 if (hr != S_OK)
196 free_writer( writer );
197 return hr;
200 hr = write_init_state( writer );
201 if (hr != S_OK)
203 free_writer( writer );
204 return hr;
207 *handle = (WS_XML_WRITER *)writer;
208 return S_OK;
211 /**************************************************************************
212 * WsFreeWriter [webservices.@]
214 void WINAPI WsFreeWriter( WS_XML_WRITER *handle )
216 struct writer *writer = (struct writer *)handle;
218 TRACE( "%p\n", handle );
219 free_writer( writer );
222 #define XML_BUFFER_INITIAL_ALLOCATED_SIZE 256
223 static struct xmlbuf *alloc_xmlbuf( WS_HEAP *heap )
225 struct xmlbuf *ret;
227 if (!(ret = ws_alloc( heap, sizeof(*ret) ))) return NULL;
228 if (!(ret->ptr = ws_alloc( heap, XML_BUFFER_INITIAL_ALLOCATED_SIZE )))
230 ws_free( heap, ret );
231 return NULL;
233 ret->heap = heap;
234 ret->size_allocated = XML_BUFFER_INITIAL_ALLOCATED_SIZE;
235 ret->size = 0;
236 return ret;
239 static void free_xmlbuf( struct xmlbuf *xmlbuf )
241 if (!xmlbuf) return;
242 ws_free( xmlbuf->heap, xmlbuf->ptr );
243 ws_free( xmlbuf->heap, xmlbuf );
246 /**************************************************************************
247 * WsCreateXmlBuffer [webservices.@]
249 HRESULT WINAPI WsCreateXmlBuffer( WS_HEAP *heap, const WS_XML_BUFFER_PROPERTY *properties,
250 ULONG count, WS_XML_BUFFER **handle, WS_ERROR *error )
252 struct xmlbuf *xmlbuf;
254 if (!heap || !handle) return E_INVALIDARG;
255 if (count) FIXME( "properties not implemented\n" );
257 if (!(xmlbuf = alloc_xmlbuf( heap ))) return E_OUTOFMEMORY;
259 *handle = (WS_XML_BUFFER *)xmlbuf;
260 return S_OK;
263 /**************************************************************************
264 * WsGetWriterProperty [webservices.@]
266 HRESULT WINAPI WsGetWriterProperty( WS_XML_WRITER *handle, WS_XML_WRITER_PROPERTY_ID id,
267 void *buf, ULONG size, WS_ERROR *error )
269 struct writer *writer = (struct writer *)handle;
271 TRACE( "%p %u %p %u %p\n", handle, id, buf, size, error );
272 if (error) FIXME( "ignoring error parameter\n" );
274 if (!writer->output_type) return WS_E_INVALID_OPERATION;
276 switch (id)
278 case WS_XML_WRITER_PROPERTY_BYTES:
280 WS_BYTES *bytes = buf;
281 if (size != sizeof(*bytes)) return E_INVALIDARG;
282 bytes->bytes = writer->output_buf->ptr;
283 bytes->length = writer->output_buf->size;
284 return S_OK;
286 default:
287 return prop_get( writer->prop, writer->prop_count, id, buf, size );
291 static void set_output_buffer( struct writer *writer, struct xmlbuf *xmlbuf )
293 /* free current buffer if it's ours */
294 if (writer->output_buf && writer->output_buf->heap == writer->output_heap)
296 free_xmlbuf( writer->output_buf );
298 writer->output_buf = xmlbuf;
299 writer->output_type = WS_XML_WRITER_OUTPUT_TYPE_BUFFER;
300 writer->write_bufptr = xmlbuf->ptr;
301 writer->write_pos = 0;
304 /**************************************************************************
305 * WsSetOutput [webservices.@]
307 HRESULT WINAPI WsSetOutput( WS_XML_WRITER *handle, const WS_XML_WRITER_ENCODING *encoding,
308 const WS_XML_WRITER_OUTPUT *output, const WS_XML_WRITER_PROPERTY *properties,
309 ULONG count, WS_ERROR *error )
311 struct writer *writer = (struct writer *)handle;
312 struct node *node;
313 HRESULT hr;
314 ULONG i;
316 TRACE( "%p %p %p %p %u %p\n", handle, encoding, output, properties, count, error );
317 if (error) FIXME( "ignoring error parameter\n" );
319 if (!writer) return E_INVALIDARG;
321 for (i = 0; i < count; i++)
323 hr = prop_set( writer->prop, writer->prop_count, properties[i].id, properties[i].value,
324 properties[i].valueSize );
325 if (hr != S_OK) return hr;
328 if ((hr = write_init_state( writer )) != S_OK) return hr;
330 switch (encoding->encodingType)
332 case WS_XML_WRITER_ENCODING_TYPE_TEXT:
334 WS_XML_WRITER_TEXT_ENCODING *text = (WS_XML_WRITER_TEXT_ENCODING *)encoding;
335 if (text->charSet != WS_CHARSET_UTF8)
337 FIXME( "charset %u not supported\n", text->charSet );
338 return E_NOTIMPL;
340 break;
342 default:
343 FIXME( "encoding type %u not supported\n", encoding->encodingType );
344 return E_NOTIMPL;
346 switch (output->outputType)
348 case WS_XML_WRITER_OUTPUT_TYPE_BUFFER:
350 struct xmlbuf *xmlbuf;
352 if (!(xmlbuf = alloc_xmlbuf( writer->output_heap ))) return E_OUTOFMEMORY;
353 set_output_buffer( writer, xmlbuf );
354 break;
356 default:
357 FIXME( "output type %u not supported\n", output->outputType );
358 return E_NOTIMPL;
361 if (!(node = alloc_node( WS_XML_NODE_TYPE_BOF ))) return E_OUTOFMEMORY;
362 write_insert_bof( writer, node );
363 return S_OK;
366 /**************************************************************************
367 * WsSetOutputToBuffer [webservices.@]
369 HRESULT WINAPI WsSetOutputToBuffer( WS_XML_WRITER *handle, WS_XML_BUFFER *buffer,
370 const WS_XML_WRITER_PROPERTY *properties, ULONG count,
371 WS_ERROR *error )
373 struct writer *writer = (struct writer *)handle;
374 struct xmlbuf *xmlbuf = (struct xmlbuf *)buffer;
375 struct node *node;
376 HRESULT hr;
377 ULONG i;
379 TRACE( "%p %p %p %u %p\n", handle, buffer, properties, count, error );
380 if (error) FIXME( "ignoring error parameter\n" );
382 if (!writer || !xmlbuf) return E_INVALIDARG;
384 for (i = 0; i < count; i++)
386 hr = prop_set( writer->prop, writer->prop_count, properties[i].id, properties[i].value,
387 properties[i].valueSize );
388 if (hr != S_OK) return hr;
391 if ((hr = write_init_state( writer )) != S_OK) return hr;
392 set_output_buffer( writer, xmlbuf );
394 if (!(node = alloc_node( WS_XML_NODE_TYPE_BOF ))) return E_OUTOFMEMORY;
395 write_insert_bof( writer, node );
396 return S_OK;
399 static HRESULT write_grow_buffer( struct writer *writer, ULONG size )
401 struct xmlbuf *buf = writer->output_buf;
402 SIZE_T new_size;
403 void *tmp;
405 if (buf->size_allocated >= writer->write_pos + size)
407 buf->size = writer->write_pos + size;
408 return S_OK;
410 new_size = max( buf->size_allocated * 2, writer->write_pos + size );
411 if (!(tmp = ws_realloc( buf->heap, buf->ptr, new_size ))) return E_OUTOFMEMORY;
412 writer->write_bufptr = buf->ptr = tmp;
413 buf->size_allocated = new_size;
414 buf->size = writer->write_pos + size;
415 return S_OK;
418 static inline void write_char( struct writer *writer, unsigned char ch )
420 writer->write_bufptr[writer->write_pos++] = ch;
423 static inline void write_bytes( struct writer *writer, const BYTE *bytes, ULONG len )
425 memcpy( writer->write_bufptr + writer->write_pos, bytes, len );
426 writer->write_pos += len;
429 static HRESULT write_attribute( struct writer *writer, WS_XML_ATTRIBUTE *attr )
431 WS_XML_UTF8_TEXT *text = (WS_XML_UTF8_TEXT *)attr->value;
432 unsigned char quote = attr->singleQuote ? '\'' : '"';
433 const WS_XML_STRING *prefix;
434 ULONG size;
435 HRESULT hr;
437 if (attr->prefix) prefix = attr->prefix;
438 else prefix = writer->current->hdr.prefix;
440 /* ' prefix:attr="value"' */
442 size = attr->localName->length + 4 /* ' =""' */;
443 if (prefix) size += prefix->length + 1 /* ':' */;
444 if (text) size += text->value.length;
445 if ((hr = write_grow_buffer( writer, size )) != S_OK) return hr;
447 write_char( writer, ' ' );
448 if (prefix)
450 write_bytes( writer, prefix->bytes, prefix->length );
451 write_char( writer, ':' );
453 write_bytes( writer, attr->localName->bytes, attr->localName->length );
454 write_char( writer, '=' );
455 write_char( writer, quote );
456 if (text) write_bytes( writer, text->value.bytes, text->value.length );
457 write_char( writer, quote );
459 return S_OK;
462 static inline BOOL is_current_namespace( struct writer *writer, const WS_XML_STRING *ns )
464 return (WsXmlStringEquals( writer->current_ns, ns, NULL ) == S_OK);
467 /**************************************************************************
468 * WsGetPrefixFromNamespace [webservices.@]
470 HRESULT WINAPI WsGetPrefixFromNamespace( WS_XML_WRITER *handle, const WS_XML_STRING *ns,
471 BOOL required, const WS_XML_STRING **prefix,
472 WS_ERROR *error )
474 struct writer *writer = (struct writer *)handle;
475 WS_XML_ELEMENT_NODE *elem;
476 BOOL found = FALSE;
478 TRACE( "%p %s %d %p %p\n", handle, debugstr_xmlstr(ns), required, prefix, error );
479 if (error) FIXME( "ignoring error parameter\n" );
481 if (!writer || !ns || !prefix) return E_INVALIDARG;
483 elem = &writer->current->hdr;
484 if (elem->prefix && is_current_namespace( writer, ns ))
486 *prefix = elem->prefix;
487 found = TRUE;
489 if (!found)
491 if (required) return WS_E_INVALID_FORMAT;
492 *prefix = NULL;
493 return S_FALSE;
495 return S_OK;
498 static HRESULT set_current_namespace( struct writer *writer, const WS_XML_STRING *ns )
500 WS_XML_STRING *str;
501 if (!(str = alloc_xml_string( ns->bytes, ns->length ))) return E_OUTOFMEMORY;
502 heap_free( writer->current_ns );
503 writer->current_ns = str;
504 return S_OK;
507 static HRESULT write_namespace_attribute( struct writer *writer, WS_XML_ATTRIBUTE *attr )
509 unsigned char quote = attr->singleQuote ? '\'' : '"';
510 ULONG size;
511 HRESULT hr;
513 /* ' xmlns:prefix="namespace"' */
515 size = attr->ns->length + 9 /* ' xmlns=""' */;
516 if (attr->prefix) size += attr->prefix->length + 1 /* ':' */;
517 if ((hr = write_grow_buffer( writer, size )) != S_OK) return hr;
519 write_bytes( writer, (const BYTE *)" xmlns", 6 );
520 if (attr->prefix)
522 write_char( writer, ':' );
523 write_bytes( writer, attr->prefix->bytes, attr->prefix->length );
525 write_char( writer, '=' );
526 write_char( writer, quote );
527 write_bytes( writer, attr->ns->bytes, attr->ns->length );
528 write_char( writer, quote );
530 return S_OK;
533 static HRESULT write_startelement( struct writer *writer )
535 WS_XML_ELEMENT_NODE *elem = &writer->current->hdr;
536 ULONG size, i;
537 HRESULT hr;
539 /* '<prefix:localname prefix:attr="value"... xmlns:prefix="ns"'... */
541 size = elem->localName->length + 1 /* '<' */;
542 if (elem->prefix) size += elem->prefix->length + 1 /* ':' */;
543 if ((hr = write_grow_buffer( writer, size )) != S_OK) return hr;
545 write_char( writer, '<' );
546 if (elem->prefix)
548 write_bytes( writer, elem->prefix->bytes, elem->prefix->length );
549 write_char( writer, ':' );
551 write_bytes( writer, elem->localName->bytes, elem->localName->length );
552 for (i = 0; i < elem->attributeCount; i++)
554 if (elem->attributes[i]->isXmlNs) continue;
555 if ((hr = write_attribute( writer, elem->attributes[i] )) != S_OK) return hr;
557 for (i = 0; i < elem->attributeCount; i++)
559 if (!elem->attributes[i]->isXmlNs || !elem->attributes[i]->prefix) continue;
560 if ((hr = write_namespace_attribute( writer, elem->attributes[i] )) != S_OK) return hr;
562 for (i = 0; i < elem->attributeCount; i++)
564 if (!elem->attributes[i]->isXmlNs || elem->attributes[i]->prefix) continue;
565 if ((hr = write_namespace_attribute( writer, elem->attributes[i] )) != S_OK) return hr;
568 return S_OK;
571 static struct node *write_find_parent_element( struct writer *writer )
573 struct node *node = writer->current;
575 if (node_type( node ) == WS_XML_NODE_TYPE_ELEMENT) return node;
576 if (node_type( node->parent ) == WS_XML_NODE_TYPE_ELEMENT) return node->parent;
577 return NULL;
580 static HRESULT write_endelement( struct writer *writer )
582 struct node *node = write_find_parent_element( writer );
583 WS_XML_ELEMENT_NODE *elem = &node->hdr;
584 ULONG size;
585 HRESULT hr;
587 if (!elem) return WS_E_INVALID_FORMAT;
589 /* '</prefix:localname>' */
591 size = elem->localName->length + 3 /* '</>' */;
592 if (elem->prefix) size += elem->prefix->length + 1 /* ':' */;
593 if ((hr = write_grow_buffer( writer, size )) != S_OK) return hr;
595 write_char( writer, '<' );
596 write_char( writer, '/' );
597 if (elem->prefix)
599 write_bytes( writer, elem->prefix->bytes, elem->prefix->length );
600 write_char( writer, ':' );
602 write_bytes( writer, elem->localName->bytes, elem->localName->length );
603 write_char( writer, '>' );
604 return S_OK;
607 static HRESULT write_add_namespace_attribute( struct writer *writer, const WS_XML_STRING *prefix,
608 const WS_XML_STRING *ns, BOOL single )
610 WS_XML_ATTRIBUTE *attr;
611 WS_XML_ELEMENT_NODE *elem = &writer->current->hdr;
612 HRESULT hr;
614 if (!(attr = heap_alloc_zero( sizeof(*attr) ))) return E_OUTOFMEMORY;
616 attr->singleQuote = !!single;
617 attr->isXmlNs = 1;
618 if (prefix && !(attr->prefix = alloc_xml_string( prefix->bytes, prefix->length )))
620 free_attribute( attr );
621 return E_OUTOFMEMORY;
623 if (!(attr->ns = alloc_xml_string( ns->bytes, ns->length )))
625 free_attribute( attr );
626 return E_OUTOFMEMORY;
628 if ((hr = append_attribute( elem, attr )) != S_OK)
630 free_attribute( attr );
631 return hr;
633 return S_OK;
636 static BOOL namespace_in_scope( const WS_XML_ELEMENT_NODE *elem, const WS_XML_STRING *prefix,
637 const WS_XML_STRING *ns )
639 ULONG i;
640 const struct node *node;
642 for (node = (const struct node *)elem; node; node = node->parent)
644 if (node_type( node ) != WS_XML_NODE_TYPE_ELEMENT) break;
646 elem = &node->hdr;
647 for (i = 0; i < elem->attributeCount; i++)
649 if (!elem->attributes[i]->isXmlNs) continue;
650 if (WsXmlStringEquals( elem->attributes[i]->prefix, prefix, NULL ) == S_OK &&
651 WsXmlStringEquals( elem->attributes[i]->ns, ns, NULL ) == S_OK)
653 return TRUE;
657 return FALSE;
660 static HRESULT write_set_element_namespace( struct writer *writer )
662 WS_XML_ELEMENT_NODE *elem = &writer->current->hdr;
663 HRESULT hr;
665 if (!elem->ns->length || is_current_namespace( writer, elem->ns ) ||
666 namespace_in_scope( elem, elem->prefix, elem->ns )) return S_OK;
668 if ((hr = write_add_namespace_attribute( writer, elem->prefix, elem->ns, FALSE )) != S_OK)
669 return hr;
671 return set_current_namespace( writer, elem->ns );
674 static HRESULT write_endstartelement( struct writer *writer )
676 HRESULT hr;
677 if ((hr = write_set_element_namespace( writer )) != S_OK) return hr;
678 if ((hr = write_startelement( writer )) != S_OK) return hr;
679 if ((hr = write_grow_buffer( writer, 1 )) != S_OK) return hr;
680 write_char( writer, '>' );
681 return S_OK;
684 /**************************************************************************
685 * WsWriteEndAttribute [webservices.@]
687 HRESULT WINAPI WsWriteEndAttribute( WS_XML_WRITER *handle, WS_ERROR *error )
689 struct writer *writer = (struct writer *)handle;
691 TRACE( "%p %p\n", handle, error );
692 if (error) FIXME( "ignoring error parameter\n" );
694 if (!writer) return E_INVALIDARG;
696 writer->state = WRITER_STATE_STARTELEMENT;
697 return S_OK;
700 static HRESULT write_close_element( struct writer *writer )
702 HRESULT hr;
704 if (writer->state == WRITER_STATE_STARTELEMENT)
706 /* '/>' */
707 if ((hr = write_set_element_namespace( writer )) != S_OK) return hr;
708 if ((hr = write_startelement( writer )) != S_OK) return hr;
709 if ((hr = write_grow_buffer( writer, 2 )) != S_OK) return hr;
710 write_char( writer, '/' );
711 write_char( writer, '>' );
713 writer->current = writer->current->parent;
714 writer->state = WRITER_STATE_STARTENDELEMENT;
715 return S_OK;
717 else
719 struct node *node = alloc_node( WS_XML_NODE_TYPE_END_ELEMENT );
720 if (!node) return E_OUTOFMEMORY;
722 /* '</prefix:localname>' */
723 if ((hr = write_endelement( writer )) != S_OK)
725 free_node( node );
726 return hr;
729 write_insert_node( writer, node );
730 writer->current = node->parent;
731 writer->state = WRITER_STATE_ENDELEMENT;
732 return S_OK;
734 return WS_E_INVALID_OPERATION;
737 /**************************************************************************
738 * WsWriteEndElement [webservices.@]
740 HRESULT WINAPI WsWriteEndElement( WS_XML_WRITER *handle, WS_ERROR *error )
742 struct writer *writer = (struct writer *)handle;
744 TRACE( "%p %p\n", handle, error );
745 if (error) FIXME( "ignoring error parameter\n" );
747 if (!writer) return E_INVALIDARG;
749 return write_close_element( writer );
752 /**************************************************************************
753 * WsWriteEndStartElement [webservices.@]
755 HRESULT WINAPI WsWriteEndStartElement( WS_XML_WRITER *handle, WS_ERROR *error )
757 struct writer *writer = (struct writer *)handle;
758 HRESULT hr;
760 TRACE( "%p %p\n", handle, error );
761 if (error) FIXME( "ignoring error parameter\n" );
763 if (!writer) return E_INVALIDARG;
764 if (writer->state != WRITER_STATE_STARTELEMENT) return WS_E_INVALID_OPERATION;
766 if ((hr = write_endstartelement( writer )) != S_OK) return hr;
767 writer->state = WRITER_STATE_ENDSTARTELEMENT;
768 return S_OK;
771 static HRESULT write_add_attribute( struct writer *writer, const WS_XML_STRING *prefix,
772 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
773 BOOL single )
775 WS_XML_ATTRIBUTE *attr;
776 WS_XML_ELEMENT_NODE *elem = &writer->current->hdr;
777 HRESULT hr;
779 if (!(attr = heap_alloc_zero( sizeof(*attr) ))) return E_OUTOFMEMORY;
781 if (!prefix) prefix = elem->prefix;
783 attr->singleQuote = !!single;
784 if (prefix && !(attr->prefix = alloc_xml_string( prefix->bytes, prefix->length )))
786 free_attribute( attr );
787 return E_OUTOFMEMORY;
789 if (!(attr->localName = alloc_xml_string( localname->bytes, localname->length )))
791 free_attribute( attr );
792 return E_OUTOFMEMORY;
794 if (!(attr->ns = alloc_xml_string( ns->bytes, ns->length )))
796 free_attribute( attr );
797 return E_OUTOFMEMORY;
799 if ((hr = append_attribute( elem, attr )) != S_OK)
801 free_attribute( attr );
802 return hr;
804 writer->state = WRITER_STATE_STARTATTRIBUTE;
805 return S_OK;
808 /**************************************************************************
809 * WsWriteStartAttribute [webservices.@]
811 HRESULT WINAPI WsWriteStartAttribute( WS_XML_WRITER *handle, const WS_XML_STRING *prefix,
812 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
813 BOOL single, WS_ERROR *error )
815 struct writer *writer = (struct writer *)handle;
817 TRACE( "%p %s %s %s %d %p\n", handle, debugstr_xmlstr(prefix), debugstr_xmlstr(localname),
818 debugstr_xmlstr(ns), single, error );
819 if (error) FIXME( "ignoring error parameter\n" );
821 if (!writer || !localname || !ns) return E_INVALIDARG;
823 if (writer->state != WRITER_STATE_STARTELEMENT) return WS_E_INVALID_OPERATION;
825 return write_add_attribute( writer, prefix, localname, ns, single );
828 /**************************************************************************
829 * WsWriteStartCData [webservices.@]
831 HRESULT WINAPI WsWriteStartCData( WS_XML_WRITER *handle, WS_ERROR *error )
833 struct writer *writer = (struct writer *)handle;
834 HRESULT hr;
836 TRACE( "%p %p\n", handle, error );
837 if (error) FIXME( "ignoring error parameter\n" );
839 if (!writer) return E_INVALIDARG;
841 /* flush current start element if necessary */
842 if (writer->state == WRITER_STATE_STARTELEMENT && ((hr = write_endstartelement( writer )) != S_OK))
843 return hr;
845 if ((hr = write_grow_buffer( writer, 9 )) != S_OK) return hr;
846 write_bytes( writer, (const BYTE *)"<![CDATA[", 9 );
847 writer->state = WRITER_STATE_STARTCDATA;
848 return S_OK;
851 /**************************************************************************
852 * WsWriteEndCData [webservices.@]
854 HRESULT WINAPI WsWriteEndCData( WS_XML_WRITER *handle, WS_ERROR *error )
856 struct writer *writer = (struct writer *)handle;
857 HRESULT hr;
859 TRACE( "%p %p\n", handle, error );
860 if (error) FIXME( "ignoring error parameter\n" );
862 if (!writer) return E_INVALIDARG;
863 if (writer->state != WRITER_STATE_STARTCDATA) return WS_E_INVALID_OPERATION;
865 if ((hr = write_grow_buffer( writer, 3 )) != S_OK) return hr;
866 write_bytes( writer, (const BYTE *)"]]>", 3 );
867 writer->state = WRITER_STATE_ENDCDATA;
868 return S_OK;
871 /* flush current start element if necessary */
872 static HRESULT write_flush( struct writer *writer )
874 if (writer->state == WRITER_STATE_STARTELEMENT) return write_endstartelement( writer );
875 return S_OK;
878 static HRESULT write_add_element_node( struct writer *writer, const WS_XML_STRING *prefix,
879 const WS_XML_STRING *localname, const WS_XML_STRING *ns )
881 struct node *node;
882 WS_XML_ELEMENT_NODE *elem;
883 HRESULT hr;
885 if ((hr = write_flush( writer )) != S_OK) return hr;
887 if (!prefix && node_type( writer->current ) == WS_XML_NODE_TYPE_ELEMENT)
888 prefix = writer->current->hdr.prefix;
890 if (!(node = alloc_node( WS_XML_NODE_TYPE_ELEMENT ))) return E_OUTOFMEMORY;
891 elem = &node->hdr;
893 if (prefix && !(elem->prefix = alloc_xml_string( prefix->bytes, prefix->length )))
895 free_node( node );
896 return E_OUTOFMEMORY;
898 if (!(elem->localName = alloc_xml_string( localname->bytes, localname->length )))
900 free_node( node );
901 return E_OUTOFMEMORY;
903 if (!(elem->ns = alloc_xml_string( ns->bytes, ns->length )))
905 free_node( node );
906 return E_OUTOFMEMORY;
908 write_insert_node( writer, node );
909 writer->state = WRITER_STATE_STARTELEMENT;
910 return S_OK;
913 /**************************************************************************
914 * WsWriteStartElement [webservices.@]
916 HRESULT WINAPI WsWriteStartElement( WS_XML_WRITER *handle, const WS_XML_STRING *prefix,
917 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
918 WS_ERROR *error )
920 struct writer *writer = (struct writer *)handle;
922 TRACE( "%p %s %s %s %p\n", handle, debugstr_xmlstr(prefix), debugstr_xmlstr(localname),
923 debugstr_xmlstr(ns), error );
924 if (error) FIXME( "ignoring error parameter\n" );
926 if (!writer || !localname || !ns) return E_INVALIDARG;
928 return write_add_element_node( writer, prefix, localname, ns );
931 static inline void write_set_attribute_value( struct writer *writer, WS_XML_TEXT *text )
933 WS_XML_ELEMENT_NODE *elem = &writer->current->hdr;
934 elem->attributes[elem->attributeCount - 1]->value = text;
937 /**************************************************************************
938 * WsWriteText [webservices.@]
940 HRESULT WINAPI WsWriteText( WS_XML_WRITER *handle, const WS_XML_TEXT *text, WS_ERROR *error )
942 struct writer *writer = (struct writer *)handle;
943 WS_XML_UTF8_TEXT *dst, *src = (WS_XML_UTF8_TEXT *)text;
944 HRESULT hr;
946 TRACE( "%p %p %p\n", handle, text, error );
948 if (!writer || !text) return E_INVALIDARG;
950 if (text->textType != WS_XML_TEXT_TYPE_UTF8)
952 FIXME( "text type %u not supported\n", text->textType );
953 return E_NOTIMPL;
956 if (writer->state == WRITER_STATE_STARTATTRIBUTE)
958 if (!(dst = alloc_utf8_text( src->value.bytes, src->value.length )))
959 return E_OUTOFMEMORY;
961 write_set_attribute_value( writer, &dst->text );
963 else
965 if ((hr = write_flush( writer )) != S_OK) return hr;
966 if ((hr = write_grow_buffer( writer, src->value.length )) != S_OK) return hr;
967 write_bytes( writer, src->value.bytes, src->value.length );
970 return S_OK;
973 static WS_XML_TEXT *widechar_to_xmltext( const WCHAR *src, WS_XML_TEXT_TYPE type )
975 switch (type)
977 case WS_XML_TEXT_TYPE_UTF8:
979 WS_XML_UTF8_TEXT *text;
980 int len = WideCharToMultiByte( CP_UTF8, 0, src, -1, NULL, 0, NULL, NULL ) - 1;
981 if (!(text = alloc_utf8_text( NULL, len ))) return NULL;
982 WideCharToMultiByte( CP_UTF8, 0, src, -1, (char *)text->value.bytes, text->value.length, NULL, NULL );
983 return &text->text;
985 default:
986 FIXME( "unhandled type %u\n", type );
987 return NULL;
991 static WS_XML_UTF8_TEXT *format_bool( const BOOL *ptr )
993 static const unsigned char bool_true[] = {'t','r','u','e'}, bool_false[] = {'f','a','l','s','e'};
994 if (*ptr) return alloc_utf8_text( bool_true, sizeof(bool_true) );
995 else return alloc_utf8_text( bool_false, sizeof(bool_false) );
998 static WS_XML_UTF8_TEXT *format_int8( const INT8 *ptr )
1000 char buf[5]; /* "-128" */
1001 int len = wsprintfA( buf, "%d", *ptr );
1002 return alloc_utf8_text( (const unsigned char *)buf, len );
1005 static WS_XML_UTF8_TEXT *format_int16( const INT16 *ptr )
1007 char buf[7]; /* "-32768" */
1008 int len = wsprintfA( buf, "%d", *ptr );
1009 return alloc_utf8_text( (const unsigned char *)buf, len );
1012 static WS_XML_UTF8_TEXT *format_int32( const INT32 *ptr )
1014 char buf[12]; /* "-2147483648" */
1015 int len = wsprintfA( buf, "%d", *ptr );
1016 return alloc_utf8_text( (const unsigned char *)buf, len );
1019 static WS_XML_UTF8_TEXT *format_int64( const INT64 *ptr )
1021 char buf[21]; /* "-9223372036854775808" */
1022 int len = wsprintfA( buf, "%I64d", *ptr );
1023 return alloc_utf8_text( (const unsigned char *)buf, len );
1026 static WS_XML_UTF8_TEXT *format_uint8( const UINT8 *ptr )
1028 char buf[4]; /* "255" */
1029 int len = wsprintfA( buf, "%u", *ptr );
1030 return alloc_utf8_text( (const unsigned char *)buf, len );
1033 static WS_XML_UTF8_TEXT *format_uint16( const UINT16 *ptr )
1035 char buf[6]; /* "65535" */
1036 int len = wsprintfA( buf, "%u", *ptr );
1037 return alloc_utf8_text( (const unsigned char *)buf, len );
1040 static WS_XML_UTF8_TEXT *format_uint32( const UINT32 *ptr )
1042 char buf[11]; /* "4294967295" */
1043 int len = wsprintfA( buf, "%u", *ptr );
1044 return alloc_utf8_text( (const unsigned char *)buf, len );
1047 static WS_XML_UTF8_TEXT *format_uint64( const UINT64 *ptr )
1049 char buf[21]; /* "18446744073709551615" */
1050 int len = wsprintfA( buf, "%I64u", *ptr );
1051 return alloc_utf8_text( (const unsigned char *)buf, len );
1054 static HRESULT write_add_text_node( struct writer *writer, WS_XML_TEXT *value )
1056 struct node *node;
1057 WS_XML_TEXT_NODE *text;
1059 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return E_OUTOFMEMORY;
1060 text = (WS_XML_TEXT_NODE *)node;
1061 text->text = value;
1063 write_insert_node( writer, node );
1064 writer->state = WRITER_STATE_TEXT;
1065 return S_OK;
1068 static HRESULT write_text_node( struct writer *writer )
1070 HRESULT hr;
1071 WS_XML_TEXT_NODE *node = (WS_XML_TEXT_NODE *)writer->current;
1072 WS_XML_UTF8_TEXT *text = (WS_XML_UTF8_TEXT *)node->text;
1074 if ((hr = write_grow_buffer( writer, text->value.length )) != S_OK) return hr;
1075 write_bytes( writer, text->value.bytes, text->value.length );
1076 return S_OK;
1079 static HRESULT write_type_text( struct writer *writer, WS_TYPE_MAPPING mapping,
1080 WS_XML_TEXT *text )
1082 HRESULT hr;
1084 switch (mapping)
1086 case WS_ELEMENT_TYPE_MAPPING:
1087 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
1088 if ((hr = write_endstartelement( writer )) != S_OK) return hr;
1089 if ((hr = write_add_text_node( writer, text )) != S_OK) return hr;
1090 return write_text_node( writer );
1092 case WS_ATTRIBUTE_TYPE_MAPPING:
1093 write_set_attribute_value( writer, text );
1094 return S_OK;
1096 case WS_ANY_ELEMENT_TYPE_MAPPING:
1097 switch (writer->state)
1099 case WRITER_STATE_STARTATTRIBUTE:
1100 write_set_attribute_value( writer, text );
1101 return S_OK;
1103 case WRITER_STATE_STARTELEMENT:
1104 if ((hr = write_endstartelement( writer )) != S_OK) return hr;
1105 if ((hr = write_add_text_node( writer, text )) != S_OK) return hr;
1106 return write_text_node( writer );
1108 default:
1109 FIXME( "writer state %u not handled\n", writer->state );
1110 return E_NOTIMPL;
1113 default:
1114 FIXME( "mapping %u not implemented\n", mapping );
1115 return E_NOTIMPL;
1119 static HRESULT write_type_bool( struct writer *writer, WS_TYPE_MAPPING mapping,
1120 const WS_BOOL_DESCRIPTION *desc, const BOOL *value )
1122 WS_XML_UTF8_TEXT *text;
1123 HRESULT hr;
1125 if (desc)
1127 FIXME( "description not supported\n" );
1128 return E_NOTIMPL;
1130 if (!(text = format_bool( value ))) return E_OUTOFMEMORY;
1131 if ((hr = write_type_text( writer, mapping, &text->text )) == S_OK) return S_OK;
1132 heap_free( text );
1133 return hr;
1136 static HRESULT write_type_int8( struct writer *writer, WS_TYPE_MAPPING mapping,
1137 const WS_INT8_DESCRIPTION *desc, const INT8 *value )
1139 WS_XML_UTF8_TEXT *text;
1140 HRESULT hr;
1142 if (desc)
1144 FIXME( "description not supported\n" );
1145 return E_NOTIMPL;
1147 if (!(text = format_int8( value ))) return E_OUTOFMEMORY;
1148 if ((hr = write_type_text( writer, mapping, &text->text )) == S_OK) return S_OK;
1149 heap_free( text );
1150 return hr;
1153 static HRESULT write_type_int16( struct writer *writer, WS_TYPE_MAPPING mapping,
1154 const WS_INT16_DESCRIPTION *desc, const INT16 *value )
1156 WS_XML_UTF8_TEXT *text;
1157 HRESULT hr;
1159 if (desc)
1161 FIXME( "description not supported\n" );
1162 return E_NOTIMPL;
1164 if (!(text = format_int16( value ))) return E_OUTOFMEMORY;
1165 if ((hr = write_type_text( writer, mapping, &text->text )) == S_OK) return S_OK;
1166 heap_free( text );
1167 return hr;
1170 static HRESULT write_type_int32( struct writer *writer, WS_TYPE_MAPPING mapping,
1171 const WS_INT32_DESCRIPTION *desc, const INT32 *value )
1173 WS_XML_UTF8_TEXT *text;
1174 HRESULT hr;
1176 if (desc)
1178 FIXME( "description not supported\n" );
1179 return E_NOTIMPL;
1181 if (!(text = format_int32( value ))) return E_OUTOFMEMORY;
1182 if ((hr = write_type_text( writer, mapping, &text->text )) == S_OK) return S_OK;
1183 heap_free( text );
1184 return hr;
1187 static HRESULT write_type_int64( struct writer *writer, WS_TYPE_MAPPING mapping,
1188 const WS_INT64_DESCRIPTION *desc, const INT64 *value )
1190 WS_XML_UTF8_TEXT *text;
1191 HRESULT hr;
1193 if (desc)
1195 FIXME( "description not supported\n" );
1196 return E_NOTIMPL;
1198 if (!(text = format_int64( value ))) return E_OUTOFMEMORY;
1199 if ((hr = write_type_text( writer, mapping, &text->text )) == S_OK) return S_OK;
1200 heap_free( text );
1201 return hr;
1204 static HRESULT write_type_uint8( struct writer *writer, WS_TYPE_MAPPING mapping,
1205 const WS_UINT8_DESCRIPTION *desc, const UINT8 *value )
1207 WS_XML_UTF8_TEXT *text;
1208 HRESULT hr;
1210 if (desc)
1212 FIXME( "description not supported\n" );
1213 return E_NOTIMPL;
1215 if (!(text = format_uint8( value ))) return E_OUTOFMEMORY;
1216 if ((hr = write_type_text( writer, mapping, &text->text )) == S_OK) return S_OK;
1217 heap_free( text );
1218 return hr;
1221 static HRESULT write_type_uint16( struct writer *writer, WS_TYPE_MAPPING mapping,
1222 const WS_UINT16_DESCRIPTION *desc, const UINT16 *value )
1224 WS_XML_UTF8_TEXT *text;
1225 HRESULT hr;
1227 if (desc)
1229 FIXME( "description not supported\n" );
1230 return E_NOTIMPL;
1232 if (!(text = format_uint16( value ))) return E_OUTOFMEMORY;
1233 if ((hr = write_type_text( writer, mapping, &text->text )) == S_OK) return S_OK;
1234 heap_free( text );
1235 return hr;
1238 static HRESULT write_type_uint32( struct writer *writer, WS_TYPE_MAPPING mapping,
1239 const WS_UINT32_DESCRIPTION *desc, const UINT32 *value )
1241 WS_XML_UTF8_TEXT *text;
1242 HRESULT hr;
1244 if (desc)
1246 FIXME( "description not supported\n" );
1247 return E_NOTIMPL;
1249 if (!(text = format_uint32( value ))) return E_OUTOFMEMORY;
1250 if ((hr = write_type_text( writer, mapping, &text->text )) == S_OK) return S_OK;
1251 heap_free( text );
1252 return hr;
1255 static HRESULT write_type_uint64( struct writer *writer, WS_TYPE_MAPPING mapping,
1256 const WS_UINT64_DESCRIPTION *desc, const UINT64 *value )
1258 WS_XML_UTF8_TEXT *text;
1259 HRESULT hr;
1261 if (desc)
1263 FIXME( "description not supported\n" );
1264 return E_NOTIMPL;
1266 if (!(text = format_uint64( value ))) return E_OUTOFMEMORY;
1267 if ((hr = write_type_text( writer, mapping, &text->text )) == S_OK) return S_OK;
1268 heap_free( text );
1269 return hr;
1272 static HRESULT write_type_wsz( struct writer *writer, WS_TYPE_MAPPING mapping,
1273 const WS_WSZ_DESCRIPTION *desc, const WCHAR *value )
1275 WS_XML_TEXT *text;
1276 HRESULT hr;
1278 if (desc)
1280 FIXME( "description not supported\n" );
1281 return E_NOTIMPL;
1283 if (!(text = widechar_to_xmltext( value, WS_XML_TEXT_TYPE_UTF8 ))) return E_OUTOFMEMORY;
1284 if ((hr = write_type_text( writer, mapping, text )) == S_OK) return S_OK;
1285 heap_free( text );
1286 return hr;
1289 static HRESULT write_type( struct writer *, WS_TYPE_MAPPING, WS_TYPE, const void *, WS_WRITE_OPTION,
1290 const void *, ULONG );
1292 static HRESULT write_type_struct_field( struct writer *writer, const WS_FIELD_DESCRIPTION *desc,
1293 const void *value, ULONG size )
1295 HRESULT hr;
1296 WS_TYPE_MAPPING mapping;
1297 WS_WRITE_OPTION option;
1299 if (!desc->options || desc->options == WS_FIELD_OPTIONAL) option = 0;
1300 else if (desc->options == WS_FIELD_POINTER) option = WS_WRITE_REQUIRED_POINTER;
1301 else
1303 FIXME( "options 0x%x not supported\n", desc->options );
1304 return E_NOTIMPL;
1307 switch (desc->mapping)
1309 case WS_ATTRIBUTE_FIELD_MAPPING:
1310 if (!desc->localName || !desc->ns) return E_INVALIDARG;
1311 if ((hr = write_add_attribute( writer, NULL, desc->localName, desc->ns, FALSE )) != S_OK)
1312 return hr;
1314 mapping = WS_ATTRIBUTE_TYPE_MAPPING;
1315 break;
1317 case WS_ELEMENT_FIELD_MAPPING:
1318 if ((hr = write_add_element_node( writer, NULL, desc->localName, desc->ns )) != S_OK)
1319 return hr;
1321 mapping = WS_ELEMENT_TYPE_MAPPING;
1322 break;
1324 case WS_TEXT_FIELD_MAPPING:
1325 switch (writer->state)
1327 case WRITER_STATE_STARTELEMENT:
1328 mapping = WS_ELEMENT_CONTENT_TYPE_MAPPING;
1329 break;
1331 case WRITER_STATE_STARTATTRIBUTE:
1332 mapping = WS_ATTRIBUTE_TYPE_MAPPING;
1333 break;
1335 default:
1336 FIXME( "unhandled writer state %u\n", writer->state );
1337 return E_NOTIMPL;
1339 break;
1341 default:
1342 FIXME( "field mapping %u not supported\n", desc->mapping );
1343 return E_NOTIMPL;
1346 if ((hr = write_type( writer, mapping, desc->type, desc->typeDescription, option, value, size )) != S_OK)
1347 return hr;
1349 switch (mapping)
1351 case WS_ATTRIBUTE_TYPE_MAPPING:
1352 writer->state = WRITER_STATE_STARTELEMENT;
1353 break;
1355 case WS_ELEMENT_TYPE_MAPPING:
1356 if ((hr = write_close_element( writer )) != S_OK) return hr;
1357 break;
1359 default: break;
1362 return S_OK;
1365 static ULONG get_field_size( const WS_STRUCT_DESCRIPTION *desc, ULONG index )
1367 if (index < desc->fieldCount - 1) return desc->fields[index + 1]->offset - desc->fields[index]->offset;
1368 return desc->size - desc->fields[index]->offset;
1371 static HRESULT write_type_struct( struct writer *writer, WS_TYPE_MAPPING mapping,
1372 const WS_STRUCT_DESCRIPTION *desc, const void *value )
1374 ULONG i, size;
1375 HRESULT hr;
1376 const char *ptr;
1378 if (!desc) return E_INVALIDARG;
1380 if (desc->structOptions)
1382 FIXME( "struct options 0x%x not supported\n", desc->structOptions );
1383 return E_NOTIMPL;
1386 for (i = 0; i < desc->fieldCount; i++)
1388 ptr = (const char *)value + desc->fields[i]->offset;
1389 size = get_field_size( desc, i );
1390 if ((hr = write_type_struct_field( writer, desc->fields[i], ptr, size )) != S_OK)
1391 return hr;
1394 return S_OK;
1397 static HRESULT write_type( struct writer *writer, WS_TYPE_MAPPING mapping, WS_TYPE type,
1398 const void *desc, WS_WRITE_OPTION option, const void *value,
1399 ULONG size )
1401 switch (type)
1403 case WS_STRUCT_TYPE:
1405 const void * const *ptr = value;
1407 if (!desc || (option && option != WS_WRITE_REQUIRED_POINTER) || size != sizeof(*ptr))
1408 return E_INVALIDARG;
1410 return write_type_struct( writer, mapping, desc, *ptr );
1412 case WS_BOOL_TYPE:
1414 const BOOL *ptr = value;
1415 if (option != WS_WRITE_REQUIRED_VALUE || size != sizeof(*ptr)) return E_INVALIDARG;
1416 return write_type_bool( writer, mapping, desc, ptr );
1418 case WS_INT8_TYPE:
1420 const INT8 *ptr = value;
1421 if (option != WS_WRITE_REQUIRED_VALUE || size != sizeof(*ptr)) return E_INVALIDARG;
1422 return write_type_int8( writer, mapping, desc, ptr );
1424 case WS_INT16_TYPE:
1426 const INT16 *ptr = value;
1427 if (option != WS_WRITE_REQUIRED_VALUE || size != sizeof(*ptr)) return E_INVALIDARG;
1428 return write_type_int16( writer, mapping, desc, ptr );
1430 case WS_INT32_TYPE:
1432 const INT32 *ptr = value;
1433 if (option != WS_WRITE_REQUIRED_VALUE || size != sizeof(*ptr)) return E_INVALIDARG;
1434 return write_type_int32( writer, mapping, desc, ptr );
1436 case WS_INT64_TYPE:
1438 const INT64 *ptr = value;
1439 if (option != WS_WRITE_REQUIRED_VALUE || size != sizeof(*ptr)) return E_INVALIDARG;
1440 return write_type_int64( writer, mapping, desc, ptr );
1442 case WS_UINT8_TYPE:
1444 const UINT8 *ptr = value;
1445 if (option != WS_WRITE_REQUIRED_VALUE || size != sizeof(*ptr)) return E_INVALIDARG;
1446 return write_type_uint8( writer, mapping, desc, ptr );
1448 case WS_UINT16_TYPE:
1450 const UINT16 *ptr = value;
1451 if (option != WS_WRITE_REQUIRED_VALUE || size != sizeof(*ptr)) return E_INVALIDARG;
1452 return write_type_uint16( writer, mapping, desc, ptr );
1454 case WS_UINT32_TYPE:
1456 const UINT32 *ptr = value;
1457 if (option != WS_WRITE_REQUIRED_VALUE || size != sizeof(*ptr)) return E_INVALIDARG;
1458 return write_type_uint32( writer, mapping, desc, ptr );
1460 case WS_UINT64_TYPE:
1462 const UINT64 *ptr = value;
1463 if (option != WS_WRITE_REQUIRED_VALUE || size != sizeof(*ptr)) return E_INVALIDARG;
1464 return write_type_uint64( writer, mapping, desc, ptr );
1466 case WS_WSZ_TYPE:
1468 const WCHAR * const *ptr = value;
1469 if ((option && option != WS_WRITE_REQUIRED_POINTER) || size != sizeof(*ptr)) return E_INVALIDARG;
1470 return write_type_wsz( writer, mapping, desc, *ptr );
1472 default:
1473 FIXME( "type %u not supported\n", type );
1474 return E_NOTIMPL;
1478 /**************************************************************************
1479 * WsWriteAttribute [webservices.@]
1481 HRESULT WINAPI WsWriteAttribute( WS_XML_WRITER *handle, const WS_ATTRIBUTE_DESCRIPTION *desc,
1482 WS_WRITE_OPTION option, const void *value, ULONG size,
1483 WS_ERROR *error )
1485 struct writer *writer = (struct writer *)handle;
1486 HRESULT hr;
1488 TRACE( "%p %p %u %p %u %p\n", handle, desc, option, value, size, error );
1489 if (error) FIXME( "ignoring error parameter\n" );
1491 if (!writer || !desc || !desc->attributeLocalName || !desc->attributeNs || !value)
1492 return E_INVALIDARG;
1494 if (writer->state != WRITER_STATE_STARTELEMENT) return WS_E_INVALID_OPERATION;
1496 if ((hr = write_add_attribute( writer, NULL, desc->attributeLocalName, desc->attributeNs,
1497 FALSE )) != S_OK) return hr;
1499 return write_type( writer, WS_ATTRIBUTE_TYPE_MAPPING, desc->type, desc->typeDescription,
1500 option, value, size );
1503 /**************************************************************************
1504 * WsWriteElement [webservices.@]
1506 HRESULT WINAPI WsWriteElement( WS_XML_WRITER *handle, const WS_ELEMENT_DESCRIPTION *desc,
1507 WS_WRITE_OPTION option, const void *value, ULONG size,
1508 WS_ERROR *error )
1510 struct writer *writer = (struct writer *)handle;
1511 HRESULT hr;
1513 TRACE( "%p %p %u %p %u %p\n", handle, desc, option, value, size, error );
1514 if (error) FIXME( "ignoring error parameter\n" );
1516 if (!writer || !desc || !desc->elementLocalName || !desc->elementNs || !value)
1517 return E_INVALIDARG;
1519 if ((hr = write_add_element_node( writer, NULL, desc->elementLocalName, desc->elementNs )) != S_OK)
1520 return hr;
1522 if ((hr = write_type( writer, WS_ANY_ELEMENT_TYPE_MAPPING, desc->type, desc->typeDescription,
1523 option, value, size )) != S_OK) return hr;
1525 return write_close_element( writer );
1528 /**************************************************************************
1529 * WsWriteType [webservices.@]
1531 HRESULT WINAPI WsWriteType( WS_XML_WRITER *handle, WS_TYPE_MAPPING mapping, WS_TYPE type,
1532 const void *desc, WS_WRITE_OPTION option, const void *value,
1533 ULONG size, WS_ERROR *error )
1535 struct writer *writer = (struct writer *)handle;
1536 HRESULT hr;
1538 TRACE( "%p %u %u %p %u %p %u %p\n", handle, mapping, type, desc, option, value,
1539 size, error );
1540 if (error) FIXME( "ignoring error parameter\n" );
1542 if (!writer || !value) return E_INVALIDARG;
1544 switch (mapping)
1546 case WS_ATTRIBUTE_TYPE_MAPPING:
1547 if (writer->state != WRITER_STATE_STARTATTRIBUTE) return WS_E_INVALID_FORMAT;
1548 hr = write_type( writer, mapping, type, desc, option, value, size );
1549 break;
1551 case WS_ELEMENT_TYPE_MAPPING:
1552 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
1553 if (writer->state != WRITER_STATE_STARTELEMENT) return WS_E_INVALID_FORMAT;
1554 hr = write_type( writer, mapping, type, desc, option, value, size );
1555 break;
1557 case WS_ANY_ELEMENT_TYPE_MAPPING:
1558 hr = write_type( writer, mapping, type, desc, option, value, size );
1559 break;
1561 default:
1562 FIXME( "mapping %u not implemented\n", mapping );
1563 return E_NOTIMPL;
1566 return hr;
1569 WS_TYPE map_value_type( WS_VALUE_TYPE type )
1571 switch (type)
1573 case WS_BOOL_VALUE_TYPE: return WS_BOOL_TYPE;
1574 case WS_INT8_VALUE_TYPE: return WS_INT8_TYPE;
1575 case WS_INT16_VALUE_TYPE: return WS_INT16_TYPE;
1576 case WS_INT32_VALUE_TYPE: return WS_INT32_TYPE;
1577 case WS_INT64_VALUE_TYPE: return WS_INT64_TYPE;
1578 case WS_UINT8_VALUE_TYPE: return WS_UINT8_TYPE;
1579 case WS_UINT16_VALUE_TYPE: return WS_UINT16_TYPE;
1580 case WS_UINT32_VALUE_TYPE: return WS_UINT32_TYPE;
1581 case WS_UINT64_VALUE_TYPE: return WS_UINT64_TYPE;
1582 case WS_FLOAT_VALUE_TYPE: return WS_FLOAT_TYPE;
1583 case WS_DOUBLE_VALUE_TYPE: return WS_DOUBLE_TYPE;
1584 case WS_DECIMAL_VALUE_TYPE: return WS_DECIMAL_TYPE;
1585 case WS_DATETIME_VALUE_TYPE: return WS_DATETIME_TYPE;
1586 case WS_TIMESPAN_VALUE_TYPE: return WS_TIMESPAN_TYPE;
1587 case WS_GUID_VALUE_TYPE: return WS_GUID_TYPE;
1588 default:
1589 FIXME( "unhandled type %u\n", type );
1590 return ~0u;
1594 /**************************************************************************
1595 * WsWriteValue [webservices.@]
1597 HRESULT WINAPI WsWriteValue( WS_XML_WRITER *handle, WS_VALUE_TYPE value_type, const void *value,
1598 ULONG size, WS_ERROR *error )
1600 struct writer *writer = (struct writer *)handle;
1601 WS_TYPE_MAPPING mapping;
1602 WS_TYPE type;
1604 TRACE( "%p %u %p %u %p\n", handle, value_type, value, size, error );
1605 if (error) FIXME( "ignoring error parameter\n" );
1607 if (!writer || !value || (type = map_value_type( value_type )) == ~0u) return E_INVALIDARG;
1609 switch (writer->state)
1611 case WRITER_STATE_STARTATTRIBUTE:
1612 mapping = WS_ATTRIBUTE_TYPE_MAPPING;
1613 break;
1615 case WRITER_STATE_STARTELEMENT:
1616 mapping = WS_ELEMENT_TYPE_MAPPING;
1617 break;
1619 default:
1620 return WS_E_INVALID_FORMAT;
1623 return write_type( writer, mapping, type, NULL, WS_WRITE_REQUIRED_VALUE, value, size );
1626 /**************************************************************************
1627 * WsWriteXmlBuffer [webservices.@]
1629 HRESULT WINAPI WsWriteXmlBuffer( WS_XML_WRITER *handle, WS_XML_BUFFER *buffer, WS_ERROR *error )
1631 struct writer *writer = (struct writer *)handle;
1632 struct xmlbuf *xmlbuf = (struct xmlbuf *)buffer;
1633 HRESULT hr;
1635 TRACE( "%p %p %p\n", handle, buffer, error );
1636 if (error) FIXME( "ignoring error parameter\n" );
1638 if (!writer || !xmlbuf) return E_INVALIDARG;
1640 if ((hr = write_grow_buffer( writer, xmlbuf->size )) != S_OK) return hr;
1641 write_bytes( writer, xmlbuf->ptr, xmlbuf->size );
1642 return S_OK;
1645 /**************************************************************************
1646 * WsWriteXmlBufferToBytes [webservices.@]
1648 HRESULT WINAPI WsWriteXmlBufferToBytes( WS_XML_WRITER *handle, WS_XML_BUFFER *buffer,
1649 const WS_XML_WRITER_ENCODING *encoding,
1650 const WS_XML_WRITER_PROPERTY *properties, ULONG count,
1651 WS_HEAP *heap, void **bytes, ULONG *size, WS_ERROR *error )
1653 struct writer *writer = (struct writer *)handle;
1654 struct xmlbuf *xmlbuf = (struct xmlbuf *)buffer;
1655 HRESULT hr;
1656 char *buf;
1657 ULONG i;
1659 TRACE( "%p %p %p %p %u %p %p %p %p\n", handle, buffer, encoding, properties, count, heap,
1660 bytes, size, error );
1661 if (error) FIXME( "ignoring error parameter\n" );
1663 if (!writer || !xmlbuf || !heap || !bytes) return E_INVALIDARG;
1665 if (encoding && encoding->encodingType != WS_XML_WRITER_ENCODING_TYPE_TEXT)
1667 FIXME( "encoding type %u not supported\n", encoding->encodingType );
1668 return E_NOTIMPL;
1671 for (i = 0; i < count; i++)
1673 hr = prop_set( writer->prop, writer->prop_count, properties[i].id, properties[i].value,
1674 properties[i].valueSize );
1675 if (hr != S_OK) return hr;
1678 if (!(buf = ws_alloc( heap, xmlbuf->size ))) return WS_E_QUOTA_EXCEEDED;
1679 memcpy( buf, xmlbuf->ptr, xmlbuf->size );
1680 *bytes = buf;
1681 return S_OK;
1684 /**************************************************************************
1685 * WsWriteXmlnsAttribute [webservices.@]
1687 HRESULT WINAPI WsWriteXmlnsAttribute( WS_XML_WRITER *handle, const WS_XML_STRING *prefix,
1688 const WS_XML_STRING *ns, BOOL single, WS_ERROR *error )
1690 struct writer *writer = (struct writer *)handle;
1692 TRACE( "%p %s %s %d %p\n", handle, debugstr_xmlstr(prefix), debugstr_xmlstr(ns),
1693 single, error );
1694 if (error) FIXME( "ignoring error parameter\n" );
1696 if (!writer || !ns) return E_INVALIDARG;
1697 if (writer->state != WRITER_STATE_STARTELEMENT) return WS_E_INVALID_OPERATION;
1699 if (namespace_in_scope( &writer->current->hdr, prefix, ns )) return S_OK;
1700 return write_add_namespace_attribute( writer, prefix, ns, single );