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
26 #include "webservices.h"
28 #include "wine/debug.h"
29 #include "wine/list.h"
30 #include "wine/unicode.h"
31 #include "webservices_private.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(webservices
);
35 static const struct prop_desc writer_props
[] =
37 { sizeof(ULONG
), FALSE
}, /* WS_XML_WRITER_PROPERTY_MAX_DEPTH */
38 { sizeof(BOOL
), FALSE
}, /* WS_XML_WRITER_PROPERTY_ALLOW_FRAGMENT */
39 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_MAX_ATTRIBUTES */
40 { sizeof(BOOL
), FALSE
}, /* WS_XML_WRITER_PROPERTY_WRITE_DECLARATION */
41 { sizeof(ULONG
), FALSE
}, /* WS_XML_WRITER_PROPERTY_INDENT */
42 { sizeof(ULONG
), FALSE
}, /* WS_XML_WRITER_PROPERTY_BUFFER_TRIM_SIZE */
43 { sizeof(WS_CHARSET
), FALSE
}, /* WS_XML_WRITER_PROPERTY_CHARSET */
44 { sizeof(WS_BUFFERS
), FALSE
}, /* WS_XML_WRITER_PROPERTY_BUFFERS */
45 { sizeof(ULONG
), FALSE
}, /* WS_XML_WRITER_PROPERTY_BUFFER_MAX_SIZE */
46 { sizeof(WS_BYTES
), FALSE
}, /* WS_XML_WRITER_PROPERTY_BYTES */
47 { sizeof(BOOL
), TRUE
}, /* WS_XML_WRITER_PROPERTY_IN_ATTRIBUTE */
48 { sizeof(ULONG
), FALSE
}, /* WS_XML_WRITER_PROPERTY_MAX_MIME_PARTS_BUFFER_SIZE */
49 { sizeof(WS_BYTES
), FALSE
}, /* WS_XML_WRITER_PROPERTY_INITIAL_BUFFER */
50 { sizeof(BOOL
), FALSE
}, /* WS_XML_WRITER_PROPERTY_ALLOW_INVALID_CHARACTER_REFERENCES */
51 { sizeof(ULONG
), FALSE
}, /* WS_XML_WRITER_PROPERTY_MAX_NAMESPACES */
52 { sizeof(ULONG
), TRUE
}, /* WS_XML_WRITER_PROPERTY_BYTES_WRITTEN */
53 { sizeof(ULONG
), TRUE
}, /* WS_XML_WRITER_PROPERTY_BYTES_TO_CLOSE */
54 { sizeof(BOOL
), FALSE
}, /* WS_XML_WRITER_PROPERTY_COMPRESS_EMPTY_ELEMENTS */
55 { sizeof(BOOL
), FALSE
} /* WS_XML_WRITER_PROPERTY_EMIT_UNCOMPRESSED_EMPTY_ELEMENTS */
61 WRITER_STATE_STARTELEMENT
,
62 WRITER_STATE_STARTATTRIBUTE
,
63 WRITER_STATE_STARTCDATA
,
64 WRITER_STATE_ENDSTARTELEMENT
,
67 WRITER_STATE_ENDELEMENT
,
74 unsigned char *write_bufptr
;
75 enum writer_state state
;
78 WS_XML_STRING
*current_ns
;
79 WS_XML_WRITER_OUTPUT_TYPE output_type
;
80 struct xmlbuf
*output_buf
;
83 struct prop prop
[sizeof(writer_props
)/sizeof(writer_props
[0])];
86 static struct writer
*alloc_writer(void)
88 static const ULONG count
= sizeof(writer_props
)/sizeof(writer_props
[0]);
90 ULONG size
= sizeof(*ret
) + prop_size( writer_props
, count
);
92 if (!(ret
= heap_alloc_zero( size
))) return NULL
;
93 prop_init( writer_props
, count
, ret
->prop
, &ret
[1] );
94 ret
->prop_count
= count
;
98 static void free_writer( struct writer
*writer
)
100 destroy_nodes( writer
->root
);
101 heap_free( writer
->current_ns
);
102 WsFreeHeap( writer
->output_heap
);
106 static void write_insert_eof( struct writer
*writer
, struct node
*eof
)
108 if (!writer
->root
) writer
->root
= eof
;
111 eof
->parent
= writer
->root
;
112 list_add_tail( &writer
->root
->children
, &eof
->entry
);
114 writer
->current
= eof
;
117 static void write_insert_bof( struct writer
*writer
, struct node
*bof
)
119 writer
->root
->parent
= bof
;
120 list_add_tail( &bof
->children
, &writer
->root
->entry
);
121 writer
->current
= writer
->root
= bof
;
124 static void write_insert_node( struct writer
*writer
, struct node
*parent
, struct node
*node
)
126 node
->parent
= parent
;
127 list_add_before( list_tail( &parent
->children
), &node
->entry
);
128 writer
->current
= node
;
131 static HRESULT
write_init_state( struct writer
*writer
)
135 heap_free( writer
->current_ns
);
136 writer
->current_ns
= NULL
;
137 destroy_nodes( writer
->root
);
140 if (!(node
= alloc_node( WS_XML_NODE_TYPE_EOF
))) return E_OUTOFMEMORY
;
141 write_insert_eof( writer
, node
);
142 writer
->state
= WRITER_STATE_INITIAL
;
146 /**************************************************************************
147 * WsCreateWriter [webservices.@]
149 HRESULT WINAPI
WsCreateWriter( const WS_XML_WRITER_PROPERTY
*properties
, ULONG count
,
150 WS_XML_WRITER
**handle
, WS_ERROR
*error
)
152 struct writer
*writer
;
153 ULONG i
, max_depth
= 32, max_attrs
= 128, trim_size
= 4096, max_size
= 65536, max_ns
= 32;
154 WS_CHARSET charset
= WS_CHARSET_UTF8
;
157 TRACE( "%p %u %p %p\n", properties
, count
, handle
, error
);
158 if (error
) FIXME( "ignoring error parameter\n" );
160 if (!handle
) return E_INVALIDARG
;
161 if (!(writer
= alloc_writer())) return E_OUTOFMEMORY
;
163 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_MAX_DEPTH
, &max_depth
, sizeof(max_depth
) );
164 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_MAX_ATTRIBUTES
, &max_attrs
, sizeof(max_attrs
) );
165 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_BUFFER_TRIM_SIZE
, &trim_size
, sizeof(trim_size
) );
166 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_CHARSET
, &charset
, sizeof(charset
) );
167 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_BUFFER_MAX_SIZE
, &max_size
, sizeof(max_size
) );
168 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_MAX_MIME_PARTS_BUFFER_SIZE
, &max_size
, sizeof(max_size
) );
169 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_MAX_NAMESPACES
, &max_ns
, sizeof(max_ns
) );
171 for (i
= 0; i
< count
; i
++)
173 hr
= prop_set( writer
->prop
, writer
->prop_count
, properties
[i
].id
, properties
[i
].value
,
174 properties
[i
].valueSize
);
177 free_writer( writer
);
182 hr
= prop_get( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_BUFFER_MAX_SIZE
,
183 &max_size
, sizeof(max_size
) );
186 free_writer( writer
);
190 hr
= WsCreateHeap( max_size
, 0, NULL
, 0, &writer
->output_heap
, NULL
);
193 free_writer( writer
);
197 hr
= write_init_state( writer
);
200 free_writer( writer
);
204 *handle
= (WS_XML_WRITER
*)writer
;
208 /**************************************************************************
209 * WsFreeWriter [webservices.@]
211 void WINAPI
WsFreeWriter( WS_XML_WRITER
*handle
)
213 struct writer
*writer
= (struct writer
*)handle
;
215 TRACE( "%p\n", handle
);
216 free_writer( writer
);
219 #define XML_BUFFER_INITIAL_ALLOCATED_SIZE 256
220 static struct xmlbuf
*alloc_xmlbuf( WS_HEAP
*heap
)
224 if (!(ret
= ws_alloc( heap
, sizeof(*ret
) ))) return NULL
;
225 if (!(ret
->ptr
= ws_alloc( heap
, XML_BUFFER_INITIAL_ALLOCATED_SIZE
)))
227 ws_free( heap
, ret
);
231 ret
->size_allocated
= XML_BUFFER_INITIAL_ALLOCATED_SIZE
;
236 static void free_xmlbuf( struct xmlbuf
*xmlbuf
)
239 ws_free( xmlbuf
->heap
, xmlbuf
->ptr
);
240 ws_free( xmlbuf
->heap
, xmlbuf
);
243 /**************************************************************************
244 * WsCreateXmlBuffer [webservices.@]
246 HRESULT WINAPI
WsCreateXmlBuffer( WS_HEAP
*heap
, const WS_XML_BUFFER_PROPERTY
*properties
,
247 ULONG count
, WS_XML_BUFFER
**handle
, WS_ERROR
*error
)
249 struct xmlbuf
*xmlbuf
;
251 if (!heap
|| !handle
) return E_INVALIDARG
;
252 if (count
) FIXME( "properties not implemented\n" );
254 if (!(xmlbuf
= alloc_xmlbuf( heap
))) return E_OUTOFMEMORY
;
256 *handle
= (WS_XML_BUFFER
*)xmlbuf
;
260 /**************************************************************************
261 * WsGetWriterProperty [webservices.@]
263 HRESULT WINAPI
WsGetWriterProperty( WS_XML_WRITER
*handle
, WS_XML_WRITER_PROPERTY_ID id
,
264 void *buf
, ULONG size
, WS_ERROR
*error
)
266 struct writer
*writer
= (struct writer
*)handle
;
268 TRACE( "%p %u %p %u %p\n", handle
, id
, buf
, size
, error
);
269 if (error
) FIXME( "ignoring error parameter\n" );
271 if (!writer
->output_type
) return WS_E_INVALID_OPERATION
;
275 case WS_XML_WRITER_PROPERTY_BYTES
:
277 WS_BYTES
*bytes
= buf
;
278 if (size
!= sizeof(*bytes
)) return E_INVALIDARG
;
279 bytes
->bytes
= writer
->output_buf
->ptr
;
280 bytes
->length
= writer
->output_buf
->size
;
284 return prop_get( writer
->prop
, writer
->prop_count
, id
, buf
, size
);
288 static void set_output_buffer( struct writer
*writer
, struct xmlbuf
*xmlbuf
)
290 /* free current buffer if it's ours */
291 if (writer
->output_buf
&& writer
->output_buf
->heap
== writer
->output_heap
)
293 free_xmlbuf( writer
->output_buf
);
295 writer
->output_buf
= xmlbuf
;
296 writer
->output_type
= WS_XML_WRITER_OUTPUT_TYPE_BUFFER
;
297 writer
->write_bufptr
= xmlbuf
->ptr
;
298 writer
->write_pos
= 0;
301 /**************************************************************************
302 * WsSetOutput [webservices.@]
304 HRESULT WINAPI
WsSetOutput( WS_XML_WRITER
*handle
, const WS_XML_WRITER_ENCODING
*encoding
,
305 const WS_XML_WRITER_OUTPUT
*output
, const WS_XML_WRITER_PROPERTY
*properties
,
306 ULONG count
, WS_ERROR
*error
)
308 struct writer
*writer
= (struct writer
*)handle
;
313 TRACE( "%p %p %p %p %u %p\n", handle
, encoding
, output
, properties
, count
, error
);
314 if (error
) FIXME( "ignoring error parameter\n" );
316 if (!writer
) return E_INVALIDARG
;
318 for (i
= 0; i
< count
; i
++)
320 hr
= prop_set( writer
->prop
, writer
->prop_count
, properties
[i
].id
, properties
[i
].value
,
321 properties
[i
].valueSize
);
322 if (hr
!= S_OK
) return hr
;
325 if ((hr
= write_init_state( writer
)) != S_OK
) return hr
;
327 switch (encoding
->encodingType
)
329 case WS_XML_WRITER_ENCODING_TYPE_TEXT
:
331 WS_XML_WRITER_TEXT_ENCODING
*text
= (WS_XML_WRITER_TEXT_ENCODING
*)encoding
;
332 if (text
->charSet
!= WS_CHARSET_UTF8
)
334 FIXME( "charset %u not supported\n", text
->charSet
);
340 FIXME( "encoding type %u not supported\n", encoding
->encodingType
);
343 switch (output
->outputType
)
345 case WS_XML_WRITER_OUTPUT_TYPE_BUFFER
:
347 struct xmlbuf
*xmlbuf
;
349 if (!(xmlbuf
= alloc_xmlbuf( writer
->output_heap
))) return E_OUTOFMEMORY
;
350 set_output_buffer( writer
, xmlbuf
);
354 FIXME( "output type %u not supported\n", output
->outputType
);
358 if (!(node
= alloc_node( WS_XML_NODE_TYPE_BOF
))) return E_OUTOFMEMORY
;
359 write_insert_bof( writer
, node
);
363 /**************************************************************************
364 * WsSetOutputToBuffer [webservices.@]
366 HRESULT WINAPI
WsSetOutputToBuffer( WS_XML_WRITER
*handle
, WS_XML_BUFFER
*buffer
,
367 const WS_XML_WRITER_PROPERTY
*properties
, ULONG count
,
370 struct writer
*writer
= (struct writer
*)handle
;
371 struct xmlbuf
*xmlbuf
= (struct xmlbuf
*)buffer
;
376 TRACE( "%p %p %p %u %p\n", handle
, buffer
, properties
, count
, error
);
377 if (error
) FIXME( "ignoring error parameter\n" );
379 if (!writer
|| !xmlbuf
) return E_INVALIDARG
;
381 for (i
= 0; i
< count
; i
++)
383 hr
= prop_set( writer
->prop
, writer
->prop_count
, properties
[i
].id
, properties
[i
].value
,
384 properties
[i
].valueSize
);
385 if (hr
!= S_OK
) return hr
;
388 if ((hr
= write_init_state( writer
)) != S_OK
) return hr
;
389 set_output_buffer( writer
, xmlbuf
);
391 if (!(node
= alloc_node( WS_XML_NODE_TYPE_BOF
))) return E_OUTOFMEMORY
;
392 write_insert_bof( writer
, node
);
396 static HRESULT
write_grow_buffer( struct writer
*writer
, ULONG size
)
398 struct xmlbuf
*buf
= writer
->output_buf
;
402 if (buf
->size_allocated
>= writer
->write_pos
+ size
)
404 buf
->size
= writer
->write_pos
+ size
;
407 new_size
= max( buf
->size_allocated
* 2, writer
->write_pos
+ size
);
408 if (!(tmp
= ws_realloc( buf
->heap
, buf
->ptr
, new_size
))) return E_OUTOFMEMORY
;
409 writer
->write_bufptr
= buf
->ptr
= tmp
;
410 buf
->size_allocated
= new_size
;
411 buf
->size
= writer
->write_pos
+ size
;
415 static inline void write_char( struct writer
*writer
, unsigned char ch
)
417 writer
->write_bufptr
[writer
->write_pos
++] = ch
;
420 static inline void write_bytes( struct writer
*writer
, const BYTE
*bytes
, ULONG len
)
422 memcpy( writer
->write_bufptr
+ writer
->write_pos
, bytes
, len
);
423 writer
->write_pos
+= len
;
426 static HRESULT
write_attribute( struct writer
*writer
, WS_XML_ATTRIBUTE
*attr
)
428 WS_XML_UTF8_TEXT
*text
= (WS_XML_UTF8_TEXT
*)attr
->value
;
429 unsigned char quote
= attr
->singleQuote
? '\'' : '"';
430 const WS_XML_STRING
*prefix
;
434 if (attr
->prefix
) prefix
= attr
->prefix
;
435 else prefix
= writer
->current
->hdr
.prefix
;
437 /* ' prefix:attr="value"' */
439 size
= attr
->localName
->length
+ 4 /* ' =""' */;
440 if (prefix
) size
+= prefix
->length
+ 1 /* ':' */;
441 if (text
) size
+= text
->value
.length
;
442 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
444 write_char( writer
, ' ' );
447 write_bytes( writer
, prefix
->bytes
, prefix
->length
);
448 write_char( writer
, ':' );
450 write_bytes( writer
, attr
->localName
->bytes
, attr
->localName
->length
);
451 write_char( writer
, '=' );
452 write_char( writer
, quote
);
453 if (text
) write_bytes( writer
, text
->value
.bytes
, text
->value
.length
);
454 write_char( writer
, quote
);
459 static inline BOOL
is_current_namespace( struct writer
*writer
, const WS_XML_STRING
*ns
)
461 return (WsXmlStringEquals( writer
->current_ns
, ns
, NULL
) == S_OK
);
464 /**************************************************************************
465 * WsGetPrefixFromNamespace [webservices.@]
467 HRESULT WINAPI
WsGetPrefixFromNamespace( WS_XML_WRITER
*handle
, const WS_XML_STRING
*ns
,
468 BOOL required
, const WS_XML_STRING
**prefix
,
471 struct writer
*writer
= (struct writer
*)handle
;
472 WS_XML_ELEMENT_NODE
*elem
;
475 TRACE( "%p %s %d %p %p\n", handle
, debugstr_xmlstr(ns
), required
, prefix
, error
);
476 if (error
) FIXME( "ignoring error parameter\n" );
478 if (!writer
|| !ns
|| !prefix
) return E_INVALIDARG
;
480 elem
= &writer
->current
->hdr
;
481 if (elem
->prefix
&& is_current_namespace( writer
, ns
))
483 *prefix
= elem
->prefix
;
488 if (required
) return WS_E_INVALID_FORMAT
;
495 static HRESULT
set_current_namespace( struct writer
*writer
, const WS_XML_STRING
*ns
)
498 if (!(str
= alloc_xml_string( ns
->bytes
, ns
->length
))) return E_OUTOFMEMORY
;
499 heap_free( writer
->current_ns
);
500 writer
->current_ns
= str
;
504 static HRESULT
write_namespace_attribute( struct writer
*writer
, WS_XML_ATTRIBUTE
*attr
)
506 unsigned char quote
= attr
->singleQuote
? '\'' : '"';
510 /* ' xmlns:prefix="namespace"' */
512 size
= attr
->ns
->length
+ 9 /* ' xmlns=""' */;
513 if (attr
->prefix
) size
+= attr
->prefix
->length
+ 1 /* ':' */;
514 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
516 write_bytes( writer
, (const BYTE
*)" xmlns", 6 );
519 write_char( writer
, ':' );
520 write_bytes( writer
, attr
->prefix
->bytes
, attr
->prefix
->length
);
522 write_char( writer
, '=' );
523 write_char( writer
, quote
);
524 write_bytes( writer
, attr
->ns
->bytes
, attr
->ns
->length
);
525 write_char( writer
, quote
);
530 static HRESULT
write_add_namespace_attribute( struct writer
*writer
, const WS_XML_STRING
*prefix
,
531 const WS_XML_STRING
*ns
, BOOL single
)
533 WS_XML_ATTRIBUTE
*attr
;
534 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
537 if (!(attr
= heap_alloc_zero( sizeof(*attr
) ))) return E_OUTOFMEMORY
;
539 attr
->singleQuote
= !!single
;
541 if (prefix
&& !(attr
->prefix
= alloc_xml_string( prefix
->bytes
, prefix
->length
)))
543 free_attribute( attr
);
544 return E_OUTOFMEMORY
;
546 if (!(attr
->ns
= alloc_xml_string( ns
->bytes
, ns
->length
)))
548 free_attribute( attr
);
549 return E_OUTOFMEMORY
;
551 if ((hr
= append_attribute( elem
, attr
)) != S_OK
)
553 free_attribute( attr
);
559 static BOOL
namespace_in_scope( const WS_XML_ELEMENT_NODE
*elem
, const WS_XML_STRING
*prefix
,
560 const WS_XML_STRING
*ns
)
563 const struct node
*node
;
565 for (node
= (const struct node
*)elem
; node
; node
= node
->parent
)
567 if (node_type( node
) != WS_XML_NODE_TYPE_ELEMENT
) break;
570 for (i
= 0; i
< elem
->attributeCount
; i
++)
572 if (!elem
->attributes
[i
]->isXmlNs
) continue;
573 if (WsXmlStringEquals( elem
->attributes
[i
]->prefix
, prefix
, NULL
) == S_OK
&&
574 WsXmlStringEquals( elem
->attributes
[i
]->ns
, ns
, NULL
) == S_OK
)
583 static HRESULT
write_set_element_namespace( struct writer
*writer
)
585 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
588 if (!elem
->ns
->length
|| is_current_namespace( writer
, elem
->ns
) ||
589 namespace_in_scope( elem
, elem
->prefix
, elem
->ns
)) return S_OK
;
591 if ((hr
= write_add_namespace_attribute( writer
, elem
->prefix
, elem
->ns
, FALSE
)) != S_OK
)
594 return set_current_namespace( writer
, elem
->ns
);
597 /**************************************************************************
598 * WsWriteEndAttribute [webservices.@]
600 HRESULT WINAPI
WsWriteEndAttribute( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
602 struct writer
*writer
= (struct writer
*)handle
;
604 TRACE( "%p %p\n", handle
, error
);
605 if (error
) FIXME( "ignoring error parameter\n" );
607 if (!writer
) return E_INVALIDARG
;
609 writer
->state
= WRITER_STATE_STARTELEMENT
;
613 static HRESULT
write_startelement( struct writer
*writer
)
615 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
619 /* '<prefix:localname prefix:attr="value"... xmlns:prefix="ns"'... */
621 size
= elem
->localName
->length
+ 1 /* '<' */;
622 if (elem
->prefix
) size
+= elem
->prefix
->length
+ 1 /* ':' */;
623 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
625 write_char( writer
, '<' );
628 write_bytes( writer
, elem
->prefix
->bytes
, elem
->prefix
->length
);
629 write_char( writer
, ':' );
631 write_bytes( writer
, elem
->localName
->bytes
, elem
->localName
->length
);
632 for (i
= 0; i
< elem
->attributeCount
; i
++)
634 if (elem
->attributes
[i
]->isXmlNs
) continue;
635 if ((hr
= write_attribute( writer
, elem
->attributes
[i
] )) != S_OK
) return hr
;
637 for (i
= 0; i
< elem
->attributeCount
; i
++)
639 if (!elem
->attributes
[i
]->isXmlNs
|| !elem
->attributes
[i
]->prefix
) continue;
640 if ((hr
= write_namespace_attribute( writer
, elem
->attributes
[i
] )) != S_OK
) return hr
;
642 for (i
= 0; i
< elem
->attributeCount
; i
++)
644 if (!elem
->attributes
[i
]->isXmlNs
|| elem
->attributes
[i
]->prefix
) continue;
645 if ((hr
= write_namespace_attribute( writer
, elem
->attributes
[i
] )) != S_OK
) return hr
;
650 static struct node
*write_find_startelement( struct writer
*writer
)
653 for (node
= writer
->current
; node
; node
= node
->parent
)
655 if (node_type( node
) == WS_XML_NODE_TYPE_ELEMENT
) return node
;
660 static inline BOOL
is_empty_element( const struct node
*node
)
662 const struct node
*head
= LIST_ENTRY( list_head( &node
->children
), struct node
, entry
);
663 return node_type( head
) == WS_XML_NODE_TYPE_END_ELEMENT
;
666 static HRESULT
write_endelement( struct writer
*writer
, const WS_XML_ELEMENT_NODE
*elem
)
673 if (elem
->isEmpty
&& writer
->state
!= WRITER_STATE_ENDSTARTELEMENT
)
675 if ((hr
= write_grow_buffer( writer
, 2 )) != S_OK
) return hr
;
676 write_char( writer
, '/' );
677 write_char( writer
, '>' );
681 /* '</prefix:localname>' */
683 size
= elem
->localName
->length
+ 3 /* '</>' */;
684 if (elem
->prefix
) size
+= elem
->prefix
->length
+ 1 /* ':' */;
685 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
687 write_char( writer
, '<' );
688 write_char( writer
, '/' );
691 write_bytes( writer
, elem
->prefix
->bytes
, elem
->prefix
->length
);
692 write_char( writer
, ':' );
694 write_bytes( writer
, elem
->localName
->bytes
, elem
->localName
->length
);
695 write_char( writer
, '>' );
699 static HRESULT
write_close_element( struct writer
*writer
, struct node
*node
)
701 WS_XML_ELEMENT_NODE
*elem
= &node
->hdr
;
702 elem
->isEmpty
= is_empty_element( node
);
703 return write_endelement( writer
, elem
);
706 static HRESULT
write_endelement_node( struct writer
*writer
)
711 if (!(node
= write_find_startelement( writer
))) return WS_E_INVALID_FORMAT
;
712 if (writer
->state
== WRITER_STATE_STARTELEMENT
)
714 if ((hr
= write_set_element_namespace( writer
)) != S_OK
) return hr
;
715 if ((hr
= write_startelement( writer
)) != S_OK
) return hr
;
717 if ((hr
= write_close_element( writer
, node
)) != S_OK
) return hr
;
718 writer
->current
= node
->parent
;
719 writer
->state
= WRITER_STATE_ENDELEMENT
;
723 /**************************************************************************
724 * WsWriteEndElement [webservices.@]
726 HRESULT WINAPI
WsWriteEndElement( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
728 struct writer
*writer
= (struct writer
*)handle
;
730 TRACE( "%p %p\n", handle
, error
);
731 if (error
) FIXME( "ignoring error parameter\n" );
733 if (!writer
) return E_INVALIDARG
;
734 return write_endelement_node( writer
);
737 static HRESULT
write_endstartelement( struct writer
*writer
)
740 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
741 write_char( writer
, '>' );
745 /**************************************************************************
746 * WsWriteEndStartElement [webservices.@]
748 HRESULT WINAPI
WsWriteEndStartElement( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
750 struct writer
*writer
= (struct writer
*)handle
;
753 TRACE( "%p %p\n", handle
, error
);
754 if (error
) FIXME( "ignoring error parameter\n" );
756 if (!writer
) return E_INVALIDARG
;
757 if (writer
->state
!= WRITER_STATE_STARTELEMENT
) return WS_E_INVALID_OPERATION
;
759 if ((hr
= write_set_element_namespace( writer
)) != S_OK
) return hr
;
760 if ((hr
= write_startelement( writer
)) != S_OK
) return hr
;
761 if ((hr
= write_endstartelement( writer
)) != S_OK
) return hr
;
763 writer
->state
= WRITER_STATE_ENDSTARTELEMENT
;
767 static HRESULT
write_add_attribute( struct writer
*writer
, const WS_XML_STRING
*prefix
,
768 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
771 WS_XML_ATTRIBUTE
*attr
;
772 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
775 if (!(attr
= heap_alloc_zero( sizeof(*attr
) ))) return E_OUTOFMEMORY
;
777 if (!prefix
) prefix
= elem
->prefix
;
779 attr
->singleQuote
= !!single
;
780 if (prefix
&& !(attr
->prefix
= alloc_xml_string( prefix
->bytes
, prefix
->length
)))
782 free_attribute( attr
);
783 return E_OUTOFMEMORY
;
785 if (!(attr
->localName
= alloc_xml_string( localname
->bytes
, localname
->length
)))
787 free_attribute( attr
);
788 return E_OUTOFMEMORY
;
790 if (!(attr
->ns
= alloc_xml_string( ns
->bytes
, ns
->length
)))
792 free_attribute( attr
);
793 return E_OUTOFMEMORY
;
795 if ((hr
= append_attribute( elem
, attr
)) != S_OK
)
797 free_attribute( attr
);
803 /**************************************************************************
804 * WsWriteStartAttribute [webservices.@]
806 HRESULT WINAPI
WsWriteStartAttribute( WS_XML_WRITER
*handle
, const WS_XML_STRING
*prefix
,
807 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
808 BOOL single
, WS_ERROR
*error
)
810 struct writer
*writer
= (struct writer
*)handle
;
813 TRACE( "%p %s %s %s %d %p\n", handle
, debugstr_xmlstr(prefix
), debugstr_xmlstr(localname
),
814 debugstr_xmlstr(ns
), single
, error
);
815 if (error
) FIXME( "ignoring error parameter\n" );
817 if (!writer
|| !localname
|| !ns
) return E_INVALIDARG
;
819 if (writer
->state
!= WRITER_STATE_STARTELEMENT
) return WS_E_INVALID_OPERATION
;
821 if ((hr
= write_add_attribute( writer
, prefix
, localname
, ns
, single
)) != S_OK
) return hr
;
822 writer
->state
= WRITER_STATE_STARTATTRIBUTE
;
826 /* flush current start element if necessary */
827 static HRESULT
write_flush( struct writer
*writer
)
829 if (writer
->state
== WRITER_STATE_STARTELEMENT
)
832 if ((hr
= write_set_element_namespace( writer
)) != S_OK
) return hr
;
833 if ((hr
= write_startelement( writer
)) != S_OK
) return hr
;
834 if ((hr
= write_endstartelement( writer
)) != S_OK
) return hr
;
835 writer
->state
= WRITER_STATE_ENDSTARTELEMENT
;
840 static HRESULT
write_add_cdata_node( struct writer
*writer
)
842 struct node
*node
, *parent
;
843 if (!(parent
= find_parent( writer
->current
))) return WS_E_INVALID_FORMAT
;
844 if (!(node
= alloc_node( WS_XML_NODE_TYPE_CDATA
))) return E_OUTOFMEMORY
;
845 write_insert_node( writer
, parent
, node
);
849 static HRESULT
write_add_endcdata_node( struct writer
*writer
)
852 if (!(node
= alloc_node( WS_XML_NODE_TYPE_END_CDATA
))) return E_OUTOFMEMORY
;
853 node
->parent
= writer
->current
;
854 list_add_tail( &node
->parent
->children
, &node
->entry
);
858 static HRESULT
write_cdata( struct writer
*writer
)
861 if ((hr
= write_grow_buffer( writer
, 9 )) != S_OK
) return hr
;
862 write_bytes( writer
, (const BYTE
*)"<![CDATA[", 9 );
866 static HRESULT
write_cdata_node( struct writer
*writer
)
869 if ((hr
= write_flush( writer
)) != S_OK
) return hr
;
870 if ((hr
= write_add_cdata_node( writer
)) != S_OK
) return hr
;
871 if ((hr
= write_add_endcdata_node( writer
)) != S_OK
) return hr
;
872 if ((hr
= write_cdata( writer
)) != S_OK
) return hr
;
873 writer
->state
= WRITER_STATE_STARTCDATA
;
877 /**************************************************************************
878 * WsWriteStartCData [webservices.@]
880 HRESULT WINAPI
WsWriteStartCData( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
882 struct writer
*writer
= (struct writer
*)handle
;
884 TRACE( "%p %p\n", handle
, error
);
885 if (error
) FIXME( "ignoring error parameter\n" );
887 if (!writer
) return E_INVALIDARG
;
888 return write_cdata_node( writer
);
891 static HRESULT
write_endcdata( struct writer
*writer
)
894 if ((hr
= write_grow_buffer( writer
, 3 )) != S_OK
) return hr
;
895 write_bytes( writer
, (const BYTE
*)"]]>", 3 );
899 static HRESULT
write_endcdata_node( struct writer
*writer
)
902 if ((hr
= write_endcdata( writer
)) != S_OK
) return hr
;
903 writer
->current
= writer
->current
->parent
;
904 writer
->state
= WRITER_STATE_ENDCDATA
;
908 /**************************************************************************
909 * WsWriteEndCData [webservices.@]
911 HRESULT WINAPI
WsWriteEndCData( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
913 struct writer
*writer
= (struct writer
*)handle
;
915 TRACE( "%p %p\n", handle
, error
);
916 if (error
) FIXME( "ignoring error parameter\n" );
918 if (!writer
) return E_INVALIDARG
;
919 if (writer
->state
!= WRITER_STATE_TEXT
) return WS_E_INVALID_OPERATION
;
921 return write_endcdata_node( writer
);
924 static HRESULT
write_add_element_node( struct writer
*writer
, const WS_XML_STRING
*prefix
,
925 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
)
927 struct node
*node
, *parent
;
928 WS_XML_ELEMENT_NODE
*elem
;
930 if (!(parent
= find_parent( writer
->current
))) return WS_E_INVALID_FORMAT
;
932 if (!prefix
&& node_type( parent
) == WS_XML_NODE_TYPE_ELEMENT
)
935 if (WsXmlStringEquals( ns
, elem
->ns
, NULL
) == S_OK
) prefix
= elem
->prefix
;
938 if (!(node
= alloc_node( WS_XML_NODE_TYPE_ELEMENT
))) return E_OUTOFMEMORY
;
941 if (prefix
&& !(elem
->prefix
= alloc_xml_string( prefix
->bytes
, prefix
->length
)))
944 return E_OUTOFMEMORY
;
946 if (!(elem
->localName
= alloc_xml_string( localname
->bytes
, localname
->length
)))
949 return E_OUTOFMEMORY
;
951 if (!(elem
->ns
= alloc_xml_string( ns
->bytes
, ns
->length
)))
954 return E_OUTOFMEMORY
;
956 write_insert_node( writer
, parent
, node
);
960 static HRESULT
write_add_endelement_node( struct writer
*writer
, struct node
*parent
)
963 if (!(node
= alloc_node( WS_XML_NODE_TYPE_END_ELEMENT
))) return E_OUTOFMEMORY
;
964 node
->parent
= parent
;
965 list_add_tail( &parent
->children
, &node
->entry
);
969 static HRESULT
write_element_node( struct writer
*writer
, const WS_XML_STRING
*prefix
,
970 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
)
973 if ((hr
= write_flush( writer
)) != S_OK
) return hr
;
974 if ((hr
= write_add_element_node( writer
, prefix
, localname
, ns
)) != S_OK
) return hr
;
975 if ((hr
= write_add_endelement_node( writer
, writer
->current
)) != S_OK
) return hr
;
976 writer
->state
= WRITER_STATE_STARTELEMENT
;
980 /**************************************************************************
981 * WsWriteStartElement [webservices.@]
983 HRESULT WINAPI
WsWriteStartElement( WS_XML_WRITER
*handle
, const WS_XML_STRING
*prefix
,
984 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
987 struct writer
*writer
= (struct writer
*)handle
;
989 TRACE( "%p %s %s %s %p\n", handle
, debugstr_xmlstr(prefix
), debugstr_xmlstr(localname
),
990 debugstr_xmlstr(ns
), error
);
991 if (error
) FIXME( "ignoring error parameter\n" );
993 if (!writer
|| !localname
|| !ns
) return E_INVALIDARG
;
994 return write_element_node( writer
, prefix
, localname
, ns
);
997 static ULONG
format_bool( const BOOL
*ptr
, unsigned char *buf
)
999 static const unsigned char bool_true
[] = {'t','r','u','e'}, bool_false
[] = {'f','a','l','s','e'};
1002 memcpy( buf
, bool_true
, sizeof(bool_true
) );
1003 return sizeof(bool_true
);
1005 memcpy( buf
, bool_false
, sizeof(bool_false
) );
1006 return sizeof(bool_false
);
1009 static ULONG
format_int8( const INT8
*ptr
, unsigned char *buf
)
1011 return wsprintfA( (char *)buf
, "%d", *ptr
);
1014 static ULONG
format_int16( const INT16
*ptr
, unsigned char *buf
)
1016 return wsprintfA( (char *)buf
, "%d", *ptr
);
1019 static ULONG
format_int32( const INT32
*ptr
, unsigned char *buf
)
1021 return wsprintfA( (char *)buf
, "%d", *ptr
);
1024 static ULONG
format_int64( const INT64
*ptr
, unsigned char *buf
)
1026 return wsprintfA( (char *)buf
, "%I64d", *ptr
);
1029 static ULONG
format_uint8( const UINT8
*ptr
, unsigned char *buf
)
1031 return wsprintfA( (char *)buf
, "%u", *ptr
);
1034 static ULONG
format_uint16( const UINT16
*ptr
, unsigned char *buf
)
1036 return wsprintfA( (char *)buf
, "%u", *ptr
);
1039 static ULONG
format_uint32( const UINT32
*ptr
, unsigned char *buf
)
1041 return wsprintfA( (char *)buf
, "%u", *ptr
);
1044 static ULONG
format_uint64( const UINT64
*ptr
, unsigned char *buf
)
1046 return wsprintfA( (char *)buf
, "%I64u", *ptr
);
1049 static ULONG
format_double( const double *ptr
, unsigned char *buf
)
1051 static const double precision
= 0.0000000000000001;
1052 unsigned char *p
= buf
;
1053 double val
= *ptr
; /* FIXME: use long double */
1054 int neg
, mag
, mag2
, use_exp
;
1058 memcpy( buf
, "NaN", 3 );
1065 memcpy( buf
, "-INF", 4 );
1068 memcpy( buf
, "INF", 3 );
1077 if ((neg
= val
< 0))
1084 use_exp
= (mag
>= 15 || (neg
&& mag
>= 1) || mag
<= -1);
1087 if (mag
< 0) mag
-= 1;
1088 val
= val
/ pow( 10.0, mag
);
1092 else if (mag
< 1) mag
= 0;
1094 while (val
> precision
|| mag
>= 0)
1096 double weight
= pow( 10.0, mag
);
1097 if (weight
> 0 && !isinf( weight
))
1099 int digit
= floor( val
/ weight
);
1100 val
-= digit
* weight
;
1101 *(p
++) = '0' + digit
;
1103 if (!mag
&& val
> 0) *(p
++) = '.';
1111 if (mag2
> 0) *(p
++) = '+';
1120 *(p
++) = '0' + mag2
% 10;
1124 for (i
= -mag
, j
= -1; i
< j
; i
++, j
--)
1135 static ULONG
format_guid( const GUID
*ptr
, unsigned char *buf
)
1137 static const char fmt
[] = "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x";
1138 return sprintf( (char *)buf
, fmt
, ptr
->Data1
, ptr
->Data2
, ptr
->Data3
,
1139 ptr
->Data4
[0], ptr
->Data4
[1], ptr
->Data4
[2], ptr
->Data4
[3],
1140 ptr
->Data4
[4], ptr
->Data4
[5], ptr
->Data4
[6], ptr
->Data4
[7] );
1143 static ULONG
format_urn( const GUID
*ptr
, unsigned char *buf
)
1145 static const char fmt
[] = "urn:uuid:%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x";
1146 return sprintf( (char *)buf
, fmt
, ptr
->Data1
, ptr
->Data2
, ptr
->Data3
,
1147 ptr
->Data4
[0], ptr
->Data4
[1], ptr
->Data4
[2], ptr
->Data4
[3],
1148 ptr
->Data4
[4], ptr
->Data4
[5], ptr
->Data4
[6], ptr
->Data4
[7] );
1151 static HRESULT
text_to_utf8text( const WS_XML_TEXT
*text
, WS_XML_UTF8_TEXT
**ret
)
1153 switch (text
->textType
)
1155 case WS_XML_TEXT_TYPE_UTF8
:
1157 const WS_XML_UTF8_TEXT
*src
= (const WS_XML_UTF8_TEXT
*)text
;
1158 if (!(*ret
= alloc_utf8_text( src
->value
.bytes
, src
->value
.length
))) return E_OUTOFMEMORY
;
1161 case WS_XML_TEXT_TYPE_UTF16
:
1163 const WS_XML_UTF16_TEXT
*src
= (const WS_XML_UTF16_TEXT
*)text
;
1164 const WCHAR
*str
= (const WCHAR
*)src
->bytes
;
1165 ULONG len
= src
->byteCount
/ sizeof(WCHAR
), len_utf8
;
1167 if (src
->byteCount
% sizeof(WCHAR
)) return E_INVALIDARG
;
1168 len_utf8
= WideCharToMultiByte( CP_UTF8
, 0, str
, len
, NULL
, 0, NULL
, NULL
);
1169 if (!(*ret
= alloc_utf8_text( NULL
, len_utf8
))) return E_OUTOFMEMORY
;
1170 WideCharToMultiByte( CP_UTF8
, 0, str
, len
, (char *)(*ret
)->value
.bytes
, (*ret
)->value
.length
, NULL
, NULL
);
1173 case WS_XML_TEXT_TYPE_BOOL
:
1175 const WS_XML_BOOL_TEXT
*bool_text
= (const WS_XML_BOOL_TEXT
*)text
;
1176 if (!(*ret
= alloc_utf8_text( NULL
, 5 ))) return E_OUTOFMEMORY
;
1177 (*ret
)->value
.length
= format_bool( &bool_text
->value
, (*ret
)->value
.bytes
);
1180 case WS_XML_TEXT_TYPE_INT32
:
1182 const WS_XML_INT32_TEXT
*int32_text
= (const WS_XML_INT32_TEXT
*)text
;
1183 unsigned char buf
[12]; /* "-2147483648" */
1184 ULONG len
= format_int32( &int32_text
->value
, buf
);
1185 if (!(*ret
= alloc_utf8_text( buf
, len
))) return E_OUTOFMEMORY
;
1188 case WS_XML_TEXT_TYPE_INT64
:
1190 const WS_XML_INT64_TEXT
*int64_text
= (const WS_XML_INT64_TEXT
*)text
;
1191 unsigned char buf
[21]; /* "-9223372036854775808" */
1192 ULONG len
= format_int64( &int64_text
->value
, buf
);
1193 if (!(*ret
= alloc_utf8_text( buf
, len
))) return E_OUTOFMEMORY
;
1196 case WS_XML_TEXT_TYPE_UINT64
:
1198 const WS_XML_UINT64_TEXT
*uint64_text
= (const WS_XML_UINT64_TEXT
*)text
;
1199 unsigned char buf
[21]; /* "18446744073709551615" */
1200 ULONG len
= format_uint64( &uint64_text
->value
, buf
);
1201 if (!(*ret
= alloc_utf8_text( buf
, len
))) return E_OUTOFMEMORY
;
1204 case WS_XML_TEXT_TYPE_DOUBLE
:
1206 const WS_XML_DOUBLE_TEXT
*double_text
= (const WS_XML_DOUBLE_TEXT
*)text
;
1207 unsigned char buf
[24]; /* "-1.1111111111111111E-308" */
1208 unsigned short fpword
;
1211 if (!set_fp_rounding( &fpword
)) return E_NOTIMPL
;
1212 len
= format_double( &double_text
->value
, buf
);
1213 restore_fp_rounding( fpword
);
1214 if (!(*ret
= alloc_utf8_text( buf
, len
))) return E_OUTOFMEMORY
;
1217 case WS_XML_TEXT_TYPE_GUID
:
1219 const WS_XML_GUID_TEXT
*id
= (const WS_XML_GUID_TEXT
*)text
;
1220 if (!(*ret
= alloc_utf8_text( NULL
, 37 ))) return E_OUTOFMEMORY
;
1221 (*ret
)->value
.length
= format_guid( &id
->value
, (*ret
)->value
.bytes
);
1224 case WS_XML_TEXT_TYPE_UNIQUE_ID
:
1226 const WS_XML_UNIQUE_ID_TEXT
*id
= (const WS_XML_UNIQUE_ID_TEXT
*)text
;
1227 if (!(*ret
= alloc_utf8_text( NULL
, 46 ))) return E_OUTOFMEMORY
;
1228 (*ret
)->value
.length
= format_urn( &id
->value
, (*ret
)->value
.bytes
);
1232 FIXME( "unhandled text type %u\n", text
->textType
);
1237 static HRESULT
write_set_attribute_value( struct writer
*writer
, const WS_XML_TEXT
*value
)
1239 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
1240 WS_XML_UTF8_TEXT
*utf8
;
1243 if ((hr
= text_to_utf8text( value
, &utf8
)) != S_OK
) return hr
;
1244 elem
->attributes
[elem
->attributeCount
- 1]->value
= &utf8
->text
;
1248 static HRESULT
write_add_text_node( struct writer
*writer
, const WS_XML_TEXT
*value
)
1251 WS_XML_TEXT_NODE
*text
;
1252 WS_XML_UTF8_TEXT
*utf8
;
1255 if (node_type( writer
->current
) != WS_XML_NODE_TYPE_ELEMENT
&&
1256 node_type( writer
->current
) != WS_XML_NODE_TYPE_BOF
&&
1257 node_type( writer
->current
) != WS_XML_NODE_TYPE_CDATA
) return WS_E_INVALID_FORMAT
;
1259 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return E_OUTOFMEMORY
;
1260 if ((hr
= text_to_utf8text( value
, &utf8
)) != S_OK
)
1265 text
= (WS_XML_TEXT_NODE
*)node
;
1266 text
->text
= &utf8
->text
;
1268 write_insert_node( writer
, writer
->current
, node
);
1272 static HRESULT
write_text( struct writer
*writer
)
1274 const WS_XML_TEXT_NODE
*text
= (const WS_XML_TEXT_NODE
*)writer
->current
;
1275 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)text
->text
;
1278 if ((hr
= write_grow_buffer( writer
, utf8
->value
.length
)) != S_OK
) return hr
;
1279 write_bytes( writer
, utf8
->value
.bytes
, utf8
->value
.length
);
1283 static HRESULT
write_text_node( struct writer
*writer
, const WS_XML_TEXT
*text
)
1286 if ((hr
= write_flush( writer
)) != S_OK
) return hr
;
1287 if ((hr
= write_add_text_node( writer
, text
)) != S_OK
) return hr
;
1288 if ((hr
= write_text( writer
)) != S_OK
) return hr
;
1289 writer
->state
= WRITER_STATE_TEXT
;
1293 /**************************************************************************
1294 * WsWriteText [webservices.@]
1296 HRESULT WINAPI
WsWriteText( WS_XML_WRITER
*handle
, const WS_XML_TEXT
*text
, WS_ERROR
*error
)
1298 struct writer
*writer
= (struct writer
*)handle
;
1300 TRACE( "%p %p %p\n", handle
, text
, error
);
1302 if (!writer
|| !text
) return E_INVALIDARG
;
1304 if (writer
->state
== WRITER_STATE_STARTATTRIBUTE
) return write_set_attribute_value( writer
, text
);
1305 return write_text_node( writer
, text
);
1308 static HRESULT
write_type_text( struct writer
*writer
, WS_TYPE_MAPPING mapping
, const WS_XML_TEXT
*text
)
1312 case WS_ELEMENT_TYPE_MAPPING
:
1313 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
1314 return write_text_node( writer
, text
);
1316 case WS_ATTRIBUTE_TYPE_MAPPING
:
1317 return write_set_attribute_value( writer
, text
);
1319 case WS_ANY_ELEMENT_TYPE_MAPPING
:
1320 switch (writer
->state
)
1322 case WRITER_STATE_STARTATTRIBUTE
:
1323 return write_set_attribute_value( writer
, text
);
1325 case WRITER_STATE_STARTELEMENT
:
1326 return write_text_node( writer
, text
);
1329 FIXME( "writer state %u not handled\n", writer
->state
);
1334 FIXME( "mapping %u not implemented\n", mapping
);
1339 static HRESULT
write_type_bool( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1340 const WS_BOOL_DESCRIPTION
*desc
, const BOOL
*value
)
1342 WS_XML_UTF8_TEXT utf8
;
1343 unsigned char buf
[6]; /* "false" */
1347 FIXME( "description not supported\n" );
1350 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
1351 utf8
.value
.bytes
= buf
;
1352 utf8
.value
.length
= format_bool( value
, buf
);
1353 return write_type_text( writer
, mapping
, &utf8
.text
);
1356 static HRESULT
write_type_int8( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1357 const WS_INT8_DESCRIPTION
*desc
, const INT8
*value
)
1359 WS_XML_UTF8_TEXT utf8
;
1360 unsigned char buf
[5]; /* "-128" */
1364 FIXME( "description not supported\n" );
1367 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
1368 utf8
.value
.bytes
= buf
;
1369 utf8
.value
.length
= format_int8( value
, buf
);
1370 return write_type_text( writer
, mapping
, &utf8
.text
);
1373 static HRESULT
write_type_int16( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1374 const WS_INT16_DESCRIPTION
*desc
, const INT16
*value
)
1376 WS_XML_UTF8_TEXT utf8
;
1377 unsigned char buf
[7]; /* "-32768" */
1381 FIXME( "description not supported\n" );
1384 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
1385 utf8
.value
.bytes
= buf
;
1386 utf8
.value
.length
= format_int16( value
, buf
);
1387 return write_type_text( writer
, mapping
, &utf8
.text
);
1390 static HRESULT
write_type_int32( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1391 const WS_INT32_DESCRIPTION
*desc
, const INT32
*value
)
1393 WS_XML_UTF8_TEXT utf8
;
1394 unsigned char buf
[12]; /* "-2147483648" */
1398 FIXME( "description not supported\n" );
1401 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
1402 utf8
.value
.bytes
= buf
;
1403 utf8
.value
.length
= format_int32( value
, buf
);
1404 return write_type_text( writer
, mapping
, &utf8
.text
);
1407 static HRESULT
write_type_int64( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1408 const WS_INT64_DESCRIPTION
*desc
, const INT64
*value
)
1410 WS_XML_UTF8_TEXT utf8
;
1411 unsigned char buf
[21]; /* "-9223372036854775808" */
1415 FIXME( "description not supported\n" );
1418 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
1419 utf8
.value
.bytes
= buf
;
1420 utf8
.value
.length
= format_int64( value
, buf
);
1421 return write_type_text( writer
, mapping
, &utf8
.text
);
1424 static HRESULT
write_type_uint8( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1425 const WS_UINT8_DESCRIPTION
*desc
, const UINT8
*value
)
1427 WS_XML_UTF8_TEXT utf8
;
1428 unsigned char buf
[4]; /* "255" */
1432 FIXME( "description not supported\n" );
1435 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
1436 utf8
.value
.bytes
= buf
;
1437 utf8
.value
.length
= format_uint8( value
, buf
);
1438 return write_type_text( writer
, mapping
, &utf8
.text
);
1441 static HRESULT
write_type_uint16( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1442 const WS_UINT16_DESCRIPTION
*desc
, const UINT16
*value
)
1444 WS_XML_UTF8_TEXT utf8
;
1445 unsigned char buf
[6]; /* "65535" */
1449 FIXME( "description not supported\n" );
1452 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
1453 utf8
.value
.bytes
= buf
;
1454 utf8
.value
.length
= format_uint16( value
, buf
);
1455 return write_type_text( writer
, mapping
, &utf8
.text
);
1458 static HRESULT
write_type_uint32( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1459 const WS_UINT32_DESCRIPTION
*desc
, const UINT32
*value
)
1461 WS_XML_UTF8_TEXT utf8
;
1462 unsigned char buf
[11]; /* "4294967295" */
1466 FIXME( "description not supported\n" );
1469 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
1470 utf8
.value
.bytes
= buf
;
1471 utf8
.value
.length
= format_uint32( value
, buf
);
1472 return write_type_text( writer
, mapping
, &utf8
.text
);
1475 static HRESULT
write_type_uint64( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1476 const WS_UINT64_DESCRIPTION
*desc
, const UINT64
*value
)
1478 WS_XML_UTF8_TEXT utf8
;
1479 unsigned char buf
[21]; /* "18446744073709551615" */
1483 FIXME( "description not supported\n" );
1486 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
1487 utf8
.value
.bytes
= buf
;
1488 utf8
.value
.length
= format_uint64( value
, buf
);
1489 return write_type_text( writer
, mapping
, &utf8
.text
);
1492 static HRESULT
write_type_wsz( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1493 const WS_WSZ_DESCRIPTION
*desc
, const WCHAR
*value
)
1495 WS_XML_UTF16_TEXT utf16
;
1499 FIXME( "description not supported\n" );
1502 utf16
.text
.textType
= WS_XML_TEXT_TYPE_UTF16
;
1503 utf16
.bytes
= (BYTE
*)value
;
1504 utf16
.byteCount
= strlenW( value
) * sizeof(WCHAR
);
1505 return write_type_text( writer
, mapping
, &utf16
.text
);
1508 static HRESULT
write_type( struct writer
*, WS_TYPE_MAPPING
, WS_TYPE
, const void *, WS_WRITE_OPTION
,
1509 const void *, ULONG
);
1511 static HRESULT
write_type_struct_field( struct writer
*writer
, const WS_FIELD_DESCRIPTION
*desc
,
1512 const void *value
, ULONG size
)
1515 WS_TYPE_MAPPING mapping
;
1516 WS_WRITE_OPTION option
;
1518 if (!desc
->options
|| desc
->options
== WS_FIELD_OPTIONAL
) option
= 0;
1519 else if (desc
->options
== WS_FIELD_POINTER
) option
= WS_WRITE_REQUIRED_POINTER
;
1522 FIXME( "options 0x%x not supported\n", desc
->options
);
1526 switch (desc
->mapping
)
1528 case WS_ATTRIBUTE_FIELD_MAPPING
:
1529 if (!desc
->localName
|| !desc
->ns
) return E_INVALIDARG
;
1530 if ((hr
= write_add_attribute( writer
, NULL
, desc
->localName
, desc
->ns
, FALSE
)) != S_OK
)
1532 writer
->state
= WRITER_STATE_STARTATTRIBUTE
;
1534 mapping
= WS_ATTRIBUTE_TYPE_MAPPING
;
1537 case WS_ELEMENT_FIELD_MAPPING
:
1538 if ((hr
= write_element_node( writer
, NULL
, desc
->localName
, desc
->ns
)) != S_OK
) return hr
;
1539 mapping
= WS_ELEMENT_TYPE_MAPPING
;
1542 case WS_TEXT_FIELD_MAPPING
:
1543 switch (writer
->state
)
1545 case WRITER_STATE_STARTELEMENT
:
1546 mapping
= WS_ELEMENT_CONTENT_TYPE_MAPPING
;
1549 case WRITER_STATE_STARTATTRIBUTE
:
1550 mapping
= WS_ATTRIBUTE_TYPE_MAPPING
;
1554 FIXME( "unhandled writer state %u\n", writer
->state
);
1560 FIXME( "field mapping %u not supported\n", desc
->mapping
);
1564 if ((hr
= write_type( writer
, mapping
, desc
->type
, desc
->typeDescription
, option
, value
, size
)) != S_OK
)
1569 case WS_ATTRIBUTE_TYPE_MAPPING
:
1570 writer
->state
= WRITER_STATE_STARTELEMENT
;
1573 case WS_ELEMENT_TYPE_MAPPING
:
1574 if ((hr
= write_endelement_node( writer
)) != S_OK
) return hr
;
1583 static ULONG
get_field_size( const WS_STRUCT_DESCRIPTION
*desc
, ULONG index
)
1585 if (index
< desc
->fieldCount
- 1) return desc
->fields
[index
+ 1]->offset
- desc
->fields
[index
]->offset
;
1586 return desc
->size
- desc
->fields
[index
]->offset
;
1589 static HRESULT
write_type_struct( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1590 const WS_STRUCT_DESCRIPTION
*desc
, const void *value
)
1596 if (desc
->structOptions
)
1598 FIXME( "struct options 0x%x not supported\n", desc
->structOptions
);
1602 for (i
= 0; i
< desc
->fieldCount
; i
++)
1604 ptr
= (const char *)value
+ desc
->fields
[i
]->offset
;
1605 size
= get_field_size( desc
, i
);
1606 if ((hr
= write_type_struct_field( writer
, desc
->fields
[i
], ptr
, size
)) != S_OK
)
1613 static HRESULT
get_value_ptr( WS_WRITE_OPTION option
, const void *value
, ULONG size
, const void **ptr
)
1617 case WS_WRITE_REQUIRED_VALUE
:
1618 if (!value
|| !size
) return E_INVALIDARG
;
1622 case WS_WRITE_REQUIRED_POINTER
:
1623 if (size
!= sizeof(const void *) || !(*ptr
= *(const void **)value
)) return E_INVALIDARG
;
1627 FIXME( "option %08x not supported\n", option
);
1632 static HRESULT
write_type( struct writer
*writer
, WS_TYPE_MAPPING mapping
, WS_TYPE type
,
1633 const void *desc
, WS_WRITE_OPTION option
, const void *value
,
1640 case WS_STRUCT_TYPE
:
1644 if (!desc
|| option
== WS_WRITE_REQUIRED_VALUE
) return E_INVALIDARG
;
1646 if (!option
) option
= WS_WRITE_REQUIRED_POINTER
;
1647 if ((hr
= get_value_ptr( option
, value
, size
, (const void **)&ptr
)) != S_OK
) return hr
;
1648 return write_type_struct( writer
, mapping
, desc
, ptr
);
1653 if (!option
) option
= WS_WRITE_REQUIRED_VALUE
;
1654 if ((hr
= get_value_ptr( option
, value
, size
, (const void **)&ptr
)) != S_OK
) return hr
;
1655 return write_type_bool( writer
, mapping
, desc
, ptr
);
1659 const INT8
*ptr
= value
;
1660 if (!option
) option
= WS_WRITE_REQUIRED_VALUE
;
1661 if ((hr
= get_value_ptr( option
, value
, size
, (const void **)&ptr
)) != S_OK
) return hr
;
1662 return write_type_int8( writer
, mapping
, desc
, ptr
);
1666 const INT16
*ptr
= value
;
1667 if (!option
) option
= WS_WRITE_REQUIRED_VALUE
;
1668 if ((hr
= get_value_ptr( option
, value
, size
, (const void **)&ptr
)) != S_OK
) return hr
;
1669 return write_type_int16( writer
, mapping
, desc
, ptr
);
1674 if (!option
) option
= WS_WRITE_REQUIRED_VALUE
;
1675 if ((hr
= get_value_ptr( option
, value
, size
, (const void **)&ptr
)) != S_OK
) return hr
;
1676 return write_type_int32( writer
, mapping
, desc
, ptr
);
1680 const INT64
*ptr
= value
;
1681 if (!option
) option
= WS_WRITE_REQUIRED_VALUE
;
1682 if ((hr
= get_value_ptr( option
, value
, size
, (const void **)&ptr
)) != S_OK
) return hr
;
1683 return write_type_int64( writer
, mapping
, desc
, ptr
);
1687 const UINT8
*ptr
= value
;
1688 if (!option
) option
= WS_WRITE_REQUIRED_VALUE
;
1689 if ((hr
= get_value_ptr( option
, value
, size
, (const void **)&ptr
)) != S_OK
) return hr
;
1690 return write_type_uint8( writer
, mapping
, desc
, ptr
);
1692 case WS_UINT16_TYPE
:
1694 const UINT16
*ptr
= value
;
1695 if (!option
) option
= WS_WRITE_REQUIRED_VALUE
;
1696 if ((hr
= get_value_ptr( option
, value
, size
, (const void **)&ptr
)) != S_OK
) return hr
;
1697 return write_type_uint16( writer
, mapping
, desc
, ptr
);
1699 case WS_UINT32_TYPE
:
1701 const UINT32
*ptr
= value
;
1702 if (!option
) option
= WS_WRITE_REQUIRED_VALUE
;
1703 if ((hr
= get_value_ptr( option
, value
, size
, (const void **)&ptr
)) != S_OK
) return hr
;
1704 return write_type_uint32( writer
, mapping
, desc
, ptr
);
1706 case WS_UINT64_TYPE
:
1708 const UINT64
*ptr
= value
;
1709 if (!option
) option
= WS_WRITE_REQUIRED_VALUE
;
1710 if ((hr
= get_value_ptr( option
, value
, size
, (const void **)&ptr
)) != S_OK
) return hr
;
1711 return write_type_uint64( writer
, mapping
, desc
, ptr
);
1717 if (option
== WS_WRITE_REQUIRED_VALUE
) return E_INVALIDARG
;
1719 if (!option
) option
= WS_WRITE_REQUIRED_POINTER
;
1720 if ((hr
= get_value_ptr( option
, value
, size
, (const void **)&ptr
)) != S_OK
) return hr
;
1721 return write_type_wsz( writer
, mapping
, desc
, ptr
);
1724 FIXME( "type %u not supported\n", type
);
1729 /**************************************************************************
1730 * WsWriteAttribute [webservices.@]
1732 HRESULT WINAPI
WsWriteAttribute( WS_XML_WRITER
*handle
, const WS_ATTRIBUTE_DESCRIPTION
*desc
,
1733 WS_WRITE_OPTION option
, const void *value
, ULONG size
,
1736 struct writer
*writer
= (struct writer
*)handle
;
1739 TRACE( "%p %p %u %p %u %p\n", handle
, desc
, option
, value
, size
, error
);
1740 if (error
) FIXME( "ignoring error parameter\n" );
1742 if (!writer
|| !desc
|| !desc
->attributeLocalName
|| !desc
->attributeNs
|| !value
)
1743 return E_INVALIDARG
;
1745 if (writer
->state
!= WRITER_STATE_STARTELEMENT
) return WS_E_INVALID_OPERATION
;
1747 if ((hr
= write_add_attribute( writer
, NULL
, desc
->attributeLocalName
, desc
->attributeNs
,
1748 FALSE
)) != S_OK
) return hr
;
1749 writer
->state
= WRITER_STATE_STARTATTRIBUTE
;
1751 return write_type( writer
, WS_ATTRIBUTE_TYPE_MAPPING
, desc
->type
, desc
->typeDescription
,
1752 option
, value
, size
);
1755 /**************************************************************************
1756 * WsWriteElement [webservices.@]
1758 HRESULT WINAPI
WsWriteElement( WS_XML_WRITER
*handle
, const WS_ELEMENT_DESCRIPTION
*desc
,
1759 WS_WRITE_OPTION option
, const void *value
, ULONG size
,
1762 struct writer
*writer
= (struct writer
*)handle
;
1765 TRACE( "%p %p %u %p %u %p\n", handle
, desc
, option
, value
, size
, error
);
1766 if (error
) FIXME( "ignoring error parameter\n" );
1768 if (!writer
|| !desc
|| !desc
->elementLocalName
|| !desc
->elementNs
|| !value
)
1769 return E_INVALIDARG
;
1771 if ((hr
= write_element_node( writer
, NULL
, desc
->elementLocalName
, desc
->elementNs
)) != S_OK
) return hr
;
1773 if ((hr
= write_type( writer
, WS_ANY_ELEMENT_TYPE_MAPPING
, desc
->type
, desc
->typeDescription
,
1774 option
, value
, size
)) != S_OK
) return hr
;
1776 return write_endelement_node( writer
);
1779 /**************************************************************************
1780 * WsWriteType [webservices.@]
1782 HRESULT WINAPI
WsWriteType( WS_XML_WRITER
*handle
, WS_TYPE_MAPPING mapping
, WS_TYPE type
,
1783 const void *desc
, WS_WRITE_OPTION option
, const void *value
,
1784 ULONG size
, WS_ERROR
*error
)
1786 struct writer
*writer
= (struct writer
*)handle
;
1789 TRACE( "%p %u %u %p %u %p %u %p\n", handle
, mapping
, type
, desc
, option
, value
,
1791 if (error
) FIXME( "ignoring error parameter\n" );
1793 if (!writer
|| !value
) return E_INVALIDARG
;
1797 case WS_ATTRIBUTE_TYPE_MAPPING
:
1798 if (writer
->state
!= WRITER_STATE_STARTATTRIBUTE
) return WS_E_INVALID_FORMAT
;
1799 hr
= write_type( writer
, mapping
, type
, desc
, option
, value
, size
);
1802 case WS_ELEMENT_TYPE_MAPPING
:
1803 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
1804 if (writer
->state
!= WRITER_STATE_STARTELEMENT
) return WS_E_INVALID_FORMAT
;
1805 hr
= write_type( writer
, mapping
, type
, desc
, option
, value
, size
);
1808 case WS_ANY_ELEMENT_TYPE_MAPPING
:
1809 hr
= write_type( writer
, mapping
, type
, desc
, option
, value
, size
);
1813 FIXME( "mapping %u not implemented\n", mapping
);
1820 WS_TYPE
map_value_type( WS_VALUE_TYPE type
)
1824 case WS_BOOL_VALUE_TYPE
: return WS_BOOL_TYPE
;
1825 case WS_INT8_VALUE_TYPE
: return WS_INT8_TYPE
;
1826 case WS_INT16_VALUE_TYPE
: return WS_INT16_TYPE
;
1827 case WS_INT32_VALUE_TYPE
: return WS_INT32_TYPE
;
1828 case WS_INT64_VALUE_TYPE
: return WS_INT64_TYPE
;
1829 case WS_UINT8_VALUE_TYPE
: return WS_UINT8_TYPE
;
1830 case WS_UINT16_VALUE_TYPE
: return WS_UINT16_TYPE
;
1831 case WS_UINT32_VALUE_TYPE
: return WS_UINT32_TYPE
;
1832 case WS_UINT64_VALUE_TYPE
: return WS_UINT64_TYPE
;
1833 case WS_FLOAT_VALUE_TYPE
: return WS_FLOAT_TYPE
;
1834 case WS_DOUBLE_VALUE_TYPE
: return WS_DOUBLE_TYPE
;
1835 case WS_DECIMAL_VALUE_TYPE
: return WS_DECIMAL_TYPE
;
1836 case WS_DATETIME_VALUE_TYPE
: return WS_DATETIME_TYPE
;
1837 case WS_TIMESPAN_VALUE_TYPE
: return WS_TIMESPAN_TYPE
;
1838 case WS_GUID_VALUE_TYPE
: return WS_GUID_TYPE
;
1840 FIXME( "unhandled type %u\n", type
);
1845 /**************************************************************************
1846 * WsWriteValue [webservices.@]
1848 HRESULT WINAPI
WsWriteValue( WS_XML_WRITER
*handle
, WS_VALUE_TYPE value_type
, const void *value
,
1849 ULONG size
, WS_ERROR
*error
)
1851 struct writer
*writer
= (struct writer
*)handle
;
1852 WS_TYPE_MAPPING mapping
;
1855 TRACE( "%p %u %p %u %p\n", handle
, value_type
, value
, size
, error
);
1856 if (error
) FIXME( "ignoring error parameter\n" );
1858 if (!writer
|| !value
|| (type
= map_value_type( value_type
)) == ~0u) return E_INVALIDARG
;
1860 switch (writer
->state
)
1862 case WRITER_STATE_STARTATTRIBUTE
:
1863 mapping
= WS_ATTRIBUTE_TYPE_MAPPING
;
1866 case WRITER_STATE_STARTELEMENT
:
1867 mapping
= WS_ELEMENT_TYPE_MAPPING
;
1871 return WS_E_INVALID_FORMAT
;
1874 return write_type( writer
, mapping
, type
, NULL
, WS_WRITE_REQUIRED_VALUE
, value
, size
);
1877 /**************************************************************************
1878 * WsWriteXmlBuffer [webservices.@]
1880 HRESULT WINAPI
WsWriteXmlBuffer( WS_XML_WRITER
*handle
, WS_XML_BUFFER
*buffer
, WS_ERROR
*error
)
1882 struct writer
*writer
= (struct writer
*)handle
;
1883 struct xmlbuf
*xmlbuf
= (struct xmlbuf
*)buffer
;
1886 TRACE( "%p %p %p\n", handle
, buffer
, error
);
1887 if (error
) FIXME( "ignoring error parameter\n" );
1889 if (!writer
|| !xmlbuf
) return E_INVALIDARG
;
1891 if ((hr
= write_grow_buffer( writer
, xmlbuf
->size
)) != S_OK
) return hr
;
1892 write_bytes( writer
, xmlbuf
->ptr
, xmlbuf
->size
);
1896 /**************************************************************************
1897 * WsWriteXmlBufferToBytes [webservices.@]
1899 HRESULT WINAPI
WsWriteXmlBufferToBytes( WS_XML_WRITER
*handle
, WS_XML_BUFFER
*buffer
,
1900 const WS_XML_WRITER_ENCODING
*encoding
,
1901 const WS_XML_WRITER_PROPERTY
*properties
, ULONG count
,
1902 WS_HEAP
*heap
, void **bytes
, ULONG
*size
, WS_ERROR
*error
)
1904 struct writer
*writer
= (struct writer
*)handle
;
1905 struct xmlbuf
*xmlbuf
= (struct xmlbuf
*)buffer
;
1910 TRACE( "%p %p %p %p %u %p %p %p %p\n", handle
, buffer
, encoding
, properties
, count
, heap
,
1911 bytes
, size
, error
);
1912 if (error
) FIXME( "ignoring error parameter\n" );
1914 if (!writer
|| !xmlbuf
|| !heap
|| !bytes
) return E_INVALIDARG
;
1916 if (encoding
&& encoding
->encodingType
!= WS_XML_WRITER_ENCODING_TYPE_TEXT
)
1918 FIXME( "encoding type %u not supported\n", encoding
->encodingType
);
1922 for (i
= 0; i
< count
; i
++)
1924 hr
= prop_set( writer
->prop
, writer
->prop_count
, properties
[i
].id
, properties
[i
].value
,
1925 properties
[i
].valueSize
);
1926 if (hr
!= S_OK
) return hr
;
1929 if (!(buf
= ws_alloc( heap
, xmlbuf
->size
))) return WS_E_QUOTA_EXCEEDED
;
1930 memcpy( buf
, xmlbuf
->ptr
, xmlbuf
->size
);
1935 /**************************************************************************
1936 * WsWriteXmlnsAttribute [webservices.@]
1938 HRESULT WINAPI
WsWriteXmlnsAttribute( WS_XML_WRITER
*handle
, const WS_XML_STRING
*prefix
,
1939 const WS_XML_STRING
*ns
, BOOL single
, WS_ERROR
*error
)
1941 struct writer
*writer
= (struct writer
*)handle
;
1943 TRACE( "%p %s %s %d %p\n", handle
, debugstr_xmlstr(prefix
), debugstr_xmlstr(ns
),
1945 if (error
) FIXME( "ignoring error parameter\n" );
1947 if (!writer
|| !ns
) return E_INVALIDARG
;
1948 if (writer
->state
!= WRITER_STATE_STARTELEMENT
) return WS_E_INVALID_OPERATION
;
1950 if (namespace_in_scope( &writer
->current
->hdr
, prefix
, ns
)) return S_OK
;
1951 return write_add_namespace_attribute( writer
, prefix
, ns
, single
);
1954 static HRESULT
write_move_to( struct writer
*writer
, WS_MOVE_TO move
, BOOL
*found
)
1956 BOOL success
= FALSE
;
1957 struct node
*node
= writer
->current
;
1961 case WS_MOVE_TO_ROOT_ELEMENT
:
1962 success
= move_to_root_element( writer
->root
, &node
);
1965 case WS_MOVE_TO_NEXT_ELEMENT
:
1966 success
= move_to_next_element( &node
);
1969 case WS_MOVE_TO_PREVIOUS_ELEMENT
:
1970 success
= move_to_prev_element( &node
);
1973 case WS_MOVE_TO_CHILD_ELEMENT
:
1974 success
= move_to_child_element( &node
);
1977 case WS_MOVE_TO_END_ELEMENT
:
1978 success
= move_to_end_element( &node
);
1981 case WS_MOVE_TO_PARENT_ELEMENT
:
1982 success
= move_to_parent_element( &node
);
1985 case WS_MOVE_TO_FIRST_NODE
:
1986 success
= move_to_first_node( &node
);
1989 case WS_MOVE_TO_NEXT_NODE
:
1990 success
= move_to_next_node( &node
);
1993 case WS_MOVE_TO_PREVIOUS_NODE
:
1994 success
= move_to_prev_node( &node
);
1997 case WS_MOVE_TO_CHILD_NODE
:
1998 success
= move_to_child_node( &node
);
2001 case WS_MOVE_TO_BOF
:
2002 success
= move_to_bof( writer
->root
, &node
);
2005 case WS_MOVE_TO_EOF
:
2006 success
= move_to_eof( writer
->root
, &node
);
2010 FIXME( "unhandled move %u\n", move
);
2014 if (success
&& node
== writer
->root
) return E_INVALIDARG
;
2015 writer
->current
= node
;
2022 return success
? S_OK
: WS_E_INVALID_FORMAT
;
2025 /**************************************************************************
2026 * WsMoveWriter [webservices.@]
2028 HRESULT WINAPI
WsMoveWriter( WS_XML_WRITER
*handle
, WS_MOVE_TO move
, BOOL
*found
, WS_ERROR
*error
)
2030 struct writer
*writer
= (struct writer
*)handle
;
2032 TRACE( "%p %u %p %p\n", handle
, move
, found
, error
);
2033 if (error
) FIXME( "ignoring error parameter\n" );
2035 if (!writer
) return E_INVALIDARG
;
2036 if (!writer
->output_type
) return WS_E_INVALID_OPERATION
;
2038 return write_move_to( writer
, move
, found
);
2041 /**************************************************************************
2042 * WsGetWriterPosition [webservices.@]
2044 HRESULT WINAPI
WsGetWriterPosition( WS_XML_WRITER
*handle
, WS_XML_NODE_POSITION
*pos
, WS_ERROR
*error
)
2046 struct writer
*writer
= (struct writer
*)handle
;
2048 TRACE( "%p %p %p\n", handle
, pos
, error
);
2049 if (error
) FIXME( "ignoring error parameter\n" );
2051 if (!writer
|| !pos
) return E_INVALIDARG
;
2052 if (!writer
->output_type
) return WS_E_INVALID_OPERATION
;
2054 pos
->buffer
= (WS_XML_BUFFER
*)writer
->output_buf
;
2055 pos
->node
= writer
->current
;
2059 /**************************************************************************
2060 * WsSetWriterPosition [webservices.@]
2062 HRESULT WINAPI
WsSetWriterPosition( WS_XML_WRITER
*handle
, const WS_XML_NODE_POSITION
*pos
, WS_ERROR
*error
)
2064 struct writer
*writer
= (struct writer
*)handle
;
2066 TRACE( "%p %p %p\n", handle
, pos
, error
);
2067 if (error
) FIXME( "ignoring error parameter\n" );
2069 if (!writer
|| !pos
|| (struct xmlbuf
*)pos
->buffer
!= writer
->output_buf
) return E_INVALIDARG
;
2070 if (!writer
->output_type
) return WS_E_INVALID_OPERATION
;
2072 writer
->current
= pos
->node
;
2076 static HRESULT
write_add_comment_node( struct writer
*writer
, const WS_XML_STRING
*value
)
2078 struct node
*node
, *parent
;
2079 WS_XML_COMMENT_NODE
*comment
;
2081 if (!(parent
= find_parent( writer
->current
))) return WS_E_INVALID_FORMAT
;
2082 if (!(node
= alloc_node( WS_XML_NODE_TYPE_COMMENT
))) return E_OUTOFMEMORY
;
2083 comment
= (WS_XML_COMMENT_NODE
*)node
;
2085 if (value
->length
&& !(comment
->value
.bytes
= heap_alloc( value
->length
)))
2088 return E_OUTOFMEMORY
;
2090 memcpy( comment
->value
.bytes
, value
->bytes
, value
->length
);
2091 comment
->value
.length
= value
->length
;
2093 write_insert_node( writer
, parent
, node
);
2097 static HRESULT
write_comment( struct writer
*writer
)
2099 const WS_XML_COMMENT_NODE
*comment
= (const WS_XML_COMMENT_NODE
*)writer
->current
;
2102 if ((hr
= write_grow_buffer( writer
, comment
->value
.length
+ 7 )) != S_OK
) return hr
;
2103 write_bytes( writer
, (const BYTE
*)"<!--", 4 );
2104 write_bytes( writer
, comment
->value
.bytes
, comment
->value
.length
);
2105 write_bytes( writer
, (const BYTE
*)"-->", 3 );
2109 static HRESULT
write_comment_node( struct writer
*writer
, const WS_XML_STRING
*value
)
2112 if ((hr
= write_flush( writer
)) != S_OK
) return hr
;
2113 if ((hr
= write_add_comment_node( writer
, value
)) != S_OK
) return hr
;
2114 if ((hr
= write_comment( writer
)) != S_OK
) return hr
;
2115 writer
->state
= WRITER_STATE_COMMENT
;
2119 static HRESULT
write_set_attributes( struct writer
*writer
, WS_XML_ATTRIBUTE
**attrs
, ULONG count
)
2124 for (i
= 0; i
< count
; i
++)
2126 if ((hr
= write_add_attribute( writer
, attrs
[i
]->prefix
, attrs
[i
]->localName
, attrs
[i
]->ns
,
2127 attrs
[i
]->singleQuote
)) != S_OK
) return hr
;
2128 if ((hr
= write_set_attribute_value( writer
, attrs
[i
]->value
)) != S_OK
) return hr
;
2133 static HRESULT
write_node( struct writer
*writer
, const WS_XML_NODE
*node
)
2137 switch (node
->nodeType
)
2139 case WS_XML_NODE_TYPE_ELEMENT
:
2141 const WS_XML_ELEMENT_NODE
*elem
= (const WS_XML_ELEMENT_NODE
*)node
;
2142 if ((hr
= write_element_node( writer
, elem
->prefix
, elem
->localName
, elem
->ns
)) != S_OK
) return hr
;
2143 return write_set_attributes( writer
, elem
->attributes
, elem
->attributeCount
);
2145 case WS_XML_NODE_TYPE_TEXT
:
2147 const WS_XML_TEXT_NODE
*text
= (const WS_XML_TEXT_NODE
*)node
;
2148 return write_text_node( writer
, text
->text
);
2150 case WS_XML_NODE_TYPE_END_ELEMENT
:
2151 return write_endelement_node( writer
);
2153 case WS_XML_NODE_TYPE_COMMENT
:
2155 const WS_XML_COMMENT_NODE
*comment
= (const WS_XML_COMMENT_NODE
*)node
;
2156 return write_comment_node( writer
, &comment
->value
);
2158 case WS_XML_NODE_TYPE_CDATA
:
2159 return write_cdata_node( writer
);
2161 case WS_XML_NODE_TYPE_END_CDATA
:
2162 return write_endcdata_node( writer
);
2164 case WS_XML_NODE_TYPE_EOF
:
2165 case WS_XML_NODE_TYPE_BOF
:
2169 WARN( "unknown node type %u\n", node
->nodeType
);
2170 return E_INVALIDARG
;
2174 /**************************************************************************
2175 * WsWriteNode [webservices.@]
2177 HRESULT WINAPI
WsWriteNode( WS_XML_WRITER
*handle
, const WS_XML_NODE
*node
, WS_ERROR
*error
)
2179 struct writer
*writer
= (struct writer
*)handle
;
2181 TRACE( "%p %p %p\n", handle
, node
, error
);
2182 if (error
) FIXME( "ignoring error parameter\n" );
2184 if (!writer
|| !node
) return E_INVALIDARG
;
2185 if (!writer
->output_type
) return WS_E_INVALID_OPERATION
;
2187 return write_node( writer
, node
);
2190 static HRESULT
write_tree_node( struct writer
*writer
)
2194 switch (node_type( writer
->current
))
2196 case WS_XML_NODE_TYPE_ELEMENT
:
2197 if (writer
->state
== WRITER_STATE_STARTELEMENT
&& (hr
= write_endstartelement( writer
)) != S_OK
)
2199 if ((hr
= write_startelement( writer
)) != S_OK
) return hr
;
2200 writer
->state
= WRITER_STATE_STARTELEMENT
;
2203 case WS_XML_NODE_TYPE_TEXT
:
2204 if (writer
->state
== WRITER_STATE_STARTELEMENT
&& (hr
= write_endstartelement( writer
)) != S_OK
)
2206 if ((hr
= write_text( writer
)) != S_OK
) return hr
;
2207 writer
->state
= WRITER_STATE_TEXT
;
2210 case WS_XML_NODE_TYPE_END_ELEMENT
:
2211 if ((hr
= write_close_element( writer
, writer
->current
->parent
)) != S_OK
) return hr
;
2212 writer
->state
= WRITER_STATE_ENDELEMENT
;
2215 case WS_XML_NODE_TYPE_COMMENT
:
2216 if (writer
->state
== WRITER_STATE_STARTELEMENT
&& (hr
= write_endstartelement( writer
)) != S_OK
)
2218 if ((hr
= write_comment( writer
)) != S_OK
) return hr
;
2219 writer
->state
= WRITER_STATE_COMMENT
;
2222 case WS_XML_NODE_TYPE_CDATA
:
2223 if (writer
->state
== WRITER_STATE_STARTELEMENT
&& (hr
= write_endstartelement( writer
)) != S_OK
)
2225 if ((hr
= write_cdata( writer
)) != S_OK
) return hr
;
2226 writer
->state
= WRITER_STATE_STARTCDATA
;
2229 case WS_XML_NODE_TYPE_END_CDATA
:
2230 if ((hr
= write_endcdata( writer
)) != S_OK
) return hr
;
2231 writer
->state
= WRITER_STATE_ENDCDATA
;
2234 case WS_XML_NODE_TYPE_EOF
:
2235 case WS_XML_NODE_TYPE_BOF
:
2239 ERR( "unknown node type %u\n", node_type(writer
->current
) );
2240 return E_INVALIDARG
;
2244 static HRESULT
write_tree( struct writer
*writer
)
2248 if ((hr
= write_tree_node( writer
)) != S_OK
) return hr
;
2251 if (node_type( writer
->current
) == WS_XML_NODE_TYPE_EOF
) break;
2252 if (move_to_child_node( &writer
->current
))
2254 if ((hr
= write_tree_node( writer
)) != S_OK
) return hr
;
2257 if (move_to_next_node( &writer
->current
))
2259 if ((hr
= write_tree_node( writer
)) != S_OK
) return hr
;
2262 if (!move_to_parent_node( &writer
->current
) || !move_to_next_node( &writer
->current
))
2264 ERR( "invalid tree\n" );
2265 return WS_E_INVALID_FORMAT
;
2267 if ((hr
= write_tree_node( writer
)) != S_OK
) return hr
;
2272 static void write_rewind( struct writer
*writer
)
2274 writer
->write_pos
= 0;
2275 writer
->current
= writer
->root
;
2276 writer
->state
= WRITER_STATE_INITIAL
;
2279 /**************************************************************************
2280 * WsCopyNode [webservices.@]
2282 HRESULT WINAPI
WsCopyNode( WS_XML_WRITER
*handle
, WS_XML_READER
*reader
, WS_ERROR
*error
)
2284 struct writer
*writer
= (struct writer
*)handle
;
2285 struct node
*parent
, *current
= writer
->current
, *node
= NULL
;
2288 TRACE( "%p %p %p\n", handle
, reader
, error
);
2289 if (error
) FIXME( "ignoring error parameter\n" );
2291 if (!writer
) return E_INVALIDARG
;
2292 if (!(parent
= find_parent( writer
->current
))) return WS_E_INVALID_FORMAT
;
2294 if ((hr
= copy_node( reader
, &node
)) != S_OK
) return hr
;
2295 write_insert_node( writer
, parent
, node
);
2297 write_rewind( writer
);
2298 if ((hr
= write_tree( writer
)) != S_OK
) return hr
;
2300 writer
->current
= current
;