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
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
);
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 */
62 WRITER_STATE_STARTELEMENT
,
63 WRITER_STATE_STARTENDELEMENT
,
64 WRITER_STATE_STARTATTRIBUTE
,
65 WRITER_STATE_ENDSTARTELEMENT
,
66 WRITER_STATE_ENDELEMENT
73 enum writer_state state
;
76 WS_XML_STRING
*current_ns
;
77 WS_XML_WRITER_OUTPUT_TYPE output_type
;
78 struct xmlbuf
*output_buf
;
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]);
88 ULONG i
, size
= sizeof(*ret
) + count
* sizeof(WS_XML_WRITER_PROPERTY
);
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
;
105 static HRESULT
set_writer_prop( struct writer
*writer
, WS_XML_WRITER_PROPERTY_ID id
, const void *value
,
108 if (id
>= writer
->prop_count
|| size
!= writer_props
[id
].size
|| writer_props
[id
].readonly
)
111 memcpy( writer
->prop
[id
].value
, value
, size
);
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
)
120 memcpy( buf
, writer
->prop
[id
].value
, writer
->prop
[id
].valueSize
);
124 static void free_writer( struct writer
*writer
)
126 destroy_nodes( writer
->root
);
127 heap_free( writer
->current_ns
);
128 WsFreeHeap( writer
->output_heap
);
132 static void write_insert_eof( struct writer
*writer
, struct node
*eof
)
134 if (!writer
->root
) writer
->root
= eof
;
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
)
166 heap_free( writer
->current_ns
);
167 writer
->current_ns
= NULL
;
168 destroy_nodes( writer
->root
);
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
;
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
;
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
);
207 free_writer( writer
);
212 hr
= get_writer_prop( writer
, WS_XML_WRITER_PROPERTY_BUFFER_MAX_SIZE
, &max_size
, sizeof(max_size
) );
215 free_writer( writer
);
219 hr
= WsCreateHeap( max_size
, 0, NULL
, 0, &writer
->output_heap
, NULL
);
222 free_writer( writer
);
226 hr
= write_init_state( writer
);
229 free_writer( writer
);
233 *handle
= (WS_XML_WRITER
*)writer
;
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
)
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
);
260 ret
->size_allocated
= XML_BUFFER_INITIAL_ALLOCATED_SIZE
;
265 static void free_xmlbuf( struct xmlbuf
*xmlbuf
)
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
;
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
;
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
;
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
;
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
);
368 FIXME( "encoding type %u not supported\n", encoding
->encodingType
);
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
);
382 FIXME( "output type %u not supported\n", output
->outputType
);
386 if (!(node
= alloc_node( WS_XML_NODE_TYPE_BOF
))) return E_OUTOFMEMORY
;
387 write_insert_bof( writer
, node
);
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
,
398 struct writer
*writer
= (struct writer
*)handle
;
399 struct xmlbuf
*xmlbuf
= (struct xmlbuf
*)buffer
;
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
);
423 static HRESULT
write_grow_buffer( struct writer
*writer
, ULONG size
)
425 struct xmlbuf
*buf
= writer
->output_buf
;
429 if (buf
->size_allocated
>= writer
->write_pos
+ size
)
431 buf
->size
= writer
->write_pos
+ size
;
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
;
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
;
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
, ' ' );
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 */
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
)
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
;
498 static HRESULT
write_startelement( struct writer
*writer
)
500 WS_XML_ELEMENT_NODE
*elem
= (WS_XML_ELEMENT_NODE
*)writer
->current
;
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
, '<' );
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 );
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
, '"' );
544 static HRESULT
write_endelement( struct writer
*writer
)
546 WS_XML_ELEMENT_NODE
*elem
= (WS_XML_ELEMENT_NODE
*)writer
->current
;
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
, '/' );
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
, '>' );
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
;
585 /**************************************************************************
586 * WsWriteEndElement [webservices.@]
588 HRESULT WINAPI
WsWriteEndElement( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
590 struct writer
*writer
= (struct writer
*)handle
;
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
)
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
;
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
)
622 write_insert_node( writer
, node
);
623 writer
->current
= node
->parent
;
624 writer
->state
= WRITER_STATE_ENDELEMENT
;
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
;
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
;
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
)))
679 if (!(attr
->localName
= alloc_xml_string( (const char *)localname
->bytes
, localname
->length
)))
682 if (!(attr
->ns
= alloc_xml_string( (const char *)ns
->bytes
, ns
->length
)))
685 if ((hr
= append_attribute( elem
, attr
)) != S_OK
) goto error
;
687 writer
->state
= WRITER_STATE_STARTATTRIBUTE
;
691 free_attribute( attr
);
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
,
702 struct writer
*writer
= (struct writer
*)handle
;
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
)))
727 if (!(elem
->localName
= alloc_xml_string( (const char *)localname
->bytes
, localname
->length
)))
730 if (!(elem
->ns
= alloc_xml_string( (const char *)ns
->bytes
, ns
->length
)))
733 write_insert_node( writer
, node
);
734 writer
->state
= WRITER_STATE_STARTELEMENT
;
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
);
760 if (text
->textType
!= WS_XML_TEXT_TYPE_UTF8
)
762 FIXME( "text type %u not supported\n", text
->textType
);
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
;