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
27 #include "webservices.h"
29 #include "wine/debug.h"
30 #include "wine/list.h"
31 #include "wine/unicode.h"
32 #include "webservices_private.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(webservices
);
36 static const struct prop_desc 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 */
62 WRITER_STATE_STARTELEMENT
,
63 WRITER_STATE_STARTATTRIBUTE
,
64 WRITER_STATE_STARTCDATA
,
65 WRITER_STATE_ENDSTARTELEMENT
,
68 WRITER_STATE_ENDELEMENT
,
75 unsigned char *write_bufptr
;
76 enum writer_state state
;
79 WS_XML_STRING
*current_ns
;
80 WS_XML_WRITER_OUTPUT_TYPE output_type
;
81 struct xmlbuf
*output_buf
;
84 struct prop prop
[sizeof(writer_props
)/sizeof(writer_props
[0])];
87 static struct writer
*alloc_writer(void)
89 static const ULONG count
= sizeof(writer_props
)/sizeof(writer_props
[0]);
91 ULONG size
= sizeof(*ret
) + prop_size( writer_props
, count
);
93 if (!(ret
= heap_alloc_zero( size
))) return NULL
;
94 prop_init( writer_props
, count
, ret
->prop
, &ret
[1] );
95 ret
->prop_count
= count
;
99 static void free_writer( struct writer
*writer
)
102 destroy_nodes( writer
->root
);
103 heap_free( writer
->current_ns
);
104 WsFreeHeap( writer
->output_heap
);
108 static void write_insert_eof( struct writer
*writer
, struct node
*eof
)
110 if (!writer
->root
) writer
->root
= eof
;
113 eof
->parent
= writer
->root
;
114 list_add_tail( &writer
->root
->children
, &eof
->entry
);
116 writer
->current
= eof
;
119 static void write_insert_bof( struct writer
*writer
, struct node
*bof
)
121 writer
->root
->parent
= bof
;
122 list_add_tail( &bof
->children
, &writer
->root
->entry
);
123 writer
->current
= writer
->root
= bof
;
126 static void write_insert_node( struct writer
*writer
, struct node
*parent
, struct node
*node
)
128 node
->parent
= parent
;
129 list_add_before( list_tail( &parent
->children
), &node
->entry
);
130 writer
->current
= node
;
133 static HRESULT
write_init_state( struct writer
*writer
)
137 heap_free( writer
->current_ns
);
138 writer
->current_ns
= NULL
;
139 destroy_nodes( writer
->root
);
142 if (!(node
= alloc_node( WS_XML_NODE_TYPE_EOF
))) return E_OUTOFMEMORY
;
143 write_insert_eof( writer
, node
);
144 writer
->state
= WRITER_STATE_INITIAL
;
148 /**************************************************************************
149 * WsCreateWriter [webservices.@]
151 HRESULT WINAPI
WsCreateWriter( const WS_XML_WRITER_PROPERTY
*properties
, ULONG count
,
152 WS_XML_WRITER
**handle
, WS_ERROR
*error
)
154 struct writer
*writer
;
155 ULONG i
, max_depth
= 32, max_attrs
= 128, trim_size
= 4096, max_size
= 65536, max_ns
= 32;
156 WS_CHARSET charset
= WS_CHARSET_UTF8
;
159 TRACE( "%p %u %p %p\n", properties
, count
, handle
, error
);
160 if (error
) FIXME( "ignoring error parameter\n" );
162 if (!handle
) return E_INVALIDARG
;
163 if (!(writer
= alloc_writer())) return E_OUTOFMEMORY
;
165 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_MAX_DEPTH
, &max_depth
, sizeof(max_depth
) );
166 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_MAX_ATTRIBUTES
, &max_attrs
, sizeof(max_attrs
) );
167 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_BUFFER_TRIM_SIZE
, &trim_size
, sizeof(trim_size
) );
168 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_CHARSET
, &charset
, sizeof(charset
) );
169 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_BUFFER_MAX_SIZE
, &max_size
, sizeof(max_size
) );
170 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_MAX_MIME_PARTS_BUFFER_SIZE
, &max_size
, sizeof(max_size
) );
171 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_MAX_NAMESPACES
, &max_ns
, sizeof(max_ns
) );
173 for (i
= 0; i
< count
; i
++)
175 hr
= prop_set( writer
->prop
, writer
->prop_count
, properties
[i
].id
, properties
[i
].value
,
176 properties
[i
].valueSize
);
179 free_writer( writer
);
184 hr
= prop_get( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_BUFFER_MAX_SIZE
,
185 &max_size
, sizeof(max_size
) );
188 free_writer( writer
);
192 hr
= WsCreateHeap( max_size
, 0, NULL
, 0, &writer
->output_heap
, NULL
);
195 free_writer( writer
);
199 hr
= write_init_state( writer
);
202 free_writer( writer
);
206 *handle
= (WS_XML_WRITER
*)writer
;
210 /**************************************************************************
211 * WsFreeWriter [webservices.@]
213 void WINAPI
WsFreeWriter( WS_XML_WRITER
*handle
)
215 struct writer
*writer
= (struct writer
*)handle
;
217 TRACE( "%p\n", handle
);
218 free_writer( writer
);
221 #define XML_BUFFER_INITIAL_ALLOCATED_SIZE 256
222 static struct xmlbuf
*alloc_xmlbuf( WS_HEAP
*heap
)
226 if (!(ret
= ws_alloc( heap
, sizeof(*ret
) ))) return NULL
;
227 if (!(ret
->ptr
= ws_alloc( heap
, XML_BUFFER_INITIAL_ALLOCATED_SIZE
)))
229 ws_free( heap
, ret
);
233 ret
->size_allocated
= XML_BUFFER_INITIAL_ALLOCATED_SIZE
;
238 static void free_xmlbuf( struct xmlbuf
*xmlbuf
)
241 ws_free( xmlbuf
->heap
, xmlbuf
->ptr
);
242 ws_free( xmlbuf
->heap
, xmlbuf
);
245 /**************************************************************************
246 * WsCreateXmlBuffer [webservices.@]
248 HRESULT WINAPI
WsCreateXmlBuffer( WS_HEAP
*heap
, const WS_XML_BUFFER_PROPERTY
*properties
,
249 ULONG count
, WS_XML_BUFFER
**handle
, WS_ERROR
*error
)
251 struct xmlbuf
*xmlbuf
;
253 if (!heap
|| !handle
) return E_INVALIDARG
;
254 if (count
) FIXME( "properties not implemented\n" );
256 if (!(xmlbuf
= alloc_xmlbuf( heap
))) return E_OUTOFMEMORY
;
258 *handle
= (WS_XML_BUFFER
*)xmlbuf
;
262 /**************************************************************************
263 * WsGetWriterProperty [webservices.@]
265 HRESULT WINAPI
WsGetWriterProperty( WS_XML_WRITER
*handle
, WS_XML_WRITER_PROPERTY_ID id
,
266 void *buf
, ULONG size
, WS_ERROR
*error
)
268 struct writer
*writer
= (struct writer
*)handle
;
270 TRACE( "%p %u %p %u %p\n", handle
, id
, buf
, size
, error
);
271 if (error
) FIXME( "ignoring error parameter\n" );
273 if (!writer
->output_type
) return WS_E_INVALID_OPERATION
;
277 case WS_XML_WRITER_PROPERTY_BYTES
:
279 WS_BYTES
*bytes
= buf
;
280 if (size
!= sizeof(*bytes
)) return E_INVALIDARG
;
281 bytes
->bytes
= writer
->output_buf
->ptr
;
282 bytes
->length
= writer
->output_buf
->size
;
286 return prop_get( writer
->prop
, writer
->prop_count
, id
, buf
, size
);
290 static void set_output_buffer( struct writer
*writer
, struct xmlbuf
*xmlbuf
)
292 /* free current buffer if it's ours */
293 if (writer
->output_buf
&& writer
->output_buf
->heap
== writer
->output_heap
)
295 free_xmlbuf( writer
->output_buf
);
297 writer
->output_buf
= xmlbuf
;
298 writer
->output_type
= WS_XML_WRITER_OUTPUT_TYPE_BUFFER
;
299 writer
->write_bufptr
= xmlbuf
->ptr
;
300 writer
->write_pos
= 0;
303 /**************************************************************************
304 * WsSetOutput [webservices.@]
306 HRESULT WINAPI
WsSetOutput( WS_XML_WRITER
*handle
, const WS_XML_WRITER_ENCODING
*encoding
,
307 const WS_XML_WRITER_OUTPUT
*output
, const WS_XML_WRITER_PROPERTY
*properties
,
308 ULONG count
, WS_ERROR
*error
)
310 struct writer
*writer
= (struct writer
*)handle
;
315 TRACE( "%p %p %p %p %u %p\n", handle
, encoding
, output
, properties
, count
, error
);
316 if (error
) FIXME( "ignoring error parameter\n" );
318 if (!writer
) return E_INVALIDARG
;
320 for (i
= 0; i
< count
; i
++)
322 hr
= prop_set( writer
->prop
, writer
->prop_count
, properties
[i
].id
, properties
[i
].value
,
323 properties
[i
].valueSize
);
324 if (hr
!= S_OK
) return hr
;
327 if ((hr
= write_init_state( writer
)) != S_OK
) return hr
;
329 switch (encoding
->encodingType
)
331 case WS_XML_WRITER_ENCODING_TYPE_TEXT
:
333 WS_XML_WRITER_TEXT_ENCODING
*text
= (WS_XML_WRITER_TEXT_ENCODING
*)encoding
;
334 if (text
->charSet
!= WS_CHARSET_UTF8
)
336 FIXME( "charset %u not supported\n", text
->charSet
);
342 FIXME( "encoding type %u not supported\n", encoding
->encodingType
);
345 switch (output
->outputType
)
347 case WS_XML_WRITER_OUTPUT_TYPE_BUFFER
:
349 struct xmlbuf
*xmlbuf
;
351 if (!(xmlbuf
= alloc_xmlbuf( writer
->output_heap
))) return E_OUTOFMEMORY
;
352 set_output_buffer( writer
, xmlbuf
);
356 FIXME( "output type %u not supported\n", output
->outputType
);
360 if (!(node
= alloc_node( WS_XML_NODE_TYPE_BOF
))) return E_OUTOFMEMORY
;
361 write_insert_bof( writer
, node
);
365 /**************************************************************************
366 * WsSetOutputToBuffer [webservices.@]
368 HRESULT WINAPI
WsSetOutputToBuffer( WS_XML_WRITER
*handle
, WS_XML_BUFFER
*buffer
,
369 const WS_XML_WRITER_PROPERTY
*properties
, ULONG count
,
372 struct writer
*writer
= (struct writer
*)handle
;
373 struct xmlbuf
*xmlbuf
= (struct xmlbuf
*)buffer
;
378 TRACE( "%p %p %p %u %p\n", handle
, buffer
, properties
, count
, error
);
379 if (error
) FIXME( "ignoring error parameter\n" );
381 if (!writer
|| !xmlbuf
) return E_INVALIDARG
;
383 for (i
= 0; i
< count
; i
++)
385 hr
= prop_set( writer
->prop
, writer
->prop_count
, properties
[i
].id
, properties
[i
].value
,
386 properties
[i
].valueSize
);
387 if (hr
!= S_OK
) return hr
;
390 if ((hr
= write_init_state( writer
)) != S_OK
) return hr
;
391 set_output_buffer( writer
, xmlbuf
);
393 if (!(node
= alloc_node( WS_XML_NODE_TYPE_BOF
))) return E_OUTOFMEMORY
;
394 write_insert_bof( writer
, node
);
398 static HRESULT
write_grow_buffer( struct writer
*writer
, ULONG size
)
400 struct xmlbuf
*buf
= writer
->output_buf
;
404 if (buf
->size_allocated
>= writer
->write_pos
+ size
)
406 buf
->size
= writer
->write_pos
+ size
;
409 new_size
= max( buf
->size_allocated
* 2, writer
->write_pos
+ size
);
410 if (!(tmp
= ws_realloc( buf
->heap
, buf
->ptr
, new_size
))) return E_OUTOFMEMORY
;
411 writer
->write_bufptr
= buf
->ptr
= tmp
;
412 buf
->size_allocated
= new_size
;
413 buf
->size
= writer
->write_pos
+ size
;
417 static inline void write_char( struct writer
*writer
, unsigned char ch
)
419 writer
->write_bufptr
[writer
->write_pos
++] = ch
;
422 static inline void write_bytes( struct writer
*writer
, const BYTE
*bytes
, ULONG len
)
424 memcpy( writer
->write_bufptr
+ writer
->write_pos
, bytes
, len
);
425 writer
->write_pos
+= len
;
428 static HRESULT
write_attribute( struct writer
*writer
, WS_XML_ATTRIBUTE
*attr
)
430 WS_XML_UTF8_TEXT
*text
= (WS_XML_UTF8_TEXT
*)attr
->value
;
431 unsigned char quote
= attr
->singleQuote
? '\'' : '"';
432 const WS_XML_STRING
*prefix
;
436 if (attr
->prefix
) prefix
= attr
->prefix
;
437 else prefix
= writer
->current
->hdr
.prefix
;
439 /* ' prefix:attr="value"' */
441 size
= attr
->localName
->length
+ 4 /* ' =""' */;
442 if (prefix
) size
+= prefix
->length
+ 1 /* ':' */;
443 if (text
) size
+= text
->value
.length
;
444 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
446 write_char( writer
, ' ' );
449 write_bytes( writer
, prefix
->bytes
, prefix
->length
);
450 write_char( writer
, ':' );
452 write_bytes( writer
, attr
->localName
->bytes
, attr
->localName
->length
);
453 write_char( writer
, '=' );
454 write_char( writer
, quote
);
455 if (text
) write_bytes( writer
, text
->value
.bytes
, text
->value
.length
);
456 write_char( writer
, quote
);
461 static inline BOOL
is_current_namespace( struct writer
*writer
, const WS_XML_STRING
*ns
)
463 return (WsXmlStringEquals( writer
->current_ns
, ns
, NULL
) == S_OK
);
466 /**************************************************************************
467 * WsGetPrefixFromNamespace [webservices.@]
469 HRESULT WINAPI
WsGetPrefixFromNamespace( WS_XML_WRITER
*handle
, const WS_XML_STRING
*ns
,
470 BOOL required
, const WS_XML_STRING
**prefix
,
473 struct writer
*writer
= (struct writer
*)handle
;
474 WS_XML_ELEMENT_NODE
*elem
;
477 TRACE( "%p %s %d %p %p\n", handle
, debugstr_xmlstr(ns
), required
, prefix
, error
);
478 if (error
) FIXME( "ignoring error parameter\n" );
480 if (!writer
|| !ns
|| !prefix
) return E_INVALIDARG
;
482 elem
= &writer
->current
->hdr
;
483 if (elem
->prefix
&& is_current_namespace( writer
, ns
))
485 *prefix
= elem
->prefix
;
490 if (required
) return WS_E_INVALID_FORMAT
;
497 static HRESULT
set_current_namespace( struct writer
*writer
, const WS_XML_STRING
*ns
)
500 if (!(str
= alloc_xml_string( ns
->bytes
, ns
->length
))) return E_OUTOFMEMORY
;
501 heap_free( writer
->current_ns
);
502 writer
->current_ns
= str
;
506 static HRESULT
write_namespace_attribute( struct writer
*writer
, WS_XML_ATTRIBUTE
*attr
)
508 unsigned char quote
= attr
->singleQuote
? '\'' : '"';
512 /* ' xmlns:prefix="namespace"' */
514 size
= attr
->ns
->length
+ 9 /* ' xmlns=""' */;
515 if (attr
->prefix
) size
+= attr
->prefix
->length
+ 1 /* ':' */;
516 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
518 write_bytes( writer
, (const BYTE
*)" xmlns", 6 );
521 write_char( writer
, ':' );
522 write_bytes( writer
, attr
->prefix
->bytes
, attr
->prefix
->length
);
524 write_char( writer
, '=' );
525 write_char( writer
, quote
);
526 write_bytes( writer
, attr
->ns
->bytes
, attr
->ns
->length
);
527 write_char( writer
, quote
);
532 static HRESULT
write_add_namespace_attribute( struct writer
*writer
, const WS_XML_STRING
*prefix
,
533 const WS_XML_STRING
*ns
, BOOL single
)
535 WS_XML_ATTRIBUTE
*attr
;
536 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
539 if (!(attr
= heap_alloc_zero( sizeof(*attr
) ))) return E_OUTOFMEMORY
;
541 attr
->singleQuote
= !!single
;
543 if (prefix
&& !(attr
->prefix
= alloc_xml_string( prefix
->bytes
, prefix
->length
)))
545 free_attribute( attr
);
546 return E_OUTOFMEMORY
;
548 if (!(attr
->ns
= alloc_xml_string( ns
->bytes
, ns
->length
)))
550 free_attribute( attr
);
551 return E_OUTOFMEMORY
;
553 if ((hr
= append_attribute( elem
, attr
)) != S_OK
)
555 free_attribute( attr
);
561 static BOOL
namespace_in_scope( const WS_XML_ELEMENT_NODE
*elem
, const WS_XML_STRING
*prefix
,
562 const WS_XML_STRING
*ns
)
565 const struct node
*node
;
567 for (node
= (const struct node
*)elem
; node
; node
= node
->parent
)
569 if (node_type( node
) != WS_XML_NODE_TYPE_ELEMENT
) break;
572 for (i
= 0; i
< elem
->attributeCount
; i
++)
574 if (!elem
->attributes
[i
]->isXmlNs
) continue;
575 if (WsXmlStringEquals( elem
->attributes
[i
]->prefix
, prefix
, NULL
) == S_OK
&&
576 WsXmlStringEquals( elem
->attributes
[i
]->ns
, ns
, NULL
) == S_OK
)
585 static HRESULT
write_set_element_namespace( struct writer
*writer
)
587 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
590 if (!elem
->ns
->length
|| is_current_namespace( writer
, elem
->ns
) ||
591 namespace_in_scope( elem
, elem
->prefix
, elem
->ns
)) return S_OK
;
593 if ((hr
= write_add_namespace_attribute( writer
, elem
->prefix
, elem
->ns
, FALSE
)) != S_OK
)
596 return set_current_namespace( writer
, elem
->ns
);
599 /**************************************************************************
600 * WsWriteEndAttribute [webservices.@]
602 HRESULT WINAPI
WsWriteEndAttribute( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
604 struct writer
*writer
= (struct writer
*)handle
;
606 TRACE( "%p %p\n", handle
, error
);
607 if (error
) FIXME( "ignoring error parameter\n" );
609 if (!writer
) return E_INVALIDARG
;
611 writer
->state
= WRITER_STATE_STARTELEMENT
;
615 static HRESULT
write_startelement( struct writer
*writer
)
617 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
621 /* '<prefix:localname prefix:attr="value"... xmlns:prefix="ns"'... */
623 size
= elem
->localName
->length
+ 1 /* '<' */;
624 if (elem
->prefix
) size
+= elem
->prefix
->length
+ 1 /* ':' */;
625 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
627 write_char( writer
, '<' );
630 write_bytes( writer
, elem
->prefix
->bytes
, elem
->prefix
->length
);
631 write_char( writer
, ':' );
633 write_bytes( writer
, elem
->localName
->bytes
, elem
->localName
->length
);
634 for (i
= 0; i
< elem
->attributeCount
; i
++)
636 if (elem
->attributes
[i
]->isXmlNs
) continue;
637 if ((hr
= write_attribute( writer
, elem
->attributes
[i
] )) != S_OK
) return hr
;
639 for (i
= 0; i
< elem
->attributeCount
; i
++)
641 if (!elem
->attributes
[i
]->isXmlNs
|| !elem
->attributes
[i
]->prefix
) continue;
642 if ((hr
= write_namespace_attribute( writer
, elem
->attributes
[i
] )) != S_OK
) return hr
;
644 for (i
= 0; i
< elem
->attributeCount
; i
++)
646 if (!elem
->attributes
[i
]->isXmlNs
|| elem
->attributes
[i
]->prefix
) continue;
647 if ((hr
= write_namespace_attribute( writer
, elem
->attributes
[i
] )) != S_OK
) return hr
;
652 static struct node
*write_find_startelement( struct writer
*writer
)
655 for (node
= writer
->current
; node
; node
= node
->parent
)
657 if (node_type( node
) == WS_XML_NODE_TYPE_ELEMENT
) return node
;
662 static inline BOOL
is_empty_element( const struct node
*node
)
664 const struct node
*head
= LIST_ENTRY( list_head( &node
->children
), struct node
, entry
);
665 return node_type( head
) == WS_XML_NODE_TYPE_END_ELEMENT
;
668 static HRESULT
write_endelement( struct writer
*writer
, const WS_XML_ELEMENT_NODE
*elem
)
675 if (elem
->isEmpty
&& writer
->state
!= WRITER_STATE_ENDSTARTELEMENT
)
677 if ((hr
= write_grow_buffer( writer
, 2 )) != S_OK
) return hr
;
678 write_char( writer
, '/' );
679 write_char( writer
, '>' );
683 /* '</prefix:localname>' */
685 size
= elem
->localName
->length
+ 3 /* '</>' */;
686 if (elem
->prefix
) size
+= elem
->prefix
->length
+ 1 /* ':' */;
687 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
689 write_char( writer
, '<' );
690 write_char( writer
, '/' );
693 write_bytes( writer
, elem
->prefix
->bytes
, elem
->prefix
->length
);
694 write_char( writer
, ':' );
696 write_bytes( writer
, elem
->localName
->bytes
, elem
->localName
->length
);
697 write_char( writer
, '>' );
701 static HRESULT
write_close_element( struct writer
*writer
, struct node
*node
)
703 WS_XML_ELEMENT_NODE
*elem
= &node
->hdr
;
704 elem
->isEmpty
= is_empty_element( node
);
705 return write_endelement( writer
, elem
);
708 static HRESULT
write_endelement_node( struct writer
*writer
)
713 if (!(node
= write_find_startelement( writer
))) return WS_E_INVALID_FORMAT
;
714 if (writer
->state
== WRITER_STATE_STARTELEMENT
)
716 if ((hr
= write_set_element_namespace( writer
)) != S_OK
) return hr
;
717 if ((hr
= write_startelement( writer
)) != S_OK
) return hr
;
719 if ((hr
= write_close_element( writer
, node
)) != S_OK
) return hr
;
720 writer
->current
= node
->parent
;
721 writer
->state
= WRITER_STATE_ENDELEMENT
;
725 /**************************************************************************
726 * WsWriteEndElement [webservices.@]
728 HRESULT WINAPI
WsWriteEndElement( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
730 struct writer
*writer
= (struct writer
*)handle
;
732 TRACE( "%p %p\n", handle
, error
);
733 if (error
) FIXME( "ignoring error parameter\n" );
735 if (!writer
) return E_INVALIDARG
;
736 return write_endelement_node( writer
);
739 static HRESULT
write_endstartelement( struct writer
*writer
)
742 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
743 write_char( writer
, '>' );
747 /**************************************************************************
748 * WsWriteEndStartElement [webservices.@]
750 HRESULT WINAPI
WsWriteEndStartElement( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
752 struct writer
*writer
= (struct writer
*)handle
;
755 TRACE( "%p %p\n", handle
, error
);
756 if (error
) FIXME( "ignoring error parameter\n" );
758 if (!writer
) return E_INVALIDARG
;
759 if (writer
->state
!= WRITER_STATE_STARTELEMENT
) return WS_E_INVALID_OPERATION
;
761 if ((hr
= write_set_element_namespace( writer
)) != S_OK
) return hr
;
762 if ((hr
= write_startelement( writer
)) != S_OK
) return hr
;
763 if ((hr
= write_endstartelement( writer
)) != S_OK
) return hr
;
765 writer
->state
= WRITER_STATE_ENDSTARTELEMENT
;
769 static HRESULT
write_add_attribute( struct writer
*writer
, const WS_XML_STRING
*prefix
,
770 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
773 WS_XML_ATTRIBUTE
*attr
;
774 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
777 if (!(attr
= heap_alloc_zero( sizeof(*attr
) ))) return E_OUTOFMEMORY
;
779 if (!prefix
) prefix
= elem
->prefix
;
781 attr
->singleQuote
= !!single
;
782 if (prefix
&& !(attr
->prefix
= alloc_xml_string( prefix
->bytes
, prefix
->length
)))
784 free_attribute( attr
);
785 return E_OUTOFMEMORY
;
787 if (!(attr
->localName
= alloc_xml_string( localname
->bytes
, localname
->length
)))
789 free_attribute( attr
);
790 return E_OUTOFMEMORY
;
792 if (!(attr
->ns
= alloc_xml_string( ns
->bytes
, ns
->length
)))
794 free_attribute( attr
);
795 return E_OUTOFMEMORY
;
797 if ((hr
= append_attribute( elem
, attr
)) != S_OK
)
799 free_attribute( attr
);
805 /**************************************************************************
806 * WsWriteStartAttribute [webservices.@]
808 HRESULT WINAPI
WsWriteStartAttribute( WS_XML_WRITER
*handle
, const WS_XML_STRING
*prefix
,
809 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
810 BOOL single
, WS_ERROR
*error
)
812 struct writer
*writer
= (struct writer
*)handle
;
815 TRACE( "%p %s %s %s %d %p\n", handle
, debugstr_xmlstr(prefix
), debugstr_xmlstr(localname
),
816 debugstr_xmlstr(ns
), single
, error
);
817 if (error
) FIXME( "ignoring error parameter\n" );
819 if (!writer
|| !localname
|| !ns
) return E_INVALIDARG
;
821 if (writer
->state
!= WRITER_STATE_STARTELEMENT
) return WS_E_INVALID_OPERATION
;
823 if ((hr
= write_add_attribute( writer
, prefix
, localname
, ns
, single
)) != S_OK
) return hr
;
824 writer
->state
= WRITER_STATE_STARTATTRIBUTE
;
828 /* flush current start element if necessary */
829 static HRESULT
write_flush( struct writer
*writer
)
831 if (writer
->state
== WRITER_STATE_STARTELEMENT
)
834 if ((hr
= write_set_element_namespace( writer
)) != S_OK
) return hr
;
835 if ((hr
= write_startelement( writer
)) != S_OK
) return hr
;
836 if ((hr
= write_endstartelement( writer
)) != S_OK
) return hr
;
837 writer
->state
= WRITER_STATE_ENDSTARTELEMENT
;
842 static HRESULT
write_add_cdata_node( struct writer
*writer
)
844 struct node
*node
, *parent
;
845 if (!(parent
= find_parent( writer
->current
))) return WS_E_INVALID_FORMAT
;
846 if (!(node
= alloc_node( WS_XML_NODE_TYPE_CDATA
))) return E_OUTOFMEMORY
;
847 write_insert_node( writer
, parent
, node
);
851 static HRESULT
write_add_endcdata_node( struct writer
*writer
)
854 if (!(node
= alloc_node( WS_XML_NODE_TYPE_END_CDATA
))) return E_OUTOFMEMORY
;
855 node
->parent
= writer
->current
;
856 list_add_tail( &node
->parent
->children
, &node
->entry
);
860 static HRESULT
write_cdata( struct writer
*writer
)
863 if ((hr
= write_grow_buffer( writer
, 9 )) != S_OK
) return hr
;
864 write_bytes( writer
, (const BYTE
*)"<![CDATA[", 9 );
868 static HRESULT
write_cdata_node( struct writer
*writer
)
871 if ((hr
= write_flush( writer
)) != S_OK
) return hr
;
872 if ((hr
= write_add_cdata_node( writer
)) != S_OK
) return hr
;
873 if ((hr
= write_add_endcdata_node( writer
)) != S_OK
) return hr
;
874 if ((hr
= write_cdata( writer
)) != S_OK
) return hr
;
875 writer
->state
= WRITER_STATE_STARTCDATA
;
879 /**************************************************************************
880 * WsWriteStartCData [webservices.@]
882 HRESULT WINAPI
WsWriteStartCData( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
884 struct writer
*writer
= (struct writer
*)handle
;
886 TRACE( "%p %p\n", handle
, error
);
887 if (error
) FIXME( "ignoring error parameter\n" );
889 if (!writer
) return E_INVALIDARG
;
890 return write_cdata_node( writer
);
893 static HRESULT
write_endcdata( struct writer
*writer
)
896 if ((hr
= write_grow_buffer( writer
, 3 )) != S_OK
) return hr
;
897 write_bytes( writer
, (const BYTE
*)"]]>", 3 );
901 static HRESULT
write_endcdata_node( struct writer
*writer
)
904 if ((hr
= write_endcdata( writer
)) != S_OK
) return hr
;
905 writer
->current
= writer
->current
->parent
;
906 writer
->state
= WRITER_STATE_ENDCDATA
;
910 /**************************************************************************
911 * WsWriteEndCData [webservices.@]
913 HRESULT WINAPI
WsWriteEndCData( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
915 struct writer
*writer
= (struct writer
*)handle
;
917 TRACE( "%p %p\n", handle
, error
);
918 if (error
) FIXME( "ignoring error parameter\n" );
920 if (!writer
) return E_INVALIDARG
;
921 if (writer
->state
!= WRITER_STATE_TEXT
) return WS_E_INVALID_OPERATION
;
923 return write_endcdata_node( writer
);
926 static HRESULT
write_add_element_node( struct writer
*writer
, const WS_XML_STRING
*prefix
,
927 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
)
929 struct node
*node
, *parent
;
930 WS_XML_ELEMENT_NODE
*elem
;
932 if (!(parent
= find_parent( writer
->current
))) return WS_E_INVALID_FORMAT
;
934 if (!prefix
&& node_type( parent
) == WS_XML_NODE_TYPE_ELEMENT
)
937 if (WsXmlStringEquals( ns
, elem
->ns
, NULL
) == S_OK
) prefix
= elem
->prefix
;
940 if (!(node
= alloc_node( WS_XML_NODE_TYPE_ELEMENT
))) return E_OUTOFMEMORY
;
943 if (prefix
&& !(elem
->prefix
= alloc_xml_string( prefix
->bytes
, prefix
->length
)))
946 return E_OUTOFMEMORY
;
948 if (!(elem
->localName
= alloc_xml_string( localname
->bytes
, localname
->length
)))
951 return E_OUTOFMEMORY
;
953 if (!(elem
->ns
= alloc_xml_string( ns
->bytes
, ns
->length
)))
956 return E_OUTOFMEMORY
;
958 write_insert_node( writer
, parent
, node
);
962 static HRESULT
write_add_endelement_node( struct writer
*writer
, struct node
*parent
)
965 if (!(node
= alloc_node( WS_XML_NODE_TYPE_END_ELEMENT
))) return E_OUTOFMEMORY
;
966 node
->parent
= parent
;
967 list_add_tail( &parent
->children
, &node
->entry
);
971 static HRESULT
write_element_node( struct writer
*writer
, const WS_XML_STRING
*prefix
,
972 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
)
975 if ((hr
= write_flush( writer
)) != S_OK
) return hr
;
976 if ((hr
= write_add_element_node( writer
, prefix
, localname
, ns
)) != S_OK
) return hr
;
977 if ((hr
= write_add_endelement_node( writer
, writer
->current
)) != S_OK
) return hr
;
978 writer
->state
= WRITER_STATE_STARTELEMENT
;
982 /**************************************************************************
983 * WsWriteStartElement [webservices.@]
985 HRESULT WINAPI
WsWriteStartElement( WS_XML_WRITER
*handle
, const WS_XML_STRING
*prefix
,
986 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
989 struct writer
*writer
= (struct writer
*)handle
;
991 TRACE( "%p %s %s %s %p\n", handle
, debugstr_xmlstr(prefix
), debugstr_xmlstr(localname
),
992 debugstr_xmlstr(ns
), error
);
993 if (error
) FIXME( "ignoring error parameter\n" );
995 if (!writer
|| !localname
|| !ns
) return E_INVALIDARG
;
996 return write_element_node( writer
, prefix
, localname
, ns
);
999 static ULONG
format_bool( const BOOL
*ptr
, unsigned char *buf
)
1001 static const unsigned char bool_true
[] = {'t','r','u','e'}, bool_false
[] = {'f','a','l','s','e'};
1004 memcpy( buf
, bool_true
, sizeof(bool_true
) );
1005 return sizeof(bool_true
);
1007 memcpy( buf
, bool_false
, sizeof(bool_false
) );
1008 return sizeof(bool_false
);
1011 static ULONG
format_int8( const INT8
*ptr
, unsigned char *buf
)
1013 return wsprintfA( (char *)buf
, "%d", *ptr
);
1016 static ULONG
format_int16( const INT16
*ptr
, unsigned char *buf
)
1018 return wsprintfA( (char *)buf
, "%d", *ptr
);
1021 static ULONG
format_int32( const INT32
*ptr
, unsigned char *buf
)
1023 return wsprintfA( (char *)buf
, "%d", *ptr
);
1026 static ULONG
format_int64( const INT64
*ptr
, unsigned char *buf
)
1028 return wsprintfA( (char *)buf
, "%I64d", *ptr
);
1031 static ULONG
format_uint8( const UINT8
*ptr
, unsigned char *buf
)
1033 return wsprintfA( (char *)buf
, "%u", *ptr
);
1036 static ULONG
format_uint16( const UINT16
*ptr
, unsigned char *buf
)
1038 return wsprintfA( (char *)buf
, "%u", *ptr
);
1041 static ULONG
format_uint32( const UINT32
*ptr
, unsigned char *buf
)
1043 return wsprintfA( (char *)buf
, "%u", *ptr
);
1046 static ULONG
format_uint64( const UINT64
*ptr
, unsigned char *buf
)
1048 return wsprintfA( (char *)buf
, "%I64u", *ptr
);
1051 static ULONG
format_double( const double *ptr
, unsigned char *buf
)
1054 static const long double precision
= 0.0000000000000001;
1055 unsigned char *p
= buf
;
1056 long double val
= *ptr
;
1057 int neg
, mag
, mag2
, use_exp
;
1061 memcpy( buf
, "NaN", 3 );
1068 memcpy( buf
, "-INF", 4 );
1071 memcpy( buf
, "INF", 3 );
1080 if ((neg
= val
< 0))
1086 mag
= log10l( val
);
1087 use_exp
= (mag
>= 15 || (neg
&& mag
>= 1) || mag
<= -1);
1090 if (mag
< 0) mag
-= 1;
1091 val
= val
/ powl( 10.0, mag
);
1095 else if (mag
< 1) mag
= 0;
1097 while (val
> precision
|| mag
>= 0)
1099 long double weight
= powl( 10.0, mag
);
1100 if (weight
> 0 && !isinf( weight
))
1102 int digit
= floorl( val
/ weight
);
1103 val
-= digit
* weight
;
1104 *(p
++) = '0' + digit
;
1106 if (!mag
&& val
> precision
) *(p
++) = '.';
1114 if (mag2
> 0) *(p
++) = '+';
1123 *(p
++) = '0' + mag2
% 10;
1127 for (i
= -mag
, j
= -1; i
< j
; i
++, j
--)
1137 FIXME( "powl not found at build time\n" );
1142 static ULONG
format_guid( const GUID
*ptr
, unsigned char *buf
)
1144 static const char fmt
[] = "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x";
1145 return sprintf( (char *)buf
, fmt
, ptr
->Data1
, ptr
->Data2
, ptr
->Data3
,
1146 ptr
->Data4
[0], ptr
->Data4
[1], ptr
->Data4
[2], ptr
->Data4
[3],
1147 ptr
->Data4
[4], ptr
->Data4
[5], ptr
->Data4
[6], ptr
->Data4
[7] );
1150 static ULONG
format_urn( const GUID
*ptr
, unsigned char *buf
)
1152 static const char fmt
[] = "urn:uuid:%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x";
1153 return sprintf( (char *)buf
, fmt
, ptr
->Data1
, ptr
->Data2
, ptr
->Data3
,
1154 ptr
->Data4
[0], ptr
->Data4
[1], ptr
->Data4
[2], ptr
->Data4
[3],
1155 ptr
->Data4
[4], ptr
->Data4
[5], ptr
->Data4
[6], ptr
->Data4
[7] );
1158 static HRESULT
text_to_utf8text( const WS_XML_TEXT
*text
, WS_XML_UTF8_TEXT
**ret
)
1160 switch (text
->textType
)
1162 case WS_XML_TEXT_TYPE_UTF8
:
1164 const WS_XML_UTF8_TEXT
*src
= (const WS_XML_UTF8_TEXT
*)text
;
1165 if (!(*ret
= alloc_utf8_text( src
->value
.bytes
, src
->value
.length
))) return E_OUTOFMEMORY
;
1168 case WS_XML_TEXT_TYPE_UTF16
:
1170 const WS_XML_UTF16_TEXT
*src
= (const WS_XML_UTF16_TEXT
*)text
;
1171 const WCHAR
*str
= (const WCHAR
*)src
->bytes
;
1172 ULONG len
= src
->byteCount
/ sizeof(WCHAR
), len_utf8
;
1174 if (src
->byteCount
% sizeof(WCHAR
)) return E_INVALIDARG
;
1175 len_utf8
= WideCharToMultiByte( CP_UTF8
, 0, str
, len
, NULL
, 0, NULL
, NULL
);
1176 if (!(*ret
= alloc_utf8_text( NULL
, len_utf8
))) return E_OUTOFMEMORY
;
1177 WideCharToMultiByte( CP_UTF8
, 0, str
, len
, (char *)(*ret
)->value
.bytes
, (*ret
)->value
.length
, NULL
, NULL
);
1180 case WS_XML_TEXT_TYPE_BOOL
:
1182 const WS_XML_BOOL_TEXT
*bool_text
= (const WS_XML_BOOL_TEXT
*)text
;
1183 if (!(*ret
= alloc_utf8_text( NULL
, 5 ))) return E_OUTOFMEMORY
;
1184 (*ret
)->value
.length
= format_bool( &bool_text
->value
, (*ret
)->value
.bytes
);
1187 case WS_XML_TEXT_TYPE_INT32
:
1189 const WS_XML_INT32_TEXT
*int32_text
= (const WS_XML_INT32_TEXT
*)text
;
1190 unsigned char buf
[12]; /* "-2147483648" */
1191 ULONG len
= format_int32( &int32_text
->value
, buf
);
1192 if (!(*ret
= alloc_utf8_text( buf
, len
))) return E_OUTOFMEMORY
;
1195 case WS_XML_TEXT_TYPE_INT64
:
1197 const WS_XML_INT64_TEXT
*int64_text
= (const WS_XML_INT64_TEXT
*)text
;
1198 unsigned char buf
[21]; /* "-9223372036854775808" */
1199 ULONG len
= format_int64( &int64_text
->value
, buf
);
1200 if (!(*ret
= alloc_utf8_text( buf
, len
))) return E_OUTOFMEMORY
;
1203 case WS_XML_TEXT_TYPE_UINT64
:
1205 const WS_XML_UINT64_TEXT
*uint64_text
= (const WS_XML_UINT64_TEXT
*)text
;
1206 unsigned char buf
[21]; /* "18446744073709551615" */
1207 ULONG len
= format_uint64( &uint64_text
->value
, buf
);
1208 if (!(*ret
= alloc_utf8_text( buf
, len
))) return E_OUTOFMEMORY
;
1211 case WS_XML_TEXT_TYPE_DOUBLE
:
1213 const WS_XML_DOUBLE_TEXT
*double_text
= (const WS_XML_DOUBLE_TEXT
*)text
;
1214 unsigned char buf
[24]; /* "-1.1111111111111111E-308" */
1215 unsigned short fpword
;
1218 if (!set_fp_rounding( &fpword
)) return E_NOTIMPL
;
1219 len
= format_double( &double_text
->value
, buf
);
1220 restore_fp_rounding( fpword
);
1221 if (!len
) return E_NOTIMPL
;
1222 if (!(*ret
= alloc_utf8_text( buf
, len
))) return E_OUTOFMEMORY
;
1225 case WS_XML_TEXT_TYPE_GUID
:
1227 const WS_XML_GUID_TEXT
*id
= (const WS_XML_GUID_TEXT
*)text
;
1228 if (!(*ret
= alloc_utf8_text( NULL
, 37 ))) return E_OUTOFMEMORY
;
1229 (*ret
)->value
.length
= format_guid( &id
->value
, (*ret
)->value
.bytes
);
1232 case WS_XML_TEXT_TYPE_UNIQUE_ID
:
1234 const WS_XML_UNIQUE_ID_TEXT
*id
= (const WS_XML_UNIQUE_ID_TEXT
*)text
;
1235 if (!(*ret
= alloc_utf8_text( NULL
, 46 ))) return E_OUTOFMEMORY
;
1236 (*ret
)->value
.length
= format_urn( &id
->value
, (*ret
)->value
.bytes
);
1240 FIXME( "unhandled text type %u\n", text
->textType
);
1245 static HRESULT
write_set_attribute_value( struct writer
*writer
, const WS_XML_TEXT
*value
)
1247 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
1248 WS_XML_UTF8_TEXT
*utf8
;
1251 if ((hr
= text_to_utf8text( value
, &utf8
)) != S_OK
) return hr
;
1252 elem
->attributes
[elem
->attributeCount
- 1]->value
= &utf8
->text
;
1256 static HRESULT
write_add_text_node( struct writer
*writer
, const WS_XML_TEXT
*value
)
1259 WS_XML_TEXT_NODE
*text
;
1260 WS_XML_UTF8_TEXT
*utf8
;
1263 if (node_type( writer
->current
) != WS_XML_NODE_TYPE_ELEMENT
&&
1264 node_type( writer
->current
) != WS_XML_NODE_TYPE_BOF
&&
1265 node_type( writer
->current
) != WS_XML_NODE_TYPE_CDATA
) return WS_E_INVALID_FORMAT
;
1267 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return E_OUTOFMEMORY
;
1268 if ((hr
= text_to_utf8text( value
, &utf8
)) != S_OK
)
1273 text
= (WS_XML_TEXT_NODE
*)node
;
1274 text
->text
= &utf8
->text
;
1276 write_insert_node( writer
, writer
->current
, node
);
1280 static HRESULT
write_text( struct writer
*writer
)
1282 const WS_XML_TEXT_NODE
*text
= (const WS_XML_TEXT_NODE
*)writer
->current
;
1283 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)text
->text
;
1286 if ((hr
= write_grow_buffer( writer
, utf8
->value
.length
)) != S_OK
) return hr
;
1287 write_bytes( writer
, utf8
->value
.bytes
, utf8
->value
.length
);
1291 static HRESULT
write_text_node( struct writer
*writer
, const WS_XML_TEXT
*text
)
1294 if ((hr
= write_flush( writer
)) != S_OK
) return hr
;
1295 if ((hr
= write_add_text_node( writer
, text
)) != S_OK
) return hr
;
1296 if ((hr
= write_text( writer
)) != S_OK
) return hr
;
1297 writer
->state
= WRITER_STATE_TEXT
;
1301 /**************************************************************************
1302 * WsWriteText [webservices.@]
1304 HRESULT WINAPI
WsWriteText( WS_XML_WRITER
*handle
, const WS_XML_TEXT
*text
, WS_ERROR
*error
)
1306 struct writer
*writer
= (struct writer
*)handle
;
1308 TRACE( "%p %p %p\n", handle
, text
, error
);
1310 if (!writer
|| !text
) return E_INVALIDARG
;
1312 if (writer
->state
== WRITER_STATE_STARTATTRIBUTE
) return write_set_attribute_value( writer
, text
);
1313 return write_text_node( writer
, text
);
1316 static HRESULT
write_type_text( struct writer
*writer
, WS_TYPE_MAPPING mapping
, const WS_XML_TEXT
*text
)
1320 case WS_ELEMENT_TYPE_MAPPING
:
1321 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
1322 return write_text_node( writer
, text
);
1324 case WS_ATTRIBUTE_TYPE_MAPPING
:
1325 return write_set_attribute_value( writer
, text
);
1327 case WS_ANY_ELEMENT_TYPE_MAPPING
:
1328 switch (writer
->state
)
1330 case WRITER_STATE_STARTATTRIBUTE
:
1331 return write_set_attribute_value( writer
, text
);
1333 case WRITER_STATE_STARTELEMENT
:
1334 return write_text_node( writer
, text
);
1337 FIXME( "writer state %u not handled\n", writer
->state
);
1342 FIXME( "mapping %u not implemented\n", mapping
);
1347 static HRESULT
write_type_bool( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1348 const WS_BOOL_DESCRIPTION
*desc
, const BOOL
*value
)
1350 WS_XML_UTF8_TEXT utf8
;
1351 unsigned char buf
[6]; /* "false" */
1355 FIXME( "description not supported\n" );
1358 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
1359 utf8
.value
.bytes
= buf
;
1360 utf8
.value
.length
= format_bool( value
, buf
);
1361 return write_type_text( writer
, mapping
, &utf8
.text
);
1364 static HRESULT
write_type_int8( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1365 const WS_INT8_DESCRIPTION
*desc
, const INT8
*value
)
1367 WS_XML_UTF8_TEXT utf8
;
1368 unsigned char buf
[5]; /* "-128" */
1372 FIXME( "description not supported\n" );
1375 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
1376 utf8
.value
.bytes
= buf
;
1377 utf8
.value
.length
= format_int8( value
, buf
);
1378 return write_type_text( writer
, mapping
, &utf8
.text
);
1381 static HRESULT
write_type_int16( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1382 const WS_INT16_DESCRIPTION
*desc
, const INT16
*value
)
1384 WS_XML_UTF8_TEXT utf8
;
1385 unsigned char buf
[7]; /* "-32768" */
1389 FIXME( "description not supported\n" );
1392 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
1393 utf8
.value
.bytes
= buf
;
1394 utf8
.value
.length
= format_int16( value
, buf
);
1395 return write_type_text( writer
, mapping
, &utf8
.text
);
1398 static HRESULT
write_type_int32( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1399 const WS_INT32_DESCRIPTION
*desc
, const INT32
*value
)
1401 WS_XML_UTF8_TEXT utf8
;
1402 unsigned char buf
[12]; /* "-2147483648" */
1406 FIXME( "description not supported\n" );
1409 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
1410 utf8
.value
.bytes
= buf
;
1411 utf8
.value
.length
= format_int32( value
, buf
);
1412 return write_type_text( writer
, mapping
, &utf8
.text
);
1415 static HRESULT
write_type_int64( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1416 const WS_INT64_DESCRIPTION
*desc
, const INT64
*value
)
1418 WS_XML_UTF8_TEXT utf8
;
1419 unsigned char buf
[21]; /* "-9223372036854775808" */
1423 FIXME( "description not supported\n" );
1426 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
1427 utf8
.value
.bytes
= buf
;
1428 utf8
.value
.length
= format_int64( value
, buf
);
1429 return write_type_text( writer
, mapping
, &utf8
.text
);
1432 static HRESULT
write_type_uint8( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1433 const WS_UINT8_DESCRIPTION
*desc
, const UINT8
*value
)
1435 WS_XML_UTF8_TEXT utf8
;
1436 unsigned char buf
[4]; /* "255" */
1440 FIXME( "description not supported\n" );
1443 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
1444 utf8
.value
.bytes
= buf
;
1445 utf8
.value
.length
= format_uint8( value
, buf
);
1446 return write_type_text( writer
, mapping
, &utf8
.text
);
1449 static HRESULT
write_type_uint16( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1450 const WS_UINT16_DESCRIPTION
*desc
, const UINT16
*value
)
1452 WS_XML_UTF8_TEXT utf8
;
1453 unsigned char buf
[6]; /* "65535" */
1457 FIXME( "description not supported\n" );
1460 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
1461 utf8
.value
.bytes
= buf
;
1462 utf8
.value
.length
= format_uint16( value
, buf
);
1463 return write_type_text( writer
, mapping
, &utf8
.text
);
1466 static HRESULT
write_type_uint32( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1467 const WS_UINT32_DESCRIPTION
*desc
, const UINT32
*value
)
1469 WS_XML_UTF8_TEXT utf8
;
1470 unsigned char buf
[11]; /* "4294967295" */
1474 FIXME( "description not supported\n" );
1477 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
1478 utf8
.value
.bytes
= buf
;
1479 utf8
.value
.length
= format_uint32( value
, buf
);
1480 return write_type_text( writer
, mapping
, &utf8
.text
);
1483 static HRESULT
write_type_uint64( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1484 const WS_UINT64_DESCRIPTION
*desc
, const UINT64
*value
)
1486 WS_XML_UTF8_TEXT utf8
;
1487 unsigned char buf
[21]; /* "18446744073709551615" */
1491 FIXME( "description not supported\n" );
1494 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
1495 utf8
.value
.bytes
= buf
;
1496 utf8
.value
.length
= format_uint64( value
, buf
);
1497 return write_type_text( writer
, mapping
, &utf8
.text
);
1500 static HRESULT
write_type_wsz( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1501 const WS_WSZ_DESCRIPTION
*desc
, const WCHAR
*value
)
1503 WS_XML_UTF16_TEXT utf16
;
1507 FIXME( "description not supported\n" );
1510 utf16
.text
.textType
= WS_XML_TEXT_TYPE_UTF16
;
1511 utf16
.bytes
= (BYTE
*)value
;
1512 utf16
.byteCount
= strlenW( value
) * sizeof(WCHAR
);
1513 return write_type_text( writer
, mapping
, &utf16
.text
);
1516 static HRESULT
write_type( struct writer
*, WS_TYPE_MAPPING
, WS_TYPE
, const void *, WS_WRITE_OPTION
,
1517 const void *, ULONG
);
1519 static HRESULT
write_type_struct_field( struct writer
*writer
, const WS_FIELD_DESCRIPTION
*desc
,
1520 const void *value
, ULONG size
)
1523 WS_TYPE_MAPPING mapping
;
1524 WS_WRITE_OPTION option
;
1526 if (!desc
->options
|| desc
->options
== WS_FIELD_OPTIONAL
) option
= 0;
1527 else if (desc
->options
== WS_FIELD_POINTER
) option
= WS_WRITE_REQUIRED_POINTER
;
1530 FIXME( "options 0x%x not supported\n", desc
->options
);
1534 switch (desc
->mapping
)
1536 case WS_ATTRIBUTE_FIELD_MAPPING
:
1537 if (!desc
->localName
|| !desc
->ns
) return E_INVALIDARG
;
1538 if ((hr
= write_add_attribute( writer
, NULL
, desc
->localName
, desc
->ns
, FALSE
)) != S_OK
)
1540 writer
->state
= WRITER_STATE_STARTATTRIBUTE
;
1542 mapping
= WS_ATTRIBUTE_TYPE_MAPPING
;
1545 case WS_ELEMENT_FIELD_MAPPING
:
1546 if ((hr
= write_element_node( writer
, NULL
, desc
->localName
, desc
->ns
)) != S_OK
) return hr
;
1547 mapping
= WS_ELEMENT_TYPE_MAPPING
;
1550 case WS_TEXT_FIELD_MAPPING
:
1551 switch (writer
->state
)
1553 case WRITER_STATE_STARTELEMENT
:
1554 mapping
= WS_ELEMENT_CONTENT_TYPE_MAPPING
;
1557 case WRITER_STATE_STARTATTRIBUTE
:
1558 mapping
= WS_ATTRIBUTE_TYPE_MAPPING
;
1562 FIXME( "unhandled writer state %u\n", writer
->state
);
1568 FIXME( "field mapping %u not supported\n", desc
->mapping
);
1572 if ((hr
= write_type( writer
, mapping
, desc
->type
, desc
->typeDescription
, option
, value
, size
)) != S_OK
)
1577 case WS_ATTRIBUTE_TYPE_MAPPING
:
1578 writer
->state
= WRITER_STATE_STARTELEMENT
;
1581 case WS_ELEMENT_TYPE_MAPPING
:
1582 if ((hr
= write_endelement_node( writer
)) != S_OK
) return hr
;
1591 static ULONG
get_field_size( const WS_STRUCT_DESCRIPTION
*desc
, ULONG index
)
1593 if (index
< desc
->fieldCount
- 1) return desc
->fields
[index
+ 1]->offset
- desc
->fields
[index
]->offset
;
1594 return desc
->size
- desc
->fields
[index
]->offset
;
1597 static HRESULT
write_type_struct( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1598 const WS_STRUCT_DESCRIPTION
*desc
, const void *value
)
1604 if (desc
->structOptions
)
1606 FIXME( "struct options 0x%x not supported\n", desc
->structOptions
);
1610 for (i
= 0; i
< desc
->fieldCount
; i
++)
1612 ptr
= (const char *)value
+ desc
->fields
[i
]->offset
;
1613 size
= get_field_size( desc
, i
);
1614 if ((hr
= write_type_struct_field( writer
, desc
->fields
[i
], ptr
, size
)) != S_OK
)
1621 static HRESULT
get_value_ptr( WS_WRITE_OPTION option
, const void *value
, ULONG size
, const void **ptr
)
1625 case WS_WRITE_REQUIRED_VALUE
:
1626 if (!value
|| !size
) return E_INVALIDARG
;
1630 case WS_WRITE_REQUIRED_POINTER
:
1631 if (size
!= sizeof(const void *) || !(*ptr
= *(const void **)value
)) return E_INVALIDARG
;
1635 FIXME( "option %08x not supported\n", option
);
1640 static HRESULT
write_type( struct writer
*writer
, WS_TYPE_MAPPING mapping
, WS_TYPE type
,
1641 const void *desc
, WS_WRITE_OPTION option
, const void *value
,
1648 case WS_STRUCT_TYPE
:
1652 if (!desc
|| option
== WS_WRITE_REQUIRED_VALUE
) return E_INVALIDARG
;
1654 if (!option
) option
= WS_WRITE_REQUIRED_POINTER
;
1655 if ((hr
= get_value_ptr( option
, value
, size
, (const void **)&ptr
)) != S_OK
) return hr
;
1656 return write_type_struct( writer
, mapping
, desc
, ptr
);
1661 if (!option
) option
= WS_WRITE_REQUIRED_VALUE
;
1662 if ((hr
= get_value_ptr( option
, value
, size
, (const void **)&ptr
)) != S_OK
) return hr
;
1663 return write_type_bool( writer
, mapping
, desc
, ptr
);
1667 const INT8
*ptr
= value
;
1668 if (!option
) option
= WS_WRITE_REQUIRED_VALUE
;
1669 if ((hr
= get_value_ptr( option
, value
, size
, (const void **)&ptr
)) != S_OK
) return hr
;
1670 return write_type_int8( writer
, mapping
, desc
, ptr
);
1674 const INT16
*ptr
= value
;
1675 if (!option
) option
= WS_WRITE_REQUIRED_VALUE
;
1676 if ((hr
= get_value_ptr( option
, value
, size
, (const void **)&ptr
)) != S_OK
) return hr
;
1677 return write_type_int16( writer
, mapping
, desc
, ptr
);
1682 if (!option
) option
= WS_WRITE_REQUIRED_VALUE
;
1683 if ((hr
= get_value_ptr( option
, value
, size
, (const void **)&ptr
)) != S_OK
) return hr
;
1684 return write_type_int32( writer
, mapping
, desc
, ptr
);
1688 const INT64
*ptr
= value
;
1689 if (!option
) option
= WS_WRITE_REQUIRED_VALUE
;
1690 if ((hr
= get_value_ptr( option
, value
, size
, (const void **)&ptr
)) != S_OK
) return hr
;
1691 return write_type_int64( writer
, mapping
, desc
, ptr
);
1695 const UINT8
*ptr
= value
;
1696 if (!option
) option
= WS_WRITE_REQUIRED_VALUE
;
1697 if ((hr
= get_value_ptr( option
, value
, size
, (const void **)&ptr
)) != S_OK
) return hr
;
1698 return write_type_uint8( writer
, mapping
, desc
, ptr
);
1700 case WS_UINT16_TYPE
:
1702 const UINT16
*ptr
= value
;
1703 if (!option
) option
= WS_WRITE_REQUIRED_VALUE
;
1704 if ((hr
= get_value_ptr( option
, value
, size
, (const void **)&ptr
)) != S_OK
) return hr
;
1705 return write_type_uint16( writer
, mapping
, desc
, ptr
);
1707 case WS_UINT32_TYPE
:
1709 const UINT32
*ptr
= value
;
1710 if (!option
) option
= WS_WRITE_REQUIRED_VALUE
;
1711 if ((hr
= get_value_ptr( option
, value
, size
, (const void **)&ptr
)) != S_OK
) return hr
;
1712 return write_type_uint32( writer
, mapping
, desc
, ptr
);
1714 case WS_UINT64_TYPE
:
1716 const UINT64
*ptr
= value
;
1717 if (!option
) option
= WS_WRITE_REQUIRED_VALUE
;
1718 if ((hr
= get_value_ptr( option
, value
, size
, (const void **)&ptr
)) != S_OK
) return hr
;
1719 return write_type_uint64( writer
, mapping
, desc
, ptr
);
1725 if (option
== WS_WRITE_REQUIRED_VALUE
) return E_INVALIDARG
;
1727 if (!option
) option
= WS_WRITE_REQUIRED_POINTER
;
1728 if ((hr
= get_value_ptr( option
, value
, size
, (const void **)&ptr
)) != S_OK
) return hr
;
1729 return write_type_wsz( writer
, mapping
, desc
, ptr
);
1732 FIXME( "type %u not supported\n", type
);
1737 /**************************************************************************
1738 * WsWriteAttribute [webservices.@]
1740 HRESULT WINAPI
WsWriteAttribute( WS_XML_WRITER
*handle
, const WS_ATTRIBUTE_DESCRIPTION
*desc
,
1741 WS_WRITE_OPTION option
, const void *value
, ULONG size
,
1744 struct writer
*writer
= (struct writer
*)handle
;
1747 TRACE( "%p %p %u %p %u %p\n", handle
, desc
, option
, value
, size
, error
);
1748 if (error
) FIXME( "ignoring error parameter\n" );
1750 if (!writer
|| !desc
|| !desc
->attributeLocalName
|| !desc
->attributeNs
|| !value
)
1751 return E_INVALIDARG
;
1753 if (writer
->state
!= WRITER_STATE_STARTELEMENT
) return WS_E_INVALID_OPERATION
;
1755 if ((hr
= write_add_attribute( writer
, NULL
, desc
->attributeLocalName
, desc
->attributeNs
,
1756 FALSE
)) != S_OK
) return hr
;
1757 writer
->state
= WRITER_STATE_STARTATTRIBUTE
;
1759 return write_type( writer
, WS_ATTRIBUTE_TYPE_MAPPING
, desc
->type
, desc
->typeDescription
,
1760 option
, value
, size
);
1763 /**************************************************************************
1764 * WsWriteElement [webservices.@]
1766 HRESULT WINAPI
WsWriteElement( WS_XML_WRITER
*handle
, const WS_ELEMENT_DESCRIPTION
*desc
,
1767 WS_WRITE_OPTION option
, const void *value
, ULONG size
,
1770 struct writer
*writer
= (struct writer
*)handle
;
1773 TRACE( "%p %p %u %p %u %p\n", handle
, desc
, option
, value
, size
, error
);
1774 if (error
) FIXME( "ignoring error parameter\n" );
1776 if (!writer
|| !desc
|| !desc
->elementLocalName
|| !desc
->elementNs
|| !value
)
1777 return E_INVALIDARG
;
1779 if ((hr
= write_element_node( writer
, NULL
, desc
->elementLocalName
, desc
->elementNs
)) != S_OK
) return hr
;
1781 if ((hr
= write_type( writer
, WS_ANY_ELEMENT_TYPE_MAPPING
, desc
->type
, desc
->typeDescription
,
1782 option
, value
, size
)) != S_OK
) return hr
;
1784 return write_endelement_node( writer
);
1787 /**************************************************************************
1788 * WsWriteType [webservices.@]
1790 HRESULT WINAPI
WsWriteType( WS_XML_WRITER
*handle
, WS_TYPE_MAPPING mapping
, WS_TYPE type
,
1791 const void *desc
, WS_WRITE_OPTION option
, const void *value
,
1792 ULONG size
, WS_ERROR
*error
)
1794 struct writer
*writer
= (struct writer
*)handle
;
1797 TRACE( "%p %u %u %p %u %p %u %p\n", handle
, mapping
, type
, desc
, option
, value
,
1799 if (error
) FIXME( "ignoring error parameter\n" );
1801 if (!writer
|| !value
) return E_INVALIDARG
;
1805 case WS_ATTRIBUTE_TYPE_MAPPING
:
1806 if (writer
->state
!= WRITER_STATE_STARTATTRIBUTE
) return WS_E_INVALID_FORMAT
;
1807 hr
= write_type( writer
, mapping
, type
, desc
, option
, value
, size
);
1810 case WS_ELEMENT_TYPE_MAPPING
:
1811 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
1812 if (writer
->state
!= WRITER_STATE_STARTELEMENT
) return WS_E_INVALID_FORMAT
;
1813 hr
= write_type( writer
, mapping
, type
, desc
, option
, value
, size
);
1816 case WS_ANY_ELEMENT_TYPE_MAPPING
:
1817 hr
= write_type( writer
, mapping
, type
, desc
, option
, value
, size
);
1821 FIXME( "mapping %u not implemented\n", mapping
);
1828 WS_TYPE
map_value_type( WS_VALUE_TYPE type
)
1832 case WS_BOOL_VALUE_TYPE
: return WS_BOOL_TYPE
;
1833 case WS_INT8_VALUE_TYPE
: return WS_INT8_TYPE
;
1834 case WS_INT16_VALUE_TYPE
: return WS_INT16_TYPE
;
1835 case WS_INT32_VALUE_TYPE
: return WS_INT32_TYPE
;
1836 case WS_INT64_VALUE_TYPE
: return WS_INT64_TYPE
;
1837 case WS_UINT8_VALUE_TYPE
: return WS_UINT8_TYPE
;
1838 case WS_UINT16_VALUE_TYPE
: return WS_UINT16_TYPE
;
1839 case WS_UINT32_VALUE_TYPE
: return WS_UINT32_TYPE
;
1840 case WS_UINT64_VALUE_TYPE
: return WS_UINT64_TYPE
;
1841 case WS_FLOAT_VALUE_TYPE
: return WS_FLOAT_TYPE
;
1842 case WS_DOUBLE_VALUE_TYPE
: return WS_DOUBLE_TYPE
;
1843 case WS_DECIMAL_VALUE_TYPE
: return WS_DECIMAL_TYPE
;
1844 case WS_DATETIME_VALUE_TYPE
: return WS_DATETIME_TYPE
;
1845 case WS_TIMESPAN_VALUE_TYPE
: return WS_TIMESPAN_TYPE
;
1846 case WS_GUID_VALUE_TYPE
: return WS_GUID_TYPE
;
1848 FIXME( "unhandled type %u\n", type
);
1853 /**************************************************************************
1854 * WsWriteValue [webservices.@]
1856 HRESULT WINAPI
WsWriteValue( WS_XML_WRITER
*handle
, WS_VALUE_TYPE value_type
, const void *value
,
1857 ULONG size
, WS_ERROR
*error
)
1859 struct writer
*writer
= (struct writer
*)handle
;
1860 WS_TYPE_MAPPING mapping
;
1863 TRACE( "%p %u %p %u %p\n", handle
, value_type
, value
, size
, error
);
1864 if (error
) FIXME( "ignoring error parameter\n" );
1866 if (!writer
|| !value
|| (type
= map_value_type( value_type
)) == ~0u) return E_INVALIDARG
;
1868 switch (writer
->state
)
1870 case WRITER_STATE_STARTATTRIBUTE
:
1871 mapping
= WS_ATTRIBUTE_TYPE_MAPPING
;
1874 case WRITER_STATE_STARTELEMENT
:
1875 mapping
= WS_ELEMENT_TYPE_MAPPING
;
1879 return WS_E_INVALID_FORMAT
;
1882 return write_type( writer
, mapping
, type
, NULL
, WS_WRITE_REQUIRED_VALUE
, value
, size
);
1885 /**************************************************************************
1886 * WsWriteXmlBuffer [webservices.@]
1888 HRESULT WINAPI
WsWriteXmlBuffer( WS_XML_WRITER
*handle
, WS_XML_BUFFER
*buffer
, WS_ERROR
*error
)
1890 struct writer
*writer
= (struct writer
*)handle
;
1891 struct xmlbuf
*xmlbuf
= (struct xmlbuf
*)buffer
;
1894 TRACE( "%p %p %p\n", handle
, buffer
, error
);
1895 if (error
) FIXME( "ignoring error parameter\n" );
1897 if (!writer
|| !xmlbuf
) return E_INVALIDARG
;
1899 if ((hr
= write_grow_buffer( writer
, xmlbuf
->size
)) != S_OK
) return hr
;
1900 write_bytes( writer
, xmlbuf
->ptr
, xmlbuf
->size
);
1904 /**************************************************************************
1905 * WsWriteXmlBufferToBytes [webservices.@]
1907 HRESULT WINAPI
WsWriteXmlBufferToBytes( WS_XML_WRITER
*handle
, WS_XML_BUFFER
*buffer
,
1908 const WS_XML_WRITER_ENCODING
*encoding
,
1909 const WS_XML_WRITER_PROPERTY
*properties
, ULONG count
,
1910 WS_HEAP
*heap
, void **bytes
, ULONG
*size
, WS_ERROR
*error
)
1912 struct writer
*writer
= (struct writer
*)handle
;
1913 struct xmlbuf
*xmlbuf
= (struct xmlbuf
*)buffer
;
1918 TRACE( "%p %p %p %p %u %p %p %p %p\n", handle
, buffer
, encoding
, properties
, count
, heap
,
1919 bytes
, size
, error
);
1920 if (error
) FIXME( "ignoring error parameter\n" );
1922 if (!writer
|| !xmlbuf
|| !heap
|| !bytes
) return E_INVALIDARG
;
1924 if (encoding
&& encoding
->encodingType
!= WS_XML_WRITER_ENCODING_TYPE_TEXT
)
1926 FIXME( "encoding type %u not supported\n", encoding
->encodingType
);
1930 for (i
= 0; i
< count
; i
++)
1932 hr
= prop_set( writer
->prop
, writer
->prop_count
, properties
[i
].id
, properties
[i
].value
,
1933 properties
[i
].valueSize
);
1934 if (hr
!= S_OK
) return hr
;
1937 if (!(buf
= ws_alloc( heap
, xmlbuf
->size
))) return WS_E_QUOTA_EXCEEDED
;
1938 memcpy( buf
, xmlbuf
->ptr
, xmlbuf
->size
);
1940 *size
= xmlbuf
->size
;
1944 /**************************************************************************
1945 * WsWriteXmlnsAttribute [webservices.@]
1947 HRESULT WINAPI
WsWriteXmlnsAttribute( WS_XML_WRITER
*handle
, const WS_XML_STRING
*prefix
,
1948 const WS_XML_STRING
*ns
, BOOL single
, WS_ERROR
*error
)
1950 struct writer
*writer
= (struct writer
*)handle
;
1952 TRACE( "%p %s %s %d %p\n", handle
, debugstr_xmlstr(prefix
), debugstr_xmlstr(ns
),
1954 if (error
) FIXME( "ignoring error parameter\n" );
1956 if (!writer
|| !ns
) return E_INVALIDARG
;
1957 if (writer
->state
!= WRITER_STATE_STARTELEMENT
) return WS_E_INVALID_OPERATION
;
1959 if (namespace_in_scope( &writer
->current
->hdr
, prefix
, ns
)) return S_OK
;
1960 return write_add_namespace_attribute( writer
, prefix
, ns
, single
);
1963 static HRESULT
write_move_to( struct writer
*writer
, WS_MOVE_TO move
, BOOL
*found
)
1965 BOOL success
= FALSE
;
1966 struct node
*node
= writer
->current
;
1970 case WS_MOVE_TO_ROOT_ELEMENT
:
1971 success
= move_to_root_element( writer
->root
, &node
);
1974 case WS_MOVE_TO_NEXT_ELEMENT
:
1975 success
= move_to_next_element( &node
);
1978 case WS_MOVE_TO_PREVIOUS_ELEMENT
:
1979 success
= move_to_prev_element( &node
);
1982 case WS_MOVE_TO_CHILD_ELEMENT
:
1983 success
= move_to_child_element( &node
);
1986 case WS_MOVE_TO_END_ELEMENT
:
1987 success
= move_to_end_element( &node
);
1990 case WS_MOVE_TO_PARENT_ELEMENT
:
1991 success
= move_to_parent_element( &node
);
1994 case WS_MOVE_TO_FIRST_NODE
:
1995 success
= move_to_first_node( &node
);
1998 case WS_MOVE_TO_NEXT_NODE
:
1999 success
= move_to_next_node( &node
);
2002 case WS_MOVE_TO_PREVIOUS_NODE
:
2003 success
= move_to_prev_node( &node
);
2006 case WS_MOVE_TO_CHILD_NODE
:
2007 success
= move_to_child_node( &node
);
2010 case WS_MOVE_TO_BOF
:
2011 success
= move_to_bof( writer
->root
, &node
);
2014 case WS_MOVE_TO_EOF
:
2015 success
= move_to_eof( writer
->root
, &node
);
2019 FIXME( "unhandled move %u\n", move
);
2023 if (success
&& node
== writer
->root
) return E_INVALIDARG
;
2024 writer
->current
= node
;
2031 return success
? S_OK
: WS_E_INVALID_FORMAT
;
2034 /**************************************************************************
2035 * WsMoveWriter [webservices.@]
2037 HRESULT WINAPI
WsMoveWriter( WS_XML_WRITER
*handle
, WS_MOVE_TO move
, BOOL
*found
, WS_ERROR
*error
)
2039 struct writer
*writer
= (struct writer
*)handle
;
2041 TRACE( "%p %u %p %p\n", handle
, move
, found
, error
);
2042 if (error
) FIXME( "ignoring error parameter\n" );
2044 if (!writer
) return E_INVALIDARG
;
2045 if (!writer
->output_type
) return WS_E_INVALID_OPERATION
;
2047 return write_move_to( writer
, move
, found
);
2050 /**************************************************************************
2051 * WsGetWriterPosition [webservices.@]
2053 HRESULT WINAPI
WsGetWriterPosition( WS_XML_WRITER
*handle
, WS_XML_NODE_POSITION
*pos
, WS_ERROR
*error
)
2055 struct writer
*writer
= (struct writer
*)handle
;
2057 TRACE( "%p %p %p\n", handle
, pos
, error
);
2058 if (error
) FIXME( "ignoring error parameter\n" );
2060 if (!writer
|| !pos
) return E_INVALIDARG
;
2061 if (!writer
->output_type
) return WS_E_INVALID_OPERATION
;
2063 pos
->buffer
= (WS_XML_BUFFER
*)writer
->output_buf
;
2064 pos
->node
= writer
->current
;
2068 /**************************************************************************
2069 * WsSetWriterPosition [webservices.@]
2071 HRESULT WINAPI
WsSetWriterPosition( WS_XML_WRITER
*handle
, const WS_XML_NODE_POSITION
*pos
, WS_ERROR
*error
)
2073 struct writer
*writer
= (struct writer
*)handle
;
2075 TRACE( "%p %p %p\n", handle
, pos
, error
);
2076 if (error
) FIXME( "ignoring error parameter\n" );
2078 if (!writer
|| !pos
|| (struct xmlbuf
*)pos
->buffer
!= writer
->output_buf
) return E_INVALIDARG
;
2079 if (!writer
->output_type
) return WS_E_INVALID_OPERATION
;
2081 writer
->current
= pos
->node
;
2085 static HRESULT
write_add_comment_node( struct writer
*writer
, const WS_XML_STRING
*value
)
2087 struct node
*node
, *parent
;
2088 WS_XML_COMMENT_NODE
*comment
;
2090 if (!(parent
= find_parent( writer
->current
))) return WS_E_INVALID_FORMAT
;
2091 if (!(node
= alloc_node( WS_XML_NODE_TYPE_COMMENT
))) return E_OUTOFMEMORY
;
2092 comment
= (WS_XML_COMMENT_NODE
*)node
;
2094 if (value
->length
&& !(comment
->value
.bytes
= heap_alloc( value
->length
)))
2097 return E_OUTOFMEMORY
;
2099 memcpy( comment
->value
.bytes
, value
->bytes
, value
->length
);
2100 comment
->value
.length
= value
->length
;
2102 write_insert_node( writer
, parent
, node
);
2106 static HRESULT
write_comment( struct writer
*writer
)
2108 const WS_XML_COMMENT_NODE
*comment
= (const WS_XML_COMMENT_NODE
*)writer
->current
;
2111 if ((hr
= write_grow_buffer( writer
, comment
->value
.length
+ 7 )) != S_OK
) return hr
;
2112 write_bytes( writer
, (const BYTE
*)"<!--", 4 );
2113 write_bytes( writer
, comment
->value
.bytes
, comment
->value
.length
);
2114 write_bytes( writer
, (const BYTE
*)"-->", 3 );
2118 static HRESULT
write_comment_node( struct writer
*writer
, const WS_XML_STRING
*value
)
2121 if ((hr
= write_flush( writer
)) != S_OK
) return hr
;
2122 if ((hr
= write_add_comment_node( writer
, value
)) != S_OK
) return hr
;
2123 if ((hr
= write_comment( writer
)) != S_OK
) return hr
;
2124 writer
->state
= WRITER_STATE_COMMENT
;
2128 static HRESULT
write_set_attributes( struct writer
*writer
, WS_XML_ATTRIBUTE
**attrs
, ULONG count
)
2133 for (i
= 0; i
< count
; i
++)
2135 if ((hr
= write_add_attribute( writer
, attrs
[i
]->prefix
, attrs
[i
]->localName
, attrs
[i
]->ns
,
2136 attrs
[i
]->singleQuote
)) != S_OK
) return hr
;
2137 if ((hr
= write_set_attribute_value( writer
, attrs
[i
]->value
)) != S_OK
) return hr
;
2142 static HRESULT
write_node( struct writer
*writer
, const WS_XML_NODE
*node
)
2146 switch (node
->nodeType
)
2148 case WS_XML_NODE_TYPE_ELEMENT
:
2150 const WS_XML_ELEMENT_NODE
*elem
= (const WS_XML_ELEMENT_NODE
*)node
;
2151 if ((hr
= write_element_node( writer
, elem
->prefix
, elem
->localName
, elem
->ns
)) != S_OK
) return hr
;
2152 return write_set_attributes( writer
, elem
->attributes
, elem
->attributeCount
);
2154 case WS_XML_NODE_TYPE_TEXT
:
2156 const WS_XML_TEXT_NODE
*text
= (const WS_XML_TEXT_NODE
*)node
;
2157 return write_text_node( writer
, text
->text
);
2159 case WS_XML_NODE_TYPE_END_ELEMENT
:
2160 return write_endelement_node( writer
);
2162 case WS_XML_NODE_TYPE_COMMENT
:
2164 const WS_XML_COMMENT_NODE
*comment
= (const WS_XML_COMMENT_NODE
*)node
;
2165 return write_comment_node( writer
, &comment
->value
);
2167 case WS_XML_NODE_TYPE_CDATA
:
2168 return write_cdata_node( writer
);
2170 case WS_XML_NODE_TYPE_END_CDATA
:
2171 return write_endcdata_node( writer
);
2173 case WS_XML_NODE_TYPE_EOF
:
2174 case WS_XML_NODE_TYPE_BOF
:
2178 WARN( "unknown node type %u\n", node
->nodeType
);
2179 return E_INVALIDARG
;
2183 /**************************************************************************
2184 * WsWriteNode [webservices.@]
2186 HRESULT WINAPI
WsWriteNode( WS_XML_WRITER
*handle
, const WS_XML_NODE
*node
, WS_ERROR
*error
)
2188 struct writer
*writer
= (struct writer
*)handle
;
2190 TRACE( "%p %p %p\n", handle
, node
, error
);
2191 if (error
) FIXME( "ignoring error parameter\n" );
2193 if (!writer
|| !node
) return E_INVALIDARG
;
2194 if (!writer
->output_type
) return WS_E_INVALID_OPERATION
;
2196 return write_node( writer
, node
);
2199 static HRESULT
write_tree_node( struct writer
*writer
)
2203 switch (node_type( writer
->current
))
2205 case WS_XML_NODE_TYPE_ELEMENT
:
2206 if (writer
->state
== WRITER_STATE_STARTELEMENT
&& (hr
= write_endstartelement( writer
)) != S_OK
)
2208 if ((hr
= write_startelement( writer
)) != S_OK
) return hr
;
2209 writer
->state
= WRITER_STATE_STARTELEMENT
;
2212 case WS_XML_NODE_TYPE_TEXT
:
2213 if (writer
->state
== WRITER_STATE_STARTELEMENT
&& (hr
= write_endstartelement( writer
)) != S_OK
)
2215 if ((hr
= write_text( writer
)) != S_OK
) return hr
;
2216 writer
->state
= WRITER_STATE_TEXT
;
2219 case WS_XML_NODE_TYPE_END_ELEMENT
:
2220 if ((hr
= write_close_element( writer
, writer
->current
->parent
)) != S_OK
) return hr
;
2221 writer
->state
= WRITER_STATE_ENDELEMENT
;
2224 case WS_XML_NODE_TYPE_COMMENT
:
2225 if (writer
->state
== WRITER_STATE_STARTELEMENT
&& (hr
= write_endstartelement( writer
)) != S_OK
)
2227 if ((hr
= write_comment( writer
)) != S_OK
) return hr
;
2228 writer
->state
= WRITER_STATE_COMMENT
;
2231 case WS_XML_NODE_TYPE_CDATA
:
2232 if (writer
->state
== WRITER_STATE_STARTELEMENT
&& (hr
= write_endstartelement( writer
)) != S_OK
)
2234 if ((hr
= write_cdata( writer
)) != S_OK
) return hr
;
2235 writer
->state
= WRITER_STATE_STARTCDATA
;
2238 case WS_XML_NODE_TYPE_END_CDATA
:
2239 if ((hr
= write_endcdata( writer
)) != S_OK
) return hr
;
2240 writer
->state
= WRITER_STATE_ENDCDATA
;
2243 case WS_XML_NODE_TYPE_EOF
:
2244 case WS_XML_NODE_TYPE_BOF
:
2248 ERR( "unknown node type %u\n", node_type(writer
->current
) );
2249 return E_INVALIDARG
;
2253 static HRESULT
write_tree( struct writer
*writer
)
2257 if ((hr
= write_tree_node( writer
)) != S_OK
) return hr
;
2260 if (node_type( writer
->current
) == WS_XML_NODE_TYPE_EOF
) break;
2261 if (move_to_child_node( &writer
->current
))
2263 if ((hr
= write_tree_node( writer
)) != S_OK
) return hr
;
2266 if (move_to_next_node( &writer
->current
))
2268 if ((hr
= write_tree_node( writer
)) != S_OK
) return hr
;
2271 if (!move_to_parent_node( &writer
->current
) || !move_to_next_node( &writer
->current
))
2273 ERR( "invalid tree\n" );
2274 return WS_E_INVALID_FORMAT
;
2276 if ((hr
= write_tree_node( writer
)) != S_OK
) return hr
;
2281 static void write_rewind( struct writer
*writer
)
2283 writer
->write_pos
= 0;
2284 writer
->current
= writer
->root
;
2285 writer
->state
= WRITER_STATE_INITIAL
;
2288 /**************************************************************************
2289 * WsCopyNode [webservices.@]
2291 HRESULT WINAPI
WsCopyNode( WS_XML_WRITER
*handle
, WS_XML_READER
*reader
, WS_ERROR
*error
)
2293 struct writer
*writer
= (struct writer
*)handle
;
2294 struct node
*parent
, *current
= writer
->current
, *node
= NULL
;
2297 TRACE( "%p %p %p\n", handle
, reader
, error
);
2298 if (error
) FIXME( "ignoring error parameter\n" );
2300 if (!writer
) return E_INVALIDARG
;
2301 if (!(parent
= find_parent( writer
->current
))) return WS_E_INVALID_FORMAT
;
2303 if ((hr
= copy_node( reader
, &node
)) != S_OK
) return hr
;
2304 write_insert_node( writer
, parent
, node
);
2306 write_rewind( writer
);
2307 if ((hr
= write_tree( writer
)) != S_OK
) return hr
;
2309 writer
->current
= current
;