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
;
434 static const struct escape escape_lt
= { '<', "<", 4 };
435 static const struct escape escape_gt
= { '>', ">", 4 };
436 static const struct escape escape_amp
= { '&', "&", 5 };
437 static const struct escape escape_apos
= { '\'', "'", 6 };
438 static const struct escape escape_quot
= { '"', """, 6 };
440 static HRESULT
write_bytes_escape( struct writer
*writer
, const BYTE
*bytes
, ULONG len
,
441 const struct escape
**escapes
, ULONG nb_escapes
)
447 for (i
= 0; i
< len
; i
++)
451 for (j
= 0; j
< nb_escapes
; j
++)
453 if (bytes
[i
] == escapes
[j
]->ch
)
455 ptr
= (const BYTE
*)escapes
[j
]->entity
;
456 size
= escapes
[j
]->len
;
460 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
461 write_bytes( writer
, ptr
, size
);
467 static HRESULT
write_attribute( struct writer
*writer
, WS_XML_ATTRIBUTE
*attr
)
469 WS_XML_UTF8_TEXT
*text
= (WS_XML_UTF8_TEXT
*)attr
->value
;
470 unsigned char quote
= attr
->singleQuote
? '\'' : '"';
471 const WS_XML_STRING
*prefix
;
475 if (attr
->prefix
) prefix
= attr
->prefix
;
476 else prefix
= writer
->current
->hdr
.prefix
;
478 /* ' prefix:attr="value"' */
480 size
= attr
->localName
->length
+ 4 /* ' =""' */;
481 if (prefix
) size
+= prefix
->length
+ 1 /* ':' */;
482 if (text
) size
+= text
->value
.length
;
483 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
485 write_char( writer
, ' ' );
488 write_bytes( writer
, prefix
->bytes
, prefix
->length
);
489 write_char( writer
, ':' );
491 write_bytes( writer
, attr
->localName
->bytes
, attr
->localName
->length
);
492 write_char( writer
, '=' );
493 write_char( writer
, quote
);
496 const struct escape
*escapes
[3];
497 escapes
[0] = attr
->singleQuote
? &escape_apos
: &escape_quot
;
498 escapes
[1] = &escape_lt
;
499 escapes
[2] = &escape_amp
;
500 hr
= write_bytes_escape( writer
, text
->value
.bytes
, text
->value
.length
, escapes
, 3 );
502 write_char( writer
, quote
);
507 static inline BOOL
is_current_namespace( struct writer
*writer
, const WS_XML_STRING
*ns
)
509 return (WsXmlStringEquals( writer
->current_ns
, ns
, NULL
) == S_OK
);
512 /**************************************************************************
513 * WsGetPrefixFromNamespace [webservices.@]
515 HRESULT WINAPI
WsGetPrefixFromNamespace( WS_XML_WRITER
*handle
, const WS_XML_STRING
*ns
,
516 BOOL required
, const WS_XML_STRING
**prefix
,
519 struct writer
*writer
= (struct writer
*)handle
;
520 WS_XML_ELEMENT_NODE
*elem
;
523 TRACE( "%p %s %d %p %p\n", handle
, debugstr_xmlstr(ns
), required
, prefix
, error
);
524 if (error
) FIXME( "ignoring error parameter\n" );
526 if (!writer
|| !ns
|| !prefix
) return E_INVALIDARG
;
528 elem
= &writer
->current
->hdr
;
529 if (elem
->prefix
&& is_current_namespace( writer
, ns
))
531 *prefix
= elem
->prefix
;
536 if (required
) return WS_E_INVALID_FORMAT
;
543 static HRESULT
set_current_namespace( struct writer
*writer
, const WS_XML_STRING
*ns
)
546 if (!(str
= alloc_xml_string( ns
->bytes
, ns
->length
))) return E_OUTOFMEMORY
;
547 heap_free( writer
->current_ns
);
548 writer
->current_ns
= str
;
552 static HRESULT
write_namespace_attribute( struct writer
*writer
, WS_XML_ATTRIBUTE
*attr
)
554 unsigned char quote
= attr
->singleQuote
? '\'' : '"';
558 /* ' xmlns:prefix="namespace"' */
560 size
= attr
->ns
->length
+ 9 /* ' xmlns=""' */;
561 if (attr
->prefix
) size
+= attr
->prefix
->length
+ 1 /* ':' */;
562 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
564 write_bytes( writer
, (const BYTE
*)" xmlns", 6 );
567 write_char( writer
, ':' );
568 write_bytes( writer
, attr
->prefix
->bytes
, attr
->prefix
->length
);
570 write_char( writer
, '=' );
571 write_char( writer
, quote
);
572 write_bytes( writer
, attr
->ns
->bytes
, attr
->ns
->length
);
573 write_char( writer
, quote
);
578 static HRESULT
write_add_namespace_attribute( struct writer
*writer
, const WS_XML_STRING
*prefix
,
579 const WS_XML_STRING
*ns
, BOOL single
)
581 WS_XML_ATTRIBUTE
*attr
;
582 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
585 if (!(attr
= heap_alloc_zero( sizeof(*attr
) ))) return E_OUTOFMEMORY
;
587 attr
->singleQuote
= !!single
;
589 if (prefix
&& !(attr
->prefix
= alloc_xml_string( prefix
->bytes
, prefix
->length
)))
591 free_attribute( attr
);
592 return E_OUTOFMEMORY
;
594 if (!(attr
->ns
= alloc_xml_string( ns
->bytes
, ns
->length
)))
596 free_attribute( attr
);
597 return E_OUTOFMEMORY
;
599 if ((hr
= append_attribute( elem
, attr
)) != S_OK
)
601 free_attribute( attr
);
607 static inline BOOL
str_equal( const WS_XML_STRING
*str1
, const WS_XML_STRING
*str2
)
609 if (!str1
&& !str2
) return TRUE
;
610 return WsXmlStringEquals( str1
, str2
, NULL
) == S_OK
;
613 static BOOL
namespace_in_scope( const WS_XML_ELEMENT_NODE
*elem
, const WS_XML_STRING
*prefix
,
614 const WS_XML_STRING
*ns
)
617 const struct node
*node
;
619 for (node
= (const struct node
*)elem
; node
; node
= node
->parent
)
621 if (node_type( node
) != WS_XML_NODE_TYPE_ELEMENT
) break;
624 for (i
= 0; i
< elem
->attributeCount
; i
++)
626 if (!elem
->attributes
[i
]->isXmlNs
) continue;
627 if (str_equal( elem
->attributes
[i
]->prefix
, prefix
) &&
628 str_equal( elem
->attributes
[i
]->ns
, ns
)) return TRUE
;
634 static HRESULT
write_set_element_namespace( struct writer
*writer
)
636 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
639 if (!elem
->ns
->length
|| namespace_in_scope( elem
, elem
->prefix
, elem
->ns
)) return S_OK
;
641 if ((hr
= write_add_namespace_attribute( writer
, elem
->prefix
, elem
->ns
, FALSE
)) != S_OK
)
644 return set_current_namespace( writer
, elem
->ns
);
647 /**************************************************************************
648 * WsWriteEndAttribute [webservices.@]
650 HRESULT WINAPI
WsWriteEndAttribute( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
652 struct writer
*writer
= (struct writer
*)handle
;
654 TRACE( "%p %p\n", handle
, error
);
655 if (error
) FIXME( "ignoring error parameter\n" );
657 if (!writer
) return E_INVALIDARG
;
659 writer
->state
= WRITER_STATE_STARTELEMENT
;
663 static HRESULT
write_startelement( struct writer
*writer
)
665 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
669 /* '<prefix:localname prefix:attr="value"... xmlns:prefix="ns"'... */
671 size
= elem
->localName
->length
+ 1 /* '<' */;
672 if (elem
->prefix
) size
+= elem
->prefix
->length
+ 1 /* ':' */;
673 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
675 write_char( writer
, '<' );
678 write_bytes( writer
, elem
->prefix
->bytes
, elem
->prefix
->length
);
679 write_char( writer
, ':' );
681 write_bytes( writer
, elem
->localName
->bytes
, elem
->localName
->length
);
682 for (i
= 0; i
< elem
->attributeCount
; i
++)
684 if (elem
->attributes
[i
]->isXmlNs
) continue;
685 if ((hr
= write_attribute( writer
, elem
->attributes
[i
] )) != S_OK
) return hr
;
687 for (i
= 0; i
< elem
->attributeCount
; i
++)
689 if (!elem
->attributes
[i
]->isXmlNs
|| !elem
->attributes
[i
]->prefix
) continue;
690 if ((hr
= write_namespace_attribute( writer
, elem
->attributes
[i
] )) != S_OK
) return hr
;
692 for (i
= 0; i
< elem
->attributeCount
; i
++)
694 if (!elem
->attributes
[i
]->isXmlNs
|| elem
->attributes
[i
]->prefix
) continue;
695 if ((hr
= write_namespace_attribute( writer
, elem
->attributes
[i
] )) != S_OK
) return hr
;
700 static struct node
*write_find_startelement( struct writer
*writer
)
703 for (node
= writer
->current
; node
; node
= node
->parent
)
705 if (node_type( node
) == WS_XML_NODE_TYPE_ELEMENT
) return node
;
710 static inline BOOL
is_empty_element( const struct node
*node
)
712 const struct node
*head
= LIST_ENTRY( list_head( &node
->children
), struct node
, entry
);
713 return node_type( head
) == WS_XML_NODE_TYPE_END_ELEMENT
;
716 static HRESULT
write_endelement( struct writer
*writer
, const WS_XML_ELEMENT_NODE
*elem
)
723 if (elem
->isEmpty
&& writer
->state
!= WRITER_STATE_ENDSTARTELEMENT
)
725 if ((hr
= write_grow_buffer( writer
, 2 )) != S_OK
) return hr
;
726 write_char( writer
, '/' );
727 write_char( writer
, '>' );
731 /* '</prefix:localname>' */
733 size
= elem
->localName
->length
+ 3 /* '</>' */;
734 if (elem
->prefix
) size
+= elem
->prefix
->length
+ 1 /* ':' */;
735 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
737 write_char( writer
, '<' );
738 write_char( writer
, '/' );
741 write_bytes( writer
, elem
->prefix
->bytes
, elem
->prefix
->length
);
742 write_char( writer
, ':' );
744 write_bytes( writer
, elem
->localName
->bytes
, elem
->localName
->length
);
745 write_char( writer
, '>' );
749 static HRESULT
write_close_element( struct writer
*writer
, struct node
*node
)
751 WS_XML_ELEMENT_NODE
*elem
= &node
->hdr
;
752 elem
->isEmpty
= is_empty_element( node
);
753 return write_endelement( writer
, elem
);
756 static HRESULT
write_endelement_node( struct writer
*writer
)
761 if (!(node
= write_find_startelement( writer
))) return WS_E_INVALID_FORMAT
;
762 if (writer
->state
== WRITER_STATE_STARTELEMENT
)
764 if ((hr
= write_set_element_namespace( writer
)) != S_OK
) return hr
;
765 if ((hr
= write_startelement( writer
)) != S_OK
) return hr
;
767 if ((hr
= write_close_element( writer
, node
)) != S_OK
) return hr
;
768 writer
->current
= node
->parent
;
769 writer
->state
= WRITER_STATE_ENDELEMENT
;
773 /**************************************************************************
774 * WsWriteEndElement [webservices.@]
776 HRESULT WINAPI
WsWriteEndElement( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
778 struct writer
*writer
= (struct writer
*)handle
;
780 TRACE( "%p %p\n", handle
, error
);
781 if (error
) FIXME( "ignoring error parameter\n" );
783 if (!writer
) return E_INVALIDARG
;
784 return write_endelement_node( writer
);
787 static HRESULT
write_endstartelement( struct writer
*writer
)
790 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
791 write_char( writer
, '>' );
795 /**************************************************************************
796 * WsWriteEndStartElement [webservices.@]
798 HRESULT WINAPI
WsWriteEndStartElement( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
800 struct writer
*writer
= (struct writer
*)handle
;
803 TRACE( "%p %p\n", handle
, error
);
804 if (error
) FIXME( "ignoring error parameter\n" );
806 if (!writer
) return E_INVALIDARG
;
807 if (writer
->state
!= WRITER_STATE_STARTELEMENT
) return WS_E_INVALID_OPERATION
;
809 if ((hr
= write_set_element_namespace( writer
)) != S_OK
) return hr
;
810 if ((hr
= write_startelement( writer
)) != S_OK
) return hr
;
811 if ((hr
= write_endstartelement( writer
)) != S_OK
) return hr
;
813 writer
->state
= WRITER_STATE_ENDSTARTELEMENT
;
817 static HRESULT
write_add_attribute( struct writer
*writer
, const WS_XML_STRING
*prefix
,
818 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
821 WS_XML_ATTRIBUTE
*attr
;
822 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
825 if (!(attr
= heap_alloc_zero( sizeof(*attr
) ))) return E_OUTOFMEMORY
;
827 if (!prefix
) prefix
= elem
->prefix
;
829 attr
->singleQuote
= !!single
;
830 if (prefix
&& !(attr
->prefix
= alloc_xml_string( prefix
->bytes
, prefix
->length
)))
832 free_attribute( attr
);
833 return E_OUTOFMEMORY
;
835 if (!(attr
->localName
= alloc_xml_string( localname
->bytes
, localname
->length
)))
837 free_attribute( attr
);
838 return E_OUTOFMEMORY
;
840 if (!(attr
->ns
= alloc_xml_string( ns
->bytes
, ns
->length
)))
842 free_attribute( attr
);
843 return E_OUTOFMEMORY
;
845 if ((hr
= append_attribute( elem
, attr
)) != S_OK
)
847 free_attribute( attr
);
853 /**************************************************************************
854 * WsWriteStartAttribute [webservices.@]
856 HRESULT WINAPI
WsWriteStartAttribute( WS_XML_WRITER
*handle
, const WS_XML_STRING
*prefix
,
857 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
858 BOOL single
, WS_ERROR
*error
)
860 struct writer
*writer
= (struct writer
*)handle
;
863 TRACE( "%p %s %s %s %d %p\n", handle
, debugstr_xmlstr(prefix
), debugstr_xmlstr(localname
),
864 debugstr_xmlstr(ns
), single
, error
);
865 if (error
) FIXME( "ignoring error parameter\n" );
867 if (!writer
|| !localname
|| !ns
) return E_INVALIDARG
;
869 if (writer
->state
!= WRITER_STATE_STARTELEMENT
) return WS_E_INVALID_OPERATION
;
871 if ((hr
= write_add_attribute( writer
, prefix
, localname
, ns
, single
)) != S_OK
) return hr
;
872 writer
->state
= WRITER_STATE_STARTATTRIBUTE
;
876 /* flush current start element if necessary */
877 static HRESULT
write_flush( struct writer
*writer
)
879 if (writer
->state
== WRITER_STATE_STARTELEMENT
)
882 if ((hr
= write_set_element_namespace( writer
)) != S_OK
) return hr
;
883 if ((hr
= write_startelement( writer
)) != S_OK
) return hr
;
884 if ((hr
= write_endstartelement( writer
)) != S_OK
) return hr
;
885 writer
->state
= WRITER_STATE_ENDSTARTELEMENT
;
890 static HRESULT
write_add_cdata_node( struct writer
*writer
)
892 struct node
*node
, *parent
;
893 if (!(parent
= find_parent( writer
->current
))) return WS_E_INVALID_FORMAT
;
894 if (!(node
= alloc_node( WS_XML_NODE_TYPE_CDATA
))) return E_OUTOFMEMORY
;
895 write_insert_node( writer
, parent
, node
);
899 static HRESULT
write_add_endcdata_node( struct writer
*writer
)
902 if (!(node
= alloc_node( WS_XML_NODE_TYPE_END_CDATA
))) return E_OUTOFMEMORY
;
903 node
->parent
= writer
->current
;
904 list_add_tail( &node
->parent
->children
, &node
->entry
);
908 static HRESULT
write_cdata( struct writer
*writer
)
911 if ((hr
= write_grow_buffer( writer
, 9 )) != S_OK
) return hr
;
912 write_bytes( writer
, (const BYTE
*)"<![CDATA[", 9 );
916 static HRESULT
write_cdata_node( struct writer
*writer
)
919 if ((hr
= write_flush( writer
)) != S_OK
) return hr
;
920 if ((hr
= write_add_cdata_node( writer
)) != S_OK
) return hr
;
921 if ((hr
= write_add_endcdata_node( writer
)) != S_OK
) return hr
;
922 if ((hr
= write_cdata( writer
)) != S_OK
) return hr
;
923 writer
->state
= WRITER_STATE_STARTCDATA
;
927 /**************************************************************************
928 * WsWriteStartCData [webservices.@]
930 HRESULT WINAPI
WsWriteStartCData( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
932 struct writer
*writer
= (struct writer
*)handle
;
934 TRACE( "%p %p\n", handle
, error
);
935 if (error
) FIXME( "ignoring error parameter\n" );
937 if (!writer
) return E_INVALIDARG
;
938 return write_cdata_node( writer
);
941 static HRESULT
write_endcdata( struct writer
*writer
)
944 if ((hr
= write_grow_buffer( writer
, 3 )) != S_OK
) return hr
;
945 write_bytes( writer
, (const BYTE
*)"]]>", 3 );
949 static HRESULT
write_endcdata_node( struct writer
*writer
)
952 if ((hr
= write_endcdata( writer
)) != S_OK
) return hr
;
953 writer
->current
= writer
->current
->parent
;
954 writer
->state
= WRITER_STATE_ENDCDATA
;
958 /**************************************************************************
959 * WsWriteEndCData [webservices.@]
961 HRESULT WINAPI
WsWriteEndCData( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
963 struct writer
*writer
= (struct writer
*)handle
;
965 TRACE( "%p %p\n", handle
, error
);
966 if (error
) FIXME( "ignoring error parameter\n" );
968 if (!writer
) return E_INVALIDARG
;
969 if (writer
->state
!= WRITER_STATE_TEXT
) return WS_E_INVALID_OPERATION
;
971 return write_endcdata_node( writer
);
974 static HRESULT
write_add_element_node( struct writer
*writer
, const WS_XML_STRING
*prefix
,
975 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
)
977 struct node
*node
, *parent
;
978 WS_XML_ELEMENT_NODE
*elem
;
980 if (!(parent
= find_parent( writer
->current
))) return WS_E_INVALID_FORMAT
;
982 if (!prefix
&& node_type( parent
) == WS_XML_NODE_TYPE_ELEMENT
)
985 if (WsXmlStringEquals( ns
, elem
->ns
, NULL
) == S_OK
) prefix
= elem
->prefix
;
988 if (!(node
= alloc_node( WS_XML_NODE_TYPE_ELEMENT
))) return E_OUTOFMEMORY
;
991 if (prefix
&& !(elem
->prefix
= alloc_xml_string( prefix
->bytes
, prefix
->length
)))
994 return E_OUTOFMEMORY
;
996 if (!(elem
->localName
= alloc_xml_string( localname
->bytes
, localname
->length
)))
999 return E_OUTOFMEMORY
;
1001 if (!(elem
->ns
= alloc_xml_string( ns
->bytes
, ns
->length
)))
1004 return E_OUTOFMEMORY
;
1006 write_insert_node( writer
, parent
, node
);
1010 static HRESULT
write_add_endelement_node( struct writer
*writer
, struct node
*parent
)
1013 if (!(node
= alloc_node( WS_XML_NODE_TYPE_END_ELEMENT
))) return E_OUTOFMEMORY
;
1014 node
->parent
= parent
;
1015 list_add_tail( &parent
->children
, &node
->entry
);
1019 static HRESULT
write_element_node( struct writer
*writer
, const WS_XML_STRING
*prefix
,
1020 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
)
1023 if ((hr
= write_flush( writer
)) != S_OK
) return hr
;
1024 if ((hr
= write_add_element_node( writer
, prefix
, localname
, ns
)) != S_OK
) return hr
;
1025 if ((hr
= write_add_endelement_node( writer
, writer
->current
)) != S_OK
) return hr
;
1026 writer
->state
= WRITER_STATE_STARTELEMENT
;
1030 /**************************************************************************
1031 * WsWriteStartElement [webservices.@]
1033 HRESULT WINAPI
WsWriteStartElement( WS_XML_WRITER
*handle
, const WS_XML_STRING
*prefix
,
1034 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
1037 struct writer
*writer
= (struct writer
*)handle
;
1039 TRACE( "%p %s %s %s %p\n", handle
, debugstr_xmlstr(prefix
), debugstr_xmlstr(localname
),
1040 debugstr_xmlstr(ns
), error
);
1041 if (error
) FIXME( "ignoring error parameter\n" );
1043 if (!writer
|| !localname
|| !ns
) return E_INVALIDARG
;
1044 return write_element_node( writer
, prefix
, localname
, ns
);
1047 static ULONG
format_bool( const BOOL
*ptr
, unsigned char *buf
)
1049 static const unsigned char bool_true
[] = {'t','r','u','e'}, bool_false
[] = {'f','a','l','s','e'};
1052 memcpy( buf
, bool_true
, sizeof(bool_true
) );
1053 return sizeof(bool_true
);
1055 memcpy( buf
, bool_false
, sizeof(bool_false
) );
1056 return sizeof(bool_false
);
1059 static ULONG
format_int8( const INT8
*ptr
, unsigned char *buf
)
1061 return wsprintfA( (char *)buf
, "%d", *ptr
);
1064 static ULONG
format_int16( const INT16
*ptr
, unsigned char *buf
)
1066 return wsprintfA( (char *)buf
, "%d", *ptr
);
1069 static ULONG
format_int32( const INT32
*ptr
, unsigned char *buf
)
1071 return wsprintfA( (char *)buf
, "%d", *ptr
);
1074 static ULONG
format_int64( const INT64
*ptr
, unsigned char *buf
)
1076 return wsprintfA( (char *)buf
, "%I64d", *ptr
);
1079 static ULONG
format_uint8( const UINT8
*ptr
, unsigned char *buf
)
1081 return wsprintfA( (char *)buf
, "%u", *ptr
);
1084 static ULONG
format_uint16( const UINT16
*ptr
, unsigned char *buf
)
1086 return wsprintfA( (char *)buf
, "%u", *ptr
);
1089 static ULONG
format_uint32( const UINT32
*ptr
, unsigned char *buf
)
1091 return wsprintfA( (char *)buf
, "%u", *ptr
);
1094 static ULONG
format_uint64( const UINT64
*ptr
, unsigned char *buf
)
1096 return wsprintfA( (char *)buf
, "%I64u", *ptr
);
1099 static ULONG
format_double( const double *ptr
, unsigned char *buf
)
1102 static const long double precision
= 0.0000000000000001;
1103 unsigned char *p
= buf
;
1104 long double val
= *ptr
;
1105 int neg
, mag
, mag2
, use_exp
;
1109 memcpy( buf
, "NaN", 3 );
1116 memcpy( buf
, "-INF", 4 );
1119 memcpy( buf
, "INF", 3 );
1128 if ((neg
= val
< 0))
1134 mag
= log10l( val
);
1135 use_exp
= (mag
>= 15 || (neg
&& mag
>= 1) || mag
<= -1);
1138 if (mag
< 0) mag
-= 1;
1139 val
= val
/ powl( 10.0, mag
);
1143 else if (mag
< 1) mag
= 0;
1145 while (val
> precision
|| mag
>= 0)
1147 long double weight
= powl( 10.0, mag
);
1148 if (weight
> 0 && !isinf( weight
))
1150 int digit
= floorl( val
/ weight
);
1151 val
-= digit
* weight
;
1152 *(p
++) = '0' + digit
;
1154 if (!mag
&& val
> precision
) *(p
++) = '.';
1162 if (mag2
> 0) *(p
++) = '+';
1171 *(p
++) = '0' + mag2
% 10;
1175 for (i
= -mag
, j
= -1; i
< j
; i
++, j
--)
1185 FIXME( "powl not found at build time\n" );
1190 static inline int year_size( int year
)
1192 return leap_year( year
) ? 366 : 365;
1196 static ULONG
format_datetime( const WS_DATETIME
*ptr
, unsigned char *buf
)
1198 static const char fmt
[] = "%04u-%02u-%02uT%02u:%02u:%02u";
1199 int day
, hour
, min
, sec
, sec_frac
, month
= 1, year
= 1, tz_hour
;
1200 unsigned __int64 ticks
, day_ticks
;
1203 if (ptr
->format
== WS_DATETIME_FORMAT_LOCAL
&&
1204 ptr
->ticks
>= TICKS_1601_01_01
+ TZ_OFFSET
* TICKS_PER_HOUR
)
1206 ticks
= ptr
->ticks
- TZ_OFFSET
* TICKS_PER_HOUR
;
1207 tz_hour
= TZ_OFFSET
;
1214 day
= ticks
/ TICKS_PER_DAY
;
1215 day_ticks
= ticks
% TICKS_PER_DAY
;
1216 hour
= day_ticks
/ TICKS_PER_HOUR
;
1217 min
= (day_ticks
% TICKS_PER_HOUR
) / TICKS_PER_MIN
;
1218 sec
= (day_ticks
% TICKS_PER_MIN
) / TICKS_PER_SEC
;
1219 sec_frac
= day_ticks
% TICKS_PER_SEC
;
1221 while (day
>= year_size( year
))
1223 day
-= year_size( year
);
1226 while (day
>= month_days
[leap_year( year
)][month
])
1228 day
-= month_days
[leap_year( year
)][month
];
1233 len
= sprintf( (char *)buf
, fmt
, year
, month
, day
, hour
, min
, sec
);
1236 static const char fmt_frac
[] = ".%07u";
1237 len
+= sprintf( (char *)buf
+ len
, fmt_frac
, sec_frac
);
1238 while (buf
[len
- 1] == '0') len
--;
1240 if (ptr
->format
== WS_DATETIME_FORMAT_UTC
)
1244 else if (ptr
->format
== WS_DATETIME_FORMAT_LOCAL
)
1246 static const char fmt_tz
[] = "%c%02u:00";
1247 len
+= sprintf( (char *)buf
+ len
, fmt_tz
, tz_hour
? '-' : '+', tz_hour
);
1253 static ULONG
format_guid( const GUID
*ptr
, unsigned char *buf
)
1255 static const char fmt
[] = "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x";
1256 return sprintf( (char *)buf
, fmt
, ptr
->Data1
, ptr
->Data2
, ptr
->Data3
,
1257 ptr
->Data4
[0], ptr
->Data4
[1], ptr
->Data4
[2], ptr
->Data4
[3],
1258 ptr
->Data4
[4], ptr
->Data4
[5], ptr
->Data4
[6], ptr
->Data4
[7] );
1261 static ULONG
format_urn( const GUID
*ptr
, unsigned char *buf
)
1263 static const char fmt
[] = "urn:uuid:%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x";
1264 return sprintf( (char *)buf
, fmt
, ptr
->Data1
, ptr
->Data2
, ptr
->Data3
,
1265 ptr
->Data4
[0], ptr
->Data4
[1], ptr
->Data4
[2], ptr
->Data4
[3],
1266 ptr
->Data4
[4], ptr
->Data4
[5], ptr
->Data4
[6], ptr
->Data4
[7] );
1269 static ULONG
encode_base64( const unsigned char *bin
, ULONG len
, unsigned char *buf
)
1271 static const char base64
[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1276 buf
[i
++] = base64
[(bin
[0] & 0xfc) >> 2];
1277 x
= (bin
[0] & 3) << 4;
1280 buf
[i
++] = base64
[x
];
1285 buf
[i
++] = base64
[x
| ((bin
[1] & 0xf0) >> 4)];
1286 x
= (bin
[1] & 0x0f) << 2;
1289 buf
[i
++] = base64
[x
];
1293 buf
[i
++] = base64
[x
| ((bin
[2] & 0xc0) >> 6)];
1294 buf
[i
++] = base64
[bin
[2] & 0x3f];
1301 static HRESULT
text_to_utf8text( const WS_XML_TEXT
*text
, WS_XML_UTF8_TEXT
**ret
)
1303 switch (text
->textType
)
1305 case WS_XML_TEXT_TYPE_UTF8
:
1307 const WS_XML_UTF8_TEXT
*src
= (const WS_XML_UTF8_TEXT
*)text
;
1308 if (!(*ret
= alloc_utf8_text( src
->value
.bytes
, src
->value
.length
))) return E_OUTOFMEMORY
;
1311 case WS_XML_TEXT_TYPE_UTF16
:
1313 const WS_XML_UTF16_TEXT
*src
= (const WS_XML_UTF16_TEXT
*)text
;
1314 const WCHAR
*str
= (const WCHAR
*)src
->bytes
;
1315 ULONG len
= src
->byteCount
/ sizeof(WCHAR
), len_utf8
;
1317 if (src
->byteCount
% sizeof(WCHAR
)) return E_INVALIDARG
;
1318 len_utf8
= WideCharToMultiByte( CP_UTF8
, 0, str
, len
, NULL
, 0, NULL
, NULL
);
1319 if (!(*ret
= alloc_utf8_text( NULL
, len_utf8
))) return E_OUTOFMEMORY
;
1320 WideCharToMultiByte( CP_UTF8
, 0, str
, len
, (char *)(*ret
)->value
.bytes
, (*ret
)->value
.length
, NULL
, NULL
);
1323 case WS_XML_TEXT_TYPE_BASE64
:
1325 const WS_XML_BASE64_TEXT
*base64
= (const WS_XML_BASE64_TEXT
*)text
;
1326 ULONG len
= ((4 * base64
->length
/ 3) + 3) & ~3;
1327 if (!(*ret
= alloc_utf8_text( NULL
, len
))) return E_OUTOFMEMORY
;
1328 (*ret
)->value
.length
= encode_base64( base64
->bytes
, base64
->length
, (*ret
)->value
.bytes
);
1331 case WS_XML_TEXT_TYPE_BOOL
:
1333 const WS_XML_BOOL_TEXT
*bool_text
= (const WS_XML_BOOL_TEXT
*)text
;
1334 if (!(*ret
= alloc_utf8_text( NULL
, 5 ))) return E_OUTOFMEMORY
;
1335 (*ret
)->value
.length
= format_bool( &bool_text
->value
, (*ret
)->value
.bytes
);
1338 case WS_XML_TEXT_TYPE_INT32
:
1340 const WS_XML_INT32_TEXT
*int32_text
= (const WS_XML_INT32_TEXT
*)text
;
1341 unsigned char buf
[12]; /* "-2147483648" */
1342 ULONG len
= format_int32( &int32_text
->value
, buf
);
1343 if (!(*ret
= alloc_utf8_text( buf
, len
))) return E_OUTOFMEMORY
;
1346 case WS_XML_TEXT_TYPE_INT64
:
1348 const WS_XML_INT64_TEXT
*int64_text
= (const WS_XML_INT64_TEXT
*)text
;
1349 unsigned char buf
[21]; /* "-9223372036854775808" */
1350 ULONG len
= format_int64( &int64_text
->value
, buf
);
1351 if (!(*ret
= alloc_utf8_text( buf
, len
))) return E_OUTOFMEMORY
;
1354 case WS_XML_TEXT_TYPE_UINT64
:
1356 const WS_XML_UINT64_TEXT
*uint64_text
= (const WS_XML_UINT64_TEXT
*)text
;
1357 unsigned char buf
[21]; /* "18446744073709551615" */
1358 ULONG len
= format_uint64( &uint64_text
->value
, buf
);
1359 if (!(*ret
= alloc_utf8_text( buf
, len
))) return E_OUTOFMEMORY
;
1362 case WS_XML_TEXT_TYPE_DOUBLE
:
1364 const WS_XML_DOUBLE_TEXT
*double_text
= (const WS_XML_DOUBLE_TEXT
*)text
;
1365 unsigned char buf
[24]; /* "-1.1111111111111111E-308" */
1366 unsigned short fpword
;
1369 if (!set_fp_rounding( &fpword
)) return E_NOTIMPL
;
1370 len
= format_double( &double_text
->value
, buf
);
1371 restore_fp_rounding( fpword
);
1372 if (!len
) return E_NOTIMPL
;
1373 if (!(*ret
= alloc_utf8_text( buf
, len
))) return E_OUTOFMEMORY
;
1376 case WS_XML_TEXT_TYPE_GUID
:
1378 const WS_XML_GUID_TEXT
*id
= (const WS_XML_GUID_TEXT
*)text
;
1379 if (!(*ret
= alloc_utf8_text( NULL
, 37 ))) return E_OUTOFMEMORY
;
1380 (*ret
)->value
.length
= format_guid( &id
->value
, (*ret
)->value
.bytes
);
1383 case WS_XML_TEXT_TYPE_UNIQUE_ID
:
1385 const WS_XML_UNIQUE_ID_TEXT
*id
= (const WS_XML_UNIQUE_ID_TEXT
*)text
;
1386 if (!(*ret
= alloc_utf8_text( NULL
, 46 ))) return E_OUTOFMEMORY
;
1387 (*ret
)->value
.length
= format_urn( &id
->value
, (*ret
)->value
.bytes
);
1390 case WS_XML_TEXT_TYPE_DATETIME
:
1392 const WS_XML_DATETIME_TEXT
*dt
= (const WS_XML_DATETIME_TEXT
*)text
;
1393 if (!(*ret
= alloc_utf8_text( NULL
, 34 ))) return E_OUTOFMEMORY
;
1394 (*ret
)->value
.length
= format_datetime( &dt
->value
, (*ret
)->value
.bytes
);
1398 FIXME( "unhandled text type %u\n", text
->textType
);
1403 static HRESULT
write_set_attribute_value( struct writer
*writer
, const WS_XML_TEXT
*value
)
1405 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
1406 WS_XML_UTF8_TEXT
*utf8
;
1409 if ((hr
= text_to_utf8text( value
, &utf8
)) != S_OK
) return hr
;
1410 elem
->attributes
[elem
->attributeCount
- 1]->value
= &utf8
->text
;
1414 static HRESULT
write_add_text_node( struct writer
*writer
, const WS_XML_TEXT
*value
)
1417 WS_XML_TEXT_NODE
*text
;
1418 WS_XML_UTF8_TEXT
*utf8
;
1421 if (node_type( writer
->current
) != WS_XML_NODE_TYPE_ELEMENT
&&
1422 node_type( writer
->current
) != WS_XML_NODE_TYPE_BOF
&&
1423 node_type( writer
->current
) != WS_XML_NODE_TYPE_CDATA
) return WS_E_INVALID_FORMAT
;
1425 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return E_OUTOFMEMORY
;
1426 if ((hr
= text_to_utf8text( value
, &utf8
)) != S_OK
)
1431 text
= (WS_XML_TEXT_NODE
*)node
;
1432 text
->text
= &utf8
->text
;
1434 write_insert_node( writer
, writer
->current
, node
);
1438 static HRESULT
write_text( struct writer
*writer
)
1440 const WS_XML_TEXT_NODE
*text
= (const WS_XML_TEXT_NODE
*)writer
->current
;
1441 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)text
->text
;
1444 if (!writer
->current
->parent
) return WS_E_INVALID_FORMAT
;
1445 if (node_type( writer
->current
->parent
) == WS_XML_NODE_TYPE_ELEMENT
)
1447 const struct escape
*escapes
[3] = { &escape_lt
, &escape_gt
, &escape_amp
};
1448 return write_bytes_escape( writer
, utf8
->value
.bytes
, utf8
->value
.length
, escapes
, 3 );
1450 else if (node_type( writer
->current
->parent
) == WS_XML_NODE_TYPE_CDATA
)
1452 if ((hr
= write_grow_buffer( writer
, utf8
->value
.length
)) != S_OK
) return hr
;
1453 write_bytes( writer
, utf8
->value
.bytes
, utf8
->value
.length
);
1457 return WS_E_INVALID_FORMAT
;
1460 static HRESULT
write_text_node( struct writer
*writer
, const WS_XML_TEXT
*text
)
1463 if ((hr
= write_flush( writer
)) != S_OK
) return hr
;
1464 if ((hr
= write_add_text_node( writer
, text
)) != S_OK
) return hr
;
1465 if ((hr
= write_text( writer
)) != S_OK
) return hr
;
1466 writer
->state
= WRITER_STATE_TEXT
;
1470 /**************************************************************************
1471 * WsWriteText [webservices.@]
1473 HRESULT WINAPI
WsWriteText( WS_XML_WRITER
*handle
, const WS_XML_TEXT
*text
, WS_ERROR
*error
)
1475 struct writer
*writer
= (struct writer
*)handle
;
1477 TRACE( "%p %p %p\n", handle
, text
, error
);
1479 if (!writer
|| !text
) return E_INVALIDARG
;
1481 if (writer
->state
== WRITER_STATE_STARTATTRIBUTE
) return write_set_attribute_value( writer
, text
);
1482 return write_text_node( writer
, text
);
1485 static HRESULT
write_type_text( struct writer
*writer
, WS_TYPE_MAPPING mapping
, const WS_XML_TEXT
*text
)
1489 case WS_ELEMENT_TYPE_MAPPING
:
1490 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
1491 return write_text_node( writer
, text
);
1493 case WS_ATTRIBUTE_TYPE_MAPPING
:
1494 return write_set_attribute_value( writer
, text
);
1496 case WS_ANY_ELEMENT_TYPE_MAPPING
:
1497 switch (writer
->state
)
1499 case WRITER_STATE_STARTATTRIBUTE
:
1500 return write_set_attribute_value( writer
, text
);
1502 case WRITER_STATE_STARTELEMENT
:
1503 return write_text_node( writer
, text
);
1506 FIXME( "writer state %u not handled\n", writer
->state
);
1511 FIXME( "mapping %u not implemented\n", mapping
);
1516 static HRESULT
write_add_nil_attribute( struct writer
*writer
)
1518 static const WS_XML_STRING prefix
= {1, (BYTE
*)"a"};
1519 static const WS_XML_STRING localname
= {3, (BYTE
*)"nil"};
1520 static const WS_XML_STRING ns
= {41, (BYTE
*)"http://www.w3.org/2001/XMLSchema-instance"};
1521 static const WS_XML_UTF8_TEXT value
= {{WS_XML_TEXT_TYPE_UTF8
}, {4, (BYTE
*)"true"}};
1524 if ((hr
= write_add_attribute( writer
, &prefix
, &localname
, &ns
, FALSE
)) != S_OK
) return hr
;
1525 if ((hr
= write_set_attribute_value( writer
, &value
.text
)) != S_OK
) return hr
;
1526 return write_add_namespace_attribute( writer
, &prefix
, &ns
, FALSE
);
1529 static HRESULT
get_value_ptr( WS_WRITE_OPTION option
, const void *value
, ULONG size
, ULONG expected_size
,
1534 case WS_WRITE_REQUIRED_VALUE
:
1535 case WS_WRITE_NILLABLE_VALUE
:
1536 if (!value
|| size
!= expected_size
) return E_INVALIDARG
;
1540 case WS_WRITE_REQUIRED_POINTER
:
1541 if (size
!= sizeof(const void *) || !(*ptr
= *(const void **)value
)) return E_INVALIDARG
;
1544 case WS_WRITE_NILLABLE_POINTER
:
1545 if (size
!= sizeof(const void *)) return E_INVALIDARG
;
1546 *ptr
= *(const void **)value
;
1550 return E_INVALIDARG
;
1554 static HRESULT
write_type_bool( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1555 const WS_BOOL_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
1556 const BOOL
*value
, ULONG size
)
1558 WS_XML_UTF8_TEXT utf8
;
1559 unsigned char buf
[6]; /* "false" */
1565 FIXME( "description not supported\n" );
1569 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
1570 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(BOOL
), (const void **)&ptr
)) != S_OK
) return hr
;
1571 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
1573 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
1574 utf8
.value
.bytes
= buf
;
1575 utf8
.value
.length
= format_bool( ptr
, buf
);
1576 return write_type_text( writer
, mapping
, &utf8
.text
);
1579 static HRESULT
write_type_int8( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1580 const WS_INT8_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
1581 const BOOL
*value
, ULONG size
)
1583 WS_XML_UTF8_TEXT utf8
;
1584 unsigned char buf
[5]; /* "-128" */
1590 FIXME( "description not supported\n" );
1594 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
1595 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(INT8
), (const void **)&ptr
)) != S_OK
) return hr
;
1596 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
1598 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
1599 utf8
.value
.bytes
= buf
;
1600 utf8
.value
.length
= format_int8( ptr
, buf
);
1601 return write_type_text( writer
, mapping
, &utf8
.text
);
1604 static HRESULT
write_type_int16( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1605 const WS_INT16_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
1606 const BOOL
*value
, ULONG size
)
1608 WS_XML_UTF8_TEXT utf8
;
1609 unsigned char buf
[7]; /* "-32768" */
1615 FIXME( "description not supported\n" );
1619 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
1620 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(INT16
), (const void **)&ptr
)) != S_OK
) return hr
;
1621 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
1623 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
1624 utf8
.value
.bytes
= buf
;
1625 utf8
.value
.length
= format_int16( ptr
, buf
);
1626 return write_type_text( writer
, mapping
, &utf8
.text
);
1629 static HRESULT
write_type_int32( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1630 const WS_INT32_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
1631 const void *value
, ULONG size
)
1633 WS_XML_UTF8_TEXT utf8
;
1634 unsigned char buf
[12]; /* "-2147483648" */
1640 FIXME( "description not supported\n" );
1644 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
1645 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(INT32
), (const void **)&ptr
)) != S_OK
) return hr
;
1646 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
1648 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
1649 utf8
.value
.bytes
= buf
;
1650 utf8
.value
.length
= format_int32( ptr
, buf
);
1651 return write_type_text( writer
, mapping
, &utf8
.text
);
1654 static HRESULT
write_type_int64( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1655 const WS_INT64_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
1656 const void *value
, ULONG size
)
1658 WS_XML_UTF8_TEXT utf8
;
1659 unsigned char buf
[21]; /* "-9223372036854775808" */
1665 FIXME( "description not supported\n" );
1669 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
1670 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(INT64
), (const void **)&ptr
)) != S_OK
) return hr
;
1671 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
1673 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
1674 utf8
.value
.bytes
= buf
;
1675 utf8
.value
.length
= format_int64( ptr
, buf
);
1676 return write_type_text( writer
, mapping
, &utf8
.text
);
1679 static HRESULT
write_type_uint8( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1680 const WS_UINT8_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
1681 const void *value
, ULONG size
)
1683 WS_XML_UTF8_TEXT utf8
;
1684 unsigned char buf
[4]; /* "255" */
1690 FIXME( "description not supported\n" );
1694 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
1695 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(UINT8
), (const void **)&ptr
)) != S_OK
) return hr
;
1696 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
1698 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
1699 utf8
.value
.bytes
= buf
;
1700 utf8
.value
.length
= format_uint8( ptr
, buf
);
1701 return write_type_text( writer
, mapping
, &utf8
.text
);
1704 static HRESULT
write_type_uint16( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1705 const WS_UINT16_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
1706 const void *value
, ULONG size
)
1708 WS_XML_UTF8_TEXT utf8
;
1709 unsigned char buf
[6]; /* "65535" */
1715 FIXME( "description not supported\n" );
1719 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
1720 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(UINT16
), (const void **)&ptr
)) != S_OK
) return hr
;
1721 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
1723 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
1724 utf8
.value
.bytes
= buf
;
1725 utf8
.value
.length
= format_uint16( ptr
, buf
);
1726 return write_type_text( writer
, mapping
, &utf8
.text
);
1729 static HRESULT
write_type_uint32( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1730 const WS_UINT32_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
1731 const void *value
, ULONG size
)
1733 WS_XML_UTF8_TEXT utf8
;
1734 unsigned char buf
[11]; /* "4294967295" */
1740 FIXME( "description not supported\n" );
1744 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
1745 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(UINT32
), (const void **)&ptr
)) != S_OK
) return hr
;
1746 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
1748 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
1749 utf8
.value
.bytes
= buf
;
1750 utf8
.value
.length
= format_uint32( ptr
, buf
);
1751 return write_type_text( writer
, mapping
, &utf8
.text
);
1754 static HRESULT
write_type_uint64( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1755 const WS_UINT64_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
1756 const void *value
, ULONG size
)
1758 WS_XML_UTF8_TEXT utf8
;
1759 unsigned char buf
[21]; /* "18446744073709551615" */
1765 FIXME( "description not supported\n" );
1769 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
1770 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(UINT64
), (const void **)&ptr
)) != S_OK
) return hr
;
1771 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
1773 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
1774 utf8
.value
.bytes
= buf
;
1775 utf8
.value
.length
= format_uint64( ptr
, buf
);
1776 return write_type_text( writer
, mapping
, &utf8
.text
);
1779 static HRESULT
write_type_datetime( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1780 const WS_DATETIME_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
1781 const void *value
, ULONG size
)
1783 WS_XML_UTF8_TEXT utf8
;
1784 unsigned char buf
[34]; /* "0000-00-00T00:00:00.0000000-00:00" */
1785 const WS_DATETIME
*ptr
;
1790 FIXME( "description not supported\n" );
1794 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
1795 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(WS_DATETIME
), (const void **)&ptr
)) != S_OK
) return hr
;
1796 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
1797 if (ptr
->ticks
> TICKS_MAX
|| ptr
->format
> WS_DATETIME_FORMAT_NONE
) return WS_E_INVALID_FORMAT
;
1799 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
1800 utf8
.value
.bytes
= buf
;
1801 utf8
.value
.length
= format_datetime( ptr
, buf
);
1802 return write_type_text( writer
, mapping
, &utf8
.text
);
1805 static HRESULT
write_type_guid( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1806 const WS_GUID_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
1807 const void *value
, ULONG size
)
1809 WS_XML_UTF8_TEXT utf8
;
1810 unsigned char buf
[37]; /* "00000000-0000-0000-0000-000000000000" */
1816 FIXME( "description not supported\n" );
1820 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
1821 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(GUID
), (const void **)&ptr
)) != S_OK
) return hr
;
1822 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
1824 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
1825 utf8
.value
.bytes
= buf
;
1826 utf8
.value
.length
= format_guid( ptr
, buf
);
1827 return write_type_text( writer
, mapping
, &utf8
.text
);
1830 static HRESULT
write_type_string( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1831 const WS_STRING_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
1832 const void *value
, ULONG size
)
1834 WS_XML_UTF16_TEXT utf16
;
1835 const WS_STRING
*ptr
;
1840 FIXME( "description not supported\n" );
1844 if (!option
) return E_INVALIDARG
;
1845 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(WS_STRING
), (const void **)&ptr
)) != S_OK
) return hr
;
1846 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
1847 if (!ptr
->length
) return S_OK
;
1849 utf16
.text
.textType
= WS_XML_TEXT_TYPE_UTF16
;
1850 utf16
.bytes
= (BYTE
*)ptr
->chars
;
1851 utf16
.byteCount
= ptr
->length
* sizeof(WCHAR
);
1852 return write_type_text( writer
, mapping
, &utf16
.text
);
1855 static HRESULT
write_type_wsz( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1856 const WS_WSZ_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
1857 const void *value
, ULONG size
)
1859 WS_XML_UTF16_TEXT utf16
;
1866 FIXME( "description not supported\n" );
1870 if (!option
|| option
== WS_WRITE_REQUIRED_VALUE
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
1871 if ((hr
= get_value_ptr( option
, value
, size
, 0, (const void **)&ptr
)) != S_OK
) return hr
;
1872 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
1873 if (!(len
= strlenW( ptr
))) return S_OK
;
1875 utf16
.text
.textType
= WS_XML_TEXT_TYPE_UTF16
;
1876 utf16
.bytes
= (BYTE
*)ptr
;
1877 utf16
.byteCount
= len
* sizeof(WCHAR
);
1878 return write_type_text( writer
, mapping
, &utf16
.text
);
1881 static HRESULT
write_type_bytes( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1882 const WS_BYTES_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
1883 const void *value
, ULONG size
)
1885 WS_XML_BASE64_TEXT base64
;
1886 const WS_BYTES
*ptr
;
1891 FIXME( "description not supported\n" );
1895 if (!option
) return E_INVALIDARG
;
1896 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(WS_BYTES
), (const void **)&ptr
)) != S_OK
) return hr
;
1897 if ((option
== WS_WRITE_NILLABLE_VALUE
&& is_nil_value( value
, size
)) ||
1898 (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
)) return write_add_nil_attribute( writer
);
1899 if (!ptr
->length
) return S_OK
;
1901 base64
.text
.textType
= WS_XML_TEXT_TYPE_BASE64
;
1902 base64
.bytes
= ptr
->bytes
;
1903 base64
.length
= ptr
->length
;
1904 return write_type_text( writer
, mapping
, &base64
.text
);
1907 static HRESULT
write_type_xml_string( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1908 const WS_XML_STRING_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
1909 const void *value
, ULONG size
)
1911 WS_XML_UTF8_TEXT utf8
;
1912 const WS_XML_STRING
*ptr
;
1917 FIXME( "description not supported\n" );
1921 if (!option
) return E_INVALIDARG
;
1922 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(WS_XML_STRING
), (const void **)&ptr
)) != S_OK
) return hr
;
1923 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
1924 if (option
== WS_WRITE_NILLABLE_VALUE
&& is_nil_value( value
, size
)) return write_add_nil_attribute( writer
);
1925 if (!ptr
->length
) return S_OK
;
1927 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
1928 utf8
.value
.bytes
= ptr
->bytes
;
1929 utf8
.value
.length
= ptr
->length
;
1930 return write_type_text( writer
, mapping
, &utf8
.text
);
1933 static HRESULT
write_type( struct writer
*, WS_TYPE_MAPPING
, WS_TYPE
, const void *, WS_WRITE_OPTION
,
1934 const void *, ULONG
);
1936 static HRESULT
write_type_struct_field( struct writer
*writer
, const WS_FIELD_DESCRIPTION
*desc
,
1937 const void *value
, ULONG size
)
1940 WS_TYPE_MAPPING mapping
;
1941 WS_WRITE_OPTION option
;
1942 ULONG field_options
= desc
->options
;
1944 if (field_options
& ~(WS_FIELD_POINTER
|WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
))
1946 FIXME( "options 0x%x not supported\n", desc
->options
);
1950 /* zero-terminated strings are always pointers */
1951 if (desc
->type
== WS_WSZ_TYPE
) field_options
|= WS_FIELD_POINTER
;
1953 if (is_nil_value( value
, size
))
1955 if (field_options
& WS_FIELD_OPTIONAL
) return S_OK
;
1956 if (field_options
& WS_FIELD_NILLABLE
)
1958 if (field_options
& WS_FIELD_POINTER
) option
= WS_WRITE_NILLABLE_POINTER
;
1959 else option
= WS_WRITE_NILLABLE_VALUE
;
1961 else return E_INVALIDARG
;
1965 if (field_options
& WS_FIELD_POINTER
) option
= WS_WRITE_REQUIRED_POINTER
;
1966 else option
= WS_WRITE_REQUIRED_VALUE
;
1969 switch (desc
->mapping
)
1971 case WS_ATTRIBUTE_FIELD_MAPPING
:
1972 if (!desc
->localName
|| !desc
->ns
) return E_INVALIDARG
;
1973 if ((hr
= write_add_attribute( writer
, NULL
, desc
->localName
, desc
->ns
, FALSE
)) != S_OK
)
1975 writer
->state
= WRITER_STATE_STARTATTRIBUTE
;
1977 mapping
= WS_ATTRIBUTE_TYPE_MAPPING
;
1980 case WS_ELEMENT_FIELD_MAPPING
:
1981 if ((hr
= write_element_node( writer
, NULL
, desc
->localName
, desc
->ns
)) != S_OK
) return hr
;
1982 mapping
= WS_ELEMENT_TYPE_MAPPING
;
1985 case WS_TEXT_FIELD_MAPPING
:
1986 switch (writer
->state
)
1988 case WRITER_STATE_STARTELEMENT
:
1989 mapping
= WS_ELEMENT_CONTENT_TYPE_MAPPING
;
1992 case WRITER_STATE_STARTATTRIBUTE
:
1993 mapping
= WS_ATTRIBUTE_TYPE_MAPPING
;
1997 FIXME( "unhandled writer state %u\n", writer
->state
);
2003 FIXME( "field mapping %u not supported\n", desc
->mapping
);
2007 if ((hr
= write_type( writer
, mapping
, desc
->type
, desc
->typeDescription
, option
, value
, size
)) != S_OK
)
2012 case WS_ATTRIBUTE_TYPE_MAPPING
:
2013 writer
->state
= WRITER_STATE_STARTELEMENT
;
2016 case WS_ELEMENT_TYPE_MAPPING
:
2017 if ((hr
= write_endelement_node( writer
)) != S_OK
) return hr
;
2026 static ULONG
get_field_size( const WS_STRUCT_DESCRIPTION
*desc
, ULONG index
)
2028 if (index
< desc
->fieldCount
- 1) return desc
->fields
[index
+ 1]->offset
- desc
->fields
[index
]->offset
;
2029 return desc
->size
- desc
->fields
[index
]->offset
;
2032 static HRESULT
write_type_struct( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
2033 const WS_STRUCT_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
2034 const void *value
, ULONG size
)
2036 ULONG i
, field_size
;
2037 const void *ptr
, *field_ptr
;
2040 if (!desc
) return E_INVALIDARG
;
2041 if (desc
->structOptions
) FIXME( "struct options 0x%x not supported\n", desc
->structOptions
);
2043 if ((hr
= get_value_ptr( option
, value
, size
, desc
->size
, (const void **)&ptr
)) != S_OK
) return hr
;
2045 for (i
= 0; i
< desc
->fieldCount
; i
++)
2047 field_ptr
= (const char *)ptr
+ desc
->fields
[i
]->offset
;
2048 field_size
= get_field_size( desc
, i
);
2049 if ((hr
= write_type_struct_field( writer
, desc
->fields
[i
], field_ptr
, field_size
)) != S_OK
)
2057 static HRESULT
write_type( struct writer
*writer
, WS_TYPE_MAPPING mapping
, WS_TYPE type
,
2058 const void *desc
, WS_WRITE_OPTION option
, const void *value
,
2064 return write_type_bool( writer
, mapping
, desc
, option
, value
, size
);
2067 return write_type_int8( writer
, mapping
, desc
, option
, value
, size
);
2070 return write_type_int16( writer
, mapping
, desc
, option
, value
, size
);
2073 return write_type_int32( writer
, mapping
, desc
, option
, value
, size
);
2076 return write_type_int64( writer
, mapping
, desc
, option
, value
, size
);
2079 return write_type_uint8( writer
, mapping
, desc
, option
, value
, size
);
2081 case WS_UINT16_TYPE
:
2082 return write_type_uint16( writer
, mapping
, desc
, option
, value
, size
);
2084 case WS_UINT32_TYPE
:
2085 return write_type_uint32( writer
, mapping
, desc
, option
, value
, size
);
2087 case WS_UINT64_TYPE
:
2088 return write_type_uint64( writer
, mapping
, desc
, option
, value
, size
);
2090 case WS_DATETIME_TYPE
:
2091 return write_type_datetime( writer
, mapping
, desc
, option
, value
, size
);
2094 return write_type_guid( writer
, mapping
, desc
, option
, value
, size
);
2096 case WS_STRING_TYPE
:
2097 return write_type_string( writer
, mapping
, desc
, option
, value
, size
);
2100 return write_type_wsz( writer
, mapping
, desc
, option
, value
, size
);
2103 return write_type_bytes( writer
, mapping
, desc
, option
, value
, size
);
2105 case WS_XML_STRING_TYPE
:
2106 return write_type_xml_string( writer
, mapping
, desc
, option
, value
, size
);
2108 case WS_STRUCT_TYPE
:
2109 return write_type_struct( writer
, mapping
, desc
, option
, value
, size
);
2112 FIXME( "type %u not supported\n", type
);
2117 /**************************************************************************
2118 * WsWriteAttribute [webservices.@]
2120 HRESULT WINAPI
WsWriteAttribute( WS_XML_WRITER
*handle
, const WS_ATTRIBUTE_DESCRIPTION
*desc
,
2121 WS_WRITE_OPTION option
, const void *value
, ULONG size
,
2124 struct writer
*writer
= (struct writer
*)handle
;
2127 TRACE( "%p %p %u %p %u %p\n", handle
, desc
, option
, value
, size
, error
);
2128 if (error
) FIXME( "ignoring error parameter\n" );
2130 if (!writer
|| !desc
|| !desc
->attributeLocalName
|| !desc
->attributeNs
|| !value
)
2131 return E_INVALIDARG
;
2133 if (writer
->state
!= WRITER_STATE_STARTELEMENT
) return WS_E_INVALID_OPERATION
;
2135 if ((hr
= write_add_attribute( writer
, NULL
, desc
->attributeLocalName
, desc
->attributeNs
,
2136 FALSE
)) != S_OK
) return hr
;
2137 writer
->state
= WRITER_STATE_STARTATTRIBUTE
;
2139 return write_type( writer
, WS_ATTRIBUTE_TYPE_MAPPING
, desc
->type
, desc
->typeDescription
,
2140 option
, value
, size
);
2143 /**************************************************************************
2144 * WsWriteElement [webservices.@]
2146 HRESULT WINAPI
WsWriteElement( WS_XML_WRITER
*handle
, const WS_ELEMENT_DESCRIPTION
*desc
,
2147 WS_WRITE_OPTION option
, const void *value
, ULONG size
,
2150 struct writer
*writer
= (struct writer
*)handle
;
2153 TRACE( "%p %p %u %p %u %p\n", handle
, desc
, option
, value
, size
, error
);
2154 if (error
) FIXME( "ignoring error parameter\n" );
2156 if (!writer
|| !desc
|| !desc
->elementLocalName
|| !desc
->elementNs
|| !value
)
2157 return E_INVALIDARG
;
2159 if ((hr
= write_element_node( writer
, NULL
, desc
->elementLocalName
, desc
->elementNs
)) != S_OK
) return hr
;
2161 if ((hr
= write_type( writer
, WS_ANY_ELEMENT_TYPE_MAPPING
, desc
->type
, desc
->typeDescription
,
2162 option
, value
, size
)) != S_OK
) return hr
;
2164 return write_endelement_node( writer
);
2167 /**************************************************************************
2168 * WsWriteType [webservices.@]
2170 HRESULT WINAPI
WsWriteType( WS_XML_WRITER
*handle
, WS_TYPE_MAPPING mapping
, WS_TYPE type
,
2171 const void *desc
, WS_WRITE_OPTION option
, const void *value
,
2172 ULONG size
, WS_ERROR
*error
)
2174 struct writer
*writer
= (struct writer
*)handle
;
2177 TRACE( "%p %u %u %p %u %p %u %p\n", handle
, mapping
, type
, desc
, option
, value
,
2179 if (error
) FIXME( "ignoring error parameter\n" );
2181 if (!writer
|| !value
) return E_INVALIDARG
;
2185 case WS_ATTRIBUTE_TYPE_MAPPING
:
2186 if (writer
->state
!= WRITER_STATE_STARTATTRIBUTE
) return WS_E_INVALID_FORMAT
;
2187 hr
= write_type( writer
, mapping
, type
, desc
, option
, value
, size
);
2190 case WS_ELEMENT_TYPE_MAPPING
:
2191 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
2192 if (writer
->state
!= WRITER_STATE_STARTELEMENT
) return WS_E_INVALID_FORMAT
;
2193 hr
= write_type( writer
, mapping
, type
, desc
, option
, value
, size
);
2196 case WS_ANY_ELEMENT_TYPE_MAPPING
:
2197 hr
= write_type( writer
, mapping
, type
, desc
, option
, value
, size
);
2201 FIXME( "mapping %u not implemented\n", mapping
);
2208 WS_TYPE
map_value_type( WS_VALUE_TYPE type
)
2212 case WS_BOOL_VALUE_TYPE
: return WS_BOOL_TYPE
;
2213 case WS_INT8_VALUE_TYPE
: return WS_INT8_TYPE
;
2214 case WS_INT16_VALUE_TYPE
: return WS_INT16_TYPE
;
2215 case WS_INT32_VALUE_TYPE
: return WS_INT32_TYPE
;
2216 case WS_INT64_VALUE_TYPE
: return WS_INT64_TYPE
;
2217 case WS_UINT8_VALUE_TYPE
: return WS_UINT8_TYPE
;
2218 case WS_UINT16_VALUE_TYPE
: return WS_UINT16_TYPE
;
2219 case WS_UINT32_VALUE_TYPE
: return WS_UINT32_TYPE
;
2220 case WS_UINT64_VALUE_TYPE
: return WS_UINT64_TYPE
;
2221 case WS_FLOAT_VALUE_TYPE
: return WS_FLOAT_TYPE
;
2222 case WS_DOUBLE_VALUE_TYPE
: return WS_DOUBLE_TYPE
;
2223 case WS_DECIMAL_VALUE_TYPE
: return WS_DECIMAL_TYPE
;
2224 case WS_DATETIME_VALUE_TYPE
: return WS_DATETIME_TYPE
;
2225 case WS_TIMESPAN_VALUE_TYPE
: return WS_TIMESPAN_TYPE
;
2226 case WS_GUID_VALUE_TYPE
: return WS_GUID_TYPE
;
2228 FIXME( "unhandled type %u\n", type
);
2233 /**************************************************************************
2234 * WsWriteValue [webservices.@]
2236 HRESULT WINAPI
WsWriteValue( WS_XML_WRITER
*handle
, WS_VALUE_TYPE value_type
, const void *value
,
2237 ULONG size
, WS_ERROR
*error
)
2239 struct writer
*writer
= (struct writer
*)handle
;
2240 WS_TYPE_MAPPING mapping
;
2243 TRACE( "%p %u %p %u %p\n", handle
, value_type
, value
, size
, error
);
2244 if (error
) FIXME( "ignoring error parameter\n" );
2246 if (!writer
|| !value
|| (type
= map_value_type( value_type
)) == ~0u) return E_INVALIDARG
;
2248 switch (writer
->state
)
2250 case WRITER_STATE_STARTATTRIBUTE
:
2251 mapping
= WS_ATTRIBUTE_TYPE_MAPPING
;
2254 case WRITER_STATE_STARTELEMENT
:
2255 mapping
= WS_ELEMENT_TYPE_MAPPING
;
2259 return WS_E_INVALID_FORMAT
;
2262 return write_type( writer
, mapping
, type
, NULL
, WS_WRITE_REQUIRED_VALUE
, value
, size
);
2265 /**************************************************************************
2266 * WsWriteArray [webservices.@]
2268 HRESULT WINAPI
WsWriteArray( WS_XML_WRITER
*handle
, const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
2269 WS_VALUE_TYPE value_type
, const void *array
, ULONG size
, ULONG offset
,
2270 ULONG count
, WS_ERROR
*error
)
2272 struct writer
*writer
= (struct writer
*)handle
;
2277 TRACE( "%p %s %s %u %p %u %u %u %p\n", handle
, debugstr_xmlstr(localname
), debugstr_xmlstr(ns
),
2278 value_type
, array
, size
, offset
, count
, error
);
2279 if (error
) FIXME( "ignoring error parameter\n" );
2281 if (!writer
) return E_INVALIDARG
;
2282 if (!writer
->output_type
) return WS_E_INVALID_OPERATION
;
2283 if (!localname
|| !ns
|| (type
= map_value_type( value_type
)) == ~0u) return E_INVALIDARG
;
2285 type_size
= get_type_size( type
, NULL
);
2286 if (size
% type_size
|| (offset
+ count
) * type_size
> size
|| (count
&& !array
)) return E_INVALIDARG
;
2288 for (i
= offset
; i
< count
; i
++)
2290 const char *ptr
= (const char *)array
+ (offset
+ i
) * type_size
;
2291 if ((hr
= write_element_node( writer
, NULL
, localname
, ns
)) != S_OK
) return hr
;
2292 if ((hr
= write_type( writer
, WS_ELEMENT_TYPE_MAPPING
, type
, NULL
, WS_WRITE_REQUIRED_POINTER
,
2293 &ptr
, sizeof(ptr
) )) != S_OK
) return hr
;
2294 if ((hr
= write_endelement_node( writer
)) != S_OK
) return hr
;
2300 /**************************************************************************
2301 * WsWriteXmlBuffer [webservices.@]
2303 HRESULT WINAPI
WsWriteXmlBuffer( WS_XML_WRITER
*handle
, WS_XML_BUFFER
*buffer
, WS_ERROR
*error
)
2305 struct writer
*writer
= (struct writer
*)handle
;
2306 struct xmlbuf
*xmlbuf
= (struct xmlbuf
*)buffer
;
2309 TRACE( "%p %p %p\n", handle
, buffer
, error
);
2310 if (error
) FIXME( "ignoring error parameter\n" );
2312 if (!writer
|| !xmlbuf
) return E_INVALIDARG
;
2314 if ((hr
= write_flush( writer
)) != S_OK
) return hr
;
2315 if ((hr
= write_grow_buffer( writer
, xmlbuf
->size
)) != S_OK
) return hr
;
2316 write_bytes( writer
, xmlbuf
->ptr
, xmlbuf
->size
);
2320 /**************************************************************************
2321 * WsWriteXmlBufferToBytes [webservices.@]
2323 HRESULT WINAPI
WsWriteXmlBufferToBytes( WS_XML_WRITER
*handle
, WS_XML_BUFFER
*buffer
,
2324 const WS_XML_WRITER_ENCODING
*encoding
,
2325 const WS_XML_WRITER_PROPERTY
*properties
, ULONG count
,
2326 WS_HEAP
*heap
, void **bytes
, ULONG
*size
, WS_ERROR
*error
)
2328 struct writer
*writer
= (struct writer
*)handle
;
2329 struct xmlbuf
*xmlbuf
= (struct xmlbuf
*)buffer
;
2334 TRACE( "%p %p %p %p %u %p %p %p %p\n", handle
, buffer
, encoding
, properties
, count
, heap
,
2335 bytes
, size
, error
);
2336 if (error
) FIXME( "ignoring error parameter\n" );
2338 if (!writer
|| !xmlbuf
|| !heap
|| !bytes
) return E_INVALIDARG
;
2340 if (encoding
&& encoding
->encodingType
!= WS_XML_WRITER_ENCODING_TYPE_TEXT
)
2342 FIXME( "encoding type %u not supported\n", encoding
->encodingType
);
2346 for (i
= 0; i
< count
; i
++)
2348 hr
= prop_set( writer
->prop
, writer
->prop_count
, properties
[i
].id
, properties
[i
].value
,
2349 properties
[i
].valueSize
);
2350 if (hr
!= S_OK
) return hr
;
2353 if (!(buf
= ws_alloc( heap
, xmlbuf
->size
))) return WS_E_QUOTA_EXCEEDED
;
2354 memcpy( buf
, xmlbuf
->ptr
, xmlbuf
->size
);
2356 *size
= xmlbuf
->size
;
2360 /**************************************************************************
2361 * WsWriteXmlnsAttribute [webservices.@]
2363 HRESULT WINAPI
WsWriteXmlnsAttribute( WS_XML_WRITER
*handle
, const WS_XML_STRING
*prefix
,
2364 const WS_XML_STRING
*ns
, BOOL single
, WS_ERROR
*error
)
2366 struct writer
*writer
= (struct writer
*)handle
;
2368 TRACE( "%p %s %s %d %p\n", handle
, debugstr_xmlstr(prefix
), debugstr_xmlstr(ns
),
2370 if (error
) FIXME( "ignoring error parameter\n" );
2372 if (!writer
|| !ns
) return E_INVALIDARG
;
2373 if (writer
->state
!= WRITER_STATE_STARTELEMENT
) return WS_E_INVALID_OPERATION
;
2375 if (namespace_in_scope( &writer
->current
->hdr
, prefix
, ns
)) return S_OK
;
2376 return write_add_namespace_attribute( writer
, prefix
, ns
, single
);
2379 static HRESULT
write_move_to( struct writer
*writer
, WS_MOVE_TO move
, BOOL
*found
)
2381 BOOL success
= FALSE
;
2382 struct node
*node
= writer
->current
;
2386 case WS_MOVE_TO_ROOT_ELEMENT
:
2387 success
= move_to_root_element( writer
->root
, &node
);
2390 case WS_MOVE_TO_NEXT_ELEMENT
:
2391 success
= move_to_next_element( &node
);
2394 case WS_MOVE_TO_PREVIOUS_ELEMENT
:
2395 success
= move_to_prev_element( &node
);
2398 case WS_MOVE_TO_CHILD_ELEMENT
:
2399 success
= move_to_child_element( &node
);
2402 case WS_MOVE_TO_END_ELEMENT
:
2403 success
= move_to_end_element( &node
);
2406 case WS_MOVE_TO_PARENT_ELEMENT
:
2407 success
= move_to_parent_element( &node
);
2410 case WS_MOVE_TO_FIRST_NODE
:
2411 success
= move_to_first_node( &node
);
2414 case WS_MOVE_TO_NEXT_NODE
:
2415 success
= move_to_next_node( &node
);
2418 case WS_MOVE_TO_PREVIOUS_NODE
:
2419 success
= move_to_prev_node( &node
);
2422 case WS_MOVE_TO_CHILD_NODE
:
2423 success
= move_to_child_node( &node
);
2426 case WS_MOVE_TO_BOF
:
2427 success
= move_to_bof( writer
->root
, &node
);
2430 case WS_MOVE_TO_EOF
:
2431 success
= move_to_eof( writer
->root
, &node
);
2435 FIXME( "unhandled move %u\n", move
);
2439 if (success
&& node
== writer
->root
) return E_INVALIDARG
;
2440 writer
->current
= node
;
2447 return success
? S_OK
: WS_E_INVALID_FORMAT
;
2450 /**************************************************************************
2451 * WsMoveWriter [webservices.@]
2453 HRESULT WINAPI
WsMoveWriter( WS_XML_WRITER
*handle
, WS_MOVE_TO move
, BOOL
*found
, WS_ERROR
*error
)
2455 struct writer
*writer
= (struct writer
*)handle
;
2457 TRACE( "%p %u %p %p\n", handle
, move
, found
, error
);
2458 if (error
) FIXME( "ignoring error parameter\n" );
2460 if (!writer
) return E_INVALIDARG
;
2461 if (!writer
->output_type
) return WS_E_INVALID_OPERATION
;
2463 return write_move_to( writer
, move
, found
);
2466 /**************************************************************************
2467 * WsGetWriterPosition [webservices.@]
2469 HRESULT WINAPI
WsGetWriterPosition( WS_XML_WRITER
*handle
, WS_XML_NODE_POSITION
*pos
, WS_ERROR
*error
)
2471 struct writer
*writer
= (struct writer
*)handle
;
2473 TRACE( "%p %p %p\n", handle
, pos
, error
);
2474 if (error
) FIXME( "ignoring error parameter\n" );
2476 if (!writer
|| !pos
) return E_INVALIDARG
;
2477 if (!writer
->output_type
) return WS_E_INVALID_OPERATION
;
2479 pos
->buffer
= (WS_XML_BUFFER
*)writer
->output_buf
;
2480 pos
->node
= writer
->current
;
2484 /**************************************************************************
2485 * WsSetWriterPosition [webservices.@]
2487 HRESULT WINAPI
WsSetWriterPosition( WS_XML_WRITER
*handle
, const WS_XML_NODE_POSITION
*pos
, WS_ERROR
*error
)
2489 struct writer
*writer
= (struct writer
*)handle
;
2491 TRACE( "%p %p %p\n", handle
, pos
, error
);
2492 if (error
) FIXME( "ignoring error parameter\n" );
2494 if (!writer
|| !pos
|| (struct xmlbuf
*)pos
->buffer
!= writer
->output_buf
) return E_INVALIDARG
;
2495 if (!writer
->output_type
) return WS_E_INVALID_OPERATION
;
2497 writer
->current
= pos
->node
;
2501 static HRESULT
write_add_comment_node( struct writer
*writer
, const WS_XML_STRING
*value
)
2503 struct node
*node
, *parent
;
2504 WS_XML_COMMENT_NODE
*comment
;
2506 if (!(parent
= find_parent( writer
->current
))) return WS_E_INVALID_FORMAT
;
2507 if (!(node
= alloc_node( WS_XML_NODE_TYPE_COMMENT
))) return E_OUTOFMEMORY
;
2508 comment
= (WS_XML_COMMENT_NODE
*)node
;
2510 if (value
->length
&& !(comment
->value
.bytes
= heap_alloc( value
->length
)))
2513 return E_OUTOFMEMORY
;
2515 memcpy( comment
->value
.bytes
, value
->bytes
, value
->length
);
2516 comment
->value
.length
= value
->length
;
2518 write_insert_node( writer
, parent
, node
);
2522 static HRESULT
write_comment( struct writer
*writer
)
2524 const WS_XML_COMMENT_NODE
*comment
= (const WS_XML_COMMENT_NODE
*)writer
->current
;
2527 if ((hr
= write_grow_buffer( writer
, comment
->value
.length
+ 7 )) != S_OK
) return hr
;
2528 write_bytes( writer
, (const BYTE
*)"<!--", 4 );
2529 write_bytes( writer
, comment
->value
.bytes
, comment
->value
.length
);
2530 write_bytes( writer
, (const BYTE
*)"-->", 3 );
2534 static HRESULT
write_comment_node( struct writer
*writer
, const WS_XML_STRING
*value
)
2537 if ((hr
= write_flush( writer
)) != S_OK
) return hr
;
2538 if ((hr
= write_add_comment_node( writer
, value
)) != S_OK
) return hr
;
2539 if ((hr
= write_comment( writer
)) != S_OK
) return hr
;
2540 writer
->state
= WRITER_STATE_COMMENT
;
2544 static HRESULT
write_set_attributes( struct writer
*writer
, WS_XML_ATTRIBUTE
**attrs
, ULONG count
)
2549 for (i
= 0; i
< count
; i
++)
2551 if ((hr
= write_add_attribute( writer
, attrs
[i
]->prefix
, attrs
[i
]->localName
, attrs
[i
]->ns
,
2552 attrs
[i
]->singleQuote
)) != S_OK
) return hr
;
2553 if ((hr
= write_set_attribute_value( writer
, attrs
[i
]->value
)) != S_OK
) return hr
;
2558 static HRESULT
write_node( struct writer
*writer
, const WS_XML_NODE
*node
)
2562 switch (node
->nodeType
)
2564 case WS_XML_NODE_TYPE_ELEMENT
:
2566 const WS_XML_ELEMENT_NODE
*elem
= (const WS_XML_ELEMENT_NODE
*)node
;
2567 if ((hr
= write_element_node( writer
, elem
->prefix
, elem
->localName
, elem
->ns
)) != S_OK
) return hr
;
2568 return write_set_attributes( writer
, elem
->attributes
, elem
->attributeCount
);
2570 case WS_XML_NODE_TYPE_TEXT
:
2572 const WS_XML_TEXT_NODE
*text
= (const WS_XML_TEXT_NODE
*)node
;
2573 return write_text_node( writer
, text
->text
);
2575 case WS_XML_NODE_TYPE_END_ELEMENT
:
2576 return write_endelement_node( writer
);
2578 case WS_XML_NODE_TYPE_COMMENT
:
2580 const WS_XML_COMMENT_NODE
*comment
= (const WS_XML_COMMENT_NODE
*)node
;
2581 return write_comment_node( writer
, &comment
->value
);
2583 case WS_XML_NODE_TYPE_CDATA
:
2584 return write_cdata_node( writer
);
2586 case WS_XML_NODE_TYPE_END_CDATA
:
2587 return write_endcdata_node( writer
);
2589 case WS_XML_NODE_TYPE_EOF
:
2590 case WS_XML_NODE_TYPE_BOF
:
2594 WARN( "unknown node type %u\n", node
->nodeType
);
2595 return E_INVALIDARG
;
2599 /**************************************************************************
2600 * WsWriteNode [webservices.@]
2602 HRESULT WINAPI
WsWriteNode( WS_XML_WRITER
*handle
, const WS_XML_NODE
*node
, WS_ERROR
*error
)
2604 struct writer
*writer
= (struct writer
*)handle
;
2606 TRACE( "%p %p %p\n", handle
, node
, error
);
2607 if (error
) FIXME( "ignoring error parameter\n" );
2609 if (!writer
|| !node
) return E_INVALIDARG
;
2610 if (!writer
->output_type
) return WS_E_INVALID_OPERATION
;
2612 return write_node( writer
, node
);
2615 static HRESULT
write_tree_node( struct writer
*writer
)
2619 switch (node_type( writer
->current
))
2621 case WS_XML_NODE_TYPE_ELEMENT
:
2622 if (writer
->state
== WRITER_STATE_STARTELEMENT
&& (hr
= write_endstartelement( writer
)) != S_OK
)
2624 if ((hr
= write_startelement( writer
)) != S_OK
) return hr
;
2625 writer
->state
= WRITER_STATE_STARTELEMENT
;
2628 case WS_XML_NODE_TYPE_TEXT
:
2629 if (writer
->state
== WRITER_STATE_STARTELEMENT
&& (hr
= write_endstartelement( writer
)) != S_OK
)
2631 if ((hr
= write_text( writer
)) != S_OK
) return hr
;
2632 writer
->state
= WRITER_STATE_TEXT
;
2635 case WS_XML_NODE_TYPE_END_ELEMENT
:
2636 if ((hr
= write_close_element( writer
, writer
->current
->parent
)) != S_OK
) return hr
;
2637 writer
->state
= WRITER_STATE_ENDELEMENT
;
2640 case WS_XML_NODE_TYPE_COMMENT
:
2641 if (writer
->state
== WRITER_STATE_STARTELEMENT
&& (hr
= write_endstartelement( writer
)) != S_OK
)
2643 if ((hr
= write_comment( writer
)) != S_OK
) return hr
;
2644 writer
->state
= WRITER_STATE_COMMENT
;
2647 case WS_XML_NODE_TYPE_CDATA
:
2648 if (writer
->state
== WRITER_STATE_STARTELEMENT
&& (hr
= write_endstartelement( writer
)) != S_OK
)
2650 if ((hr
= write_cdata( writer
)) != S_OK
) return hr
;
2651 writer
->state
= WRITER_STATE_STARTCDATA
;
2654 case WS_XML_NODE_TYPE_END_CDATA
:
2655 if ((hr
= write_endcdata( writer
)) != S_OK
) return hr
;
2656 writer
->state
= WRITER_STATE_ENDCDATA
;
2659 case WS_XML_NODE_TYPE_EOF
:
2660 case WS_XML_NODE_TYPE_BOF
:
2664 ERR( "unknown node type %u\n", node_type(writer
->current
) );
2665 return E_INVALIDARG
;
2669 static HRESULT
write_tree( struct writer
*writer
)
2673 if ((hr
= write_tree_node( writer
)) != S_OK
) return hr
;
2676 if (node_type( writer
->current
) == WS_XML_NODE_TYPE_EOF
) break;
2677 if (move_to_child_node( &writer
->current
))
2679 if ((hr
= write_tree_node( writer
)) != S_OK
) return hr
;
2682 if (move_to_next_node( &writer
->current
))
2684 if ((hr
= write_tree_node( writer
)) != S_OK
) return hr
;
2687 if (!move_to_parent_node( &writer
->current
) || !move_to_next_node( &writer
->current
))
2689 ERR( "invalid tree\n" );
2690 return WS_E_INVALID_FORMAT
;
2692 if ((hr
= write_tree_node( writer
)) != S_OK
) return hr
;
2697 static void write_rewind( struct writer
*writer
)
2699 writer
->write_pos
= 0;
2700 writer
->current
= writer
->root
;
2701 writer
->state
= WRITER_STATE_INITIAL
;
2704 /**************************************************************************
2705 * WsCopyNode [webservices.@]
2707 HRESULT WINAPI
WsCopyNode( WS_XML_WRITER
*handle
, WS_XML_READER
*reader
, WS_ERROR
*error
)
2709 struct writer
*writer
= (struct writer
*)handle
;
2710 struct node
*parent
, *current
= writer
->current
, *node
= NULL
;
2713 TRACE( "%p %p %p\n", handle
, reader
, error
);
2714 if (error
) FIXME( "ignoring error parameter\n" );
2716 if (!writer
) return E_INVALIDARG
;
2717 if (!(parent
= find_parent( writer
->current
))) return WS_E_INVALID_FORMAT
;
2719 if ((hr
= copy_node( reader
, &node
)) != S_OK
) return hr
;
2720 write_insert_node( writer
, parent
, node
);
2722 write_rewind( writer
);
2723 if ((hr
= write_tree( writer
)) != S_OK
) return hr
;
2725 writer
->current
= current
;