TESTING -- override pthreads to fix gstreamer v5
[wine/multimedia.git] / dlls / webservices / writer.c
blobb03b15dde180cd37f4d83b3c5c8616403208f74e
1 /*
2 * Copyright 2015 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 "webservices.h"
25 #include "wine/debug.h"
26 #include "wine/list.h"
27 #include "webservices_private.h"
29 WINE_DEFAULT_DEBUG_CHANNEL(webservices);
31 static const struct
33 ULONG size;
34 BOOL readonly;
36 writer_props[] =
38 { sizeof(ULONG), FALSE }, /* WS_XML_WRITER_PROPERTY_MAX_DEPTH */
39 { sizeof(BOOL), FALSE }, /* WS_XML_WRITER_PROPERTY_ALLOW_FRAGMENT */
40 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_MAX_ATTRIBUTES */
41 { sizeof(BOOL), FALSE }, /* WS_XML_WRITER_PROPERTY_WRITE_DECLARATION */
42 { sizeof(ULONG), FALSE }, /* WS_XML_WRITER_PROPERTY_INDENT */
43 { sizeof(ULONG), FALSE }, /* WS_XML_WRITER_PROPERTY_BUFFER_TRIM_SIZE */
44 { sizeof(WS_CHARSET), FALSE }, /* WS_XML_WRITER_PROPERTY_CHARSET */
45 { sizeof(WS_BUFFERS), FALSE }, /* WS_XML_WRITER_PROPERTY_BUFFERS */
46 { sizeof(ULONG), FALSE }, /* WS_XML_WRITER_PROPERTY_BUFFER_MAX_SIZE */
47 { sizeof(WS_BYTES), FALSE }, /* WS_XML_WRITER_PROPERTY_BYTES */
48 { sizeof(BOOL), TRUE }, /* WS_XML_WRITER_PROPERTY_IN_ATTRIBUTE */
49 { sizeof(ULONG), FALSE }, /* WS_XML_WRITER_PROPERTY_MAX_MIME_PARTS_BUFFER_SIZE */
50 { sizeof(WS_BYTES), FALSE }, /* WS_XML_WRITER_PROPERTY_INITIAL_BUFFER */
51 { sizeof(BOOL), FALSE }, /* WS_XML_WRITER_PROPERTY_ALLOW_INVALID_CHARACTER_REFERENCES */
52 { sizeof(ULONG), FALSE }, /* WS_XML_WRITER_PROPERTY_MAX_NAMESPACES */
53 { sizeof(ULONG), TRUE }, /* WS_XML_WRITER_PROPERTY_BYTES_WRITTEN */
54 { sizeof(ULONG), TRUE }, /* WS_XML_WRITER_PROPERTY_BYTES_TO_CLOSE */
55 { sizeof(BOOL), FALSE }, /* WS_XML_WRITER_PROPERTY_COMPRESS_EMPTY_ELEMENTS */
56 { sizeof(BOOL), FALSE } /* WS_XML_WRITER_PROPERTY_EMIT_UNCOMPRESSED_EMPTY_ELEMENTS */
59 enum writer_state
61 WRITER_STATE_INITIAL,
62 WRITER_STATE_STARTELEMENT,
63 WRITER_STATE_STARTENDELEMENT,
64 WRITER_STATE_STARTATTRIBUTE,
65 WRITER_STATE_ENDSTARTELEMENT,
66 WRITER_STATE_ENDELEMENT
69 struct writer
71 ULONG write_pos;
72 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 WS_XML_WRITER_PROPERTY 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 i, size = sizeof(*ret) + count * sizeof(WS_XML_WRITER_PROPERTY);
89 char *ptr;
91 for (i = 0; i < count; i++) size += writer_props[i].size;
92 if (!(ret = heap_alloc_zero( size ))) return NULL;
94 ptr = (char *)&ret->prop[count];
95 for (i = 0; i < count; i++)
97 ret->prop[i].value = ptr;
98 ret->prop[i].valueSize = writer_props[i].size;
99 ptr += ret->prop[i].valueSize;
101 ret->prop_count = count;
102 return ret;
105 static HRESULT set_writer_prop( struct writer *writer, WS_XML_WRITER_PROPERTY_ID id, const void *value,
106 ULONG size )
108 if (id >= writer->prop_count || size != writer_props[id].size || writer_props[id].readonly)
109 return E_INVALIDARG;
111 memcpy( writer->prop[id].value, value, size );
112 return S_OK;
115 static HRESULT get_writer_prop( struct writer *writer, WS_XML_WRITER_PROPERTY_ID id, void *buf, ULONG size )
117 if (id >= writer->prop_count || size != writer_props[id].size)
118 return E_INVALIDARG;
120 memcpy( buf, writer->prop[id].value, writer->prop[id].valueSize );
121 return S_OK;
124 static void free_writer( struct writer *writer )
126 destroy_nodes( writer->root );
127 heap_free( writer->current_ns );
128 WsFreeHeap( writer->output_heap );
129 heap_free( writer );
132 static void write_insert_eof( struct writer *writer, struct node *eof )
134 if (!writer->root) writer->root = eof;
135 else
137 eof->parent = writer->root;
138 list_add_tail( &writer->root->children, &eof->entry );
140 writer->current = eof;
143 static void write_insert_bof( struct writer *writer, struct node *bof )
145 writer->root->parent = bof;
146 list_add_tail( &bof->children, &writer->root->entry );
147 writer->current = writer->root = bof;
150 static void write_insert_node( struct writer *writer, struct node *node )
152 node->parent = writer->current;
153 if (writer->current == writer->root)
155 struct list *eof = list_tail( &writer->root->children );
156 list_add_before( eof, &node->entry );
158 else list_add_tail( &writer->current->children, &node->entry );
159 writer->current = node;
162 static HRESULT write_init_state( struct writer *writer )
164 struct node *node;
166 heap_free( writer->current_ns );
167 writer->current_ns = NULL;
168 destroy_nodes( writer->root );
169 writer->root = NULL;
171 if (!(node = alloc_node( WS_XML_NODE_TYPE_EOF ))) return E_OUTOFMEMORY;
172 write_insert_eof( writer, node );
173 writer->state = WRITER_STATE_INITIAL;
174 return S_OK;
177 /**************************************************************************
178 * WsCreateWriter [webservices.@]
180 HRESULT WINAPI WsCreateWriter( const WS_XML_WRITER_PROPERTY *properties, ULONG count,
181 WS_XML_WRITER **handle, WS_ERROR *error )
183 struct writer *writer;
184 ULONG i, max_depth = 32, max_attrs = 128, trim_size = 4096, max_size = 65536, max_ns = 32;
185 WS_CHARSET charset = WS_CHARSET_UTF8;
186 HRESULT hr;
188 TRACE( "%p %u %p %p\n", properties, count, handle, error );
189 if (error) FIXME( "ignoring error parameter\n" );
191 if (!handle) return E_INVALIDARG;
192 if (!(writer = alloc_writer())) return E_OUTOFMEMORY;
194 set_writer_prop( writer, WS_XML_WRITER_PROPERTY_MAX_DEPTH, &max_depth, sizeof(max_depth) );
195 set_writer_prop( writer, WS_XML_WRITER_PROPERTY_MAX_ATTRIBUTES, &max_attrs, sizeof(max_attrs) );
196 set_writer_prop( writer, WS_XML_WRITER_PROPERTY_BUFFER_TRIM_SIZE, &trim_size, sizeof(trim_size) );
197 set_writer_prop( writer, WS_XML_WRITER_PROPERTY_CHARSET, &charset, sizeof(charset) );
198 set_writer_prop( writer, WS_XML_WRITER_PROPERTY_BUFFER_MAX_SIZE, &max_size, sizeof(max_size) );
199 set_writer_prop( writer, WS_XML_WRITER_PROPERTY_MAX_MIME_PARTS_BUFFER_SIZE, &max_size, sizeof(max_size) );
200 set_writer_prop( writer, WS_XML_WRITER_PROPERTY_MAX_NAMESPACES, &max_ns, sizeof(max_ns) );
202 for (i = 0; i < count; i++)
204 hr = set_writer_prop( writer, properties[i].id, properties[i].value, properties[i].valueSize );
205 if (hr != S_OK)
207 free_writer( writer );
208 return hr;
212 hr = get_writer_prop( writer, WS_XML_WRITER_PROPERTY_BUFFER_MAX_SIZE, &max_size, sizeof(max_size) );
213 if (hr != S_OK)
215 free_writer( writer );
216 return hr;
219 hr = WsCreateHeap( max_size, 0, NULL, 0, &writer->output_heap, NULL );
220 if (hr != S_OK)
222 free_writer( writer );
223 return hr;
226 hr = write_init_state( writer );
227 if (hr != S_OK)
229 free_writer( writer );
230 return hr;
233 *handle = (WS_XML_WRITER *)writer;
234 return S_OK;
237 /**************************************************************************
238 * WsFreeWriter [webservices.@]
240 void WINAPI WsFreeWriter( WS_XML_WRITER *handle )
242 struct writer *writer = (struct writer *)handle;
244 TRACE( "%p\n", handle );
245 free_writer( writer );
248 #define XML_BUFFER_INITIAL_ALLOCATED_SIZE 256
249 static struct xmlbuf *alloc_xmlbuf( WS_HEAP *heap )
251 struct xmlbuf *ret;
253 if (!(ret = ws_alloc( heap, sizeof(*ret) ))) return NULL;
254 if (!(ret->ptr = ws_alloc( heap, XML_BUFFER_INITIAL_ALLOCATED_SIZE )))
256 ws_free( heap, ret );
257 return NULL;
259 ret->heap = heap;
260 ret->size_allocated = XML_BUFFER_INITIAL_ALLOCATED_SIZE;
261 ret->size = 0;
262 return ret;
265 static void free_xmlbuf( struct xmlbuf *xmlbuf )
267 if (!xmlbuf) return;
268 ws_free( xmlbuf->heap, xmlbuf->ptr );
269 ws_free( xmlbuf->heap, xmlbuf );
272 /**************************************************************************
273 * WsCreateXmlBuffer [webservices.@]
275 HRESULT WINAPI WsCreateXmlBuffer( WS_HEAP *heap, const WS_XML_BUFFER_PROPERTY *properties,
276 ULONG count, WS_XML_BUFFER **handle, WS_ERROR *error )
278 struct xmlbuf *xmlbuf;
280 if (!heap || !handle) return E_INVALIDARG;
281 if (count) FIXME( "properties not implemented\n" );
283 if (!(xmlbuf = alloc_xmlbuf( heap ))) return E_OUTOFMEMORY;
285 *handle = (WS_XML_BUFFER *)xmlbuf;
286 return S_OK;
289 /**************************************************************************
290 * WsGetWriterProperty [webservices.@]
292 HRESULT WINAPI WsGetWriterProperty( WS_XML_WRITER *handle, WS_XML_WRITER_PROPERTY_ID id,
293 void *buf, ULONG size, WS_ERROR *error )
295 struct writer *writer = (struct writer *)handle;
297 TRACE( "%p %u %p %u %p\n", handle, id, buf, size, error );
298 if (error) FIXME( "ignoring error parameter\n" );
300 if (!writer->output_type) return WS_E_INVALID_OPERATION;
302 switch (id)
304 case WS_XML_WRITER_PROPERTY_BYTES:
306 WS_BYTES *bytes = buf;
307 if (size != sizeof(*bytes)) return E_INVALIDARG;
308 bytes->bytes = writer->output_buf->ptr;
309 bytes->length = writer->output_buf->size;
310 return S_OK;
312 default:
313 return get_writer_prop( writer, id, buf, size );
317 static void set_output_buffer( struct writer *writer, struct xmlbuf *xmlbuf )
319 /* free current buffer if it's ours */
320 if (writer->output_buf && writer->output_buf->heap == writer->output_heap)
322 free_xmlbuf( writer->output_buf );
324 writer->output_buf = xmlbuf;
325 writer->output_type = WS_XML_WRITER_OUTPUT_TYPE_BUFFER;
326 writer->write_bufptr = xmlbuf->ptr;
327 writer->write_pos = 0;
330 /**************************************************************************
331 * WsSetOutput [webservices.@]
333 HRESULT WINAPI WsSetOutput( WS_XML_WRITER *handle, const WS_XML_WRITER_ENCODING *encoding,
334 const WS_XML_WRITER_OUTPUT *output, const WS_XML_WRITER_PROPERTY *properties,
335 ULONG count, WS_ERROR *error )
337 struct writer *writer = (struct writer *)handle;
338 struct node *node;
339 HRESULT hr;
340 ULONG i;
342 TRACE( "%p %p %p %p %u %p\n", handle, encoding, output, properties, count, error );
343 if (error) FIXME( "ignoring error parameter\n" );
345 if (!writer) return E_INVALIDARG;
347 for (i = 0; i < count; i++)
349 hr = set_writer_prop( writer, properties[i].id, properties[i].value, properties[i].valueSize );
350 if (hr != S_OK) return hr;
353 if ((hr = write_init_state( writer )) != S_OK) return hr;
355 switch (encoding->encodingType)
357 case WS_XML_WRITER_ENCODING_TYPE_TEXT:
359 WS_XML_WRITER_TEXT_ENCODING *text = (WS_XML_WRITER_TEXT_ENCODING *)encoding;
360 if (text->charSet != WS_CHARSET_UTF8)
362 FIXME( "charset %u not supported\n", text->charSet );
363 return E_NOTIMPL;
365 break;
367 default:
368 FIXME( "encoding type %u not supported\n", encoding->encodingType );
369 return E_NOTIMPL;
371 switch (output->outputType)
373 case WS_XML_WRITER_OUTPUT_TYPE_BUFFER:
375 struct xmlbuf *xmlbuf;
377 if (!(xmlbuf = alloc_xmlbuf( writer->output_heap ))) return E_OUTOFMEMORY;
378 set_output_buffer( writer, xmlbuf );
379 break;
381 default:
382 FIXME( "output type %u not supported\n", output->outputType );
383 return E_NOTIMPL;
386 if (!(node = alloc_node( WS_XML_NODE_TYPE_BOF ))) return E_OUTOFMEMORY;
387 write_insert_bof( writer, node );
388 return S_OK;
391 /**************************************************************************
392 * WsSetOutputToBuffer [webservices.@]
394 HRESULT WINAPI WsSetOutputToBuffer( WS_XML_WRITER *handle, WS_XML_BUFFER *buffer,
395 const WS_XML_WRITER_PROPERTY *properties, ULONG count,
396 WS_ERROR *error )
398 struct writer *writer = (struct writer *)handle;
399 struct xmlbuf *xmlbuf = (struct xmlbuf *)buffer;
400 struct node *node;
401 HRESULT hr;
402 ULONG i;
404 TRACE( "%p %p %p %u %p\n", handle, buffer, properties, count, error );
405 if (error) FIXME( "ignoring error parameter\n" );
407 if (!writer || !xmlbuf) return E_INVALIDARG;
409 for (i = 0; i < count; i++)
411 hr = set_writer_prop( writer, properties[i].id, properties[i].value, properties[i].valueSize );
412 if (hr != S_OK) return hr;
415 if ((hr = write_init_state( writer )) != S_OK) return hr;
416 set_output_buffer( writer, xmlbuf );
418 if (!(node = alloc_node( WS_XML_NODE_TYPE_BOF ))) return E_OUTOFMEMORY;
419 write_insert_bof( writer, node );
420 return S_OK;
423 static HRESULT write_grow_buffer( struct writer *writer, ULONG size )
425 struct xmlbuf *buf = writer->output_buf;
426 SIZE_T new_size;
427 void *tmp;
429 if (buf->size_allocated >= writer->write_pos + size)
431 buf->size = writer->write_pos + size;
432 return S_OK;
434 new_size = max( buf->size_allocated * 2, writer->write_pos + size );
435 if (!(tmp = ws_realloc( buf->heap, buf->ptr, new_size ))) return E_OUTOFMEMORY;
436 writer->write_bufptr = buf->ptr = tmp;
437 buf->size_allocated = new_size;
438 buf->size = writer->write_pos + size;
439 return S_OK;
442 static inline void write_char( struct writer *writer, char ch )
444 writer->write_bufptr[writer->write_pos++] = ch;
447 static inline void write_bytes( struct writer *writer, const BYTE *bytes, ULONG len )
449 memcpy( writer->write_bufptr + writer->write_pos, bytes, len );
450 writer->write_pos += len;
453 static HRESULT write_attribute( struct writer *writer, WS_XML_ATTRIBUTE *attr )
455 WS_XML_UTF8_TEXT *text = (WS_XML_UTF8_TEXT *)attr->value;
456 ULONG size;
457 HRESULT hr;
459 /* ' prefix:attr="value"' */
461 size = attr->localName->length + 4 /* ' =""' */;
462 if (attr->prefix) size += attr->prefix->length + 1 /* ':' */;
463 if (text) size += text->value.length;
464 if ((hr = write_grow_buffer( writer, size )) != S_OK) return hr;
466 write_char( writer, ' ' );
467 if (attr->prefix)
469 write_bytes( writer, attr->prefix->bytes, attr->prefix->length );
470 write_char( writer, ':' );
472 write_bytes( writer, attr->localName->bytes, attr->localName->length );
473 write_char( writer, '=' );
474 if (attr->singleQuote) write_char( writer, '\'' );
475 else write_char( writer, '"' );
476 if (text) write_bytes( writer, text->value.bytes, text->value.length );
477 if (attr->singleQuote) write_char( writer, '\'' );
478 else write_char( writer, '"' );
480 /* FIXME: ignoring namespace */
481 return S_OK;
484 static inline BOOL is_current_namespace( struct writer *writer, const WS_XML_STRING *ns )
486 return (WsXmlStringEquals( writer->current_ns, ns, NULL ) == S_OK);
489 static HRESULT set_current_namespace( struct writer *writer, const WS_XML_STRING *ns )
491 WS_XML_STRING *str;
492 if (!(str = alloc_xml_string( (const char *)ns->bytes, ns->length ))) return E_OUTOFMEMORY;
493 heap_free( writer->current_ns );
494 writer->current_ns = str;
495 return S_OK;
498 static HRESULT write_startelement( struct writer *writer )
500 WS_XML_ELEMENT_NODE *elem = (WS_XML_ELEMENT_NODE *)writer->current;
501 ULONG size, i;
502 HRESULT hr;
504 /* '<prefix:localname prefix:attr="value"... xmlns:prefix="ns"' */
506 size = elem->localName->length + 1 /* '<' */;
507 if (elem->prefix) size += elem->prefix->length + 1 /* ':' */;
508 if (elem->ns->length && !is_current_namespace( writer, elem->ns ))
510 size += strlen(" xmlns") + elem->ns->length + 3 /* '=""' */;
511 if (elem->prefix) size += elem->prefix->length + 1 /* ':' */;
513 if ((hr = write_grow_buffer( writer, size )) != S_OK) return hr;
515 write_char( writer, '<' );
516 if (elem->prefix)
518 write_bytes( writer, elem->prefix->bytes, elem->prefix->length );
519 write_char( writer, ':' );
521 write_bytes( writer, elem->localName->bytes, elem->localName->length );
522 for (i = 0; i < elem->attributeCount; i++)
524 if ((hr = write_attribute( writer, elem->attributes[i] )) != S_OK) return hr;
526 if (elem->ns->length && !is_current_namespace( writer, elem->ns ))
528 if ((hr = set_current_namespace( writer, elem->ns )) != S_OK) return hr;
530 write_bytes( writer, (const BYTE *)" xmlns", 6 );
531 if (elem->prefix)
533 write_char( writer, ':' );
534 write_bytes( writer, elem->prefix->bytes, elem->prefix->length );
536 write_char( writer, '=' );
537 write_char( writer, '"' );
538 write_bytes( writer, elem->ns->bytes, elem->ns->length );
539 write_char( writer, '"' );
541 return S_OK;
544 static HRESULT write_endelement( struct writer *writer )
546 WS_XML_ELEMENT_NODE *elem = (WS_XML_ELEMENT_NODE *)writer->current;
547 ULONG size;
548 HRESULT hr;
550 /* '</prefix:localname>' */
552 size = elem->localName->length + 3 /* '</>' */;
553 if (elem->prefix) size += elem->prefix->length + 1 /* ':' */;
554 if ((hr = write_grow_buffer( writer, size )) != S_OK) return hr;
556 write_char( writer, '<' );
557 write_char( writer, '/' );
558 if (elem->prefix)
560 write_bytes( writer, elem->prefix->bytes, elem->prefix->length );
561 write_char( writer, ':' );
563 write_bytes( writer, elem->localName->bytes, elem->localName->length );
564 write_char( writer, '>' );
565 return S_OK;
568 /**************************************************************************
569 * WsWriteEndAttribute [webservices.@]
571 HRESULT WINAPI WsWriteEndAttribute( WS_XML_WRITER *handle, WS_ERROR *error )
573 struct writer *writer = (struct writer *)handle;
575 TRACE( "%p %p\n", handle, error );
576 if (error) FIXME( "ignoring error parameter\n" );
578 if (!writer) return E_INVALIDARG;
579 if (writer->state != WRITER_STATE_STARTATTRIBUTE) return WS_E_INVALID_OPERATION;
581 writer->state = WRITER_STATE_STARTELEMENT;
582 return S_OK;
585 /**************************************************************************
586 * WsWriteEndElement [webservices.@]
588 HRESULT WINAPI WsWriteEndElement( WS_XML_WRITER *handle, WS_ERROR *error )
590 struct writer *writer = (struct writer *)handle;
591 HRESULT hr;
593 TRACE( "%p %p\n", handle, error );
594 if (error) FIXME( "ignoring error parameter\n" );
596 if (!writer) return E_INVALIDARG;
598 if (writer->state == WRITER_STATE_STARTELEMENT)
600 /* '/>' */
601 if ((hr = write_startelement( writer )) != S_OK) return hr;
602 if ((hr = write_grow_buffer( writer, 2 )) != S_OK) return hr;
603 write_char( writer, '/' );
604 write_char( writer, '>' );
606 writer->current = writer->current->parent;
607 writer->state = WRITER_STATE_STARTENDELEMENT;
608 return S_OK;
610 else
612 struct node *node = alloc_node( WS_XML_NODE_TYPE_END_ELEMENT );
613 if (!node) return E_OUTOFMEMORY;
615 /* '</prefix:localname>' */
616 if ((hr = write_endelement( writer )) != S_OK)
618 free_node( node );
619 return hr;
622 write_insert_node( writer, node );
623 writer->current = node->parent;
624 writer->state = WRITER_STATE_ENDELEMENT;
625 return S_OK;
627 return WS_E_INVALID_OPERATION;
630 /**************************************************************************
631 * WsWriteEndStartElement [webservices.@]
633 HRESULT WINAPI WsWriteEndStartElement( WS_XML_WRITER *handle, WS_ERROR *error )
635 struct writer *writer = (struct writer *)handle;
636 HRESULT hr;
638 TRACE( "%p %p\n", handle, error );
639 if (error) FIXME( "ignoring error parameter\n" );
641 if (!writer) return E_INVALIDARG;
642 if (writer->state != WRITER_STATE_STARTELEMENT) return WS_E_INVALID_OPERATION;
644 if ((hr = write_startelement( writer )) != S_OK) return hr;
645 if ((hr = write_grow_buffer( writer, 1 )) != S_OK) return hr;
646 write_char( writer, '>' );
648 writer->state = WRITER_STATE_ENDSTARTELEMENT;
649 return S_OK;
652 /**************************************************************************
653 * WsWriteStartAttribute [webservices.@]
655 HRESULT WINAPI WsWriteStartAttribute( WS_XML_WRITER *handle, const WS_XML_STRING *prefix,
656 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
657 BOOL single, WS_ERROR *error )
659 struct writer *writer = (struct writer *)handle;
660 WS_XML_ELEMENT_NODE *elem;
661 WS_XML_ATTRIBUTE *attr;
662 HRESULT hr = E_OUTOFMEMORY;
664 TRACE( "%p %s %s %s %d %p\n", handle, debugstr_xmlstr(prefix), debugstr_xmlstr(localname),
665 debugstr_xmlstr(ns), single, error );
666 if (error) FIXME( "ignoring error parameter\n" );
668 if (!writer || !localname || !ns) return E_INVALIDARG;
670 if (writer->state != WRITER_STATE_STARTELEMENT) return WS_E_INVALID_OPERATION;
671 elem = (WS_XML_ELEMENT_NODE *)writer->current;
673 if (!(attr = heap_alloc_zero( sizeof(*attr) ))) return E_OUTOFMEMORY;
674 attr->singleQuote = !!single;
676 if (prefix && !(attr->prefix = alloc_xml_string( (const char *)prefix->bytes, prefix->length )))
677 goto error;
679 if (!(attr->localName = alloc_xml_string( (const char *)localname->bytes, localname->length )))
680 goto error;
682 if (!(attr->ns = alloc_xml_string( (const char *)ns->bytes, ns->length )))
683 goto error;
685 if ((hr = append_attribute( elem, attr )) != S_OK) goto error;
687 writer->state = WRITER_STATE_STARTATTRIBUTE;
688 return S_OK;
690 error:
691 free_attribute( attr );
692 return hr;
695 /**************************************************************************
696 * WsWriteStartElement [webservices.@]
698 HRESULT WINAPI WsWriteStartElement( WS_XML_WRITER *handle, const WS_XML_STRING *prefix,
699 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
700 WS_ERROR *error )
702 struct writer *writer = (struct writer *)handle;
703 struct node *node;
704 WS_XML_ELEMENT_NODE *elem;
705 HRESULT hr = E_OUTOFMEMORY;
707 TRACE( "%p %s %s %s %p\n", handle, debugstr_xmlstr(prefix), debugstr_xmlstr(localname),
708 debugstr_xmlstr(ns), error );
709 if (error) FIXME( "ignoring error parameter\n" );
711 if (!writer || !localname || !ns) return E_INVALIDARG;
713 /* flush current start element */
714 if (writer->state == WRITER_STATE_STARTELEMENT)
716 if ((hr = write_startelement( writer )) != S_OK) return hr;
717 if ((hr = write_grow_buffer( writer, 1 )) != S_OK) return hr;
718 write_char( writer, '>' );
721 if (!(node = alloc_node( WS_XML_NODE_TYPE_ELEMENT ))) return E_OUTOFMEMORY;
722 elem = (WS_XML_ELEMENT_NODE *)node;
724 if (prefix && !(elem->prefix = alloc_xml_string( (const char *)prefix->bytes, prefix->length )))
725 goto error;
727 if (!(elem->localName = alloc_xml_string( (const char *)localname->bytes, localname->length )))
728 goto error;
730 if (!(elem->ns = alloc_xml_string( (const char *)ns->bytes, ns->length )))
731 goto error;
733 write_insert_node( writer, node );
734 writer->state = WRITER_STATE_STARTELEMENT;
735 return S_OK;
737 error:
738 free_node( node );
739 return hr;
742 /**************************************************************************
743 * WsWriteText [webservices.@]
745 HRESULT WINAPI WsWriteText( WS_XML_WRITER *handle, const WS_XML_TEXT *text, WS_ERROR *error )
747 struct writer *writer = (struct writer *)handle;
748 WS_XML_ELEMENT_NODE *elem;
749 WS_XML_UTF8_TEXT *src, *dst;
751 TRACE( "%p %p %p\n", handle, text, error );
753 if (!writer || !text) return E_INVALIDARG;
755 if (writer->state != WRITER_STATE_STARTATTRIBUTE)
757 FIXME( "can't handle writer state %u\n", writer->state );
758 return E_NOTIMPL;
760 if (text->textType != WS_XML_TEXT_TYPE_UTF8)
762 FIXME( "text type %u not supported\n", text->textType );
763 return E_NOTIMPL;
765 src = (WS_XML_UTF8_TEXT *)text;
766 if (!(dst = alloc_utf8_text( (const char *)src->value.bytes, src->value.length )))
767 return E_OUTOFMEMORY;
769 elem = (WS_XML_ELEMENT_NODE *)writer->current;
770 elem->attributes[elem->attributeCount - 1]->value = (WS_XML_TEXT *)dst;
771 return S_OK;