webservices: Implement WsSetWriterPosition.
[wine.git] / dlls / webservices / writer.c
blob8c9e202db51f6fb20e1ce555e2a48d757644c099
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 *parent, struct node *node )
124 node->parent = parent;
125 if (node->parent == writer->root)
127 struct list *eof = list_tail( &writer->root->children );
128 list_add_before( eof, &node->entry );
130 else list_add_tail( &parent->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 HRESULT write_endelement( struct writer *writer, struct node *parent )
573 WS_XML_ELEMENT_NODE *elem = &parent->hdr;
574 ULONG size;
575 HRESULT hr;
577 if (!elem) return WS_E_INVALID_FORMAT;
579 /* '</prefix:localname>' */
581 size = elem->localName->length + 3 /* '</>' */;
582 if (elem->prefix) size += elem->prefix->length + 1 /* ':' */;
583 if ((hr = write_grow_buffer( writer, size )) != S_OK) return hr;
585 write_char( writer, '<' );
586 write_char( writer, '/' );
587 if (elem->prefix)
589 write_bytes( writer, elem->prefix->bytes, elem->prefix->length );
590 write_char( writer, ':' );
592 write_bytes( writer, elem->localName->bytes, elem->localName->length );
593 write_char( writer, '>' );
594 return S_OK;
597 static HRESULT write_add_namespace_attribute( struct writer *writer, const WS_XML_STRING *prefix,
598 const WS_XML_STRING *ns, BOOL single )
600 WS_XML_ATTRIBUTE *attr;
601 WS_XML_ELEMENT_NODE *elem = &writer->current->hdr;
602 HRESULT hr;
604 if (!(attr = heap_alloc_zero( sizeof(*attr) ))) return E_OUTOFMEMORY;
606 attr->singleQuote = !!single;
607 attr->isXmlNs = 1;
608 if (prefix && !(attr->prefix = alloc_xml_string( prefix->bytes, prefix->length )))
610 free_attribute( attr );
611 return E_OUTOFMEMORY;
613 if (!(attr->ns = alloc_xml_string( ns->bytes, ns->length )))
615 free_attribute( attr );
616 return E_OUTOFMEMORY;
618 if ((hr = append_attribute( elem, attr )) != S_OK)
620 free_attribute( attr );
621 return hr;
623 return S_OK;
626 static BOOL namespace_in_scope( const WS_XML_ELEMENT_NODE *elem, const WS_XML_STRING *prefix,
627 const WS_XML_STRING *ns )
629 ULONG i;
630 const struct node *node;
632 for (node = (const struct node *)elem; node; node = node->parent)
634 if (node_type( node ) != WS_XML_NODE_TYPE_ELEMENT) break;
636 elem = &node->hdr;
637 for (i = 0; i < elem->attributeCount; i++)
639 if (!elem->attributes[i]->isXmlNs) continue;
640 if (WsXmlStringEquals( elem->attributes[i]->prefix, prefix, NULL ) == S_OK &&
641 WsXmlStringEquals( elem->attributes[i]->ns, ns, NULL ) == S_OK)
643 return TRUE;
647 return FALSE;
650 static HRESULT write_set_element_namespace( struct writer *writer )
652 WS_XML_ELEMENT_NODE *elem = &writer->current->hdr;
653 HRESULT hr;
655 if (!elem->ns->length || is_current_namespace( writer, elem->ns ) ||
656 namespace_in_scope( elem, elem->prefix, elem->ns )) return S_OK;
658 if ((hr = write_add_namespace_attribute( writer, elem->prefix, elem->ns, FALSE )) != S_OK)
659 return hr;
661 return set_current_namespace( writer, elem->ns );
664 static HRESULT write_endstartelement( struct writer *writer )
666 HRESULT hr;
667 if ((hr = write_set_element_namespace( writer )) != S_OK) return hr;
668 if ((hr = write_startelement( writer )) != S_OK) return hr;
669 if ((hr = write_grow_buffer( writer, 1 )) != S_OK) return hr;
670 write_char( writer, '>' );
671 return S_OK;
674 /**************************************************************************
675 * WsWriteEndAttribute [webservices.@]
677 HRESULT WINAPI WsWriteEndAttribute( WS_XML_WRITER *handle, WS_ERROR *error )
679 struct writer *writer = (struct writer *)handle;
681 TRACE( "%p %p\n", handle, error );
682 if (error) FIXME( "ignoring error parameter\n" );
684 if (!writer) return E_INVALIDARG;
686 writer->state = WRITER_STATE_STARTELEMENT;
687 return S_OK;
690 static struct node *write_find_start_element( struct writer *writer )
692 struct node *node = writer->current, *child;
693 struct list *ptr;
695 for (node = writer->current; node; node = node->parent)
697 if (node_type( node ) != WS_XML_NODE_TYPE_ELEMENT) continue;
699 if (!(ptr = list_tail( &node->children ))) return node;
700 child = LIST_ENTRY( ptr, struct node, entry );
701 if (node_type( child ) != WS_XML_NODE_TYPE_END_ELEMENT) return node;
703 return NULL;
706 static HRESULT write_close_element( struct writer *writer )
708 struct node *node, *parent;
709 HRESULT hr;
711 if (!(parent = write_find_start_element( writer ))) return WS_E_INVALID_FORMAT;
712 if (!(node = alloc_node( WS_XML_NODE_TYPE_END_ELEMENT ))) return E_OUTOFMEMORY;
714 if (writer->state == WRITER_STATE_STARTELEMENT)
716 /* '/>' */
717 if ((hr = write_set_element_namespace( writer )) != S_OK) goto error;
718 if ((hr = write_startelement( writer )) != S_OK) goto error;
719 if ((hr = write_grow_buffer( writer, 2 )) != S_OK) goto error;
720 write_char( writer, '/' );
721 write_char( writer, '>' );
722 writer->state = WRITER_STATE_STARTENDELEMENT;
724 else
726 /* '</prefix:localname>' */
727 if ((hr = write_endelement( writer, parent )) != S_OK) goto error;
728 writer->state = WRITER_STATE_ENDELEMENT;
731 write_insert_node( writer, parent, node );
732 return S_OK;
734 error:
735 free_node( node );
736 return hr;
739 /**************************************************************************
740 * WsWriteEndElement [webservices.@]
742 HRESULT WINAPI WsWriteEndElement( WS_XML_WRITER *handle, WS_ERROR *error )
744 struct writer *writer = (struct writer *)handle;
746 TRACE( "%p %p\n", handle, error );
747 if (error) FIXME( "ignoring error parameter\n" );
749 if (!writer) return E_INVALIDARG;
751 return write_close_element( writer );
754 /**************************************************************************
755 * WsWriteEndStartElement [webservices.@]
757 HRESULT WINAPI WsWriteEndStartElement( WS_XML_WRITER *handle, WS_ERROR *error )
759 struct writer *writer = (struct writer *)handle;
760 HRESULT hr;
762 TRACE( "%p %p\n", handle, error );
763 if (error) FIXME( "ignoring error parameter\n" );
765 if (!writer) return E_INVALIDARG;
766 if (writer->state != WRITER_STATE_STARTELEMENT) return WS_E_INVALID_OPERATION;
768 if ((hr = write_endstartelement( writer )) != S_OK) return hr;
769 writer->state = WRITER_STATE_ENDSTARTELEMENT;
770 return S_OK;
773 static HRESULT write_add_attribute( struct writer *writer, const WS_XML_STRING *prefix,
774 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
775 BOOL single )
777 WS_XML_ATTRIBUTE *attr;
778 WS_XML_ELEMENT_NODE *elem = &writer->current->hdr;
779 HRESULT hr;
781 if (!(attr = heap_alloc_zero( sizeof(*attr) ))) return E_OUTOFMEMORY;
783 if (!prefix) prefix = elem->prefix;
785 attr->singleQuote = !!single;
786 if (prefix && !(attr->prefix = alloc_xml_string( prefix->bytes, prefix->length )))
788 free_attribute( attr );
789 return E_OUTOFMEMORY;
791 if (!(attr->localName = alloc_xml_string( localname->bytes, localname->length )))
793 free_attribute( attr );
794 return E_OUTOFMEMORY;
796 if (!(attr->ns = alloc_xml_string( ns->bytes, ns->length )))
798 free_attribute( attr );
799 return E_OUTOFMEMORY;
801 if ((hr = append_attribute( elem, attr )) != S_OK)
803 free_attribute( attr );
804 return hr;
806 writer->state = WRITER_STATE_STARTATTRIBUTE;
807 return S_OK;
810 /**************************************************************************
811 * WsWriteStartAttribute [webservices.@]
813 HRESULT WINAPI WsWriteStartAttribute( WS_XML_WRITER *handle, const WS_XML_STRING *prefix,
814 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
815 BOOL single, WS_ERROR *error )
817 struct writer *writer = (struct writer *)handle;
819 TRACE( "%p %s %s %s %d %p\n", handle, debugstr_xmlstr(prefix), debugstr_xmlstr(localname),
820 debugstr_xmlstr(ns), single, error );
821 if (error) FIXME( "ignoring error parameter\n" );
823 if (!writer || !localname || !ns) return E_INVALIDARG;
825 if (writer->state != WRITER_STATE_STARTELEMENT) return WS_E_INVALID_OPERATION;
827 return write_add_attribute( writer, prefix, localname, ns, single );
830 /**************************************************************************
831 * WsWriteStartCData [webservices.@]
833 HRESULT WINAPI WsWriteStartCData( WS_XML_WRITER *handle, WS_ERROR *error )
835 struct writer *writer = (struct writer *)handle;
836 HRESULT hr;
838 TRACE( "%p %p\n", handle, error );
839 if (error) FIXME( "ignoring error parameter\n" );
841 if (!writer) return E_INVALIDARG;
843 /* flush current start element if necessary */
844 if (writer->state == WRITER_STATE_STARTELEMENT && ((hr = write_endstartelement( writer )) != S_OK))
845 return hr;
847 if ((hr = write_grow_buffer( writer, 9 )) != S_OK) return hr;
848 write_bytes( writer, (const BYTE *)"<![CDATA[", 9 );
849 writer->state = WRITER_STATE_STARTCDATA;
850 return S_OK;
853 /**************************************************************************
854 * WsWriteEndCData [webservices.@]
856 HRESULT WINAPI WsWriteEndCData( WS_XML_WRITER *handle, WS_ERROR *error )
858 struct writer *writer = (struct writer *)handle;
859 HRESULT hr;
861 TRACE( "%p %p\n", handle, error );
862 if (error) FIXME( "ignoring error parameter\n" );
864 if (!writer) return E_INVALIDARG;
865 if (writer->state != WRITER_STATE_STARTCDATA) return WS_E_INVALID_OPERATION;
867 if ((hr = write_grow_buffer( writer, 3 )) != S_OK) return hr;
868 write_bytes( writer, (const BYTE *)"]]>", 3 );
869 writer->state = WRITER_STATE_ENDCDATA;
870 return S_OK;
873 /* flush current start element if necessary */
874 static HRESULT write_flush( struct writer *writer )
876 if (writer->state == WRITER_STATE_STARTELEMENT) return write_endstartelement( writer );
877 return S_OK;
880 static HRESULT write_add_element_node( struct writer *writer, const WS_XML_STRING *prefix,
881 const WS_XML_STRING *localname, const WS_XML_STRING *ns )
883 struct node *node, *parent;
884 WS_XML_ELEMENT_NODE *elem;
885 HRESULT hr;
887 if (!(parent = find_parent( writer->current ))) return WS_E_INVALID_FORMAT;
888 if ((hr = write_flush( writer )) != S_OK) return hr;
890 if (!prefix && node_type( writer->current ) == WS_XML_NODE_TYPE_ELEMENT)
891 prefix = writer->current->hdr.prefix;
893 if (!(node = alloc_node( WS_XML_NODE_TYPE_ELEMENT ))) return E_OUTOFMEMORY;
894 elem = &node->hdr;
896 if (prefix && !(elem->prefix = alloc_xml_string( prefix->bytes, prefix->length )))
898 free_node( node );
899 return E_OUTOFMEMORY;
901 if (!(elem->localName = alloc_xml_string( localname->bytes, localname->length )))
903 free_node( node );
904 return E_OUTOFMEMORY;
906 if (!(elem->ns = alloc_xml_string( ns->bytes, ns->length )))
908 free_node( node );
909 return E_OUTOFMEMORY;
911 write_insert_node( writer, parent, node );
912 writer->state = WRITER_STATE_STARTELEMENT;
913 return S_OK;
916 /**************************************************************************
917 * WsWriteStartElement [webservices.@]
919 HRESULT WINAPI WsWriteStartElement( WS_XML_WRITER *handle, const WS_XML_STRING *prefix,
920 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
921 WS_ERROR *error )
923 struct writer *writer = (struct writer *)handle;
925 TRACE( "%p %s %s %s %p\n", handle, debugstr_xmlstr(prefix), debugstr_xmlstr(localname),
926 debugstr_xmlstr(ns), error );
927 if (error) FIXME( "ignoring error parameter\n" );
929 if (!writer || !localname || !ns) return E_INVALIDARG;
931 return write_add_element_node( writer, prefix, localname, ns );
934 static inline void write_set_attribute_value( struct writer *writer, WS_XML_TEXT *text )
936 WS_XML_ELEMENT_NODE *elem = &writer->current->hdr;
937 elem->attributes[elem->attributeCount - 1]->value = text;
940 static HRESULT write_add_text_node( struct writer *writer, WS_XML_TEXT *value )
942 struct node *node, *parent;
943 WS_XML_TEXT_NODE *text;
945 if (!(parent = find_parent( writer->current ))) return WS_E_INVALID_FORMAT;
947 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return E_OUTOFMEMORY;
948 text = (WS_XML_TEXT_NODE *)node;
949 text->text = value;
951 write_insert_node( writer, parent, node );
952 writer->state = WRITER_STATE_TEXT;
953 return S_OK;
956 /**************************************************************************
957 * WsWriteText [webservices.@]
959 HRESULT WINAPI WsWriteText( WS_XML_WRITER *handle, const WS_XML_TEXT *text, WS_ERROR *error )
961 struct writer *writer = (struct writer *)handle;
962 WS_XML_UTF8_TEXT *dst, *src = (WS_XML_UTF8_TEXT *)text;
963 HRESULT hr;
965 TRACE( "%p %p %p\n", handle, text, error );
967 if (!writer || !text) return E_INVALIDARG;
969 if (text->textType != WS_XML_TEXT_TYPE_UTF8)
971 FIXME( "text type %u not supported\n", text->textType );
972 return E_NOTIMPL;
975 if (writer->state == WRITER_STATE_STARTATTRIBUTE)
977 if (!(dst = alloc_utf8_text( src->value.bytes, src->value.length )))
978 return E_OUTOFMEMORY;
980 write_set_attribute_value( writer, &dst->text );
981 return S_OK;
984 if ((hr = write_flush( writer )) != S_OK) return hr;
985 if (writer->state != WRITER_STATE_STARTCDATA)
987 if (!(dst = alloc_utf8_text( src->value.bytes, src->value.length )))
988 return E_OUTOFMEMORY;
990 if ((hr = write_add_text_node( writer, &dst->text )) != S_OK)
992 heap_free( dst );
993 return hr;
996 if ((hr = write_grow_buffer( writer, src->value.length )) != S_OK) return hr;
997 write_bytes( writer, src->value.bytes, src->value.length );
999 return S_OK;
1002 static WS_XML_TEXT *widechar_to_xmltext( const WCHAR *src, WS_XML_TEXT_TYPE type )
1004 switch (type)
1006 case WS_XML_TEXT_TYPE_UTF8:
1008 WS_XML_UTF8_TEXT *text;
1009 int len = WideCharToMultiByte( CP_UTF8, 0, src, -1, NULL, 0, NULL, NULL ) - 1;
1010 if (!(text = alloc_utf8_text( NULL, len ))) return NULL;
1011 WideCharToMultiByte( CP_UTF8, 0, src, -1, (char *)text->value.bytes, text->value.length, NULL, NULL );
1012 return &text->text;
1014 default:
1015 FIXME( "unhandled type %u\n", type );
1016 return NULL;
1020 static WS_XML_UTF8_TEXT *format_bool( const BOOL *ptr )
1022 static const unsigned char bool_true[] = {'t','r','u','e'}, bool_false[] = {'f','a','l','s','e'};
1023 if (*ptr) return alloc_utf8_text( bool_true, sizeof(bool_true) );
1024 else return alloc_utf8_text( bool_false, sizeof(bool_false) );
1027 static WS_XML_UTF8_TEXT *format_int8( const INT8 *ptr )
1029 char buf[5]; /* "-128" */
1030 int len = wsprintfA( buf, "%d", *ptr );
1031 return alloc_utf8_text( (const unsigned char *)buf, len );
1034 static WS_XML_UTF8_TEXT *format_int16( const INT16 *ptr )
1036 char buf[7]; /* "-32768" */
1037 int len = wsprintfA( buf, "%d", *ptr );
1038 return alloc_utf8_text( (const unsigned char *)buf, len );
1041 static WS_XML_UTF8_TEXT *format_int32( const INT32 *ptr )
1043 char buf[12]; /* "-2147483648" */
1044 int len = wsprintfA( buf, "%d", *ptr );
1045 return alloc_utf8_text( (const unsigned char *)buf, len );
1048 static WS_XML_UTF8_TEXT *format_int64( const INT64 *ptr )
1050 char buf[21]; /* "-9223372036854775808" */
1051 int len = wsprintfA( buf, "%I64d", *ptr );
1052 return alloc_utf8_text( (const unsigned char *)buf, len );
1055 static WS_XML_UTF8_TEXT *format_uint8( const UINT8 *ptr )
1057 char buf[4]; /* "255" */
1058 int len = wsprintfA( buf, "%u", *ptr );
1059 return alloc_utf8_text( (const unsigned char *)buf, len );
1062 static WS_XML_UTF8_TEXT *format_uint16( const UINT16 *ptr )
1064 char buf[6]; /* "65535" */
1065 int len = wsprintfA( buf, "%u", *ptr );
1066 return alloc_utf8_text( (const unsigned char *)buf, len );
1069 static WS_XML_UTF8_TEXT *format_uint32( const UINT32 *ptr )
1071 char buf[11]; /* "4294967295" */
1072 int len = wsprintfA( buf, "%u", *ptr );
1073 return alloc_utf8_text( (const unsigned char *)buf, len );
1076 static WS_XML_UTF8_TEXT *format_uint64( const UINT64 *ptr )
1078 char buf[21]; /* "18446744073709551615" */
1079 int len = wsprintfA( buf, "%I64u", *ptr );
1080 return alloc_utf8_text( (const unsigned char *)buf, len );
1083 static HRESULT write_text_node( struct writer *writer )
1085 HRESULT hr;
1086 WS_XML_TEXT_NODE *node = (WS_XML_TEXT_NODE *)writer->current;
1087 WS_XML_UTF8_TEXT *text = (WS_XML_UTF8_TEXT *)node->text;
1089 if ((hr = write_grow_buffer( writer, text->value.length )) != S_OK) return hr;
1090 write_bytes( writer, text->value.bytes, text->value.length );
1091 return S_OK;
1094 static HRESULT write_type_text( struct writer *writer, WS_TYPE_MAPPING mapping,
1095 WS_XML_TEXT *text )
1097 HRESULT hr;
1099 switch (mapping)
1101 case WS_ELEMENT_TYPE_MAPPING:
1102 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
1103 if ((hr = write_endstartelement( writer )) != S_OK) return hr;
1104 if ((hr = write_add_text_node( writer, text )) != S_OK) return hr;
1105 return write_text_node( writer );
1107 case WS_ATTRIBUTE_TYPE_MAPPING:
1108 write_set_attribute_value( writer, text );
1109 return S_OK;
1111 case WS_ANY_ELEMENT_TYPE_MAPPING:
1112 switch (writer->state)
1114 case WRITER_STATE_STARTATTRIBUTE:
1115 write_set_attribute_value( writer, text );
1116 return S_OK;
1118 case WRITER_STATE_STARTELEMENT:
1119 if ((hr = write_endstartelement( writer )) != S_OK) return hr;
1120 if ((hr = write_add_text_node( writer, text )) != S_OK) return hr;
1121 return write_text_node( writer );
1123 default:
1124 FIXME( "writer state %u not handled\n", writer->state );
1125 return E_NOTIMPL;
1128 default:
1129 FIXME( "mapping %u not implemented\n", mapping );
1130 return E_NOTIMPL;
1134 static HRESULT write_type_bool( struct writer *writer, WS_TYPE_MAPPING mapping,
1135 const WS_BOOL_DESCRIPTION *desc, const BOOL *value )
1137 WS_XML_UTF8_TEXT *text;
1138 HRESULT hr;
1140 if (desc)
1142 FIXME( "description not supported\n" );
1143 return E_NOTIMPL;
1145 if (!(text = format_bool( value ))) return E_OUTOFMEMORY;
1146 if ((hr = write_type_text( writer, mapping, &text->text )) == S_OK) return S_OK;
1147 heap_free( text );
1148 return hr;
1151 static HRESULT write_type_int8( struct writer *writer, WS_TYPE_MAPPING mapping,
1152 const WS_INT8_DESCRIPTION *desc, const INT8 *value )
1154 WS_XML_UTF8_TEXT *text;
1155 HRESULT hr;
1157 if (desc)
1159 FIXME( "description not supported\n" );
1160 return E_NOTIMPL;
1162 if (!(text = format_int8( value ))) return E_OUTOFMEMORY;
1163 if ((hr = write_type_text( writer, mapping, &text->text )) == S_OK) return S_OK;
1164 heap_free( text );
1165 return hr;
1168 static HRESULT write_type_int16( struct writer *writer, WS_TYPE_MAPPING mapping,
1169 const WS_INT16_DESCRIPTION *desc, const INT16 *value )
1171 WS_XML_UTF8_TEXT *text;
1172 HRESULT hr;
1174 if (desc)
1176 FIXME( "description not supported\n" );
1177 return E_NOTIMPL;
1179 if (!(text = format_int16( value ))) return E_OUTOFMEMORY;
1180 if ((hr = write_type_text( writer, mapping, &text->text )) == S_OK) return S_OK;
1181 heap_free( text );
1182 return hr;
1185 static HRESULT write_type_int32( struct writer *writer, WS_TYPE_MAPPING mapping,
1186 const WS_INT32_DESCRIPTION *desc, const INT32 *value )
1188 WS_XML_UTF8_TEXT *text;
1189 HRESULT hr;
1191 if (desc)
1193 FIXME( "description not supported\n" );
1194 return E_NOTIMPL;
1196 if (!(text = format_int32( value ))) return E_OUTOFMEMORY;
1197 if ((hr = write_type_text( writer, mapping, &text->text )) == S_OK) return S_OK;
1198 heap_free( text );
1199 return hr;
1202 static HRESULT write_type_int64( struct writer *writer, WS_TYPE_MAPPING mapping,
1203 const WS_INT64_DESCRIPTION *desc, const INT64 *value )
1205 WS_XML_UTF8_TEXT *text;
1206 HRESULT hr;
1208 if (desc)
1210 FIXME( "description not supported\n" );
1211 return E_NOTIMPL;
1213 if (!(text = format_int64( value ))) return E_OUTOFMEMORY;
1214 if ((hr = write_type_text( writer, mapping, &text->text )) == S_OK) return S_OK;
1215 heap_free( text );
1216 return hr;
1219 static HRESULT write_type_uint8( struct writer *writer, WS_TYPE_MAPPING mapping,
1220 const WS_UINT8_DESCRIPTION *desc, const UINT8 *value )
1222 WS_XML_UTF8_TEXT *text;
1223 HRESULT hr;
1225 if (desc)
1227 FIXME( "description not supported\n" );
1228 return E_NOTIMPL;
1230 if (!(text = format_uint8( value ))) return E_OUTOFMEMORY;
1231 if ((hr = write_type_text( writer, mapping, &text->text )) == S_OK) return S_OK;
1232 heap_free( text );
1233 return hr;
1236 static HRESULT write_type_uint16( struct writer *writer, WS_TYPE_MAPPING mapping,
1237 const WS_UINT16_DESCRIPTION *desc, const UINT16 *value )
1239 WS_XML_UTF8_TEXT *text;
1240 HRESULT hr;
1242 if (desc)
1244 FIXME( "description not supported\n" );
1245 return E_NOTIMPL;
1247 if (!(text = format_uint16( value ))) return E_OUTOFMEMORY;
1248 if ((hr = write_type_text( writer, mapping, &text->text )) == S_OK) return S_OK;
1249 heap_free( text );
1250 return hr;
1253 static HRESULT write_type_uint32( struct writer *writer, WS_TYPE_MAPPING mapping,
1254 const WS_UINT32_DESCRIPTION *desc, const UINT32 *value )
1256 WS_XML_UTF8_TEXT *text;
1257 HRESULT hr;
1259 if (desc)
1261 FIXME( "description not supported\n" );
1262 return E_NOTIMPL;
1264 if (!(text = format_uint32( value ))) return E_OUTOFMEMORY;
1265 if ((hr = write_type_text( writer, mapping, &text->text )) == S_OK) return S_OK;
1266 heap_free( text );
1267 return hr;
1270 static HRESULT write_type_uint64( struct writer *writer, WS_TYPE_MAPPING mapping,
1271 const WS_UINT64_DESCRIPTION *desc, const UINT64 *value )
1273 WS_XML_UTF8_TEXT *text;
1274 HRESULT hr;
1276 if (desc)
1278 FIXME( "description not supported\n" );
1279 return E_NOTIMPL;
1281 if (!(text = format_uint64( value ))) return E_OUTOFMEMORY;
1282 if ((hr = write_type_text( writer, mapping, &text->text )) == S_OK) return S_OK;
1283 heap_free( text );
1284 return hr;
1287 static HRESULT write_type_wsz( struct writer *writer, WS_TYPE_MAPPING mapping,
1288 const WS_WSZ_DESCRIPTION *desc, const WCHAR *value )
1290 WS_XML_TEXT *text;
1291 HRESULT hr;
1293 if (desc)
1295 FIXME( "description not supported\n" );
1296 return E_NOTIMPL;
1298 if (!(text = widechar_to_xmltext( value, WS_XML_TEXT_TYPE_UTF8 ))) return E_OUTOFMEMORY;
1299 if ((hr = write_type_text( writer, mapping, text )) == S_OK) return S_OK;
1300 heap_free( text );
1301 return hr;
1304 static HRESULT write_type( struct writer *, WS_TYPE_MAPPING, WS_TYPE, const void *, WS_WRITE_OPTION,
1305 const void *, ULONG );
1307 static HRESULT write_type_struct_field( struct writer *writer, const WS_FIELD_DESCRIPTION *desc,
1308 const void *value, ULONG size )
1310 HRESULT hr;
1311 WS_TYPE_MAPPING mapping;
1312 WS_WRITE_OPTION option;
1314 if (!desc->options || desc->options == WS_FIELD_OPTIONAL) option = 0;
1315 else if (desc->options == WS_FIELD_POINTER) option = WS_WRITE_REQUIRED_POINTER;
1316 else
1318 FIXME( "options 0x%x not supported\n", desc->options );
1319 return E_NOTIMPL;
1322 switch (desc->mapping)
1324 case WS_ATTRIBUTE_FIELD_MAPPING:
1325 if (!desc->localName || !desc->ns) return E_INVALIDARG;
1326 if ((hr = write_add_attribute( writer, NULL, desc->localName, desc->ns, FALSE )) != S_OK)
1327 return hr;
1329 mapping = WS_ATTRIBUTE_TYPE_MAPPING;
1330 break;
1332 case WS_ELEMENT_FIELD_MAPPING:
1333 if ((hr = write_add_element_node( writer, NULL, desc->localName, desc->ns )) != S_OK)
1334 return hr;
1336 mapping = WS_ELEMENT_TYPE_MAPPING;
1337 break;
1339 case WS_TEXT_FIELD_MAPPING:
1340 switch (writer->state)
1342 case WRITER_STATE_STARTELEMENT:
1343 mapping = WS_ELEMENT_CONTENT_TYPE_MAPPING;
1344 break;
1346 case WRITER_STATE_STARTATTRIBUTE:
1347 mapping = WS_ATTRIBUTE_TYPE_MAPPING;
1348 break;
1350 default:
1351 FIXME( "unhandled writer state %u\n", writer->state );
1352 return E_NOTIMPL;
1354 break;
1356 default:
1357 FIXME( "field mapping %u not supported\n", desc->mapping );
1358 return E_NOTIMPL;
1361 if ((hr = write_type( writer, mapping, desc->type, desc->typeDescription, option, value, size )) != S_OK)
1362 return hr;
1364 switch (mapping)
1366 case WS_ATTRIBUTE_TYPE_MAPPING:
1367 writer->state = WRITER_STATE_STARTELEMENT;
1368 break;
1370 case WS_ELEMENT_TYPE_MAPPING:
1371 if ((hr = write_close_element( writer )) != S_OK) return hr;
1372 break;
1374 default: break;
1377 return S_OK;
1380 static ULONG get_field_size( const WS_STRUCT_DESCRIPTION *desc, ULONG index )
1382 if (index < desc->fieldCount - 1) return desc->fields[index + 1]->offset - desc->fields[index]->offset;
1383 return desc->size - desc->fields[index]->offset;
1386 static HRESULT write_type_struct( struct writer *writer, WS_TYPE_MAPPING mapping,
1387 const WS_STRUCT_DESCRIPTION *desc, const void *value )
1389 ULONG i, size;
1390 HRESULT hr;
1391 const char *ptr;
1393 if (!desc) return E_INVALIDARG;
1395 if (desc->structOptions)
1397 FIXME( "struct options 0x%x not supported\n", desc->structOptions );
1398 return E_NOTIMPL;
1401 for (i = 0; i < desc->fieldCount; i++)
1403 ptr = (const char *)value + desc->fields[i]->offset;
1404 size = get_field_size( desc, i );
1405 if ((hr = write_type_struct_field( writer, desc->fields[i], ptr, size )) != S_OK)
1406 return hr;
1409 return S_OK;
1412 static HRESULT write_type( struct writer *writer, WS_TYPE_MAPPING mapping, WS_TYPE type,
1413 const void *desc, WS_WRITE_OPTION option, const void *value,
1414 ULONG size )
1416 switch (type)
1418 case WS_STRUCT_TYPE:
1420 const void * const *ptr = value;
1422 if (!desc || (option && option != WS_WRITE_REQUIRED_POINTER) || size != sizeof(*ptr))
1423 return E_INVALIDARG;
1425 return write_type_struct( writer, mapping, desc, *ptr );
1427 case WS_BOOL_TYPE:
1429 const BOOL *ptr = value;
1430 if ((option && option != WS_WRITE_REQUIRED_VALUE) || size != sizeof(*ptr)) return E_INVALIDARG;
1431 return write_type_bool( writer, mapping, desc, ptr );
1433 case WS_INT8_TYPE:
1435 const INT8 *ptr = value;
1436 if ((option && option != WS_WRITE_REQUIRED_VALUE) || size != sizeof(*ptr)) return E_INVALIDARG;
1437 return write_type_int8( writer, mapping, desc, ptr );
1439 case WS_INT16_TYPE:
1441 const INT16 *ptr = value;
1442 if ((option && option != WS_WRITE_REQUIRED_VALUE) || size != sizeof(*ptr)) return E_INVALIDARG;
1443 return write_type_int16( writer, mapping, desc, ptr );
1445 case WS_INT32_TYPE:
1447 const INT32 *ptr = value;
1448 if ((option && option != WS_WRITE_REQUIRED_VALUE) || size != sizeof(*ptr)) return E_INVALIDARG;
1449 return write_type_int32( writer, mapping, desc, ptr );
1451 case WS_INT64_TYPE:
1453 const INT64 *ptr = value;
1454 if ((option && option != WS_WRITE_REQUIRED_VALUE) || size != sizeof(*ptr)) return E_INVALIDARG;
1455 return write_type_int64( writer, mapping, desc, ptr );
1457 case WS_UINT8_TYPE:
1459 const UINT8 *ptr = value;
1460 if ((option && option != WS_WRITE_REQUIRED_VALUE) || size != sizeof(*ptr)) return E_INVALIDARG;
1461 return write_type_uint8( writer, mapping, desc, ptr );
1463 case WS_UINT16_TYPE:
1465 const UINT16 *ptr = value;
1466 if ((option && option != WS_WRITE_REQUIRED_VALUE) || size != sizeof(*ptr)) return E_INVALIDARG;
1467 return write_type_uint16( writer, mapping, desc, ptr );
1469 case WS_UINT32_TYPE:
1471 const UINT32 *ptr = value;
1472 if ((option && option != WS_WRITE_REQUIRED_VALUE) || size != sizeof(*ptr)) return E_INVALIDARG;
1473 return write_type_uint32( writer, mapping, desc, ptr );
1475 case WS_UINT64_TYPE:
1477 const UINT64 *ptr = value;
1478 if ((option && option != WS_WRITE_REQUIRED_VALUE) || size != sizeof(*ptr)) return E_INVALIDARG;
1479 return write_type_uint64( writer, mapping, desc, ptr );
1481 case WS_WSZ_TYPE:
1483 const WCHAR * const *ptr = value;
1484 if ((option && option != WS_WRITE_REQUIRED_POINTER) || size != sizeof(*ptr)) return E_INVALIDARG;
1485 return write_type_wsz( writer, mapping, desc, *ptr );
1487 default:
1488 FIXME( "type %u not supported\n", type );
1489 return E_NOTIMPL;
1493 /**************************************************************************
1494 * WsWriteAttribute [webservices.@]
1496 HRESULT WINAPI WsWriteAttribute( WS_XML_WRITER *handle, const WS_ATTRIBUTE_DESCRIPTION *desc,
1497 WS_WRITE_OPTION option, const void *value, ULONG size,
1498 WS_ERROR *error )
1500 struct writer *writer = (struct writer *)handle;
1501 HRESULT hr;
1503 TRACE( "%p %p %u %p %u %p\n", handle, desc, option, value, size, error );
1504 if (error) FIXME( "ignoring error parameter\n" );
1506 if (!writer || !desc || !desc->attributeLocalName || !desc->attributeNs || !value)
1507 return E_INVALIDARG;
1509 if (writer->state != WRITER_STATE_STARTELEMENT) return WS_E_INVALID_OPERATION;
1511 if ((hr = write_add_attribute( writer, NULL, desc->attributeLocalName, desc->attributeNs,
1512 FALSE )) != S_OK) return hr;
1514 return write_type( writer, WS_ATTRIBUTE_TYPE_MAPPING, desc->type, desc->typeDescription,
1515 option, value, size );
1518 /**************************************************************************
1519 * WsWriteElement [webservices.@]
1521 HRESULT WINAPI WsWriteElement( WS_XML_WRITER *handle, const WS_ELEMENT_DESCRIPTION *desc,
1522 WS_WRITE_OPTION option, const void *value, ULONG size,
1523 WS_ERROR *error )
1525 struct writer *writer = (struct writer *)handle;
1526 HRESULT hr;
1528 TRACE( "%p %p %u %p %u %p\n", handle, desc, option, value, size, error );
1529 if (error) FIXME( "ignoring error parameter\n" );
1531 if (!writer || !desc || !desc->elementLocalName || !desc->elementNs || !value)
1532 return E_INVALIDARG;
1534 if ((hr = write_add_element_node( writer, NULL, desc->elementLocalName, desc->elementNs )) != S_OK)
1535 return hr;
1537 if ((hr = write_type( writer, WS_ANY_ELEMENT_TYPE_MAPPING, desc->type, desc->typeDescription,
1538 option, value, size )) != S_OK) return hr;
1540 return write_close_element( writer );
1543 /**************************************************************************
1544 * WsWriteType [webservices.@]
1546 HRESULT WINAPI WsWriteType( WS_XML_WRITER *handle, WS_TYPE_MAPPING mapping, WS_TYPE type,
1547 const void *desc, WS_WRITE_OPTION option, const void *value,
1548 ULONG size, WS_ERROR *error )
1550 struct writer *writer = (struct writer *)handle;
1551 HRESULT hr;
1553 TRACE( "%p %u %u %p %u %p %u %p\n", handle, mapping, type, desc, option, value,
1554 size, error );
1555 if (error) FIXME( "ignoring error parameter\n" );
1557 if (!writer || !value) return E_INVALIDARG;
1559 switch (mapping)
1561 case WS_ATTRIBUTE_TYPE_MAPPING:
1562 if (writer->state != WRITER_STATE_STARTATTRIBUTE) return WS_E_INVALID_FORMAT;
1563 hr = write_type( writer, mapping, type, desc, option, value, size );
1564 break;
1566 case WS_ELEMENT_TYPE_MAPPING:
1567 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
1568 if (writer->state != WRITER_STATE_STARTELEMENT) return WS_E_INVALID_FORMAT;
1569 hr = write_type( writer, mapping, type, desc, option, value, size );
1570 break;
1572 case WS_ANY_ELEMENT_TYPE_MAPPING:
1573 hr = write_type( writer, mapping, type, desc, option, value, size );
1574 break;
1576 default:
1577 FIXME( "mapping %u not implemented\n", mapping );
1578 return E_NOTIMPL;
1581 return hr;
1584 WS_TYPE map_value_type( WS_VALUE_TYPE type )
1586 switch (type)
1588 case WS_BOOL_VALUE_TYPE: return WS_BOOL_TYPE;
1589 case WS_INT8_VALUE_TYPE: return WS_INT8_TYPE;
1590 case WS_INT16_VALUE_TYPE: return WS_INT16_TYPE;
1591 case WS_INT32_VALUE_TYPE: return WS_INT32_TYPE;
1592 case WS_INT64_VALUE_TYPE: return WS_INT64_TYPE;
1593 case WS_UINT8_VALUE_TYPE: return WS_UINT8_TYPE;
1594 case WS_UINT16_VALUE_TYPE: return WS_UINT16_TYPE;
1595 case WS_UINT32_VALUE_TYPE: return WS_UINT32_TYPE;
1596 case WS_UINT64_VALUE_TYPE: return WS_UINT64_TYPE;
1597 case WS_FLOAT_VALUE_TYPE: return WS_FLOAT_TYPE;
1598 case WS_DOUBLE_VALUE_TYPE: return WS_DOUBLE_TYPE;
1599 case WS_DECIMAL_VALUE_TYPE: return WS_DECIMAL_TYPE;
1600 case WS_DATETIME_VALUE_TYPE: return WS_DATETIME_TYPE;
1601 case WS_TIMESPAN_VALUE_TYPE: return WS_TIMESPAN_TYPE;
1602 case WS_GUID_VALUE_TYPE: return WS_GUID_TYPE;
1603 default:
1604 FIXME( "unhandled type %u\n", type );
1605 return ~0u;
1609 /**************************************************************************
1610 * WsWriteValue [webservices.@]
1612 HRESULT WINAPI WsWriteValue( WS_XML_WRITER *handle, WS_VALUE_TYPE value_type, const void *value,
1613 ULONG size, WS_ERROR *error )
1615 struct writer *writer = (struct writer *)handle;
1616 WS_TYPE_MAPPING mapping;
1617 WS_TYPE type;
1619 TRACE( "%p %u %p %u %p\n", handle, value_type, value, size, error );
1620 if (error) FIXME( "ignoring error parameter\n" );
1622 if (!writer || !value || (type = map_value_type( value_type )) == ~0u) return E_INVALIDARG;
1624 switch (writer->state)
1626 case WRITER_STATE_STARTATTRIBUTE:
1627 mapping = WS_ATTRIBUTE_TYPE_MAPPING;
1628 break;
1630 case WRITER_STATE_STARTELEMENT:
1631 mapping = WS_ELEMENT_TYPE_MAPPING;
1632 break;
1634 default:
1635 return WS_E_INVALID_FORMAT;
1638 return write_type( writer, mapping, type, NULL, WS_WRITE_REQUIRED_VALUE, value, size );
1641 /**************************************************************************
1642 * WsWriteXmlBuffer [webservices.@]
1644 HRESULT WINAPI WsWriteXmlBuffer( WS_XML_WRITER *handle, WS_XML_BUFFER *buffer, WS_ERROR *error )
1646 struct writer *writer = (struct writer *)handle;
1647 struct xmlbuf *xmlbuf = (struct xmlbuf *)buffer;
1648 HRESULT hr;
1650 TRACE( "%p %p %p\n", handle, buffer, error );
1651 if (error) FIXME( "ignoring error parameter\n" );
1653 if (!writer || !xmlbuf) return E_INVALIDARG;
1655 if ((hr = write_grow_buffer( writer, xmlbuf->size )) != S_OK) return hr;
1656 write_bytes( writer, xmlbuf->ptr, xmlbuf->size );
1657 return S_OK;
1660 /**************************************************************************
1661 * WsWriteXmlBufferToBytes [webservices.@]
1663 HRESULT WINAPI WsWriteXmlBufferToBytes( WS_XML_WRITER *handle, WS_XML_BUFFER *buffer,
1664 const WS_XML_WRITER_ENCODING *encoding,
1665 const WS_XML_WRITER_PROPERTY *properties, ULONG count,
1666 WS_HEAP *heap, void **bytes, ULONG *size, WS_ERROR *error )
1668 struct writer *writer = (struct writer *)handle;
1669 struct xmlbuf *xmlbuf = (struct xmlbuf *)buffer;
1670 HRESULT hr;
1671 char *buf;
1672 ULONG i;
1674 TRACE( "%p %p %p %p %u %p %p %p %p\n", handle, buffer, encoding, properties, count, heap,
1675 bytes, size, error );
1676 if (error) FIXME( "ignoring error parameter\n" );
1678 if (!writer || !xmlbuf || !heap || !bytes) return E_INVALIDARG;
1680 if (encoding && encoding->encodingType != WS_XML_WRITER_ENCODING_TYPE_TEXT)
1682 FIXME( "encoding type %u not supported\n", encoding->encodingType );
1683 return E_NOTIMPL;
1686 for (i = 0; i < count; i++)
1688 hr = prop_set( writer->prop, writer->prop_count, properties[i].id, properties[i].value,
1689 properties[i].valueSize );
1690 if (hr != S_OK) return hr;
1693 if (!(buf = ws_alloc( heap, xmlbuf->size ))) return WS_E_QUOTA_EXCEEDED;
1694 memcpy( buf, xmlbuf->ptr, xmlbuf->size );
1695 *bytes = buf;
1696 return S_OK;
1699 /**************************************************************************
1700 * WsWriteXmlnsAttribute [webservices.@]
1702 HRESULT WINAPI WsWriteXmlnsAttribute( WS_XML_WRITER *handle, const WS_XML_STRING *prefix,
1703 const WS_XML_STRING *ns, BOOL single, WS_ERROR *error )
1705 struct writer *writer = (struct writer *)handle;
1707 TRACE( "%p %s %s %d %p\n", handle, debugstr_xmlstr(prefix), debugstr_xmlstr(ns),
1708 single, error );
1709 if (error) FIXME( "ignoring error parameter\n" );
1711 if (!writer || !ns) return E_INVALIDARG;
1712 if (writer->state != WRITER_STATE_STARTELEMENT) return WS_E_INVALID_OPERATION;
1714 if (namespace_in_scope( &writer->current->hdr, prefix, ns )) return S_OK;
1715 return write_add_namespace_attribute( writer, prefix, ns, single );
1718 static HRESULT write_move_to( struct writer *writer, WS_MOVE_TO move, BOOL *found )
1720 BOOL success = FALSE;
1721 struct node *node = writer->current;
1723 switch (move)
1725 case WS_MOVE_TO_ROOT_ELEMENT:
1726 success = move_to_root_element( writer->root, &node );
1727 break;
1729 case WS_MOVE_TO_NEXT_ELEMENT:
1730 success = move_to_next_element( &node );
1731 break;
1733 case WS_MOVE_TO_PREVIOUS_ELEMENT:
1734 success = move_to_prev_element( &node );
1735 break;
1737 case WS_MOVE_TO_CHILD_ELEMENT:
1738 success = move_to_child_element( &node );
1739 break;
1741 case WS_MOVE_TO_END_ELEMENT:
1742 success = move_to_end_element( &node );
1743 break;
1745 case WS_MOVE_TO_PARENT_ELEMENT:
1746 success = move_to_parent_element( &node );
1747 break;
1749 case WS_MOVE_TO_FIRST_NODE:
1750 success = move_to_first_node( &node );
1751 break;
1753 case WS_MOVE_TO_NEXT_NODE:
1754 success = move_to_next_node( &node );
1755 break;
1757 case WS_MOVE_TO_PREVIOUS_NODE:
1758 success = move_to_prev_node( &node );
1759 break;
1761 case WS_MOVE_TO_CHILD_NODE:
1762 success = move_to_child_node( &node );
1763 break;
1765 case WS_MOVE_TO_BOF:
1766 success = move_to_bof( writer->root, &node );
1767 break;
1769 case WS_MOVE_TO_EOF:
1770 success = move_to_eof( writer->root, &node );
1771 break;
1773 default:
1774 FIXME( "unhandled move %u\n", move );
1775 return E_NOTIMPL;
1778 if (success && node == writer->root) return E_INVALIDARG;
1779 writer->current = node;
1781 if (found)
1783 *found = success;
1784 return S_OK;
1786 return success ? S_OK : WS_E_INVALID_FORMAT;
1789 /**************************************************************************
1790 * WsMoveWriter [webservices.@]
1792 HRESULT WINAPI WsMoveWriter( WS_XML_WRITER *handle, WS_MOVE_TO move, BOOL *found, WS_ERROR *error )
1794 struct writer *writer = (struct writer *)handle;
1796 TRACE( "%p %u %p %p\n", handle, move, found, error );
1797 if (error) FIXME( "ignoring error parameter\n" );
1799 if (!writer) return E_INVALIDARG;
1800 if (!writer->output_type) return WS_E_INVALID_OPERATION;
1802 return write_move_to( writer, move, found );
1805 /**************************************************************************
1806 * WsGetWriterPosition [webservices.@]
1808 HRESULT WINAPI WsGetWriterPosition( WS_XML_WRITER *handle, WS_XML_NODE_POSITION *pos, WS_ERROR *error )
1810 struct writer *writer = (struct writer *)handle;
1812 TRACE( "%p %p %p\n", handle, pos, error );
1813 if (error) FIXME( "ignoring error parameter\n" );
1815 if (!writer || !pos) return E_INVALIDARG;
1816 if (!writer->output_type) return WS_E_INVALID_OPERATION;
1818 pos->buffer = (WS_XML_BUFFER *)writer->output_buf;
1819 pos->node = writer->current;
1820 return S_OK;
1823 /**************************************************************************
1824 * WsSetWriterPosition [webservices.@]
1826 HRESULT WINAPI WsSetWriterPosition( WS_XML_WRITER *handle, const WS_XML_NODE_POSITION *pos, WS_ERROR *error )
1828 struct writer *writer = (struct writer *)handle;
1830 TRACE( "%p %p %p\n", handle, pos, error );
1831 if (error) FIXME( "ignoring error parameter\n" );
1833 if (!writer || !pos || (struct xmlbuf *)pos->buffer != writer->output_buf) return E_INVALIDARG;
1834 if (!writer->output_type) return WS_E_INVALID_OPERATION;
1836 writer->current = pos->node;
1837 return S_OK;