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
28 #include "webservices.h"
30 #include "wine/debug.h"
31 #include "wine/list.h"
32 #include "wine/unicode.h"
33 #include "webservices_private.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(webservices
);
37 static const struct prop_desc writer_props
[] =
39 { sizeof(ULONG
), FALSE
}, /* WS_XML_WRITER_PROPERTY_MAX_DEPTH */
40 { sizeof(BOOL
), FALSE
}, /* WS_XML_WRITER_PROPERTY_ALLOW_FRAGMENT */
41 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_MAX_ATTRIBUTES */
42 { sizeof(BOOL
), FALSE
}, /* WS_XML_WRITER_PROPERTY_WRITE_DECLARATION */
43 { sizeof(ULONG
), FALSE
}, /* WS_XML_WRITER_PROPERTY_INDENT */
44 { sizeof(ULONG
), FALSE
}, /* WS_XML_WRITER_PROPERTY_BUFFER_TRIM_SIZE */
45 { sizeof(WS_CHARSET
), FALSE
}, /* WS_XML_WRITER_PROPERTY_CHARSET */
46 { sizeof(WS_BUFFERS
), FALSE
}, /* WS_XML_WRITER_PROPERTY_BUFFERS */
47 { sizeof(ULONG
), FALSE
}, /* WS_XML_WRITER_PROPERTY_BUFFER_MAX_SIZE */
48 { sizeof(WS_BYTES
), FALSE
}, /* WS_XML_WRITER_PROPERTY_BYTES */
49 { sizeof(BOOL
), TRUE
}, /* WS_XML_WRITER_PROPERTY_IN_ATTRIBUTE */
50 { sizeof(ULONG
), FALSE
}, /* WS_XML_WRITER_PROPERTY_MAX_MIME_PARTS_BUFFER_SIZE */
51 { sizeof(WS_BYTES
), FALSE
}, /* WS_XML_WRITER_PROPERTY_INITIAL_BUFFER */
52 { sizeof(BOOL
), FALSE
}, /* WS_XML_WRITER_PROPERTY_ALLOW_INVALID_CHARACTER_REFERENCES */
53 { sizeof(ULONG
), FALSE
}, /* WS_XML_WRITER_PROPERTY_MAX_NAMESPACES */
54 { sizeof(ULONG
), TRUE
}, /* WS_XML_WRITER_PROPERTY_BYTES_WRITTEN */
55 { sizeof(ULONG
), TRUE
}, /* WS_XML_WRITER_PROPERTY_BYTES_TO_CLOSE */
56 { sizeof(BOOL
), FALSE
}, /* WS_XML_WRITER_PROPERTY_COMPRESS_EMPTY_ELEMENTS */
57 { sizeof(BOOL
), FALSE
} /* WS_XML_WRITER_PROPERTY_EMIT_UNCOMPRESSED_EMPTY_ELEMENTS */
63 WRITER_STATE_STARTELEMENT
,
64 WRITER_STATE_STARTATTRIBUTE
,
65 WRITER_STATE_STARTCDATA
,
66 WRITER_STATE_ENDSTARTELEMENT
,
69 WRITER_STATE_ENDELEMENT
,
78 unsigned char *write_bufptr
;
79 enum writer_state state
;
82 WS_XML_STRING
*current_ns
;
83 WS_XML_WRITER_ENCODING_TYPE output_enc
;
84 WS_CHARSET output_charset
;
85 WS_XML_WRITER_OUTPUT_TYPE output_type
;
86 struct xmlbuf
*output_buf
;
88 WS_XML_DICTIONARY
*dict
;
89 WS_DYNAMIC_STRING_CALLBACK dict_cb
;
92 struct prop prop
[sizeof(writer_props
)/sizeof(writer_props
[0])];
95 #define WRITER_MAGIC (('W' << 24) | ('R' << 16) | ('I' << 8) | 'T')
97 static struct writer
*alloc_writer(void)
99 static const ULONG count
= sizeof(writer_props
)/sizeof(writer_props
[0]);
101 ULONG size
= sizeof(*ret
) + prop_size( writer_props
, count
);
103 if (!(ret
= heap_alloc_zero( size
))) return NULL
;
105 ret
->magic
= WRITER_MAGIC
;
106 InitializeCriticalSection( &ret
->cs
);
107 ret
->cs
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": writer.cs");
109 prop_init( writer_props
, count
, ret
->prop
, &ret
[1] );
110 ret
->prop_count
= count
;
114 static void free_writer( struct writer
*writer
)
116 destroy_nodes( writer
->root
);
117 free_xml_string( writer
->current_ns
);
118 WsFreeHeap( writer
->output_heap
);
120 writer
->cs
.DebugInfo
->Spare
[0] = 0;
121 DeleteCriticalSection( &writer
->cs
);
125 static void write_insert_eof( struct writer
*writer
, struct node
*eof
)
127 if (!writer
->root
) writer
->root
= eof
;
130 eof
->parent
= writer
->root
;
131 list_add_tail( &writer
->root
->children
, &eof
->entry
);
133 writer
->current
= eof
;
136 static void write_insert_bof( struct writer
*writer
, struct node
*bof
)
138 writer
->root
->parent
= bof
;
139 list_add_tail( &bof
->children
, &writer
->root
->entry
);
140 writer
->current
= writer
->root
= bof
;
143 static void write_insert_node( struct writer
*writer
, struct node
*parent
, struct node
*node
)
145 node
->parent
= parent
;
146 list_add_before( list_tail( &parent
->children
), &node
->entry
);
147 writer
->current
= node
;
150 static struct node
*find_parent( struct writer
*writer
)
152 if (is_valid_parent( writer
->current
)) return writer
->current
;
153 if (is_valid_parent( writer
->current
->parent
)) return writer
->current
->parent
;
157 static HRESULT
init_writer( struct writer
*writer
)
161 writer
->write_pos
= 0;
162 writer
->write_bufptr
= NULL
;
163 destroy_nodes( writer
->root
);
164 writer
->root
= writer
->current
= NULL
;
165 free_xml_string( writer
->current_ns
);
166 writer
->current_ns
= NULL
;
168 if (!(node
= alloc_node( WS_XML_NODE_TYPE_EOF
))) return E_OUTOFMEMORY
;
169 write_insert_eof( writer
, node
);
170 writer
->state
= WRITER_STATE_INITIAL
;
171 writer
->output_enc
= WS_XML_WRITER_ENCODING_TYPE_TEXT
;
172 writer
->output_charset
= WS_CHARSET_UTF8
;
174 writer
->dict_cb
= NULL
;
175 writer
->dict_cb_state
= NULL
;
179 /**************************************************************************
180 * WsCreateWriter [webservices.@]
182 HRESULT WINAPI
WsCreateWriter( const WS_XML_WRITER_PROPERTY
*properties
, ULONG count
,
183 WS_XML_WRITER
**handle
, WS_ERROR
*error
)
185 struct writer
*writer
;
186 ULONG i
, max_depth
= 32, max_attrs
= 128, trim_size
= 4096, max_size
= 65536, max_ns
= 32;
187 WS_CHARSET charset
= WS_CHARSET_UTF8
;
190 TRACE( "%p %u %p %p\n", properties
, count
, handle
, error
);
191 if (error
) FIXME( "ignoring error parameter\n" );
193 if (!handle
) return E_INVALIDARG
;
194 if (!(writer
= alloc_writer())) return E_OUTOFMEMORY
;
196 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_MAX_DEPTH
, &max_depth
, sizeof(max_depth
) );
197 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_MAX_ATTRIBUTES
, &max_attrs
, sizeof(max_attrs
) );
198 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_BUFFER_TRIM_SIZE
, &trim_size
, sizeof(trim_size
) );
199 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_CHARSET
, &charset
, sizeof(charset
) );
200 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_BUFFER_MAX_SIZE
, &max_size
, sizeof(max_size
) );
201 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_MAX_MIME_PARTS_BUFFER_SIZE
, &max_size
, sizeof(max_size
) );
202 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_MAX_NAMESPACES
, &max_ns
, sizeof(max_ns
) );
204 for (i
= 0; i
< count
; i
++)
206 hr
= prop_set( writer
->prop
, writer
->prop_count
, properties
[i
].id
, properties
[i
].value
,
207 properties
[i
].valueSize
);
210 free_writer( writer
);
215 hr
= prop_get( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_BUFFER_MAX_SIZE
,
216 &max_size
, sizeof(max_size
) );
219 free_writer( writer
);
223 hr
= WsCreateHeap( max_size
, 0, NULL
, 0, &writer
->output_heap
, NULL
);
226 free_writer( writer
);
230 hr
= init_writer( writer
);
233 free_writer( writer
);
237 *handle
= (WS_XML_WRITER
*)writer
;
241 /**************************************************************************
242 * WsFreeWriter [webservices.@]
244 void WINAPI
WsFreeWriter( WS_XML_WRITER
*handle
)
246 struct writer
*writer
= (struct writer
*)handle
;
248 TRACE( "%p\n", handle
);
252 EnterCriticalSection( &writer
->cs
);
254 if (writer
->magic
!= WRITER_MAGIC
)
256 LeaveCriticalSection( &writer
->cs
);
262 LeaveCriticalSection( &writer
->cs
);
263 free_writer( writer
);
266 /**************************************************************************
267 * WsGetWriterProperty [webservices.@]
269 HRESULT WINAPI
WsGetWriterProperty( WS_XML_WRITER
*handle
, WS_XML_WRITER_PROPERTY_ID id
,
270 void *buf
, ULONG size
, WS_ERROR
*error
)
272 struct writer
*writer
= (struct writer
*)handle
;
275 TRACE( "%p %u %p %u %p\n", handle
, id
, buf
, size
, error
);
276 if (error
) FIXME( "ignoring error parameter\n" );
278 if (!writer
) return E_INVALIDARG
;
280 EnterCriticalSection( &writer
->cs
);
282 if (writer
->magic
!= WRITER_MAGIC
)
284 LeaveCriticalSection( &writer
->cs
);
288 if (!writer
->output_type
)
290 LeaveCriticalSection( &writer
->cs
);
291 return WS_E_INVALID_OPERATION
;
296 case WS_XML_WRITER_PROPERTY_BYTES
:
298 WS_BYTES
*bytes
= buf
;
299 if (size
!= sizeof(*bytes
)) hr
= E_INVALIDARG
;
302 bytes
->bytes
= writer
->output_buf
->bytes
.bytes
;
303 bytes
->length
= writer
->output_buf
->bytes
.length
;
307 case WS_XML_WRITER_PROPERTY_BUFFERS
:
308 if (writer
->output_buf
->bytes
.length
)
310 WS_BUFFERS
*buffers
= buf
;
311 if (size
!= sizeof(*buffers
)) hr
= E_INVALIDARG
;
314 buffers
->bufferCount
= 1;
315 buffers
->buffers
= &writer
->output_buf
->bytes
;
321 hr
= prop_get( writer
->prop
, writer
->prop_count
, id
, buf
, size
);
324 LeaveCriticalSection( &writer
->cs
);
328 static void set_output_buffer( struct writer
*writer
, struct xmlbuf
*xmlbuf
)
330 /* free current buffer if it's ours */
331 if (writer
->output_buf
&& writer
->output_buf
->heap
== writer
->output_heap
)
333 free_xmlbuf( writer
->output_buf
);
335 writer
->output_buf
= xmlbuf
;
336 writer
->output_type
= WS_XML_WRITER_OUTPUT_TYPE_BUFFER
;
337 writer
->write_bufptr
= xmlbuf
->bytes
.bytes
;
338 writer
->write_pos
= 0;
341 /**************************************************************************
342 * WsSetOutput [webservices.@]
344 HRESULT WINAPI
WsSetOutput( WS_XML_WRITER
*handle
, const WS_XML_WRITER_ENCODING
*encoding
,
345 const WS_XML_WRITER_OUTPUT
*output
, const WS_XML_WRITER_PROPERTY
*properties
,
346 ULONG count
, WS_ERROR
*error
)
348 struct writer
*writer
= (struct writer
*)handle
;
353 TRACE( "%p %p %p %p %u %p\n", handle
, encoding
, output
, properties
, count
, error
);
354 if (error
) FIXME( "ignoring error parameter\n" );
356 if (!writer
) return E_INVALIDARG
;
358 EnterCriticalSection( &writer
->cs
);
360 if (writer
->magic
!= WRITER_MAGIC
)
362 LeaveCriticalSection( &writer
->cs
);
366 for (i
= 0; i
< count
; i
++)
368 hr
= prop_set( writer
->prop
, writer
->prop_count
, properties
[i
].id
, properties
[i
].value
,
369 properties
[i
].valueSize
);
370 if (hr
!= S_OK
) goto done
;
373 if ((hr
= init_writer( writer
)) != S_OK
) goto done
;
375 switch (encoding
->encodingType
)
377 case WS_XML_WRITER_ENCODING_TYPE_TEXT
:
379 WS_XML_WRITER_TEXT_ENCODING
*text
= (WS_XML_WRITER_TEXT_ENCODING
*)encoding
;
380 if (text
->charSet
!= WS_CHARSET_UTF8
)
382 FIXME( "charset %u not supported\n", text
->charSet
);
386 writer
->output_enc
= WS_XML_WRITER_ENCODING_TYPE_TEXT
;
387 writer
->output_charset
= WS_CHARSET_UTF8
;
390 case WS_XML_WRITER_ENCODING_TYPE_BINARY
:
392 WS_XML_WRITER_BINARY_ENCODING
*bin
= (WS_XML_WRITER_BINARY_ENCODING
*)encoding
;
393 writer
->output_enc
= WS_XML_WRITER_ENCODING_TYPE_BINARY
;
394 writer
->output_charset
= 0;
395 writer
->dict
= bin
->staticDictionary
;
396 writer
->dict_cb
= bin
->dynamicStringCallback
;
397 writer
->dict_cb_state
= bin
->dynamicStringCallbackState
;
401 FIXME( "encoding type %u not supported\n", encoding
->encodingType
);
406 switch (output
->outputType
)
408 case WS_XML_WRITER_OUTPUT_TYPE_BUFFER
:
410 struct xmlbuf
*xmlbuf
;
411 if (!(xmlbuf
= alloc_xmlbuf( writer
->output_heap
, writer
->output_enc
, writer
->output_charset
)))
413 hr
= WS_E_QUOTA_EXCEEDED
;
416 set_output_buffer( writer
, xmlbuf
);
420 FIXME( "output type %u not supported\n", output
->outputType
);
425 if (!(node
= alloc_node( WS_XML_NODE_TYPE_BOF
))) hr
= E_OUTOFMEMORY
;
426 else write_insert_bof( writer
, node
);
429 LeaveCriticalSection( &writer
->cs
);
433 /**************************************************************************
434 * WsSetOutputToBuffer [webservices.@]
436 HRESULT WINAPI
WsSetOutputToBuffer( WS_XML_WRITER
*handle
, WS_XML_BUFFER
*buffer
,
437 const WS_XML_WRITER_PROPERTY
*properties
, ULONG count
,
440 struct writer
*writer
= (struct writer
*)handle
;
441 struct xmlbuf
*xmlbuf
= (struct xmlbuf
*)buffer
;
446 TRACE( "%p %p %p %u %p\n", handle
, buffer
, properties
, count
, error
);
447 if (error
) FIXME( "ignoring error parameter\n" );
449 if (!writer
|| !xmlbuf
) return E_INVALIDARG
;
451 EnterCriticalSection( &writer
->cs
);
453 if (writer
->magic
!= WRITER_MAGIC
)
455 LeaveCriticalSection( &writer
->cs
);
459 for (i
= 0; i
< count
; i
++)
461 hr
= prop_set( writer
->prop
, writer
->prop_count
, properties
[i
].id
, properties
[i
].value
,
462 properties
[i
].valueSize
);
463 if (hr
!= S_OK
) goto done
;
466 if ((hr
= init_writer( writer
)) != S_OK
) goto done
;
467 writer
->output_enc
= xmlbuf
->encoding
;
468 writer
->output_charset
= xmlbuf
->charset
;
469 set_output_buffer( writer
, xmlbuf
);
471 if (!(node
= alloc_node( WS_XML_NODE_TYPE_BOF
))) hr
= E_OUTOFMEMORY
;
472 else write_insert_bof( writer
, node
);
475 LeaveCriticalSection( &writer
->cs
);
479 static HRESULT
write_grow_buffer( struct writer
*writer
, ULONG size
)
481 struct xmlbuf
*buf
= writer
->output_buf
;
485 if (buf
->size
>= writer
->write_pos
+ size
)
487 buf
->bytes
.length
= writer
->write_pos
+ size
;
490 new_size
= max( buf
->size
* 2, writer
->write_pos
+ size
);
491 if (!(tmp
= ws_realloc( buf
->heap
, buf
->bytes
.bytes
, buf
->size
, new_size
))) return WS_E_QUOTA_EXCEEDED
;
492 writer
->write_bufptr
= buf
->bytes
.bytes
= tmp
;
493 buf
->size
= new_size
;
494 buf
->bytes
.length
= writer
->write_pos
+ size
;
498 static inline void write_char( struct writer
*writer
, unsigned char ch
)
500 writer
->write_bufptr
[writer
->write_pos
++] = ch
;
503 static inline void write_bytes( struct writer
*writer
, const BYTE
*bytes
, ULONG len
)
505 memcpy( writer
->write_bufptr
+ writer
->write_pos
, bytes
, len
);
506 writer
->write_pos
+= len
;
515 static const struct escape escape_lt
= { '<', "<", 4 };
516 static const struct escape escape_gt
= { '>', ">", 4 };
517 static const struct escape escape_amp
= { '&', "&", 5 };
518 static const struct escape escape_apos
= { '\'', "'", 6 };
519 static const struct escape escape_quot
= { '"', """, 6 };
521 static HRESULT
write_bytes_escape( struct writer
*writer
, const BYTE
*bytes
, ULONG len
,
522 const struct escape
**escapes
, ULONG nb_escapes
)
528 for (i
= 0; i
< len
; i
++)
532 for (j
= 0; j
< nb_escapes
; j
++)
534 if (bytes
[i
] == escapes
[j
]->ch
)
536 ptr
= (const BYTE
*)escapes
[j
]->entity
;
537 size
= escapes
[j
]->len
;
541 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
542 write_bytes( writer
, ptr
, size
);
548 static HRESULT
write_attribute_value_text( struct writer
*writer
, const WS_XML_TEXT
*text
, BOOL single
)
550 WS_XML_UTF8_TEXT
*utf8
= (WS_XML_UTF8_TEXT
*)text
;
551 const struct escape
*escapes
[3];
553 escapes
[0] = single
? &escape_apos
: &escape_quot
;
554 escapes
[1] = &escape_lt
;
555 escapes
[2] = &escape_amp
;
556 return write_bytes_escape( writer
, utf8
->value
.bytes
, utf8
->value
.length
, escapes
, 3 );
559 static HRESULT
write_attribute_text( struct writer
*writer
, const WS_XML_ATTRIBUTE
*attr
)
561 unsigned char quote
= attr
->singleQuote
? '\'' : '"';
562 const WS_XML_STRING
*prefix
= NULL
;
566 if (attr
->prefix
) prefix
= attr
->prefix
;
568 /* ' prefix:attr="value"' */
570 size
= attr
->localName
->length
+ 4 /* ' =""' */;
571 if (prefix
&& prefix
->length
) size
+= prefix
->length
+ 1 /* ':' */;
572 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
574 write_char( writer
, ' ' );
575 if (prefix
&& prefix
->length
)
577 write_bytes( writer
, prefix
->bytes
, prefix
->length
);
578 write_char( writer
, ':' );
580 write_bytes( writer
, attr
->localName
->bytes
, attr
->localName
->length
);
581 write_char( writer
, '=' );
582 write_char( writer
, quote
);
583 if (attr
->value
) hr
= write_attribute_value_text( writer
, attr
->value
, attr
->singleQuote
);
584 write_char( writer
, quote
);
589 static HRESULT
write_int31( struct writer
*writer
, ULONG len
)
593 if (len
> 0x7fffffff) return E_INVALIDARG
;
595 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
598 write_char( writer
, len
);
601 write_char( writer
, (len
& 0x7f) | 0x80 );
603 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
604 if ((len
>>= 7) < 0x80)
606 write_char( writer
, len
);
609 write_char( writer
, (len
& 0x7f) | 0x80 );
611 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
612 if ((len
>>= 7) < 0x80)
614 write_char( writer
, len
);
617 write_char( writer
, (len
& 0x7f) | 0x80 );
619 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
620 if ((len
>>= 7) < 0x80)
622 write_char( writer
, len
);
625 write_char( writer
, (len
& 0x7f) | 0x80 );
627 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
628 if ((len
>>= 7) < 0x08)
630 write_char( writer
, len
);
633 return WS_E_INVALID_FORMAT
;
636 static HRESULT
write_string( struct writer
*writer
, const BYTE
*bytes
, ULONG len
)
639 if ((hr
= write_int31( writer
, len
)) != S_OK
) return hr
;
640 if ((hr
= write_grow_buffer( writer
, len
)) != S_OK
) return hr
;
641 write_bytes( writer
, bytes
, len
);
645 static HRESULT
write_dict_string( struct writer
*writer
, ULONG id
)
648 if (id
> 0x7fffffff) return E_INVALIDARG
;
649 if ((hr
= write_int31( writer
, id
)) != S_OK
) return hr
;
653 static enum record_type
get_attr_text_record_type( const WS_XML_TEXT
*text
)
655 if (!text
) return RECORD_CHARS8_TEXT
;
656 switch (text
->textType
)
658 case WS_XML_TEXT_TYPE_UTF8
:
660 const WS_XML_UTF8_TEXT
*text_utf8
= (const WS_XML_UTF8_TEXT
*)text
;
661 if (text_utf8
->value
.length
<= MAX_UINT8
) return RECORD_CHARS8_TEXT
;
662 if (text_utf8
->value
.length
<= MAX_UINT16
) return RECORD_CHARS16_TEXT
;
663 return RECORD_CHARS32_TEXT
;
665 case WS_XML_TEXT_TYPE_BASE64
:
667 const WS_XML_BASE64_TEXT
*text_base64
= (const WS_XML_BASE64_TEXT
*)text
;
668 if (text_base64
->length
<= MAX_UINT8
) return RECORD_BYTES8_TEXT
;
669 if (text_base64
->length
<= MAX_UINT16
) return RECORD_BYTES16_TEXT
;
670 return RECORD_BYTES32_TEXT
;
672 case WS_XML_TEXT_TYPE_BOOL
:
674 const WS_XML_BOOL_TEXT
*text_bool
= (const WS_XML_BOOL_TEXT
*)text
;
675 return text_bool
->value
? RECORD_TRUE_TEXT
: RECORD_FALSE_TEXT
;
677 case WS_XML_TEXT_TYPE_INT32
:
679 const WS_XML_INT32_TEXT
*text_int32
= (const WS_XML_INT32_TEXT
*)text
;
680 if (!text_int32
->value
) return RECORD_ZERO_TEXT
;
681 if (text_int32
->value
== 1) return RECORD_ONE_TEXT
;
682 if (text_int32
->value
>= MIN_INT8
&& text_int32
->value
<= MAX_INT8
) return RECORD_INT8_TEXT
;
683 if (text_int32
->value
>= MIN_INT16
&& text_int32
->value
<= MAX_INT16
) return RECORD_INT16_TEXT
;
684 return RECORD_INT32_TEXT
;
686 case WS_XML_TEXT_TYPE_INT64
:
688 const WS_XML_INT64_TEXT
*text_int64
= (const WS_XML_INT64_TEXT
*)text
;
689 if (!text_int64
->value
) return RECORD_ZERO_TEXT
;
690 if (text_int64
->value
== 1) return RECORD_ONE_TEXT
;
691 if (text_int64
->value
>= MIN_INT8
&& text_int64
->value
<= MAX_INT8
) return RECORD_INT8_TEXT
;
692 if (text_int64
->value
>= MIN_INT16
&& text_int64
->value
<= MAX_INT16
) return RECORD_INT16_TEXT
;
693 if (text_int64
->value
>= MIN_INT32
&& text_int64
->value
<= MAX_INT32
) return RECORD_INT32_TEXT
;
694 return RECORD_INT64_TEXT
;
696 case WS_XML_TEXT_TYPE_UINT64
:
698 const WS_XML_UINT64_TEXT
*text_uint64
= (const WS_XML_UINT64_TEXT
*)text
;
699 if (!text_uint64
->value
) return RECORD_ZERO_TEXT
;
700 if (text_uint64
->value
== 1) return RECORD_ONE_TEXT
;
701 if (text_uint64
->value
<= MAX_INT8
) return RECORD_INT8_TEXT
;
702 if (text_uint64
->value
<= MAX_INT16
) return RECORD_INT16_TEXT
;
703 if (text_uint64
->value
<= MAX_INT32
) return RECORD_INT32_TEXT
;
704 if (text_uint64
->value
<= MAX_INT64
) return RECORD_INT64_TEXT
;
705 return RECORD_UINT64_TEXT
;
707 case WS_XML_TEXT_TYPE_DOUBLE
:
709 const WS_XML_DOUBLE_TEXT
*text_double
= (const WS_XML_DOUBLE_TEXT
*)text
;
710 if (!text_double
->value
) return RECORD_ZERO_TEXT
;
711 if (text_double
->value
== 1) return RECORD_ONE_TEXT
;
712 if (isinf( text_double
->value
) || (INT64
)text_double
->value
!= text_double
->value
)
713 return RECORD_DOUBLE_TEXT
;
714 if (text_double
->value
<= MAX_INT8
) return RECORD_INT8_TEXT
;
715 if (text_double
->value
<= MAX_INT16
) return RECORD_INT16_TEXT
;
716 if (text_double
->value
<= MAX_INT32
) return RECORD_INT32_TEXT
;
717 return RECORD_INT64_TEXT
;
719 case WS_XML_TEXT_TYPE_GUID
:
720 return RECORD_GUID_TEXT
;
722 case WS_XML_TEXT_TYPE_UNIQUE_ID
:
723 return RECORD_UNIQUE_ID_TEXT
;
726 FIXME( "unhandled text type %u\n", text
->textType
);
731 static INT64
get_text_value_int( const WS_XML_TEXT
*text
)
733 switch (text
->textType
)
735 case WS_XML_TEXT_TYPE_INT32
:
737 const WS_XML_INT32_TEXT
*text_int32
= (const WS_XML_INT32_TEXT
*)text
;
738 return text_int32
->value
;
740 case WS_XML_TEXT_TYPE_INT64
:
742 const WS_XML_INT64_TEXT
*text_int64
= (const WS_XML_INT64_TEXT
*)text
;
743 return text_int64
->value
;
745 case WS_XML_TEXT_TYPE_UINT64
:
747 const WS_XML_UINT64_TEXT
*text_uint64
= (const WS_XML_UINT64_TEXT
*)text
;
748 return text_uint64
->value
;
750 case WS_XML_TEXT_TYPE_DOUBLE
:
752 const WS_XML_DOUBLE_TEXT
*text_double
= (const WS_XML_DOUBLE_TEXT
*)text
;
753 return text_double
->value
;
756 ERR( "unhandled text type %u\n", text
->textType
);
762 static HRESULT
write_attribute_value_bin( struct writer
*writer
, const WS_XML_TEXT
*text
)
764 enum record_type type
= get_attr_text_record_type( text
);
767 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
768 write_char( writer
, type
);
772 case RECORD_CHARS8_TEXT
:
774 WS_XML_UTF8_TEXT
*text_utf8
= (WS_XML_UTF8_TEXT
*)text
;
777 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
778 write_char( writer
, 0 );
781 if ((hr
= write_grow_buffer( writer
, 1 + text_utf8
->value
.length
)) != S_OK
) return hr
;
782 write_char( writer
, text_utf8
->value
.length
);
783 write_bytes( writer
, text_utf8
->value
.bytes
, text_utf8
->value
.length
);
786 case RECORD_CHARS16_TEXT
:
788 WS_XML_UTF8_TEXT
*text_utf8
= (WS_XML_UTF8_TEXT
*)text
;
789 UINT16 len
= text_utf8
->value
.length
;
790 if ((hr
= write_grow_buffer( writer
, sizeof(len
) + len
)) != S_OK
) return hr
;
791 write_bytes( writer
, (const BYTE
*)&len
, sizeof(len
) );
792 write_bytes( writer
, text_utf8
->value
.bytes
, len
);
795 case RECORD_BYTES8_TEXT
:
797 WS_XML_BASE64_TEXT
*text_base64
= (WS_XML_BASE64_TEXT
*)text
;
798 if ((hr
= write_grow_buffer( writer
, 1 + text_base64
->length
)) != S_OK
) return hr
;
799 write_char( writer
, text_base64
->length
);
800 write_bytes( writer
, text_base64
->bytes
, text_base64
->length
);
803 case RECORD_BYTES16_TEXT
:
805 WS_XML_BASE64_TEXT
*text_base64
= (WS_XML_BASE64_TEXT
*)text
;
806 UINT16 len
= text_base64
->length
;
807 if ((hr
= write_grow_buffer( writer
, sizeof(len
) + len
)) != S_OK
) return hr
;
808 write_bytes( writer
, (const BYTE
*)&len
, sizeof(len
) );
809 write_bytes( writer
, text_base64
->bytes
, len
);
812 case RECORD_ZERO_TEXT
:
813 case RECORD_ONE_TEXT
:
814 case RECORD_FALSE_TEXT
:
815 case RECORD_TRUE_TEXT
:
818 case RECORD_INT8_TEXT
:
820 INT8 val
= get_text_value_int( text
);
821 if ((hr
= write_grow_buffer( writer
, sizeof(val
) )) != S_OK
) return hr
;
822 write_char( writer
, val
);
825 case RECORD_INT16_TEXT
:
827 INT16 val
= get_text_value_int( text
);
828 if ((hr
= write_grow_buffer( writer
, sizeof(val
) )) != S_OK
) return hr
;
829 write_bytes( writer
, (const BYTE
*)&val
, sizeof(val
) );
832 case RECORD_INT32_TEXT
:
834 INT32 val
= get_text_value_int( text
);
835 if ((hr
= write_grow_buffer( writer
, sizeof(val
) )) != S_OK
) return hr
;
836 write_bytes( writer
, (const BYTE
*)&val
, sizeof(val
) );
839 case RECORD_INT64_TEXT
:
841 INT64 val
= get_text_value_int( text
);
842 if ((hr
= write_grow_buffer( writer
, sizeof(val
) )) != S_OK
) return hr
;
843 write_bytes( writer
, (const BYTE
*)&val
, sizeof(val
) );
846 case RECORD_UINT64_TEXT
:
848 WS_XML_UINT64_TEXT
*text_uint64
= (WS_XML_UINT64_TEXT
*)text
;
849 if ((hr
= write_grow_buffer( writer
, sizeof(text_uint64
->value
) )) != S_OK
) return hr
;
850 write_bytes( writer
, (const BYTE
*)&text_uint64
->value
, sizeof(text_uint64
->value
) );
853 case RECORD_DOUBLE_TEXT
:
855 WS_XML_DOUBLE_TEXT
*text_double
= (WS_XML_DOUBLE_TEXT
*)text
;
856 if ((hr
= write_grow_buffer( writer
, sizeof(text_double
->value
) )) != S_OK
) return hr
;
857 write_bytes( writer
, (const BYTE
*)&text_double
->value
, sizeof(text_double
->value
) );
860 case RECORD_GUID_TEXT
:
862 WS_XML_GUID_TEXT
*text_guid
= (WS_XML_GUID_TEXT
*)text
;
863 if ((hr
= write_grow_buffer( writer
, sizeof(text_guid
->value
) )) != S_OK
) return hr
;
864 write_bytes( writer
, (const BYTE
*)&text_guid
->value
, sizeof(text_guid
->value
) );
867 case RECORD_UNIQUE_ID_TEXT
:
869 WS_XML_UNIQUE_ID_TEXT
*text_unique_id
= (WS_XML_UNIQUE_ID_TEXT
*)text
;
870 if ((hr
= write_grow_buffer( writer
, sizeof(text_unique_id
->value
) )) != S_OK
) return hr
;
871 write_bytes( writer
, (const BYTE
*)&text_unique_id
->value
, sizeof(text_unique_id
->value
) );
875 FIXME( "unhandled record type %02x\n", type
);
880 static BOOL
lookup_string_id( struct writer
*writer
, const WS_XML_STRING
*str
, ULONG
*id
)
882 if (writer
->dict
&& str
->dictionary
== writer
->dict
)
890 writer
->dict_cb( writer
->dict_cb_state
, str
, &found
, id
, NULL
);
891 if (found
) *id
= (*id
<< 1) | 1;
897 static enum record_type
get_attr_record_type( const WS_XML_ATTRIBUTE
*attr
, BOOL use_dict
)
899 if (!attr
->prefix
|| !attr
->prefix
->length
)
901 if (use_dict
) return RECORD_SHORT_DICTIONARY_ATTRIBUTE
;
902 return RECORD_SHORT_ATTRIBUTE
;
904 if (attr
->prefix
->length
== 1 && attr
->prefix
->bytes
[0] >= 'a' && attr
->prefix
->bytes
[0] <= 'z')
906 if (use_dict
) return RECORD_PREFIX_DICTIONARY_ATTRIBUTE_A
+ attr
->prefix
->bytes
[0] - 'a';
907 return RECORD_PREFIX_ATTRIBUTE_A
+ attr
->prefix
->bytes
[0] - 'a';
909 if (use_dict
) return RECORD_DICTIONARY_ATTRIBUTE
;
910 return RECORD_ATTRIBUTE
;
913 static HRESULT
write_attribute_bin( struct writer
*writer
, const WS_XML_ATTRIBUTE
*attr
)
916 enum record_type type
= get_attr_record_type( attr
, lookup_string_id(writer
, attr
->localName
, &id
) );
919 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
920 write_char( writer
, type
);
922 if (type
>= RECORD_PREFIX_ATTRIBUTE_A
&& type
<= RECORD_PREFIX_ATTRIBUTE_Z
)
924 if ((hr
= write_string( writer
, attr
->localName
->bytes
, attr
->localName
->length
)) != S_OK
) return hr
;
925 return write_attribute_value_bin( writer
, attr
->value
);
927 if (type
>= RECORD_PREFIX_DICTIONARY_ATTRIBUTE_A
&& type
<= RECORD_PREFIX_DICTIONARY_ATTRIBUTE_Z
)
929 if ((hr
= write_dict_string( writer
, id
)) != S_OK
) return hr
;
930 return write_attribute_value_bin( writer
, attr
->value
);
935 case RECORD_SHORT_ATTRIBUTE
:
936 if ((hr
= write_string( writer
, attr
->localName
->bytes
, attr
->localName
->length
)) != S_OK
) return hr
;
939 case RECORD_ATTRIBUTE
:
940 if ((hr
= write_string( writer
, attr
->prefix
->bytes
, attr
->prefix
->length
)) != S_OK
) return hr
;
941 if ((hr
= write_string( writer
, attr
->localName
->bytes
, attr
->localName
->length
)) != S_OK
) return hr
;
944 case RECORD_SHORT_DICTIONARY_ATTRIBUTE
:
945 if ((hr
= write_dict_string( writer
, id
)) != S_OK
) return hr
;
948 case RECORD_DICTIONARY_ATTRIBUTE
:
949 if ((hr
= write_string( writer
, attr
->prefix
->bytes
, attr
->prefix
->length
)) != S_OK
) return hr
;
950 if ((hr
= write_dict_string( writer
, id
)) != S_OK
) return hr
;
954 ERR( "unhandled record type %02x\n", type
);
955 return WS_E_NOT_SUPPORTED
;
958 return write_attribute_value_bin( writer
, attr
->value
);
961 static HRESULT
write_attribute( struct writer
*writer
, const WS_XML_ATTRIBUTE
*attr
)
963 switch (writer
->output_enc
)
965 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_attribute_text( writer
, attr
);
966 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return write_attribute_bin( writer
, attr
);
968 ERR( "unhandled encoding %u\n", writer
->output_enc
);
969 return WS_E_NOT_SUPPORTED
;
973 static inline BOOL
is_current_namespace( struct writer
*writer
, const WS_XML_STRING
*ns
)
975 return (WsXmlStringEquals( writer
->current_ns
, ns
, NULL
) == S_OK
);
978 /**************************************************************************
979 * WsGetPrefixFromNamespace [webservices.@]
981 HRESULT WINAPI
WsGetPrefixFromNamespace( WS_XML_WRITER
*handle
, const WS_XML_STRING
*ns
,
982 BOOL required
, const WS_XML_STRING
**prefix
,
985 struct writer
*writer
= (struct writer
*)handle
;
986 WS_XML_ELEMENT_NODE
*elem
;
990 TRACE( "%p %s %d %p %p\n", handle
, debugstr_xmlstr(ns
), required
, prefix
, error
);
991 if (error
) FIXME( "ignoring error parameter\n" );
993 if (!writer
|| !ns
|| !prefix
) return E_INVALIDARG
;
995 EnterCriticalSection( &writer
->cs
);
997 if (writer
->magic
!= WRITER_MAGIC
)
999 LeaveCriticalSection( &writer
->cs
);
1000 return E_INVALIDARG
;
1003 elem
= &writer
->current
->hdr
;
1004 if (elem
->prefix
&& is_current_namespace( writer
, ns
))
1006 *prefix
= elem
->prefix
;
1012 if (required
) hr
= WS_E_INVALID_FORMAT
;
1020 LeaveCriticalSection( &writer
->cs
);
1024 static HRESULT
write_namespace_attribute_text( struct writer
*writer
, const WS_XML_ATTRIBUTE
*attr
)
1026 unsigned char quote
= attr
->singleQuote
? '\'' : '"';
1030 /* ' xmlns:prefix="namespace"' */
1032 size
= attr
->ns
->length
+ 9 /* ' xmlns=""' */;
1033 if (attr
->prefix
) size
+= attr
->prefix
->length
+ 1 /* ':' */;
1034 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
1036 write_bytes( writer
, (const BYTE
*)" xmlns", 6 );
1039 write_char( writer
, ':' );
1040 write_bytes( writer
, attr
->prefix
->bytes
, attr
->prefix
->length
);
1042 write_char( writer
, '=' );
1043 write_char( writer
, quote
);
1044 write_bytes( writer
, attr
->ns
->bytes
, attr
->ns
->length
);
1045 write_char( writer
, quote
);
1050 static enum record_type
get_xmlns_record_type( const WS_XML_ATTRIBUTE
*attr
, BOOL use_dict
)
1052 if (!attr
->prefix
|| !attr
->prefix
->length
)
1054 if (use_dict
) return RECORD_SHORT_DICTIONARY_XMLNS_ATTRIBUTE
;
1055 return RECORD_SHORT_XMLNS_ATTRIBUTE
;
1057 if (use_dict
) return RECORD_DICTIONARY_XMLNS_ATTRIBUTE
;
1058 return RECORD_XMLNS_ATTRIBUTE
;
1061 static HRESULT
write_namespace_attribute_bin( struct writer
*writer
, const WS_XML_ATTRIBUTE
*attr
)
1064 enum record_type type
= get_xmlns_record_type( attr
, lookup_string_id(writer
, attr
->ns
, &id
) );
1067 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
1068 write_char( writer
, type
);
1072 case RECORD_SHORT_XMLNS_ATTRIBUTE
:
1075 case RECORD_XMLNS_ATTRIBUTE
:
1076 if ((hr
= write_string( writer
, attr
->prefix
->bytes
, attr
->prefix
->length
)) != S_OK
) return hr
;
1079 case RECORD_SHORT_DICTIONARY_XMLNS_ATTRIBUTE
:
1080 return write_dict_string( writer
, id
);
1082 case RECORD_DICTIONARY_XMLNS_ATTRIBUTE
:
1083 if ((hr
= write_string( writer
, attr
->prefix
->bytes
, attr
->prefix
->length
)) != S_OK
) return hr
;
1084 return write_dict_string( writer
, id
);
1087 ERR( "unhandled record type %02x\n", type
);
1088 return WS_E_NOT_SUPPORTED
;
1091 return write_string( writer
, attr
->ns
->bytes
, attr
->ns
->length
);
1094 static HRESULT
write_namespace_attribute( struct writer
*writer
, const WS_XML_ATTRIBUTE
*attr
)
1096 switch (writer
->output_enc
)
1098 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_namespace_attribute_text( writer
, attr
);
1099 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return write_namespace_attribute_bin( writer
, attr
);
1101 ERR( "unhandled encoding %u\n", writer
->output_enc
);
1102 return WS_E_NOT_SUPPORTED
;
1106 static HRESULT
add_namespace_attribute( struct writer
*writer
, const WS_XML_STRING
*prefix
,
1107 const WS_XML_STRING
*ns
, BOOL single
)
1109 WS_XML_ATTRIBUTE
*attr
;
1110 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
1113 if (!(attr
= heap_alloc_zero( sizeof(*attr
) ))) return E_OUTOFMEMORY
;
1115 attr
->singleQuote
= !!single
;
1117 if (prefix
&& !(attr
->prefix
= dup_xml_string( prefix
)))
1119 free_attribute( attr
);
1120 return E_OUTOFMEMORY
;
1122 if (!(attr
->ns
= dup_xml_string( ns
)))
1124 free_attribute( attr
);
1125 return E_OUTOFMEMORY
;
1127 if ((hr
= append_attribute( elem
, attr
)) != S_OK
)
1129 free_attribute( attr
);
1135 static inline BOOL
str_equal( const WS_XML_STRING
*str1
, const WS_XML_STRING
*str2
)
1137 if (!str1
&& !str2
) return TRUE
;
1138 return WsXmlStringEquals( str1
, str2
, NULL
) == S_OK
;
1141 static BOOL
namespace_in_scope( const WS_XML_ELEMENT_NODE
*elem
, const WS_XML_STRING
*prefix
,
1142 const WS_XML_STRING
*ns
)
1145 const struct node
*node
;
1147 for (node
= (const struct node
*)elem
; node
; node
= node
->parent
)
1149 if (node_type( node
) != WS_XML_NODE_TYPE_ELEMENT
) break;
1152 for (i
= 0; i
< elem
->attributeCount
; i
++)
1154 if (!elem
->attributes
[i
]->isXmlNs
) continue;
1155 if (str_equal( elem
->attributes
[i
]->prefix
, prefix
) &&
1156 str_equal( elem
->attributes
[i
]->ns
, ns
)) return TRUE
;
1162 static HRESULT
set_current_namespace( struct writer
*writer
, const WS_XML_STRING
*ns
)
1165 if (!(str
= dup_xml_string( ns
))) return E_OUTOFMEMORY
;
1166 free_xml_string( writer
->current_ns
);
1167 writer
->current_ns
= str
;
1171 static HRESULT
set_namespaces( struct writer
*writer
)
1173 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
1177 if (elem
->ns
->length
&& !namespace_in_scope( elem
, elem
->prefix
, elem
->ns
))
1179 if ((hr
= add_namespace_attribute( writer
, elem
->prefix
, elem
->ns
, FALSE
)) != S_OK
) return hr
;
1180 if ((hr
= set_current_namespace( writer
, elem
->ns
)) != S_OK
) return hr
;
1183 for (i
= 0; i
< elem
->attributeCount
; i
++)
1185 const WS_XML_ATTRIBUTE
*attr
= elem
->attributes
[i
];
1186 if (!attr
->ns
->length
|| namespace_in_scope( elem
, attr
->prefix
, attr
->ns
)) continue;
1187 if ((hr
= add_namespace_attribute( writer
, attr
->prefix
, attr
->ns
, FALSE
)) != S_OK
) return hr
;
1193 /**************************************************************************
1194 * WsWriteEndAttribute [webservices.@]
1196 HRESULT WINAPI
WsWriteEndAttribute( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
1198 struct writer
*writer
= (struct writer
*)handle
;
1200 TRACE( "%p %p\n", handle
, error
);
1201 if (error
) FIXME( "ignoring error parameter\n" );
1203 if (!writer
) return E_INVALIDARG
;
1205 EnterCriticalSection( &writer
->cs
);
1207 if (writer
->magic
!= WRITER_MAGIC
)
1209 LeaveCriticalSection( &writer
->cs
);
1210 return E_INVALIDARG
;
1213 writer
->state
= WRITER_STATE_STARTELEMENT
;
1215 LeaveCriticalSection( &writer
->cs
);
1219 static HRESULT
write_attributes( struct writer
*writer
, const WS_XML_ELEMENT_NODE
*elem
)
1223 for (i
= 0; i
< elem
->attributeCount
; i
++)
1225 if (elem
->attributes
[i
]->isXmlNs
) continue;
1226 if ((hr
= write_attribute( writer
, elem
->attributes
[i
] )) != S_OK
) return hr
;
1228 for (i
= 0; i
< elem
->attributeCount
; i
++)
1230 if (!elem
->attributes
[i
]->isXmlNs
|| !elem
->attributes
[i
]->prefix
) continue;
1231 if ((hr
= write_namespace_attribute( writer
, elem
->attributes
[i
] )) != S_OK
) return hr
;
1233 for (i
= 0; i
< elem
->attributeCount
; i
++)
1235 if (!elem
->attributes
[i
]->isXmlNs
|| elem
->attributes
[i
]->prefix
) continue;
1236 if ((hr
= write_namespace_attribute( writer
, elem
->attributes
[i
] )) != S_OK
) return hr
;
1241 static HRESULT
write_startelement_text( struct writer
*writer
)
1243 const WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
1247 /* '<prefix:localname prefix:attr="value"... xmlns:prefix="ns"'... */
1249 size
= elem
->localName
->length
+ 1 /* '<' */;
1250 if (elem
->prefix
&& elem
->prefix
->length
) size
+= elem
->prefix
->length
+ 1 /* ':' */;
1251 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
1253 write_char( writer
, '<' );
1254 if (elem
->prefix
&& elem
->prefix
->length
)
1256 write_bytes( writer
, elem
->prefix
->bytes
, elem
->prefix
->length
);
1257 write_char( writer
, ':' );
1259 write_bytes( writer
, elem
->localName
->bytes
, elem
->localName
->length
);
1260 return write_attributes( writer
, elem
);
1263 static enum record_type
get_elem_record_type( const WS_XML_ELEMENT_NODE
*elem
, BOOL use_dict
)
1265 if (!elem
->prefix
|| !elem
->prefix
->length
)
1267 if (use_dict
) return RECORD_SHORT_DICTIONARY_ELEMENT
;
1268 return RECORD_SHORT_ELEMENT
;
1270 if (elem
->prefix
->length
== 1 && elem
->prefix
->bytes
[0] >= 'a' && elem
->prefix
->bytes
[0] <= 'z')
1272 if (use_dict
) return RECORD_PREFIX_DICTIONARY_ELEMENT_A
+ elem
->prefix
->bytes
[0] - 'a';
1273 return RECORD_PREFIX_ELEMENT_A
+ elem
->prefix
->bytes
[0] - 'a';
1275 if (use_dict
) return RECORD_DICTIONARY_ELEMENT
;
1276 return RECORD_ELEMENT
;
1279 static HRESULT
write_startelement_bin( struct writer
*writer
)
1281 const WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
1283 enum record_type type
= get_elem_record_type( elem
, lookup_string_id(writer
, elem
->localName
, &id
) );
1286 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
1287 write_char( writer
, type
);
1289 if (type
>= RECORD_PREFIX_ELEMENT_A
&& type
<= RECORD_PREFIX_ELEMENT_Z
)
1291 if ((hr
= write_string( writer
, elem
->localName
->bytes
, elem
->localName
->length
)) != S_OK
) return hr
;
1292 return write_attributes( writer
, elem
);
1294 if (type
>= RECORD_PREFIX_DICTIONARY_ELEMENT_A
&& type
<= RECORD_PREFIX_DICTIONARY_ELEMENT_Z
)
1296 if ((hr
= write_dict_string( writer
, id
)) != S_OK
) return hr
;
1297 return write_attributes( writer
, elem
);
1302 case RECORD_SHORT_ELEMENT
:
1303 if ((hr
= write_string( writer
, elem
->localName
->bytes
, elem
->localName
->length
)) != S_OK
) return hr
;
1306 case RECORD_ELEMENT
:
1307 if ((hr
= write_string( writer
, elem
->prefix
->bytes
, elem
->prefix
->length
)) != S_OK
) return hr
;
1308 if ((hr
= write_string( writer
, elem
->localName
->bytes
, elem
->localName
->length
)) != S_OK
) return hr
;
1311 case RECORD_SHORT_DICTIONARY_ELEMENT
:
1312 if ((hr
= write_dict_string( writer
, id
)) != S_OK
) return hr
;
1315 case RECORD_DICTIONARY_ELEMENT
:
1316 if ((hr
= write_string( writer
, elem
->prefix
->bytes
, elem
->prefix
->length
)) != S_OK
) return hr
;
1317 if ((hr
= write_dict_string( writer
, id
)) != S_OK
) return hr
;
1321 ERR( "unhandled record type %02x\n", type
);
1322 return WS_E_NOT_SUPPORTED
;
1325 return write_attributes( writer
, elem
);
1328 static HRESULT
write_startelement( struct writer
*writer
)
1330 switch (writer
->output_enc
)
1332 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_startelement_text( writer
);
1333 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return write_startelement_bin( writer
);
1335 ERR( "unhandled encoding %u\n", writer
->output_enc
);
1336 return WS_E_NOT_SUPPORTED
;
1340 static struct node
*write_find_startelement( struct writer
*writer
)
1343 for (node
= writer
->current
; node
; node
= node
->parent
)
1345 if (node_type( node
) == WS_XML_NODE_TYPE_ELEMENT
) return node
;
1350 static inline BOOL
is_empty_element( const struct node
*node
)
1352 const struct node
*head
= LIST_ENTRY( list_head( &node
->children
), struct node
, entry
);
1353 return node_type( head
) == WS_XML_NODE_TYPE_END_ELEMENT
;
1356 static HRESULT
write_endelement_text( struct writer
*writer
, const WS_XML_ELEMENT_NODE
*elem
)
1363 if (elem
->isEmpty
&& writer
->state
!= WRITER_STATE_ENDSTARTELEMENT
)
1365 if ((hr
= write_grow_buffer( writer
, 2 )) != S_OK
) return hr
;
1366 write_char( writer
, '/' );
1367 write_char( writer
, '>' );
1371 /* '</prefix:localname>' */
1373 size
= elem
->localName
->length
+ 3 /* '</>' */;
1374 if (elem
->prefix
&& elem
->prefix
->length
) size
+= elem
->prefix
->length
+ 1 /* ':' */;
1375 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
1377 write_char( writer
, '<' );
1378 write_char( writer
, '/' );
1379 if (elem
->prefix
&& elem
->prefix
->length
)
1381 write_bytes( writer
, elem
->prefix
->bytes
, elem
->prefix
->length
);
1382 write_char( writer
, ':' );
1384 write_bytes( writer
, elem
->localName
->bytes
, elem
->localName
->length
);
1385 write_char( writer
, '>' );
1389 static HRESULT
write_endelement_bin( struct writer
*writer
)
1392 if (node_type( writer
->current
) == WS_XML_NODE_TYPE_TEXT
) return S_OK
;
1393 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
1394 write_char( writer
, RECORD_ENDELEMENT
);
1398 static HRESULT
write_endelement( struct writer
*writer
, const WS_XML_ELEMENT_NODE
*elem
)
1400 switch (writer
->output_enc
)
1402 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_endelement_text( writer
, elem
);
1403 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return write_endelement_bin( writer
);
1405 ERR( "unhandled encoding %u\n", writer
->output_enc
);
1406 return WS_E_NOT_SUPPORTED
;
1410 static HRESULT
write_close_element( struct writer
*writer
, struct node
*node
)
1412 WS_XML_ELEMENT_NODE
*elem
= &node
->hdr
;
1413 elem
->isEmpty
= is_empty_element( node
);
1414 return write_endelement( writer
, elem
);
1417 static HRESULT
write_endelement_node( struct writer
*writer
)
1422 if (!(node
= write_find_startelement( writer
))) return WS_E_INVALID_FORMAT
;
1423 if (writer
->state
== WRITER_STATE_STARTELEMENT
)
1425 if ((hr
= set_namespaces( writer
)) != S_OK
) return hr
;
1426 if ((hr
= write_startelement( writer
)) != S_OK
) return hr
;
1428 if ((hr
= write_close_element( writer
, node
)) != S_OK
) return hr
;
1429 writer
->current
= node
->parent
;
1430 writer
->state
= WRITER_STATE_ENDELEMENT
;
1434 /**************************************************************************
1435 * WsWriteEndElement [webservices.@]
1437 HRESULT WINAPI
WsWriteEndElement( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
1439 struct writer
*writer
= (struct writer
*)handle
;
1442 TRACE( "%p %p\n", handle
, error
);
1443 if (error
) FIXME( "ignoring error parameter\n" );
1445 if (!writer
) return E_INVALIDARG
;
1447 EnterCriticalSection( &writer
->cs
);
1449 if (writer
->magic
!= WRITER_MAGIC
)
1451 LeaveCriticalSection( &writer
->cs
);
1452 return E_INVALIDARG
;
1455 hr
= write_endelement_node( writer
);
1457 LeaveCriticalSection( &writer
->cs
);
1461 static HRESULT
write_endstartelement_text( struct writer
*writer
)
1464 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
1465 write_char( writer
, '>' );
1469 static HRESULT
write_endstartelement( struct writer
*writer
)
1471 switch (writer
->output_enc
)
1473 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_endstartelement_text( writer
);
1474 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return S_OK
;
1476 ERR( "unhandled encoding %u\n", writer
->output_enc
);
1477 return WS_E_NOT_SUPPORTED
;
1481 /**************************************************************************
1482 * WsWriteEndStartElement [webservices.@]
1484 HRESULT WINAPI
WsWriteEndStartElement( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
1486 struct writer
*writer
= (struct writer
*)handle
;
1489 TRACE( "%p %p\n", handle
, error
);
1490 if (error
) FIXME( "ignoring error parameter\n" );
1492 if (!writer
) return E_INVALIDARG
;
1494 EnterCriticalSection( &writer
->cs
);
1496 if (writer
->magic
!= WRITER_MAGIC
)
1498 LeaveCriticalSection( &writer
->cs
);
1499 return E_INVALIDARG
;
1502 if (writer
->state
!= WRITER_STATE_STARTELEMENT
)
1504 LeaveCriticalSection( &writer
->cs
);
1505 return WS_E_INVALID_OPERATION
;
1508 if ((hr
= set_namespaces( writer
)) != S_OK
) goto done
;
1509 if ((hr
= write_startelement( writer
)) != S_OK
) goto done
;
1510 if ((hr
= write_endstartelement( writer
)) != S_OK
) goto done
;
1511 writer
->state
= WRITER_STATE_ENDSTARTELEMENT
;
1514 LeaveCriticalSection( &writer
->cs
);
1518 static HRESULT
write_add_attribute( struct writer
*writer
, const WS_XML_STRING
*prefix
,
1519 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
1522 WS_XML_ATTRIBUTE
*attr
;
1523 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
1526 if (!(attr
= heap_alloc_zero( sizeof(*attr
) ))) return E_OUTOFMEMORY
;
1528 if (!prefix
&& ns
->length
) prefix
= elem
->prefix
;
1530 attr
->singleQuote
= !!single
;
1531 if (prefix
&& !(attr
->prefix
= dup_xml_string( prefix
)))
1533 free_attribute( attr
);
1534 return E_OUTOFMEMORY
;
1536 if (!(attr
->localName
= dup_xml_string( localname
)))
1538 free_attribute( attr
);
1539 return E_OUTOFMEMORY
;
1541 if (!(attr
->ns
= dup_xml_string( ns
)))
1543 free_attribute( attr
);
1544 return E_OUTOFMEMORY
;
1546 if ((hr
= append_attribute( elem
, attr
)) != S_OK
)
1548 free_attribute( attr
);
1554 /**************************************************************************
1555 * WsWriteStartAttribute [webservices.@]
1557 HRESULT WINAPI
WsWriteStartAttribute( WS_XML_WRITER
*handle
, const WS_XML_STRING
*prefix
,
1558 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
1559 BOOL single
, WS_ERROR
*error
)
1561 struct writer
*writer
= (struct writer
*)handle
;
1564 TRACE( "%p %s %s %s %d %p\n", handle
, debugstr_xmlstr(prefix
), debugstr_xmlstr(localname
),
1565 debugstr_xmlstr(ns
), single
, error
);
1566 if (error
) FIXME( "ignoring error parameter\n" );
1568 if (!writer
|| !localname
|| !ns
) return E_INVALIDARG
;
1570 EnterCriticalSection( &writer
->cs
);
1572 if (writer
->magic
!= WRITER_MAGIC
)
1574 LeaveCriticalSection( &writer
->cs
);
1575 return E_INVALIDARG
;
1578 if (writer
->state
!= WRITER_STATE_STARTELEMENT
)
1580 LeaveCriticalSection( &writer
->cs
);
1581 return WS_E_INVALID_OPERATION
;
1584 if ((hr
= write_add_attribute( writer
, prefix
, localname
, ns
, single
)) == S_OK
)
1585 writer
->state
= WRITER_STATE_STARTATTRIBUTE
;
1587 LeaveCriticalSection( &writer
->cs
);
1591 /* flush current start element if necessary */
1592 static HRESULT
write_flush( struct writer
*writer
)
1594 if (writer
->state
== WRITER_STATE_STARTELEMENT
)
1597 if ((hr
= set_namespaces( writer
)) != S_OK
) return hr
;
1598 if ((hr
= write_startelement( writer
)) != S_OK
) return hr
;
1599 if ((hr
= write_endstartelement( writer
)) != S_OK
) return hr
;
1600 writer
->state
= WRITER_STATE_ENDSTARTELEMENT
;
1605 static HRESULT
write_add_cdata_node( struct writer
*writer
)
1607 struct node
*node
, *parent
;
1608 if (!(parent
= find_parent( writer
))) return WS_E_INVALID_FORMAT
;
1609 if (!(node
= alloc_node( WS_XML_NODE_TYPE_CDATA
))) return E_OUTOFMEMORY
;
1610 write_insert_node( writer
, parent
, node
);
1614 static HRESULT
write_add_endcdata_node( struct writer
*writer
)
1617 if (!(node
= alloc_node( WS_XML_NODE_TYPE_END_CDATA
))) return E_OUTOFMEMORY
;
1618 node
->parent
= writer
->current
;
1619 list_add_tail( &node
->parent
->children
, &node
->entry
);
1623 static HRESULT
write_cdata( struct writer
*writer
)
1626 if ((hr
= write_grow_buffer( writer
, 9 )) != S_OK
) return hr
;
1627 write_bytes( writer
, (const BYTE
*)"<![CDATA[", 9 );
1631 static HRESULT
write_cdata_node( struct writer
*writer
)
1634 if ((hr
= write_flush( writer
)) != S_OK
) return hr
;
1635 if ((hr
= write_add_cdata_node( writer
)) != S_OK
) return hr
;
1636 if ((hr
= write_add_endcdata_node( writer
)) != S_OK
) return hr
;
1637 if ((hr
= write_cdata( writer
)) != S_OK
) return hr
;
1638 writer
->state
= WRITER_STATE_STARTCDATA
;
1642 /**************************************************************************
1643 * WsWriteStartCData [webservices.@]
1645 HRESULT WINAPI
WsWriteStartCData( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
1647 struct writer
*writer
= (struct writer
*)handle
;
1650 TRACE( "%p %p\n", handle
, error
);
1651 if (error
) FIXME( "ignoring error parameter\n" );
1653 if (!writer
) return E_INVALIDARG
;
1655 EnterCriticalSection( &writer
->cs
);
1657 if (writer
->magic
!= WRITER_MAGIC
)
1659 LeaveCriticalSection( &writer
->cs
);
1660 return E_INVALIDARG
;
1663 hr
= write_cdata_node( writer
);
1665 LeaveCriticalSection( &writer
->cs
);
1669 static HRESULT
write_endcdata( struct writer
*writer
)
1672 if ((hr
= write_grow_buffer( writer
, 3 )) != S_OK
) return hr
;
1673 write_bytes( writer
, (const BYTE
*)"]]>", 3 );
1677 static HRESULT
write_endcdata_node( struct writer
*writer
)
1680 if ((hr
= write_endcdata( writer
)) != S_OK
) return hr
;
1681 writer
->current
= writer
->current
->parent
;
1682 writer
->state
= WRITER_STATE_ENDCDATA
;
1686 /**************************************************************************
1687 * WsWriteEndCData [webservices.@]
1689 HRESULT WINAPI
WsWriteEndCData( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
1691 struct writer
*writer
= (struct writer
*)handle
;
1694 TRACE( "%p %p\n", handle
, error
);
1695 if (error
) FIXME( "ignoring error parameter\n" );
1697 if (!writer
) return E_INVALIDARG
;
1699 EnterCriticalSection( &writer
->cs
);
1701 if (writer
->magic
!= WRITER_MAGIC
)
1703 LeaveCriticalSection( &writer
->cs
);
1704 return E_INVALIDARG
;
1707 if (writer
->state
!= WRITER_STATE_TEXT
)
1709 LeaveCriticalSection( &writer
->cs
);
1710 return WS_E_INVALID_OPERATION
;
1713 hr
= write_endcdata_node( writer
);
1715 LeaveCriticalSection( &writer
->cs
);
1719 static HRESULT
write_add_element_node( struct writer
*writer
, const WS_XML_STRING
*prefix
,
1720 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
)
1722 struct node
*node
, *parent
;
1723 WS_XML_ELEMENT_NODE
*elem
;
1725 if (!(parent
= find_parent( writer
))) return WS_E_INVALID_FORMAT
;
1727 if (!prefix
&& node_type( parent
) == WS_XML_NODE_TYPE_ELEMENT
)
1729 elem
= &parent
->hdr
;
1730 if (WsXmlStringEquals( ns
, elem
->ns
, NULL
) == S_OK
) prefix
= elem
->prefix
;
1733 if (!(node
= alloc_node( WS_XML_NODE_TYPE_ELEMENT
))) return E_OUTOFMEMORY
;
1736 if (prefix
&& !(elem
->prefix
= dup_xml_string( prefix
)))
1739 return E_OUTOFMEMORY
;
1741 if (!(elem
->localName
= dup_xml_string( localname
)))
1744 return E_OUTOFMEMORY
;
1746 if (!(elem
->ns
= dup_xml_string( ns
)))
1749 return E_OUTOFMEMORY
;
1751 write_insert_node( writer
, parent
, node
);
1755 static HRESULT
write_add_endelement_node( struct writer
*writer
, struct node
*parent
)
1758 if (!(node
= alloc_node( WS_XML_NODE_TYPE_END_ELEMENT
))) return E_OUTOFMEMORY
;
1759 node
->parent
= parent
;
1760 list_add_tail( &parent
->children
, &node
->entry
);
1764 static HRESULT
write_element_node( struct writer
*writer
, const WS_XML_STRING
*prefix
,
1765 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
)
1768 if ((hr
= write_flush( writer
)) != S_OK
) return hr
;
1769 if ((hr
= write_add_element_node( writer
, prefix
, localname
, ns
)) != S_OK
) return hr
;
1770 if ((hr
= write_add_endelement_node( writer
, writer
->current
)) != S_OK
) return hr
;
1771 writer
->state
= WRITER_STATE_STARTELEMENT
;
1775 /**************************************************************************
1776 * WsWriteStartElement [webservices.@]
1778 HRESULT WINAPI
WsWriteStartElement( WS_XML_WRITER
*handle
, const WS_XML_STRING
*prefix
,
1779 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
1782 struct writer
*writer
= (struct writer
*)handle
;
1785 TRACE( "%p %s %s %s %p\n", handle
, debugstr_xmlstr(prefix
), debugstr_xmlstr(localname
),
1786 debugstr_xmlstr(ns
), error
);
1787 if (error
) FIXME( "ignoring error parameter\n" );
1789 if (!writer
|| !localname
|| !ns
) return E_INVALIDARG
;
1791 EnterCriticalSection( &writer
->cs
);
1793 if (writer
->magic
!= WRITER_MAGIC
)
1795 LeaveCriticalSection( &writer
->cs
);
1796 return E_INVALIDARG
;
1799 hr
= write_element_node( writer
, prefix
, localname
, ns
);
1801 LeaveCriticalSection( &writer
->cs
);
1805 static ULONG
format_bool( const BOOL
*ptr
, unsigned char *buf
)
1807 static const unsigned char bool_true
[] = {'t','r','u','e'}, bool_false
[] = {'f','a','l','s','e'};
1810 memcpy( buf
, bool_true
, sizeof(bool_true
) );
1811 return sizeof(bool_true
);
1813 memcpy( buf
, bool_false
, sizeof(bool_false
) );
1814 return sizeof(bool_false
);
1817 static ULONG
format_int32( const INT32
*ptr
, unsigned char *buf
)
1819 return wsprintfA( (char *)buf
, "%d", *ptr
);
1822 static ULONG
format_int64( const INT64
*ptr
, unsigned char *buf
)
1824 return wsprintfA( (char *)buf
, "%I64d", *ptr
);
1827 static ULONG
format_uint64( const UINT64
*ptr
, unsigned char *buf
)
1829 return wsprintfA( (char *)buf
, "%I64u", *ptr
);
1832 static ULONG
format_double( const double *ptr
, unsigned char *buf
)
1835 static const long double precision
= 0.0000000000000001;
1836 unsigned char *p
= buf
;
1837 long double val
= *ptr
;
1838 int neg
, mag
, mag2
, use_exp
;
1842 memcpy( buf
, "NaN", 3 );
1849 memcpy( buf
, "-INF", 4 );
1852 memcpy( buf
, "INF", 3 );
1861 if ((neg
= val
< 0))
1867 mag
= log10l( val
);
1868 use_exp
= (mag
>= 15 || (neg
&& mag
>= 1) || mag
<= -1);
1871 if (mag
< 0) mag
-= 1;
1872 val
= val
/ powl( 10.0, mag
);
1876 else if (mag
< 1) mag
= 0;
1878 while (val
> precision
|| mag
>= 0)
1880 long double weight
= powl( 10.0, mag
);
1881 if (weight
> 0 && !isinf( weight
))
1883 int digit
= floorl( val
/ weight
);
1884 val
-= digit
* weight
;
1885 *(p
++) = '0' + digit
;
1887 if (!mag
&& val
> precision
) *(p
++) = '.';
1895 if (mag2
> 0) *(p
++) = '+';
1904 *(p
++) = '0' + mag2
% 10;
1908 for (i
= -mag
, j
= -1; i
< j
; i
++, j
--)
1918 FIXME( "powl not found at build time\n" );
1923 static inline int year_size( int year
)
1925 return leap_year( year
) ? 366 : 365;
1929 static ULONG
format_datetime( const WS_DATETIME
*ptr
, unsigned char *buf
)
1931 static const char fmt
[] = "%04u-%02u-%02uT%02u:%02u:%02u";
1932 int day
, hour
, min
, sec
, sec_frac
, month
= 0, year
= 1, tz_hour
;
1933 unsigned __int64 ticks
, day_ticks
;
1936 if (ptr
->format
== WS_DATETIME_FORMAT_LOCAL
&&
1937 ptr
->ticks
>= TICKS_1601_01_01
+ TZ_OFFSET
* TICKS_PER_HOUR
)
1939 ticks
= ptr
->ticks
- TZ_OFFSET
* TICKS_PER_HOUR
;
1940 tz_hour
= TZ_OFFSET
;
1947 day
= ticks
/ TICKS_PER_DAY
;
1948 day_ticks
= ticks
% TICKS_PER_DAY
;
1949 hour
= day_ticks
/ TICKS_PER_HOUR
;
1950 min
= (day_ticks
% TICKS_PER_HOUR
) / TICKS_PER_MIN
;
1951 sec
= (day_ticks
% TICKS_PER_MIN
) / TICKS_PER_SEC
;
1952 sec_frac
= day_ticks
% TICKS_PER_SEC
;
1954 while (day
>= year_size( year
))
1956 day
-= year_size( year
);
1959 while (day
>= month_days
[leap_year( year
)][month
])
1961 day
-= month_days
[leap_year( year
)][month
];
1965 len
= sprintf( (char *)buf
, fmt
, year
, month
+ 1, day
+ 1, hour
, min
, sec
);
1968 static const char fmt_frac
[] = ".%07u";
1969 len
+= sprintf( (char *)buf
+ len
, fmt_frac
, sec_frac
);
1970 while (buf
[len
- 1] == '0') len
--;
1972 if (ptr
->format
== WS_DATETIME_FORMAT_UTC
)
1976 else if (ptr
->format
== WS_DATETIME_FORMAT_LOCAL
)
1978 static const char fmt_tz
[] = "%c%02u:00";
1979 len
+= sprintf( (char *)buf
+ len
, fmt_tz
, tz_hour
? '-' : '+', tz_hour
);
1985 static ULONG
format_guid( const GUID
*ptr
, unsigned char *buf
)
1987 static const char fmt
[] = "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x";
1988 return sprintf( (char *)buf
, fmt
, ptr
->Data1
, ptr
->Data2
, ptr
->Data3
,
1989 ptr
->Data4
[0], ptr
->Data4
[1], ptr
->Data4
[2], ptr
->Data4
[3],
1990 ptr
->Data4
[4], ptr
->Data4
[5], ptr
->Data4
[6], ptr
->Data4
[7] );
1993 static ULONG
format_urn( const GUID
*ptr
, unsigned char *buf
)
1995 static const char fmt
[] = "urn:uuid:%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x";
1996 return sprintf( (char *)buf
, fmt
, ptr
->Data1
, ptr
->Data2
, ptr
->Data3
,
1997 ptr
->Data4
[0], ptr
->Data4
[1], ptr
->Data4
[2], ptr
->Data4
[3],
1998 ptr
->Data4
[4], ptr
->Data4
[5], ptr
->Data4
[6], ptr
->Data4
[7] );
2001 static ULONG
format_qname( const WS_XML_STRING
*prefix
, const WS_XML_STRING
*localname
, unsigned char *buf
)
2004 if (prefix
&& prefix
->length
)
2006 memcpy( buf
, prefix
->bytes
, prefix
->length
);
2007 len
+= prefix
->length
;
2010 memcpy( buf
+ len
, localname
->bytes
, localname
->length
);
2011 return len
+ localname
->length
;
2014 static ULONG
encode_base64( const unsigned char *bin
, ULONG len
, unsigned char *buf
)
2016 static const char base64
[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
2021 buf
[i
++] = base64
[(bin
[0] & 0xfc) >> 2];
2022 x
= (bin
[0] & 3) << 4;
2025 buf
[i
++] = base64
[x
];
2030 buf
[i
++] = base64
[x
| ((bin
[1] & 0xf0) >> 4)];
2031 x
= (bin
[1] & 0x0f) << 2;
2034 buf
[i
++] = base64
[x
];
2038 buf
[i
++] = base64
[x
| ((bin
[2] & 0xc0) >> 6)];
2039 buf
[i
++] = base64
[bin
[2] & 0x3f];
2046 static HRESULT
text_to_utf8text( const WS_XML_TEXT
*text
, const WS_XML_UTF8_TEXT
*old
, ULONG
*offset
,
2047 WS_XML_UTF8_TEXT
**ret
)
2049 ULONG len_old
= old
? old
->value
.length
: 0;
2050 if (offset
) *offset
= len_old
;
2052 switch (text
->textType
)
2054 case WS_XML_TEXT_TYPE_UTF8
:
2056 const WS_XML_UTF8_TEXT
*src
= (const WS_XML_UTF8_TEXT
*)text
;
2058 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ src
->value
.length
))) return E_OUTOFMEMORY
;
2059 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
2060 memcpy( (*ret
)->value
.bytes
+ len_old
, src
->value
.bytes
, src
->value
.length
);
2063 case WS_XML_TEXT_TYPE_UTF16
:
2065 const WS_XML_UTF16_TEXT
*src
= (const WS_XML_UTF16_TEXT
*)text
;
2066 const WCHAR
*str
= (const WCHAR
*)src
->bytes
;
2067 ULONG len
= src
->byteCount
/ sizeof(WCHAR
), len_utf8
;
2069 if (src
->byteCount
% sizeof(WCHAR
)) return E_INVALIDARG
;
2070 len_utf8
= WideCharToMultiByte( CP_UTF8
, 0, str
, len
, NULL
, 0, NULL
, NULL
);
2071 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len_utf8
))) return E_OUTOFMEMORY
;
2072 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
2073 WideCharToMultiByte( CP_UTF8
, 0, str
, len
, (char *)(*ret
)->value
.bytes
+ len_old
, len_utf8
, NULL
, NULL
);
2076 case WS_XML_TEXT_TYPE_BASE64
:
2078 const WS_XML_BASE64_TEXT
*base64
= (const WS_XML_BASE64_TEXT
*)text
;
2079 ULONG len
= ((4 * base64
->length
/ 3) + 3) & ~3;
2081 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
2082 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
2083 (*ret
)->value
.length
= encode_base64( base64
->bytes
, base64
->length
, (*ret
)->value
.bytes
+ len_old
) + len_old
;
2086 case WS_XML_TEXT_TYPE_BOOL
:
2088 const WS_XML_BOOL_TEXT
*bool_text
= (const WS_XML_BOOL_TEXT
*)text
;
2090 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ 5 ))) return E_OUTOFMEMORY
;
2091 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
2092 (*ret
)->value
.length
= format_bool( &bool_text
->value
, (*ret
)->value
.bytes
+ len_old
) + len_old
;
2095 case WS_XML_TEXT_TYPE_INT32
:
2097 const WS_XML_INT32_TEXT
*int32_text
= (const WS_XML_INT32_TEXT
*)text
;
2098 unsigned char buf
[12]; /* "-2147483648" */
2099 ULONG len
= format_int32( &int32_text
->value
, buf
);
2101 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
2102 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
2103 memcpy( (*ret
)->value
.bytes
+ len_old
, buf
, len
);
2106 case WS_XML_TEXT_TYPE_INT64
:
2108 const WS_XML_INT64_TEXT
*int64_text
= (const WS_XML_INT64_TEXT
*)text
;
2109 unsigned char buf
[21]; /* "-9223372036854775808" */
2110 ULONG len
= format_int64( &int64_text
->value
, buf
);
2112 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
2113 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
2114 memcpy( (*ret
)->value
.bytes
+ len_old
, buf
, len
);
2117 case WS_XML_TEXT_TYPE_UINT64
:
2119 const WS_XML_UINT64_TEXT
*uint64_text
= (const WS_XML_UINT64_TEXT
*)text
;
2120 unsigned char buf
[21]; /* "18446744073709551615" */
2121 ULONG len
= format_uint64( &uint64_text
->value
, buf
);
2123 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
2124 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
2125 memcpy( (*ret
)->value
.bytes
+ len_old
, buf
, len
);
2128 case WS_XML_TEXT_TYPE_DOUBLE
:
2130 const WS_XML_DOUBLE_TEXT
*double_text
= (const WS_XML_DOUBLE_TEXT
*)text
;
2131 unsigned char buf
[32]; /* "-1.1111111111111111E-308", oversized to address Valgrind limitations */
2132 unsigned short fpword
;
2135 if (!set_fpword( 0x37f, &fpword
)) return E_NOTIMPL
;
2136 len
= format_double( &double_text
->value
, buf
);
2137 restore_fpword( fpword
);
2138 if (!len
) return E_NOTIMPL
;
2140 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
2141 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
2142 memcpy( (*ret
)->value
.bytes
+ len_old
, buf
, len
);
2145 case WS_XML_TEXT_TYPE_GUID
:
2147 const WS_XML_GUID_TEXT
*id
= (const WS_XML_GUID_TEXT
*)text
;
2149 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ 37 ))) return E_OUTOFMEMORY
;
2150 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
2151 (*ret
)->value
.length
= format_guid( &id
->value
, (*ret
)->value
.bytes
+ len_old
) + len_old
;
2154 case WS_XML_TEXT_TYPE_UNIQUE_ID
:
2156 const WS_XML_UNIQUE_ID_TEXT
*id
= (const WS_XML_UNIQUE_ID_TEXT
*)text
;
2158 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ 46 ))) return E_OUTOFMEMORY
;
2159 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
2160 (*ret
)->value
.length
= format_urn( &id
->value
, (*ret
)->value
.bytes
+ len_old
) + len_old
;
2163 case WS_XML_TEXT_TYPE_DATETIME
:
2165 const WS_XML_DATETIME_TEXT
*dt
= (const WS_XML_DATETIME_TEXT
*)text
;
2167 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ 34 ))) return E_OUTOFMEMORY
;
2168 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
2169 (*ret
)->value
.length
= format_datetime( &dt
->value
, (*ret
)->value
.bytes
+ len_old
) + len_old
;
2172 case WS_XML_TEXT_TYPE_QNAME
:
2174 const WS_XML_QNAME_TEXT
*qn
= (const WS_XML_QNAME_TEXT
*)text
;
2175 ULONG len
= qn
->localName
->length
;
2177 if (qn
->prefix
&& qn
->prefix
->length
) len
+= qn
->prefix
->length
+ 1;
2178 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
2179 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
2180 (*ret
)->value
.length
= format_qname( qn
->prefix
, qn
->localName
, (*ret
)->value
.bytes
+ len_old
) + len_old
;
2184 FIXME( "unhandled text type %u\n", text
->textType
);
2189 static HRESULT
text_to_text( const WS_XML_TEXT
*text
, const WS_XML_TEXT
*old
, ULONG
*offset
, WS_XML_TEXT
**ret
)
2191 if (offset
) *offset
= 0;
2192 switch (text
->textType
)
2194 case WS_XML_TEXT_TYPE_UTF8
:
2196 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)text
;
2197 const WS_XML_UTF8_TEXT
*utf8_old
= (const WS_XML_UTF8_TEXT
*)old
;
2198 WS_XML_UTF8_TEXT
*new;
2199 ULONG len
= utf8
->value
.length
, len_old
= utf8_old
? utf8_old
->value
.length
: 0;
2201 if (!(new = alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
2202 if (utf8_old
) memcpy( new->value
.bytes
, utf8_old
->value
.bytes
, len_old
);
2203 memcpy( new->value
.bytes
+ len_old
, utf8
->value
.bytes
, len
);
2204 if (offset
) *offset
= len_old
;
2208 case WS_XML_TEXT_TYPE_UTF16
:
2210 const WS_XML_UTF16_TEXT
*utf16
= (const WS_XML_UTF16_TEXT
*)text
;
2211 const WS_XML_UTF8_TEXT
*utf8_old
= (const WS_XML_UTF8_TEXT
*)old
;
2212 WS_XML_UTF8_TEXT
*new;
2213 const WCHAR
*str
= (const WCHAR
*)utf16
->bytes
;
2214 ULONG len
= utf16
->byteCount
/ sizeof(WCHAR
), len_utf8
, len_old
= utf8_old
? utf8_old
->value
.length
: 0;
2216 if (utf16
->byteCount
% sizeof(WCHAR
)) return E_INVALIDARG
;
2217 len_utf8
= WideCharToMultiByte( CP_UTF8
, 0, str
, len
, NULL
, 0, NULL
, NULL
);
2218 if (!(new = alloc_utf8_text( NULL
, len_old
+ len_utf8
))) return E_OUTOFMEMORY
;
2219 if (old
) memcpy( new->value
.bytes
, utf8_old
->value
.bytes
, len_old
);
2220 WideCharToMultiByte( CP_UTF8
, 0, str
, len
, (char *)new->value
.bytes
+ len_old
, len_utf8
, NULL
, NULL
);
2221 if (offset
) *offset
= len_old
;
2225 case WS_XML_TEXT_TYPE_BASE64
:
2227 const WS_XML_BASE64_TEXT
*base64
= (const WS_XML_BASE64_TEXT
*)text
;
2228 const WS_XML_BASE64_TEXT
*base64_old
= (const WS_XML_BASE64_TEXT
*)old
;
2229 WS_XML_BASE64_TEXT
*new;
2230 ULONG len
= base64
->length
, len_old
= base64_old
? base64_old
->length
: 0;
2232 if (!(new = alloc_base64_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
2233 if (base64_old
) memcpy( new->bytes
, base64_old
->bytes
, len_old
);
2234 memcpy( new->bytes
+ len_old
, base64
->bytes
, len
);
2235 if (offset
) *offset
= len_old
;
2239 case WS_XML_TEXT_TYPE_BOOL
:
2241 const WS_XML_BOOL_TEXT
*bool_text
= (const WS_XML_BOOL_TEXT
*)text
;
2242 WS_XML_BOOL_TEXT
*new;
2244 if (!(new = alloc_bool_text( bool_text
->value
))) return E_OUTOFMEMORY
;
2248 case WS_XML_TEXT_TYPE_INT32
:
2250 const WS_XML_INT32_TEXT
*int32_text
= (const WS_XML_INT32_TEXT
*)text
;
2251 WS_XML_INT32_TEXT
*new;
2253 if (!(new = alloc_int32_text( int32_text
->value
))) return E_OUTOFMEMORY
;
2257 case WS_XML_TEXT_TYPE_INT64
:
2259 const WS_XML_INT64_TEXT
*int64_text
= (const WS_XML_INT64_TEXT
*)text
;
2260 WS_XML_INT64_TEXT
*new;
2262 if (!(new = alloc_int64_text( int64_text
->value
))) return E_OUTOFMEMORY
;
2266 case WS_XML_TEXT_TYPE_UINT64
:
2268 const WS_XML_UINT64_TEXT
*uint64_text
= (const WS_XML_UINT64_TEXT
*)text
;
2269 WS_XML_UINT64_TEXT
*new;
2271 if (!(new = alloc_uint64_text( uint64_text
->value
))) return E_OUTOFMEMORY
;
2275 case WS_XML_TEXT_TYPE_DOUBLE
:
2277 const WS_XML_DOUBLE_TEXT
*double_text
= (const WS_XML_DOUBLE_TEXT
*)text
;
2278 WS_XML_DOUBLE_TEXT
*new;
2280 if (!(new = alloc_double_text( double_text
->value
))) return E_OUTOFMEMORY
;
2284 case WS_XML_TEXT_TYPE_GUID
:
2286 const WS_XML_GUID_TEXT
*id
= (const WS_XML_GUID_TEXT
*)text
;
2287 WS_XML_GUID_TEXT
*new;
2289 if (!(new = alloc_guid_text( &id
->value
))) return E_OUTOFMEMORY
;
2293 case WS_XML_TEXT_TYPE_UNIQUE_ID
:
2295 const WS_XML_UNIQUE_ID_TEXT
*id
= (const WS_XML_UNIQUE_ID_TEXT
*)text
;
2296 WS_XML_UNIQUE_ID_TEXT
*new;
2298 if (!(new = alloc_unique_id_text( &id
->value
))) return E_OUTOFMEMORY
;
2302 case WS_XML_TEXT_TYPE_DATETIME
:
2304 const WS_XML_DATETIME_TEXT
*dt
= (const WS_XML_DATETIME_TEXT
*)text
;
2305 WS_XML_DATETIME_TEXT
*new;
2307 if (!(new = alloc_datetime_text( &dt
->value
))) return E_OUTOFMEMORY
;
2312 FIXME( "unhandled text type %u\n", text
->textType
);
2317 static HRESULT
write_set_attribute_value( struct writer
*writer
, const WS_XML_TEXT
*value
)
2319 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
2322 switch (value
->textType
)
2324 case WS_XML_TEXT_TYPE_UTF8
:
2325 case WS_XML_TEXT_TYPE_UTF16
:
2326 case WS_XML_TEXT_TYPE_BASE64
:
2329 case WS_XML_TEXT_TYPE_BOOL
:
2330 case WS_XML_TEXT_TYPE_INT32
:
2331 case WS_XML_TEXT_TYPE_INT64
:
2332 case WS_XML_TEXT_TYPE_UINT64
:
2333 case WS_XML_TEXT_TYPE_DOUBLE
:
2334 case WS_XML_TEXT_TYPE_GUID
:
2335 case WS_XML_TEXT_TYPE_UNIQUE_ID
:
2336 case WS_XML_TEXT_TYPE_DATETIME
:
2337 if (elem
->attributes
[elem
->attributeCount
- 1]->value
) return WS_E_INVALID_OPERATION
;
2341 FIXME( "unhandled text type %u\n", value
->textType
);
2345 switch (writer
->output_enc
)
2347 case WS_XML_WRITER_ENCODING_TYPE_TEXT
:
2349 WS_XML_UTF8_TEXT
*new, *old
= (WS_XML_UTF8_TEXT
*)elem
->attributes
[elem
->attributeCount
- 1]->value
;
2350 if ((hr
= text_to_utf8text( value
, old
, NULL
, &new )) != S_OK
) return hr
;
2352 elem
->attributes
[elem
->attributeCount
- 1]->value
= &new->text
;
2355 case WS_XML_WRITER_ENCODING_TYPE_BINARY
:
2357 WS_XML_TEXT
*new, *old
= elem
->attributes
[elem
->attributeCount
- 1]->value
;
2358 if ((hr
= text_to_text( value
, old
, NULL
, &new )) != S_OK
) return hr
;
2360 elem
->attributes
[elem
->attributeCount
- 1]->value
= new;
2364 FIXME( "unhandled output encoding %u\n", writer
->output_enc
);
2371 static HRESULT
write_add_text_node( struct writer
*writer
, const WS_XML_TEXT
*value
)
2374 WS_XML_TEXT_NODE
*text
;
2377 if (node_type( writer
->current
) != WS_XML_NODE_TYPE_ELEMENT
&&
2378 node_type( writer
->current
) != WS_XML_NODE_TYPE_BOF
&&
2379 node_type( writer
->current
) != WS_XML_NODE_TYPE_CDATA
) return WS_E_INVALID_FORMAT
;
2381 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return E_OUTOFMEMORY
;
2382 text
= (WS_XML_TEXT_NODE
*)node
;
2384 switch (writer
->output_enc
)
2386 case WS_XML_WRITER_ENCODING_TYPE_TEXT
:
2388 WS_XML_UTF8_TEXT
*new;
2389 if ((hr
= text_to_utf8text( value
, NULL
, NULL
, &new )) != S_OK
)
2394 text
->text
= &new->text
;
2397 case WS_XML_WRITER_ENCODING_TYPE_BINARY
:
2400 if ((hr
= text_to_text( value
, NULL
, NULL
, &new )) != S_OK
)
2409 FIXME( "unhandled output encoding %u\n", writer
->output_enc
);
2414 write_insert_node( writer
, writer
->current
, node
);
2418 static HRESULT
write_text_text( struct writer
*writer
, const WS_XML_TEXT
*text
, ULONG offset
)
2420 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)text
;
2423 if (node_type( writer
->current
->parent
) == WS_XML_NODE_TYPE_ELEMENT
)
2425 const struct escape
*escapes
[3] = { &escape_lt
, &escape_gt
, &escape_amp
};
2426 return write_bytes_escape( writer
, utf8
->value
.bytes
+ offset
, utf8
->value
.length
- offset
, escapes
, 3 );
2428 else if (node_type( writer
->current
->parent
) == WS_XML_NODE_TYPE_CDATA
)
2430 if ((hr
= write_grow_buffer( writer
, utf8
->value
.length
- offset
)) != S_OK
) return hr
;
2431 write_bytes( writer
, utf8
->value
.bytes
+ offset
, utf8
->value
.length
- offset
);
2435 return WS_E_INVALID_FORMAT
;
2438 static enum record_type
get_text_record_type( const WS_XML_TEXT
*text
)
2440 switch (text
->textType
)
2442 case WS_XML_TEXT_TYPE_UTF8
:
2444 const WS_XML_UTF8_TEXT
*text_utf8
= (const WS_XML_UTF8_TEXT
*)text
;
2445 if (text_utf8
->value
.length
<= MAX_UINT8
) return RECORD_CHARS8_TEXT_WITH_ENDELEMENT
;
2446 if (text_utf8
->value
.length
<= MAX_UINT16
) return RECORD_CHARS16_TEXT_WITH_ENDELEMENT
;
2447 return RECORD_CHARS32_TEXT_WITH_ENDELEMENT
;
2449 case WS_XML_TEXT_TYPE_BASE64
:
2451 const WS_XML_BASE64_TEXT
*text_base64
= (const WS_XML_BASE64_TEXT
*)text
;
2452 ULONG rem
= text_base64
->length
% 3, len
= text_base64
->length
- rem
;
2453 if (len
<= MAX_UINT8
) return RECORD_BYTES8_TEXT
;
2454 if (len
<= MAX_UINT16
) return RECORD_BYTES16_TEXT
;
2455 return RECORD_BYTES32_TEXT
;
2457 case WS_XML_TEXT_TYPE_BOOL
:
2459 const WS_XML_BOOL_TEXT
*text_bool
= (const WS_XML_BOOL_TEXT
*)text
;
2460 return text_bool
->value
? RECORD_TRUE_TEXT_WITH_ENDELEMENT
: RECORD_FALSE_TEXT_WITH_ENDELEMENT
;
2462 case WS_XML_TEXT_TYPE_INT32
:
2464 const WS_XML_INT32_TEXT
*text_int32
= (const WS_XML_INT32_TEXT
*)text
;
2465 if (!text_int32
->value
) return RECORD_ZERO_TEXT_WITH_ENDELEMENT
;
2466 if (text_int32
->value
== 1) return RECORD_ONE_TEXT_WITH_ENDELEMENT
;
2467 if (text_int32
->value
>= MIN_INT8
&& text_int32
->value
<= MAX_INT8
) return RECORD_INT8_TEXT_WITH_ENDELEMENT
;
2468 if (text_int32
->value
>= MIN_INT16
&& text_int32
->value
<= MAX_INT16
) return RECORD_INT16_TEXT_WITH_ENDELEMENT
;
2469 return RECORD_INT32_TEXT_WITH_ENDELEMENT
;
2471 case WS_XML_TEXT_TYPE_INT64
:
2473 const WS_XML_INT64_TEXT
*text_int64
= (const WS_XML_INT64_TEXT
*)text
;
2474 if (!text_int64
->value
) return RECORD_ZERO_TEXT_WITH_ENDELEMENT
;
2475 if (text_int64
->value
== 1) return RECORD_ONE_TEXT_WITH_ENDELEMENT
;
2476 if (text_int64
->value
>= MIN_INT8
&& text_int64
->value
<= MAX_INT8
) return RECORD_INT8_TEXT_WITH_ENDELEMENT
;
2477 if (text_int64
->value
>= MIN_INT16
&& text_int64
->value
<= MAX_INT16
) return RECORD_INT16_TEXT_WITH_ENDELEMENT
;
2478 if (text_int64
->value
>= MIN_INT32
&& text_int64
->value
<= MAX_INT32
) return RECORD_INT32_TEXT_WITH_ENDELEMENT
;
2479 return RECORD_INT64_TEXT_WITH_ENDELEMENT
;
2481 case WS_XML_TEXT_TYPE_UINT64
:
2483 const WS_XML_UINT64_TEXT
*text_uint64
= (const WS_XML_UINT64_TEXT
*)text
;
2484 if (!text_uint64
->value
) return RECORD_ZERO_TEXT_WITH_ENDELEMENT
;
2485 if (text_uint64
->value
== 1) return RECORD_ONE_TEXT_WITH_ENDELEMENT
;
2486 if (text_uint64
->value
<= MAX_INT8
) return RECORD_INT8_TEXT_WITH_ENDELEMENT
;
2487 if (text_uint64
->value
<= MAX_INT16
) return RECORD_INT16_TEXT_WITH_ENDELEMENT
;
2488 if (text_uint64
->value
<= MAX_INT32
) return RECORD_INT32_TEXT_WITH_ENDELEMENT
;
2489 if (text_uint64
->value
<= MAX_INT64
) return RECORD_INT64_TEXT_WITH_ENDELEMENT
;
2490 return RECORD_UINT64_TEXT_WITH_ENDELEMENT
;
2492 case WS_XML_TEXT_TYPE_DOUBLE
:
2494 const WS_XML_DOUBLE_TEXT
*text_double
= (const WS_XML_DOUBLE_TEXT
*)text
;
2495 if (!text_double
->value
) return RECORD_ZERO_TEXT_WITH_ENDELEMENT
;
2496 if (text_double
->value
== 1) return RECORD_ONE_TEXT_WITH_ENDELEMENT
;
2497 if (isinf( text_double
->value
) || (INT64
)text_double
->value
!= text_double
->value
)
2498 return RECORD_DOUBLE_TEXT_WITH_ENDELEMENT
;
2499 if (text_double
->value
<= MAX_INT8
) return RECORD_INT8_TEXT_WITH_ENDELEMENT
;
2500 if (text_double
->value
<= MAX_INT16
) return RECORD_INT16_TEXT_WITH_ENDELEMENT
;
2501 if (text_double
->value
<= MAX_INT32
) return RECORD_INT32_TEXT_WITH_ENDELEMENT
;
2502 return RECORD_INT64_TEXT_WITH_ENDELEMENT
;
2504 case WS_XML_TEXT_TYPE_GUID
:
2505 return RECORD_GUID_TEXT_WITH_ENDELEMENT
;
2507 case WS_XML_TEXT_TYPE_UNIQUE_ID
:
2508 return RECORD_UNIQUE_ID_TEXT_WITH_ENDELEMENT
;
2511 FIXME( "unhandled text type %u\n", text
->textType
);
2516 static HRESULT
write_text_bin( struct writer
*writer
, const WS_XML_TEXT
*text
, ULONG offset
)
2518 enum record_type type
= get_text_record_type( text
);
2523 FIXME( "no support for appending text in binary mode\n" );
2529 case RECORD_CHARS8_TEXT_WITH_ENDELEMENT
:
2531 const WS_XML_UTF8_TEXT
*text_utf8
= (const WS_XML_UTF8_TEXT
*)text
;
2532 UINT8 len
= text_utf8
->value
.length
;
2534 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(len
) + len
)) != S_OK
) return hr
;
2535 write_char( writer
, type
);
2536 write_char( writer
, len
);
2537 write_bytes( writer
, text_utf8
->value
.bytes
, len
);
2540 case RECORD_CHARS16_TEXT_WITH_ENDELEMENT
:
2542 const WS_XML_UTF8_TEXT
*text_utf8
= (const WS_XML_UTF8_TEXT
*)text
;
2543 UINT16 len
= text_utf8
->value
.length
;
2545 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(len
) + len
)) != S_OK
) return hr
;
2546 write_char( writer
, type
);
2547 write_bytes( writer
, (const BYTE
*)&len
, sizeof(len
) );
2548 write_bytes( writer
, text_utf8
->value
.bytes
, len
);
2551 case RECORD_BYTES8_TEXT
:
2553 const WS_XML_BASE64_TEXT
*text_base64
= (const WS_XML_BASE64_TEXT
*)text
;
2554 UINT8 rem
= text_base64
->length
% 3, len
= text_base64
->length
- rem
;
2558 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(len
) + len
)) != S_OK
) return hr
;
2559 write_char( writer
, rem
? RECORD_BYTES8_TEXT
: RECORD_BYTES8_TEXT_WITH_ENDELEMENT
);
2560 write_char( writer
, len
);
2561 write_bytes( writer
, text_base64
->bytes
, len
);
2565 if ((hr
= write_grow_buffer( writer
, 3 )) != S_OK
) return hr
;
2566 write_char( writer
, RECORD_BYTES8_TEXT_WITH_ENDELEMENT
);
2567 write_char( writer
, rem
);
2568 write_bytes( writer
, (const BYTE
*)text_base64
->bytes
+ len
, rem
);
2572 case RECORD_BYTES16_TEXT
:
2574 const WS_XML_BASE64_TEXT
*text_base64
= (const WS_XML_BASE64_TEXT
*)text
;
2575 UINT16 rem
= text_base64
->length
% 3, len
= text_base64
->length
- rem
;
2579 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(len
) + len
)) != S_OK
) return hr
;
2580 write_char( writer
, rem
? RECORD_BYTES16_TEXT
: RECORD_BYTES16_TEXT_WITH_ENDELEMENT
);
2581 write_bytes( writer
, (const BYTE
*)&len
, sizeof(len
) );
2582 write_bytes( writer
, text_base64
->bytes
, len
);
2586 if ((hr
= write_grow_buffer( writer
, 3 )) != S_OK
) return hr
;
2587 write_char( writer
, RECORD_BYTES8_TEXT_WITH_ENDELEMENT
);
2588 write_char( writer
, rem
);
2589 write_bytes( writer
, (const BYTE
*)text_base64
->bytes
+ len
, rem
);
2593 case RECORD_ZERO_TEXT_WITH_ENDELEMENT
:
2594 case RECORD_ONE_TEXT_WITH_ENDELEMENT
:
2595 case RECORD_FALSE_TEXT_WITH_ENDELEMENT
:
2596 case RECORD_TRUE_TEXT_WITH_ENDELEMENT
:
2598 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
2599 write_char( writer
, type
);
2602 case RECORD_INT8_TEXT_WITH_ENDELEMENT
:
2604 INT8 val
= get_text_value_int( text
);
2605 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(val
) )) != S_OK
) return hr
;
2606 write_char( writer
, type
);
2607 write_char( writer
, val
);
2610 case RECORD_INT16_TEXT_WITH_ENDELEMENT
:
2612 INT16 val
= get_text_value_int( text
);
2613 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(val
) )) != S_OK
) return hr
;
2614 write_char( writer
, type
);
2615 write_bytes( writer
, (const BYTE
*)&val
, sizeof(val
) );
2618 case RECORD_INT32_TEXT_WITH_ENDELEMENT
:
2620 INT32 val
= get_text_value_int( text
);
2621 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(val
) )) != S_OK
) return hr
;
2622 write_char( writer
, type
);
2623 write_bytes( writer
, (const BYTE
*)&val
, sizeof(val
) );
2626 case RECORD_INT64_TEXT_WITH_ENDELEMENT
:
2628 INT64 val
= get_text_value_int( text
);
2629 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(val
) )) != S_OK
) return hr
;
2630 write_char( writer
, type
);
2631 write_bytes( writer
, (const BYTE
*)&val
, sizeof(val
) );
2634 case RECORD_UINT64_TEXT_WITH_ENDELEMENT
:
2636 WS_XML_UINT64_TEXT
*text_uint64
= (WS_XML_UINT64_TEXT
*)text
;
2637 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(text_uint64
->value
) )) != S_OK
) return hr
;
2638 write_char( writer
, type
);
2639 write_bytes( writer
, (const BYTE
*)&text_uint64
->value
, sizeof(text_uint64
->value
) );
2642 case RECORD_DOUBLE_TEXT_WITH_ENDELEMENT
:
2644 WS_XML_DOUBLE_TEXT
*text_double
= (WS_XML_DOUBLE_TEXT
*)text
;
2645 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(text_double
->value
) )) != S_OK
) return hr
;
2646 write_char( writer
, type
);
2647 write_bytes( writer
, (const BYTE
*)&text_double
->value
, sizeof(text_double
->value
) );
2650 case RECORD_GUID_TEXT_WITH_ENDELEMENT
:
2652 WS_XML_GUID_TEXT
*text_guid
= (WS_XML_GUID_TEXT
*)text
;
2653 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(text_guid
->value
) )) != S_OK
) return hr
;
2654 write_char( writer
, type
);
2655 write_bytes( writer
, (const BYTE
*)&text_guid
->value
, sizeof(text_guid
->value
) );
2658 case RECORD_UNIQUE_ID_TEXT_WITH_ENDELEMENT
:
2660 WS_XML_UNIQUE_ID_TEXT
*text_unique_id
= (WS_XML_UNIQUE_ID_TEXT
*)text
;
2661 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(text_unique_id
->value
) )) != S_OK
) return hr
;
2662 write_char( writer
, type
);
2663 write_bytes( writer
, (const BYTE
*)&text_unique_id
->value
, sizeof(text_unique_id
->value
) );
2667 FIXME( "unhandled record type %02x\n", type
);
2672 static HRESULT
write_text( struct writer
*writer
, const WS_XML_TEXT
*text
, ULONG offset
)
2674 if (!writer
->current
->parent
) return WS_E_INVALID_FORMAT
;
2676 switch (writer
->output_enc
)
2678 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_text_text( writer
, text
, offset
);
2679 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return write_text_bin( writer
, text
, offset
);
2681 ERR( "unhandled encoding %u\n", writer
->output_enc
);
2682 return WS_E_NOT_SUPPORTED
;
2686 static HRESULT
write_text_node( struct writer
*writer
, const WS_XML_TEXT
*text
)
2688 WS_XML_TEXT_NODE
*node
= (WS_XML_TEXT_NODE
*)writer
->current
;
2692 if ((hr
= write_flush( writer
)) != S_OK
) return hr
;
2693 if (node_type( writer
->current
) != WS_XML_NODE_TYPE_TEXT
)
2695 if ((hr
= write_add_text_node( writer
, text
)) != S_OK
) return hr
;
2696 node
= (WS_XML_TEXT_NODE
*)writer
->current
;
2700 switch (writer
->output_enc
)
2702 case WS_XML_WRITER_ENCODING_TYPE_TEXT
:
2704 WS_XML_UTF8_TEXT
*new, *old
= (WS_XML_UTF8_TEXT
*)node
->text
;
2705 offset
= old
->value
.length
;
2706 if ((hr
= text_to_utf8text( text
, old
, &offset
, &new )) != S_OK
) return hr
;
2708 node
->text
= &new->text
;
2711 case WS_XML_WRITER_ENCODING_TYPE_BINARY
:
2713 WS_XML_TEXT
*new, *old
= node
->text
;
2714 if ((hr
= text_to_text( text
, old
, &offset
, &new )) != S_OK
) return hr
;
2720 FIXME( "unhandled output encoding %u\n", writer
->output_enc
);
2725 if ((hr
= write_text( writer
, node
->text
, offset
)) != S_OK
) return hr
;
2727 writer
->state
= WRITER_STATE_TEXT
;
2731 /**************************************************************************
2732 * WsWriteText [webservices.@]
2734 HRESULT WINAPI
WsWriteText( WS_XML_WRITER
*handle
, const WS_XML_TEXT
*text
, WS_ERROR
*error
)
2736 struct writer
*writer
= (struct writer
*)handle
;
2739 TRACE( "%p %p %p\n", handle
, text
, error
);
2740 if (error
) FIXME( "ignoring error parameter\n" );
2742 if (!writer
|| !text
) return E_INVALIDARG
;
2744 EnterCriticalSection( &writer
->cs
);
2746 if (writer
->magic
!= WRITER_MAGIC
)
2748 LeaveCriticalSection( &writer
->cs
);
2749 return E_INVALIDARG
;
2752 if (writer
->state
== WRITER_STATE_STARTATTRIBUTE
) hr
= write_set_attribute_value( writer
, text
);
2753 else hr
= write_text_node( writer
, text
);
2755 LeaveCriticalSection( &writer
->cs
);
2759 /**************************************************************************
2760 * WsWriteBytes [webservices.@]
2762 HRESULT WINAPI
WsWriteBytes( WS_XML_WRITER
*handle
, const void *bytes
, ULONG count
, WS_ERROR
*error
)
2764 struct writer
*writer
= (struct writer
*)handle
;
2765 WS_XML_BASE64_TEXT base64
;
2768 TRACE( "%p %p %u %p\n", handle
, bytes
, count
, error
);
2769 if (error
) FIXME( "ignoring error parameter\n" );
2771 if (!writer
) return E_INVALIDARG
;
2773 EnterCriticalSection( &writer
->cs
);
2775 if (writer
->magic
!= WRITER_MAGIC
)
2777 LeaveCriticalSection( &writer
->cs
);
2778 return E_INVALIDARG
;
2781 if (!writer
->output_type
)
2783 LeaveCriticalSection( &writer
->cs
);
2784 return WS_E_INVALID_OPERATION
;
2787 base64
.text
.textType
= WS_XML_TEXT_TYPE_BASE64
;
2788 base64
.bytes
= (BYTE
*)bytes
;
2789 base64
.length
= count
;
2791 if (writer
->state
== WRITER_STATE_STARTATTRIBUTE
) hr
= write_set_attribute_value( writer
, &base64
.text
);
2792 else hr
= write_text_node( writer
, &base64
.text
);
2794 LeaveCriticalSection( &writer
->cs
);
2798 /**************************************************************************
2799 * WsWriteChars [webservices.@]
2801 HRESULT WINAPI
WsWriteChars( WS_XML_WRITER
*handle
, const WCHAR
*chars
, ULONG count
, WS_ERROR
*error
)
2803 struct writer
*writer
= (struct writer
*)handle
;
2804 WS_XML_UTF16_TEXT utf16
;
2807 TRACE( "%p %s %u %p\n", handle
, debugstr_wn(chars
, count
), count
, error
);
2808 if (error
) FIXME( "ignoring error parameter\n" );
2810 if (!writer
) return E_INVALIDARG
;
2812 EnterCriticalSection( &writer
->cs
);
2814 if (writer
->magic
!= WRITER_MAGIC
)
2816 LeaveCriticalSection( &writer
->cs
);
2817 return E_INVALIDARG
;
2820 if (!writer
->output_type
)
2822 LeaveCriticalSection( &writer
->cs
);
2823 return WS_E_INVALID_OPERATION
;
2826 utf16
.text
.textType
= WS_XML_TEXT_TYPE_UTF16
;
2827 utf16
.bytes
= (BYTE
*)chars
;
2828 utf16
.byteCount
= count
* sizeof(WCHAR
);
2830 if (writer
->state
== WRITER_STATE_STARTATTRIBUTE
) hr
= write_set_attribute_value( writer
, &utf16
.text
);
2831 else hr
= write_text_node( writer
, &utf16
.text
);
2833 LeaveCriticalSection( &writer
->cs
);
2837 /**************************************************************************
2838 * WsWriteCharsUtf8 [webservices.@]
2840 HRESULT WINAPI
WsWriteCharsUtf8( WS_XML_WRITER
*handle
, const BYTE
*bytes
, ULONG count
, WS_ERROR
*error
)
2842 struct writer
*writer
= (struct writer
*)handle
;
2843 WS_XML_UTF8_TEXT utf8
;
2846 TRACE( "%p %s %u %p\n", handle
, debugstr_an((const char *)bytes
, count
), count
, error
);
2847 if (error
) FIXME( "ignoring error parameter\n" );
2849 if (!writer
) return E_INVALIDARG
;
2851 EnterCriticalSection( &writer
->cs
);
2853 if (writer
->magic
!= WRITER_MAGIC
)
2855 LeaveCriticalSection( &writer
->cs
);
2856 return E_INVALIDARG
;
2859 if (!writer
->output_type
)
2861 LeaveCriticalSection( &writer
->cs
);
2862 return WS_E_INVALID_OPERATION
;
2865 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
2866 utf8
.value
.bytes
= (BYTE
*)bytes
;
2867 utf8
.value
.length
= count
;
2869 if (writer
->state
== WRITER_STATE_STARTATTRIBUTE
) hr
= write_set_attribute_value( writer
, &utf8
.text
);
2870 else hr
= write_text_node( writer
, &utf8
.text
);
2872 LeaveCriticalSection( &writer
->cs
);
2876 static HRESULT
write_type_text( struct writer
*writer
, WS_TYPE_MAPPING mapping
, const WS_XML_TEXT
*text
)
2880 case WS_ELEMENT_TYPE_MAPPING
:
2881 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
2882 return write_text_node( writer
, text
);
2884 case WS_ATTRIBUTE_TYPE_MAPPING
:
2885 return write_set_attribute_value( writer
, text
);
2887 case WS_ANY_ELEMENT_TYPE_MAPPING
:
2888 switch (writer
->state
)
2890 case WRITER_STATE_STARTATTRIBUTE
:
2891 return write_set_attribute_value( writer
, text
);
2893 case WRITER_STATE_STARTELEMENT
:
2894 return write_text_node( writer
, text
);
2897 FIXME( "writer state %u not handled\n", writer
->state
);
2902 FIXME( "mapping %u not implemented\n", mapping
);
2907 static HRESULT
write_add_nil_attribute( struct writer
*writer
)
2909 static const WS_XML_STRING prefix
= {1, (BYTE
*)"a"};
2910 static const WS_XML_STRING localname
= {3, (BYTE
*)"nil"};
2911 static const WS_XML_STRING ns
= {41, (BYTE
*)"http://www.w3.org/2001/XMLSchema-instance"};
2912 static const WS_XML_UTF8_TEXT value
= {{WS_XML_TEXT_TYPE_UTF8
}, {4, (BYTE
*)"true"}};
2915 if ((hr
= write_add_attribute( writer
, &prefix
, &localname
, &ns
, FALSE
)) != S_OK
) return hr
;
2916 if ((hr
= write_set_attribute_value( writer
, &value
.text
)) != S_OK
) return hr
;
2917 return add_namespace_attribute( writer
, &prefix
, &ns
, FALSE
);
2920 static HRESULT
get_value_ptr( WS_WRITE_OPTION option
, const void *value
, ULONG size
, ULONG expected_size
,
2925 case WS_WRITE_REQUIRED_VALUE
:
2926 case WS_WRITE_NILLABLE_VALUE
:
2927 if (!value
|| size
!= expected_size
) return E_INVALIDARG
;
2931 case WS_WRITE_REQUIRED_POINTER
:
2932 if (size
!= sizeof(const void *) || !(*ptr
= *(const void **)value
)) return E_INVALIDARG
;
2935 case WS_WRITE_NILLABLE_POINTER
:
2936 if (size
!= sizeof(const void *)) return E_INVALIDARG
;
2937 *ptr
= *(const void **)value
;
2941 return E_INVALIDARG
;
2945 static HRESULT
write_type_bool( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
2946 const WS_BOOL_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
2947 const BOOL
*value
, ULONG size
)
2949 WS_XML_BOOL_TEXT text_bool
;
2955 FIXME( "description not supported\n" );
2959 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
2960 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(BOOL
), (const void **)&ptr
)) != S_OK
) return hr
;
2961 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
2963 text_bool
.text
.textType
= WS_XML_TEXT_TYPE_BOOL
;
2964 text_bool
.value
= *ptr
;
2965 return write_type_text( writer
, mapping
, &text_bool
.text
);
2968 static HRESULT
write_type_int8( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
2969 const WS_INT8_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
2970 const BOOL
*value
, ULONG size
)
2972 WS_XML_INT32_TEXT text_int32
;
2978 FIXME( "description not supported\n" );
2982 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
2983 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(INT8
), (const void **)&ptr
)) != S_OK
) return hr
;
2984 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
2986 text_int32
.text
.textType
= WS_XML_TEXT_TYPE_INT32
;
2987 text_int32
.value
= *ptr
;
2988 return write_type_text( writer
, mapping
, &text_int32
.text
);
2991 static HRESULT
write_type_int16( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
2992 const WS_INT16_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
2993 const BOOL
*value
, ULONG size
)
2995 WS_XML_INT32_TEXT text_int32
;
3001 FIXME( "description not supported\n" );
3005 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3006 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(INT16
), (const void **)&ptr
)) != S_OK
) return hr
;
3007 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3009 text_int32
.text
.textType
= WS_XML_TEXT_TYPE_INT32
;
3010 text_int32
.value
= *ptr
;
3011 return write_type_text( writer
, mapping
, &text_int32
.text
);
3014 static HRESULT
write_type_int32( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3015 const WS_INT32_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3016 const void *value
, ULONG size
)
3018 WS_XML_INT32_TEXT text_int32
;
3024 FIXME( "description not supported\n" );
3028 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3029 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(INT32
), (const void **)&ptr
)) != S_OK
) return hr
;
3030 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3032 text_int32
.text
.textType
= WS_XML_TEXT_TYPE_INT32
;
3033 text_int32
.value
= *ptr
;
3034 return write_type_text( writer
, mapping
, &text_int32
.text
);
3037 static HRESULT
write_type_int64( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3038 const WS_INT64_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3039 const void *value
, ULONG size
)
3041 WS_XML_INT64_TEXT text_int64
;
3047 FIXME( "description not supported\n" );
3051 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3052 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(INT64
), (const void **)&ptr
)) != S_OK
) return hr
;
3053 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3055 text_int64
.text
.textType
= WS_XML_TEXT_TYPE_INT64
;
3056 text_int64
.value
= *ptr
;
3057 return write_type_text( writer
, mapping
, &text_int64
.text
);
3060 static HRESULT
write_type_uint8( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3061 const WS_UINT8_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3062 const void *value
, ULONG size
)
3064 WS_XML_UINT64_TEXT text_uint64
;
3070 FIXME( "description not supported\n" );
3074 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3075 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(UINT8
), (const void **)&ptr
)) != S_OK
) return hr
;
3076 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3078 text_uint64
.text
.textType
= WS_XML_TEXT_TYPE_UINT64
;
3079 text_uint64
.value
= *ptr
;
3080 return write_type_text( writer
, mapping
, &text_uint64
.text
);
3083 static HRESULT
write_type_uint16( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3084 const WS_UINT16_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3085 const void *value
, ULONG size
)
3087 WS_XML_UINT64_TEXT text_uint64
;
3093 FIXME( "description not supported\n" );
3097 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3098 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(UINT16
), (const void **)&ptr
)) != S_OK
) return hr
;
3099 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3101 text_uint64
.text
.textType
= WS_XML_TEXT_TYPE_UINT64
;
3102 text_uint64
.value
= *ptr
;
3103 return write_type_text( writer
, mapping
, &text_uint64
.text
);
3106 static HRESULT
write_type_uint32( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3107 const WS_UINT32_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3108 const void *value
, ULONG size
)
3110 WS_XML_UINT64_TEXT text_uint64
;
3116 FIXME( "description not supported\n" );
3120 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3121 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(UINT32
), (const void **)&ptr
)) != S_OK
) return hr
;
3122 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3124 text_uint64
.text
.textType
= WS_XML_TEXT_TYPE_UINT64
;
3125 text_uint64
.value
= *ptr
;
3126 return write_type_text( writer
, mapping
, &text_uint64
.text
);
3129 static HRESULT
write_type_uint64( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3130 const WS_UINT64_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3131 const void *value
, ULONG size
)
3133 WS_XML_UINT64_TEXT text_uint64
;
3139 FIXME( "description not supported\n" );
3143 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3144 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(UINT64
), (const void **)&ptr
)) != S_OK
) return hr
;
3145 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3147 text_uint64
.text
.textType
= WS_XML_TEXT_TYPE_UINT64
;
3148 text_uint64
.value
= *ptr
;
3149 return write_type_text( writer
, mapping
, &text_uint64
.text
);
3152 static HRESULT
write_type_double( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3153 const WS_DOUBLE_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3154 const void *value
, ULONG size
)
3156 WS_XML_DOUBLE_TEXT text_double
;
3162 FIXME( "description not supported\n" );
3166 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3167 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(double), (const void **)&ptr
)) != S_OK
) return hr
;
3168 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3170 text_double
.text
.textType
= WS_XML_TEXT_TYPE_DOUBLE
;
3171 text_double
.value
= *ptr
;
3172 return write_type_text( writer
, mapping
, &text_double
.text
);
3175 static HRESULT
write_type_datetime( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3176 const WS_DATETIME_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3177 const void *value
, ULONG size
)
3179 WS_XML_UTF8_TEXT utf8
;
3180 unsigned char buf
[34]; /* "0000-00-00T00:00:00.0000000-00:00" */
3181 const WS_DATETIME
*ptr
;
3186 FIXME( "description not supported\n" );
3190 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3191 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(WS_DATETIME
), (const void **)&ptr
)) != S_OK
) return hr
;
3192 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3193 if (ptr
->ticks
> TICKS_MAX
|| ptr
->format
> WS_DATETIME_FORMAT_NONE
) return WS_E_INVALID_FORMAT
;
3195 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
3196 utf8
.value
.bytes
= buf
;
3197 utf8
.value
.length
= format_datetime( ptr
, buf
);
3198 return write_type_text( writer
, mapping
, &utf8
.text
);
3201 static HRESULT
write_type_guid( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3202 const WS_GUID_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3203 const void *value
, ULONG size
)
3205 WS_XML_GUID_TEXT text_guid
;
3211 FIXME( "description not supported\n" );
3215 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3216 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(GUID
), (const void **)&ptr
)) != S_OK
) return hr
;
3217 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3219 text_guid
.text
.textType
= WS_XML_TEXT_TYPE_GUID
;
3220 text_guid
.value
= *ptr
;
3221 return write_type_text( writer
, mapping
, &text_guid
.text
);
3224 static HRESULT
write_type_unique_id( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3225 const WS_UNIQUE_ID_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3226 const void *value
, ULONG size
)
3228 WS_XML_UNIQUE_ID_TEXT text_unique_id
;
3229 WS_XML_UTF16_TEXT text_utf16
;
3230 const WS_UNIQUE_ID
*ptr
;
3235 FIXME( "description not supported\n" );
3239 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3240 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(*ptr
), (const void **)&ptr
)) != S_OK
) return hr
;
3241 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3243 if (ptr
->uri
.length
)
3245 text_utf16
.text
.textType
= WS_XML_TEXT_TYPE_UTF16
;
3246 text_utf16
.bytes
= (BYTE
*)ptr
->uri
.chars
;
3247 text_utf16
.byteCount
= ptr
->uri
.length
* sizeof(WCHAR
);
3248 return write_type_text( writer
, mapping
, &text_utf16
.text
);
3251 text_unique_id
.text
.textType
= WS_XML_TEXT_TYPE_UNIQUE_ID
;
3252 text_unique_id
.value
= ptr
->guid
;
3253 return write_type_text( writer
, mapping
, &text_unique_id
.text
);
3256 static HRESULT
write_type_string( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3257 const WS_STRING_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3258 const void *value
, ULONG size
)
3260 WS_XML_UTF16_TEXT utf16
;
3261 const WS_STRING
*ptr
;
3266 FIXME( "description not supported\n" );
3270 if (!option
) return E_INVALIDARG
;
3271 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(WS_STRING
), (const void **)&ptr
)) != S_OK
) return hr
;
3272 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3273 if (!ptr
->length
) return S_OK
;
3275 utf16
.text
.textType
= WS_XML_TEXT_TYPE_UTF16
;
3276 utf16
.bytes
= (BYTE
*)ptr
->chars
;
3277 utf16
.byteCount
= ptr
->length
* sizeof(WCHAR
);
3278 return write_type_text( writer
, mapping
, &utf16
.text
);
3281 static HRESULT
write_type_wsz( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3282 const WS_WSZ_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3283 const void *value
, ULONG size
)
3285 WS_XML_UTF16_TEXT utf16
;
3292 FIXME( "description not supported\n" );
3296 if (!option
|| option
== WS_WRITE_REQUIRED_VALUE
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3297 if ((hr
= get_value_ptr( option
, value
, size
, 0, (const void **)&ptr
)) != S_OK
) return hr
;
3298 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3299 if (!(len
= strlenW( ptr
))) return S_OK
;
3301 utf16
.text
.textType
= WS_XML_TEXT_TYPE_UTF16
;
3302 utf16
.bytes
= (BYTE
*)ptr
;
3303 utf16
.byteCount
= len
* sizeof(WCHAR
);
3304 return write_type_text( writer
, mapping
, &utf16
.text
);
3307 static HRESULT
write_type_bytes( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3308 const WS_BYTES_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3309 const void *value
, ULONG size
)
3311 WS_XML_BASE64_TEXT base64
;
3312 const WS_BYTES
*ptr
;
3317 FIXME( "description not supported\n" );
3321 if (!option
) return E_INVALIDARG
;
3322 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(WS_BYTES
), (const void **)&ptr
)) != S_OK
) return hr
;
3323 if ((option
== WS_WRITE_NILLABLE_VALUE
&& is_nil_value( value
, size
)) ||
3324 (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
)) return write_add_nil_attribute( writer
);
3325 if (!ptr
->length
) return S_OK
;
3327 base64
.text
.textType
= WS_XML_TEXT_TYPE_BASE64
;
3328 base64
.bytes
= ptr
->bytes
;
3329 base64
.length
= ptr
->length
;
3330 return write_type_text( writer
, mapping
, &base64
.text
);
3333 static HRESULT
write_type_xml_string( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3334 const WS_XML_STRING_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3335 const void *value
, ULONG size
)
3337 WS_XML_UTF8_TEXT utf8
;
3338 const WS_XML_STRING
*ptr
;
3343 FIXME( "description not supported\n" );
3347 if (!option
) return E_INVALIDARG
;
3348 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(WS_XML_STRING
), (const void **)&ptr
)) != S_OK
) return hr
;
3349 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3350 if (option
== WS_WRITE_NILLABLE_VALUE
&& is_nil_value( value
, size
)) return write_add_nil_attribute( writer
);
3351 if (!ptr
->length
) return S_OK
;
3353 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
3354 utf8
.value
.bytes
= ptr
->bytes
;
3355 utf8
.value
.length
= ptr
->length
;
3356 return write_type_text( writer
, mapping
, &utf8
.text
);
3359 static HRESULT
find_prefix( struct writer
*writer
, const WS_XML_STRING
*ns
, const WS_XML_STRING
**prefix
)
3361 const struct node
*node
;
3362 for (node
= writer
->current
; node_type( node
) == WS_XML_NODE_TYPE_ELEMENT
; node
= node
->parent
)
3364 const WS_XML_ELEMENT_NODE
*elem
= &node
->hdr
;
3366 for (i
= 0; i
< elem
->attributeCount
; i
++)
3368 if (!elem
->attributes
[i
]->isXmlNs
) continue;
3369 if (WsXmlStringEquals( elem
->attributes
[i
]->ns
, ns
, NULL
) != S_OK
) continue;
3370 *prefix
= elem
->attributes
[i
]->prefix
;
3374 return WS_E_INVALID_FORMAT
;
3377 static HRESULT
write_type_qname( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3378 const WS_XML_QNAME_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3379 const void *value
, ULONG size
)
3381 WS_XML_QNAME_TEXT qname
;
3382 const WS_XML_QNAME
*ptr
;
3383 const WS_XML_STRING
*prefix
;
3388 FIXME( "description not supported\n" );
3392 if (!option
) return E_INVALIDARG
;
3393 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(*ptr
), (const void **)&ptr
)) != S_OK
) return hr
;
3394 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3395 if (option
== WS_WRITE_NILLABLE_VALUE
&& is_nil_value( value
, size
)) return write_add_nil_attribute( writer
);
3397 if (((hr
= find_prefix( writer
, &ptr
->ns
, &prefix
)) != S_OK
)) return hr
;
3399 qname
.text
.textType
= WS_XML_TEXT_TYPE_QNAME
;
3400 qname
.prefix
= (WS_XML_STRING
*)prefix
;
3401 qname
.localName
= (WS_XML_STRING
*)&ptr
->localName
;
3402 qname
.ns
= (WS_XML_STRING
*)&ptr
->ns
;
3403 return write_type_text( writer
, mapping
, &qname
.text
);
3406 static WS_WRITE_OPTION
get_field_write_option( WS_TYPE type
, ULONG options
)
3408 if (options
& WS_FIELD_POINTER
)
3410 if (options
& (WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
)) return WS_WRITE_NILLABLE_POINTER
;
3411 return WS_WRITE_REQUIRED_POINTER
;
3422 case WS_UINT16_TYPE
:
3423 case WS_UINT32_TYPE
:
3424 case WS_UINT64_TYPE
:
3425 case WS_DOUBLE_TYPE
:
3426 case WS_DATETIME_TYPE
:
3428 case WS_UNIQUE_ID_TYPE
:
3429 case WS_STRING_TYPE
:
3431 case WS_XML_STRING_TYPE
:
3432 case WS_XML_QNAME_TYPE
:
3433 case WS_STRUCT_TYPE
:
3435 if (options
& (WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
)) return WS_WRITE_NILLABLE_VALUE
;
3436 return WS_WRITE_REQUIRED_VALUE
;
3439 case WS_DESCRIPTION_TYPE
:
3440 if (options
& (WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
)) return WS_WRITE_NILLABLE_POINTER
;
3441 return WS_WRITE_REQUIRED_POINTER
;
3444 FIXME( "unhandled type %u\n", type
);
3449 static HRESULT
write_type( struct writer
*, WS_TYPE_MAPPING
, WS_TYPE
, const void *, WS_WRITE_OPTION
,
3450 const void *, ULONG
);
3452 static HRESULT
write_type_repeating_element( struct writer
*writer
, const WS_FIELD_DESCRIPTION
*desc
,
3453 const char *buf
, ULONG count
)
3456 ULONG i
, size
, offset
= 0;
3457 WS_WRITE_OPTION option
;
3459 if (!(option
= get_field_write_option( desc
->type
, desc
->options
))) return E_INVALIDARG
;
3461 /* wrapper element */
3462 if (desc
->localName
&& ((hr
= write_element_node( writer
, NULL
, desc
->localName
, desc
->ns
)) != S_OK
))
3465 if (option
== WS_WRITE_REQUIRED_VALUE
|| option
== WS_WRITE_NILLABLE_VALUE
)
3466 size
= get_type_size( desc
->type
, desc
->typeDescription
);
3468 size
= sizeof(const void *);
3470 for (i
= 0; i
< count
; i
++)
3472 if ((hr
= write_element_node( writer
, NULL
, desc
->itemLocalName
, desc
->itemNs
)) != S_OK
) return hr
;
3473 if ((hr
= write_type( writer
, WS_ELEMENT_TYPE_MAPPING
, desc
->type
, desc
->typeDescription
, option
,
3474 buf
+ offset
, size
)) != S_OK
) return hr
;
3475 if ((hr
= write_endelement_node( writer
)) != S_OK
) return hr
;
3479 if (desc
->localName
) hr
= write_endelement_node( writer
);
3483 static HRESULT
write_type_field( struct writer
*, const WS_FIELD_DESCRIPTION
*, const char *, ULONG
);
3485 static HRESULT
write_type_union( struct writer
*writer
, const WS_UNION_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3486 const void *value
, ULONG size
)
3493 if ((hr
= get_value_ptr( option
, value
, size
, desc
->size
, &ptr
)) != S_OK
) return hr
;
3495 if (size
< sizeof(enum_value
)) return E_INVALIDARG
;
3496 if ((enum_value
= *(int *)(char *)ptr
+ desc
->enumOffset
) == desc
->noneEnumValue
)
3500 case WS_WRITE_REQUIRED_VALUE
:
3501 return WS_E_INVALID_FORMAT
;
3503 case WS_WRITE_NILLABLE_VALUE
:
3507 ERR( "unhandled write option %u\n", option
);
3508 return E_INVALIDARG
;
3512 for (i
= 0; i
< desc
->fieldCount
; i
++)
3514 if (desc
->fields
[i
]->value
== enum_value
)
3516 offset
= desc
->fields
[i
]->field
.offset
;
3517 return write_type_field( writer
, &desc
->fields
[i
]->field
, ptr
, offset
);
3521 return E_INVALIDARG
;
3524 static HRESULT
write_type_field( struct writer
*writer
, const WS_FIELD_DESCRIPTION
*desc
, const char *buf
,
3528 WS_TYPE_MAPPING mapping
;
3529 WS_WRITE_OPTION option
;
3530 ULONG count
, size
, field_options
= desc
->options
;
3531 const char *ptr
= buf
+ offset
;
3533 if (field_options
& ~(WS_FIELD_POINTER
|WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
))
3535 FIXME( "options 0x%x not supported\n", desc
->options
);
3539 /* zero-terminated strings are always pointers */
3540 if (desc
->type
== WS_WSZ_TYPE
) field_options
|= WS_FIELD_POINTER
;
3542 if (field_options
& WS_FIELD_POINTER
)
3543 size
= sizeof(const void *);
3545 size
= get_type_size( desc
->type
, desc
->typeDescription
);
3547 if (is_nil_value( ptr
, size
))
3549 if (field_options
& WS_FIELD_OPTIONAL
) return S_OK
;
3550 if (field_options
& WS_FIELD_NILLABLE
)
3552 if (field_options
& WS_FIELD_POINTER
) option
= WS_WRITE_NILLABLE_POINTER
;
3553 else option
= WS_WRITE_NILLABLE_VALUE
;
3557 if (field_options
& WS_FIELD_POINTER
) option
= WS_WRITE_REQUIRED_POINTER
;
3558 else option
= WS_WRITE_REQUIRED_VALUE
;
3563 if (field_options
& WS_FIELD_POINTER
) option
= WS_WRITE_REQUIRED_POINTER
;
3564 else option
= WS_WRITE_REQUIRED_VALUE
;
3567 switch (desc
->mapping
)
3569 case WS_ATTRIBUTE_FIELD_MAPPING
:
3570 if (!desc
->localName
|| !desc
->ns
) return E_INVALIDARG
;
3571 if ((hr
= write_add_attribute( writer
, NULL
, desc
->localName
, desc
->ns
, FALSE
)) != S_OK
)
3573 writer
->state
= WRITER_STATE_STARTATTRIBUTE
;
3575 mapping
= WS_ATTRIBUTE_TYPE_MAPPING
;
3578 case WS_ELEMENT_FIELD_MAPPING
:
3579 if ((hr
= write_element_node( writer
, NULL
, desc
->localName
, desc
->ns
)) != S_OK
) return hr
;
3580 mapping
= WS_ELEMENT_TYPE_MAPPING
;
3583 case WS_ELEMENT_CHOICE_FIELD_MAPPING
:
3584 if (desc
->type
!= WS_UNION_TYPE
|| !desc
->typeDescription
) return E_INVALIDARG
;
3585 option
= (field_options
& WS_FIELD_OPTIONAL
) ? WS_WRITE_NILLABLE_VALUE
: WS_WRITE_REQUIRED_VALUE
;
3586 return write_type_union( writer
, desc
->typeDescription
, option
, ptr
, size
);
3588 case WS_REPEATING_ELEMENT_FIELD_MAPPING
:
3589 count
= *(const ULONG
*)(buf
+ desc
->countOffset
);
3590 return write_type_repeating_element( writer
, desc
, *(const char **)ptr
, count
);
3592 case WS_TEXT_FIELD_MAPPING
:
3593 switch (writer
->state
)
3595 case WRITER_STATE_STARTELEMENT
:
3596 mapping
= WS_ELEMENT_CONTENT_TYPE_MAPPING
;
3599 case WRITER_STATE_STARTATTRIBUTE
:
3600 mapping
= WS_ATTRIBUTE_TYPE_MAPPING
;
3604 FIXME( "unhandled writer state %u\n", writer
->state
);
3610 FIXME( "field mapping %u not supported\n", desc
->mapping
);
3614 if ((hr
= write_type( writer
, mapping
, desc
->type
, desc
->typeDescription
, option
, ptr
, size
)) != S_OK
)
3619 case WS_ATTRIBUTE_TYPE_MAPPING
:
3620 writer
->state
= WRITER_STATE_STARTELEMENT
;
3623 case WS_ELEMENT_TYPE_MAPPING
:
3624 if ((hr
= write_endelement_node( writer
)) != S_OK
) return hr
;
3633 static HRESULT
write_type_struct( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3634 const WS_STRUCT_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3635 const void *value
, ULONG size
)
3641 if (!desc
) return E_INVALIDARG
;
3642 if (desc
->structOptions
) FIXME( "struct options 0x%x not supported\n", desc
->structOptions
);
3644 if ((hr
= get_value_ptr( option
, value
, size
, desc
->size
, &ptr
)) != S_OK
) return hr
;
3646 for (i
= 0; i
< desc
->fieldCount
; i
++)
3648 offset
= desc
->fields
[i
]->offset
;
3649 if ((hr
= write_type_field( writer
, desc
->fields
[i
], ptr
, offset
)) != S_OK
) return hr
;
3655 static HRESULT
write_type( struct writer
*writer
, WS_TYPE_MAPPING mapping
, WS_TYPE type
,
3656 const void *desc
, WS_WRITE_OPTION option
, const void *value
,
3662 return write_type_bool( writer
, mapping
, desc
, option
, value
, size
);
3665 return write_type_int8( writer
, mapping
, desc
, option
, value
, size
);
3668 return write_type_int16( writer
, mapping
, desc
, option
, value
, size
);
3671 return write_type_int32( writer
, mapping
, desc
, option
, value
, size
);
3674 return write_type_int64( writer
, mapping
, desc
, option
, value
, size
);
3677 return write_type_uint8( writer
, mapping
, desc
, option
, value
, size
);
3679 case WS_UINT16_TYPE
:
3680 return write_type_uint16( writer
, mapping
, desc
, option
, value
, size
);
3682 case WS_UINT32_TYPE
:
3683 return write_type_uint32( writer
, mapping
, desc
, option
, value
, size
);
3685 case WS_UINT64_TYPE
:
3686 return write_type_uint64( writer
, mapping
, desc
, option
, value
, size
);
3688 case WS_DOUBLE_TYPE
:
3689 return write_type_double( writer
, mapping
, desc
, option
, value
, size
);
3691 case WS_DATETIME_TYPE
:
3692 return write_type_datetime( writer
, mapping
, desc
, option
, value
, size
);
3695 return write_type_guid( writer
, mapping
, desc
, option
, value
, size
);
3697 case WS_UNIQUE_ID_TYPE
:
3698 return write_type_unique_id( writer
, mapping
, desc
, option
, value
, size
);
3700 case WS_STRING_TYPE
:
3701 return write_type_string( writer
, mapping
, desc
, option
, value
, size
);
3704 return write_type_wsz( writer
, mapping
, desc
, option
, value
, size
);
3707 return write_type_bytes( writer
, mapping
, desc
, option
, value
, size
);
3709 case WS_XML_STRING_TYPE
:
3710 return write_type_xml_string( writer
, mapping
, desc
, option
, value
, size
);
3712 case WS_XML_QNAME_TYPE
:
3713 return write_type_qname( writer
, mapping
, desc
, option
, value
, size
);
3715 case WS_STRUCT_TYPE
:
3716 return write_type_struct( writer
, mapping
, desc
, option
, value
, size
);
3719 FIXME( "type %u not supported\n", type
);
3724 /**************************************************************************
3725 * WsWriteAttribute [webservices.@]
3727 HRESULT WINAPI
WsWriteAttribute( WS_XML_WRITER
*handle
, const WS_ATTRIBUTE_DESCRIPTION
*desc
,
3728 WS_WRITE_OPTION option
, const void *value
, ULONG size
,
3731 struct writer
*writer
= (struct writer
*)handle
;
3734 TRACE( "%p %p %u %p %u %p\n", handle
, desc
, option
, value
, size
, error
);
3735 if (error
) FIXME( "ignoring error parameter\n" );
3737 if (!writer
|| !desc
|| !desc
->attributeLocalName
|| !desc
->attributeNs
|| !value
)
3738 return E_INVALIDARG
;
3740 EnterCriticalSection( &writer
->cs
);
3742 if (writer
->magic
!= WRITER_MAGIC
)
3744 LeaveCriticalSection( &writer
->cs
);
3745 return E_INVALIDARG
;
3748 if (writer
->state
!= WRITER_STATE_STARTELEMENT
)
3750 LeaveCriticalSection( &writer
->cs
);
3751 return WS_E_INVALID_OPERATION
;
3754 if ((hr
= write_add_attribute( writer
, NULL
, desc
->attributeLocalName
, desc
->attributeNs
, FALSE
)) != S_OK
)
3756 LeaveCriticalSection( &writer
->cs
);
3759 writer
->state
= WRITER_STATE_STARTATTRIBUTE
;
3761 hr
= write_type( writer
, WS_ATTRIBUTE_TYPE_MAPPING
, desc
->type
, desc
->typeDescription
, option
, value
, size
);
3763 LeaveCriticalSection( &writer
->cs
);
3767 /**************************************************************************
3768 * WsWriteElement [webservices.@]
3770 HRESULT WINAPI
WsWriteElement( WS_XML_WRITER
*handle
, const WS_ELEMENT_DESCRIPTION
*desc
,
3771 WS_WRITE_OPTION option
, const void *value
, ULONG size
,
3774 struct writer
*writer
= (struct writer
*)handle
;
3777 TRACE( "%p %p %u %p %u %p\n", handle
, desc
, option
, value
, size
, error
);
3778 if (error
) FIXME( "ignoring error parameter\n" );
3780 if (!writer
|| !desc
|| !desc
->elementLocalName
|| !desc
->elementNs
|| !value
)
3781 return E_INVALIDARG
;
3783 EnterCriticalSection( &writer
->cs
);
3785 if (writer
->magic
!= WRITER_MAGIC
)
3787 LeaveCriticalSection( &writer
->cs
);
3788 return E_INVALIDARG
;
3791 if ((hr
= write_element_node( writer
, NULL
, desc
->elementLocalName
, desc
->elementNs
)) != S_OK
) goto done
;
3793 if ((hr
= write_type( writer
, WS_ANY_ELEMENT_TYPE_MAPPING
, desc
->type
, desc
->typeDescription
,
3794 option
, value
, size
)) != S_OK
) goto done
;
3796 hr
= write_endelement_node( writer
);
3799 LeaveCriticalSection( &writer
->cs
);
3803 /**************************************************************************
3804 * WsWriteType [webservices.@]
3806 HRESULT WINAPI
WsWriteType( WS_XML_WRITER
*handle
, WS_TYPE_MAPPING mapping
, WS_TYPE type
,
3807 const void *desc
, WS_WRITE_OPTION option
, const void *value
,
3808 ULONG size
, WS_ERROR
*error
)
3810 struct writer
*writer
= (struct writer
*)handle
;
3813 TRACE( "%p %u %u %p %u %p %u %p\n", handle
, mapping
, type
, desc
, option
, value
,
3815 if (error
) FIXME( "ignoring error parameter\n" );
3817 if (!writer
|| !value
) return E_INVALIDARG
;
3819 EnterCriticalSection( &writer
->cs
);
3821 if (writer
->magic
!= WRITER_MAGIC
)
3823 LeaveCriticalSection( &writer
->cs
);
3824 return E_INVALIDARG
;
3829 case WS_ATTRIBUTE_TYPE_MAPPING
:
3830 if (writer
->state
!= WRITER_STATE_STARTATTRIBUTE
) hr
= WS_E_INVALID_FORMAT
;
3831 else hr
= write_type( writer
, mapping
, type
, desc
, option
, value
, size
);
3834 case WS_ELEMENT_TYPE_MAPPING
:
3835 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
3836 if (writer
->state
!= WRITER_STATE_STARTELEMENT
) hr
= WS_E_INVALID_FORMAT
;
3837 else hr
= write_type( writer
, mapping
, type
, desc
, option
, value
, size
);
3840 case WS_ANY_ELEMENT_TYPE_MAPPING
:
3841 hr
= write_type( writer
, mapping
, type
, desc
, option
, value
, size
);
3845 FIXME( "mapping %u not implemented\n", mapping
);
3849 LeaveCriticalSection( &writer
->cs
);
3853 WS_TYPE
map_value_type( WS_VALUE_TYPE type
)
3857 case WS_BOOL_VALUE_TYPE
: return WS_BOOL_TYPE
;
3858 case WS_INT8_VALUE_TYPE
: return WS_INT8_TYPE
;
3859 case WS_INT16_VALUE_TYPE
: return WS_INT16_TYPE
;
3860 case WS_INT32_VALUE_TYPE
: return WS_INT32_TYPE
;
3861 case WS_INT64_VALUE_TYPE
: return WS_INT64_TYPE
;
3862 case WS_UINT8_VALUE_TYPE
: return WS_UINT8_TYPE
;
3863 case WS_UINT16_VALUE_TYPE
: return WS_UINT16_TYPE
;
3864 case WS_UINT32_VALUE_TYPE
: return WS_UINT32_TYPE
;
3865 case WS_UINT64_VALUE_TYPE
: return WS_UINT64_TYPE
;
3866 case WS_FLOAT_VALUE_TYPE
: return WS_FLOAT_TYPE
;
3867 case WS_DOUBLE_VALUE_TYPE
: return WS_DOUBLE_TYPE
;
3868 case WS_DECIMAL_VALUE_TYPE
: return WS_DECIMAL_TYPE
;
3869 case WS_DATETIME_VALUE_TYPE
: return WS_DATETIME_TYPE
;
3870 case WS_TIMESPAN_VALUE_TYPE
: return WS_TIMESPAN_TYPE
;
3871 case WS_GUID_VALUE_TYPE
: return WS_GUID_TYPE
;
3873 FIXME( "unhandled type %u\n", type
);
3878 /**************************************************************************
3879 * WsWriteValue [webservices.@]
3881 HRESULT WINAPI
WsWriteValue( WS_XML_WRITER
*handle
, WS_VALUE_TYPE value_type
, const void *value
,
3882 ULONG size
, WS_ERROR
*error
)
3884 struct writer
*writer
= (struct writer
*)handle
;
3885 WS_TYPE_MAPPING mapping
;
3889 TRACE( "%p %u %p %u %p\n", handle
, value_type
, value
, size
, error
);
3890 if (error
) FIXME( "ignoring error parameter\n" );
3892 if (!writer
|| !value
|| (type
= map_value_type( value_type
)) == ~0u) return E_INVALIDARG
;
3894 EnterCriticalSection( &writer
->cs
);
3896 if (writer
->magic
!= WRITER_MAGIC
)
3898 LeaveCriticalSection( &writer
->cs
);
3899 return E_INVALIDARG
;
3902 switch (writer
->state
)
3904 case WRITER_STATE_STARTATTRIBUTE
:
3905 mapping
= WS_ATTRIBUTE_TYPE_MAPPING
;
3908 case WRITER_STATE_STARTELEMENT
:
3909 mapping
= WS_ELEMENT_TYPE_MAPPING
;
3913 hr
= WS_E_INVALID_FORMAT
;
3916 if (hr
== S_OK
) hr
= write_type( writer
, mapping
, type
, NULL
, WS_WRITE_REQUIRED_VALUE
, value
, size
);
3918 LeaveCriticalSection( &writer
->cs
);
3922 /**************************************************************************
3923 * WsWriteArray [webservices.@]
3925 HRESULT WINAPI
WsWriteArray( WS_XML_WRITER
*handle
, const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3926 WS_VALUE_TYPE value_type
, const void *array
, ULONG size
, ULONG offset
,
3927 ULONG count
, WS_ERROR
*error
)
3929 struct writer
*writer
= (struct writer
*)handle
;
3934 TRACE( "%p %s %s %u %p %u %u %u %p\n", handle
, debugstr_xmlstr(localname
), debugstr_xmlstr(ns
),
3935 value_type
, array
, size
, offset
, count
, error
);
3936 if (error
) FIXME( "ignoring error parameter\n" );
3938 if (!writer
) return E_INVALIDARG
;
3940 EnterCriticalSection( &writer
->cs
);
3942 if (writer
->magic
!= WRITER_MAGIC
)
3944 LeaveCriticalSection( &writer
->cs
);
3945 return E_INVALIDARG
;
3948 if (!writer
->output_type
)
3950 LeaveCriticalSection( &writer
->cs
);
3951 return WS_E_INVALID_OPERATION
;
3954 if (!localname
|| !ns
|| (type
= map_value_type( value_type
)) == ~0u)
3956 LeaveCriticalSection( &writer
->cs
);
3957 return E_INVALIDARG
;
3960 type_size
= get_type_size( type
, NULL
);
3961 if (size
% type_size
|| (offset
+ count
) * type_size
> size
|| (count
&& !array
))
3963 LeaveCriticalSection( &writer
->cs
);
3964 return E_INVALIDARG
;
3967 for (i
= offset
; i
< count
; i
++)
3969 const char *ptr
= (const char *)array
+ (offset
+ i
) * type_size
;
3970 if ((hr
= write_element_node( writer
, NULL
, localname
, ns
)) != S_OK
) goto done
;
3971 if ((hr
= write_type( writer
, WS_ELEMENT_TYPE_MAPPING
, type
, NULL
, WS_WRITE_REQUIRED_POINTER
,
3972 &ptr
, sizeof(ptr
) )) != S_OK
) goto done
;
3973 if ((hr
= write_endelement_node( writer
)) != S_OK
) goto done
;
3977 LeaveCriticalSection( &writer
->cs
);
3981 /**************************************************************************
3982 * WsWriteXmlBuffer [webservices.@]
3984 HRESULT WINAPI
WsWriteXmlBuffer( WS_XML_WRITER
*handle
, WS_XML_BUFFER
*buffer
, WS_ERROR
*error
)
3986 struct writer
*writer
= (struct writer
*)handle
;
3987 struct xmlbuf
*xmlbuf
= (struct xmlbuf
*)buffer
;
3990 TRACE( "%p %p %p\n", handle
, buffer
, error
);
3991 if (error
) FIXME( "ignoring error parameter\n" );
3993 if (!writer
|| !xmlbuf
) return E_INVALIDARG
;
3995 EnterCriticalSection( &writer
->cs
);
3997 if (writer
->magic
!= WRITER_MAGIC
)
3999 LeaveCriticalSection( &writer
->cs
);
4000 return E_INVALIDARG
;
4003 if (xmlbuf
->encoding
!= writer
->output_enc
|| xmlbuf
->charset
!= writer
->output_charset
)
4005 FIXME( "no support for different encoding and/or charset\n" );
4010 if ((hr
= write_flush( writer
)) != S_OK
) goto done
;
4011 if ((hr
= write_grow_buffer( writer
, xmlbuf
->bytes
.length
)) != S_OK
) goto done
;
4012 write_bytes( writer
, xmlbuf
->bytes
.bytes
, xmlbuf
->bytes
.length
);
4015 LeaveCriticalSection( &writer
->cs
);
4019 /**************************************************************************
4020 * WsWriteXmlBufferToBytes [webservices.@]
4022 HRESULT WINAPI
WsWriteXmlBufferToBytes( WS_XML_WRITER
*handle
, WS_XML_BUFFER
*buffer
,
4023 const WS_XML_WRITER_ENCODING
*encoding
,
4024 const WS_XML_WRITER_PROPERTY
*properties
, ULONG count
,
4025 WS_HEAP
*heap
, void **bytes
, ULONG
*size
, WS_ERROR
*error
)
4027 struct writer
*writer
= (struct writer
*)handle
;
4028 struct xmlbuf
*xmlbuf
= (struct xmlbuf
*)buffer
;
4033 TRACE( "%p %p %p %p %u %p %p %p %p\n", handle
, buffer
, encoding
, properties
, count
, heap
,
4034 bytes
, size
, error
);
4035 if (error
) FIXME( "ignoring error parameter\n" );
4037 if (!writer
|| !xmlbuf
|| !heap
|| !bytes
) return E_INVALIDARG
;
4039 if (encoding
&& encoding
->encodingType
!= WS_XML_WRITER_ENCODING_TYPE_TEXT
)
4041 FIXME( "encoding type %u not supported\n", encoding
->encodingType
);
4045 EnterCriticalSection( &writer
->cs
);
4047 if (writer
->magic
!= WRITER_MAGIC
)
4049 LeaveCriticalSection( &writer
->cs
);
4050 return E_INVALIDARG
;
4053 for (i
= 0; i
< count
; i
++)
4055 hr
= prop_set( writer
->prop
, writer
->prop_count
, properties
[i
].id
, properties
[i
].value
,
4056 properties
[i
].valueSize
);
4057 if (hr
!= S_OK
) goto done
;
4060 if (!(buf
= ws_alloc( heap
, xmlbuf
->bytes
.length
))) hr
= WS_E_QUOTA_EXCEEDED
;
4063 memcpy( buf
, xmlbuf
->bytes
.bytes
, xmlbuf
->bytes
.length
);
4065 *size
= xmlbuf
->bytes
.length
;
4069 LeaveCriticalSection( &writer
->cs
);
4073 /**************************************************************************
4074 * WsWriteXmlnsAttribute [webservices.@]
4076 HRESULT WINAPI
WsWriteXmlnsAttribute( WS_XML_WRITER
*handle
, const WS_XML_STRING
*prefix
,
4077 const WS_XML_STRING
*ns
, BOOL single
, WS_ERROR
*error
)
4079 struct writer
*writer
= (struct writer
*)handle
;
4082 TRACE( "%p %s %s %d %p\n", handle
, debugstr_xmlstr(prefix
), debugstr_xmlstr(ns
),
4084 if (error
) FIXME( "ignoring error parameter\n" );
4086 if (!writer
|| !ns
) return E_INVALIDARG
;
4088 EnterCriticalSection( &writer
->cs
);
4090 if (writer
->magic
!= WRITER_MAGIC
)
4092 LeaveCriticalSection( &writer
->cs
);
4093 return E_INVALIDARG
;
4096 if (writer
->state
!= WRITER_STATE_STARTELEMENT
)
4098 LeaveCriticalSection( &writer
->cs
);
4099 return WS_E_INVALID_OPERATION
;
4102 if (!namespace_in_scope( &writer
->current
->hdr
, prefix
, ns
))
4103 hr
= add_namespace_attribute( writer
, prefix
, ns
, single
);
4105 LeaveCriticalSection( &writer
->cs
);
4109 static HRESULT
write_qualified_name( struct writer
*writer
, const WS_XML_STRING
*prefix
,
4110 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
)
4112 WS_XML_QNAME_TEXT qname
= {{WS_XML_TEXT_TYPE_QNAME
}};
4115 if ((hr
= write_flush( writer
)) != S_OK
) return hr
;
4116 if (!prefix
&& ((hr
= find_prefix( writer
, ns
, &prefix
)) != S_OK
)) return hr
;
4118 qname
.prefix
= (WS_XML_STRING
*)prefix
;
4119 qname
.localName
= (WS_XML_STRING
*)localname
;
4120 qname
.ns
= (WS_XML_STRING
*)ns
;
4122 if ((hr
= write_add_text_node( writer
, &qname
.text
)) != S_OK
) return hr
;
4123 return write_text( writer
, ((const WS_XML_TEXT_NODE
*)writer
->current
)->text
, 0 );
4126 /**************************************************************************
4127 * WsWriteQualifiedName [webservices.@]
4129 HRESULT WINAPI
WsWriteQualifiedName( WS_XML_WRITER
*handle
, const WS_XML_STRING
*prefix
,
4130 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4133 struct writer
*writer
= (struct writer
*)handle
;
4136 TRACE( "%p %s %s %s %p\n", handle
, debugstr_xmlstr(prefix
), debugstr_xmlstr(localname
),
4137 debugstr_xmlstr(ns
), error
);
4138 if (error
) FIXME( "ignoring error parameter\n" );
4140 if (!writer
) return E_INVALIDARG
;
4142 EnterCriticalSection( &writer
->cs
);
4144 if (writer
->magic
!= WRITER_MAGIC
)
4146 LeaveCriticalSection( &writer
->cs
);
4147 return E_INVALIDARG
;
4150 if (!writer
->output_type
)
4152 LeaveCriticalSection( &writer
->cs
);
4153 return WS_E_INVALID_OPERATION
;
4156 if (writer
->state
!= WRITER_STATE_STARTELEMENT
)
4158 LeaveCriticalSection( &writer
->cs
);
4159 return WS_E_INVALID_FORMAT
;
4162 if (!localname
|| (!prefix
&& !ns
))
4164 LeaveCriticalSection( &writer
->cs
);
4165 return E_INVALIDARG
;
4168 hr
= write_qualified_name( writer
, prefix
, localname
, ns
);
4170 LeaveCriticalSection( &writer
->cs
);
4174 static HRESULT
write_move_to( struct writer
*writer
, WS_MOVE_TO move
, BOOL
*found
)
4176 BOOL success
= FALSE
;
4177 struct node
*node
= writer
->current
;
4181 case WS_MOVE_TO_ROOT_ELEMENT
:
4182 success
= move_to_root_element( writer
->root
, &node
);
4185 case WS_MOVE_TO_NEXT_ELEMENT
:
4186 success
= move_to_next_element( &node
);
4189 case WS_MOVE_TO_PREVIOUS_ELEMENT
:
4190 success
= move_to_prev_element( &node
);
4193 case WS_MOVE_TO_CHILD_ELEMENT
:
4194 success
= move_to_child_element( &node
);
4197 case WS_MOVE_TO_END_ELEMENT
:
4198 success
= move_to_end_element( &node
);
4201 case WS_MOVE_TO_PARENT_ELEMENT
:
4202 success
= move_to_parent_element( &node
);
4205 case WS_MOVE_TO_FIRST_NODE
:
4206 success
= move_to_first_node( &node
);
4209 case WS_MOVE_TO_NEXT_NODE
:
4210 success
= move_to_next_node( &node
);
4213 case WS_MOVE_TO_PREVIOUS_NODE
:
4214 success
= move_to_prev_node( &node
);
4217 case WS_MOVE_TO_CHILD_NODE
:
4218 success
= move_to_child_node( &node
);
4221 case WS_MOVE_TO_BOF
:
4222 success
= move_to_bof( writer
->root
, &node
);
4225 case WS_MOVE_TO_EOF
:
4226 success
= move_to_eof( writer
->root
, &node
);
4230 FIXME( "unhandled move %u\n", move
);
4234 if (success
&& node
== writer
->root
) return E_INVALIDARG
;
4235 writer
->current
= node
;
4242 return success
? S_OK
: WS_E_INVALID_FORMAT
;
4245 /**************************************************************************
4246 * WsMoveWriter [webservices.@]
4248 HRESULT WINAPI
WsMoveWriter( WS_XML_WRITER
*handle
, WS_MOVE_TO move
, BOOL
*found
, WS_ERROR
*error
)
4250 struct writer
*writer
= (struct writer
*)handle
;
4253 TRACE( "%p %u %p %p\n", handle
, move
, found
, error
);
4254 if (error
) FIXME( "ignoring error parameter\n" );
4256 if (!writer
) return E_INVALIDARG
;
4258 EnterCriticalSection( &writer
->cs
);
4260 if (writer
->magic
!= WRITER_MAGIC
)
4262 LeaveCriticalSection( &writer
->cs
);
4263 return E_INVALIDARG
;
4266 if (!writer
->output_type
)
4268 LeaveCriticalSection( &writer
->cs
);
4269 return WS_E_INVALID_OPERATION
;
4272 hr
= write_move_to( writer
, move
, found
);
4274 LeaveCriticalSection( &writer
->cs
);
4278 /**************************************************************************
4279 * WsGetWriterPosition [webservices.@]
4281 HRESULT WINAPI
WsGetWriterPosition( WS_XML_WRITER
*handle
, WS_XML_NODE_POSITION
*pos
, WS_ERROR
*error
)
4283 struct writer
*writer
= (struct writer
*)handle
;
4285 TRACE( "%p %p %p\n", handle
, pos
, error
);
4286 if (error
) FIXME( "ignoring error parameter\n" );
4288 if (!writer
|| !pos
) return E_INVALIDARG
;
4290 EnterCriticalSection( &writer
->cs
);
4292 if (writer
->magic
!= WRITER_MAGIC
)
4294 LeaveCriticalSection( &writer
->cs
);
4295 return E_INVALIDARG
;
4298 if (!writer
->output_type
)
4300 LeaveCriticalSection( &writer
->cs
);
4301 return WS_E_INVALID_OPERATION
;
4304 pos
->buffer
= (WS_XML_BUFFER
*)writer
->output_buf
;
4305 pos
->node
= writer
->current
;
4307 LeaveCriticalSection( &writer
->cs
);
4311 /**************************************************************************
4312 * WsSetWriterPosition [webservices.@]
4314 HRESULT WINAPI
WsSetWriterPosition( WS_XML_WRITER
*handle
, const WS_XML_NODE_POSITION
*pos
, WS_ERROR
*error
)
4316 struct writer
*writer
= (struct writer
*)handle
;
4318 TRACE( "%p %p %p\n", handle
, pos
, error
);
4319 if (error
) FIXME( "ignoring error parameter\n" );
4321 if (!writer
|| !pos
) return E_INVALIDARG
;
4323 EnterCriticalSection( &writer
->cs
);
4325 if (writer
->magic
!= WRITER_MAGIC
|| (struct xmlbuf
*)pos
->buffer
!= writer
->output_buf
)
4327 LeaveCriticalSection( &writer
->cs
);
4328 return E_INVALIDARG
;
4331 if (!writer
->output_type
)
4333 LeaveCriticalSection( &writer
->cs
);
4334 return WS_E_INVALID_OPERATION
;
4337 writer
->current
= pos
->node
;
4339 LeaveCriticalSection( &writer
->cs
);
4343 static HRESULT
write_add_comment_node( struct writer
*writer
, const WS_XML_STRING
*value
)
4345 struct node
*node
, *parent
;
4346 WS_XML_COMMENT_NODE
*comment
;
4348 if (!(parent
= find_parent( writer
))) return WS_E_INVALID_FORMAT
;
4349 if (!(node
= alloc_node( WS_XML_NODE_TYPE_COMMENT
))) return E_OUTOFMEMORY
;
4350 comment
= (WS_XML_COMMENT_NODE
*)node
;
4352 if (value
->length
&& !(comment
->value
.bytes
= heap_alloc( value
->length
)))
4355 return E_OUTOFMEMORY
;
4357 memcpy( comment
->value
.bytes
, value
->bytes
, value
->length
);
4358 comment
->value
.length
= value
->length
;
4360 write_insert_node( writer
, parent
, node
);
4364 static HRESULT
write_comment_text( struct writer
*writer
)
4366 const WS_XML_COMMENT_NODE
*comment
= (const WS_XML_COMMENT_NODE
*)writer
->current
;
4369 if ((hr
= write_grow_buffer( writer
, comment
->value
.length
+ 7 )) != S_OK
) return hr
;
4370 write_bytes( writer
, (const BYTE
*)"<!--", 4 );
4371 write_bytes( writer
, comment
->value
.bytes
, comment
->value
.length
);
4372 write_bytes( writer
, (const BYTE
*)"-->", 3 );
4376 static HRESULT
write_comment_bin( struct writer
*writer
)
4378 const WS_XML_COMMENT_NODE
*comment
= (const WS_XML_COMMENT_NODE
*)writer
->current
;
4381 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
4382 write_char( writer
, RECORD_COMMENT
);
4383 return write_string( writer
, comment
->value
.bytes
, comment
->value
.length
);
4386 static HRESULT
write_comment( struct writer
*writer
)
4388 switch (writer
->output_enc
)
4390 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_comment_text( writer
);
4391 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return write_comment_bin( writer
);
4393 ERR( "unhandled encoding %u\n", writer
->output_enc
);
4394 return WS_E_NOT_SUPPORTED
;
4398 static HRESULT
write_comment_node( struct writer
*writer
, const WS_XML_STRING
*value
)
4401 if ((hr
= write_flush( writer
)) != S_OK
) return hr
;
4402 if ((hr
= write_add_comment_node( writer
, value
)) != S_OK
) return hr
;
4403 if ((hr
= write_comment( writer
)) != S_OK
) return hr
;
4404 writer
->state
= WRITER_STATE_COMMENT
;
4408 static HRESULT
write_set_attributes( struct writer
*writer
, WS_XML_ATTRIBUTE
**attrs
, ULONG count
)
4413 for (i
= 0; i
< count
; i
++)
4415 if ((hr
= write_add_attribute( writer
, attrs
[i
]->prefix
, attrs
[i
]->localName
, attrs
[i
]->ns
,
4416 attrs
[i
]->singleQuote
)) != S_OK
) return hr
;
4417 if ((hr
= write_set_attribute_value( writer
, attrs
[i
]->value
)) != S_OK
) return hr
;
4422 static HRESULT
write_node( struct writer
*writer
, const WS_XML_NODE
*node
)
4426 switch (node
->nodeType
)
4428 case WS_XML_NODE_TYPE_ELEMENT
:
4430 const WS_XML_ELEMENT_NODE
*elem
= (const WS_XML_ELEMENT_NODE
*)node
;
4431 if ((hr
= write_element_node( writer
, elem
->prefix
, elem
->localName
, elem
->ns
)) != S_OK
) return hr
;
4432 return write_set_attributes( writer
, elem
->attributes
, elem
->attributeCount
);
4434 case WS_XML_NODE_TYPE_TEXT
:
4436 const WS_XML_TEXT_NODE
*text
= (const WS_XML_TEXT_NODE
*)node
;
4437 return write_text_node( writer
, text
->text
);
4439 case WS_XML_NODE_TYPE_END_ELEMENT
:
4440 return write_endelement_node( writer
);
4442 case WS_XML_NODE_TYPE_COMMENT
:
4444 const WS_XML_COMMENT_NODE
*comment
= (const WS_XML_COMMENT_NODE
*)node
;
4445 return write_comment_node( writer
, &comment
->value
);
4447 case WS_XML_NODE_TYPE_CDATA
:
4448 return write_cdata_node( writer
);
4450 case WS_XML_NODE_TYPE_END_CDATA
:
4451 return write_endcdata_node( writer
);
4453 case WS_XML_NODE_TYPE_EOF
:
4454 case WS_XML_NODE_TYPE_BOF
:
4458 WARN( "unknown node type %u\n", node
->nodeType
);
4459 return E_INVALIDARG
;
4463 /**************************************************************************
4464 * WsWriteNode [webservices.@]
4466 HRESULT WINAPI
WsWriteNode( WS_XML_WRITER
*handle
, const WS_XML_NODE
*node
, WS_ERROR
*error
)
4468 struct writer
*writer
= (struct writer
*)handle
;
4471 TRACE( "%p %p %p\n", handle
, node
, error
);
4472 if (error
) FIXME( "ignoring error parameter\n" );
4474 if (!writer
|| !node
) return E_INVALIDARG
;
4476 EnterCriticalSection( &writer
->cs
);
4478 if (writer
->magic
!= WRITER_MAGIC
)
4480 LeaveCriticalSection( &writer
->cs
);
4481 return E_INVALIDARG
;
4484 if (!writer
->output_type
)
4486 LeaveCriticalSection( &writer
->cs
);
4487 return WS_E_INVALID_OPERATION
;
4490 hr
= write_node( writer
, node
);
4492 LeaveCriticalSection( &writer
->cs
);
4496 static HRESULT
write_tree_node( struct writer
*writer
)
4500 switch (node_type( writer
->current
))
4502 case WS_XML_NODE_TYPE_ELEMENT
:
4503 if (writer
->state
== WRITER_STATE_STARTELEMENT
&& (hr
= write_endstartelement( writer
)) != S_OK
)
4505 if ((hr
= write_startelement( writer
)) != S_OK
) return hr
;
4506 writer
->state
= WRITER_STATE_STARTELEMENT
;
4509 case WS_XML_NODE_TYPE_TEXT
:
4510 if (writer
->state
== WRITER_STATE_STARTELEMENT
&& (hr
= write_endstartelement( writer
)) != S_OK
)
4512 if ((hr
= write_text( writer
, ((const WS_XML_TEXT_NODE
*)writer
->current
)->text
, 0 )) != S_OK
) return hr
;
4513 writer
->state
= WRITER_STATE_TEXT
;
4516 case WS_XML_NODE_TYPE_END_ELEMENT
:
4517 if ((hr
= write_close_element( writer
, writer
->current
->parent
)) != S_OK
) return hr
;
4518 writer
->state
= WRITER_STATE_ENDELEMENT
;
4521 case WS_XML_NODE_TYPE_COMMENT
:
4522 if (writer
->state
== WRITER_STATE_STARTELEMENT
&& (hr
= write_endstartelement( writer
)) != S_OK
)
4524 if ((hr
= write_comment( writer
)) != S_OK
) return hr
;
4525 writer
->state
= WRITER_STATE_COMMENT
;
4528 case WS_XML_NODE_TYPE_CDATA
:
4529 if (writer
->state
== WRITER_STATE_STARTELEMENT
&& (hr
= write_endstartelement( writer
)) != S_OK
)
4531 if ((hr
= write_cdata( writer
)) != S_OK
) return hr
;
4532 writer
->state
= WRITER_STATE_STARTCDATA
;
4535 case WS_XML_NODE_TYPE_END_CDATA
:
4536 if ((hr
= write_endcdata( writer
)) != S_OK
) return hr
;
4537 writer
->state
= WRITER_STATE_ENDCDATA
;
4540 case WS_XML_NODE_TYPE_EOF
:
4541 case WS_XML_NODE_TYPE_BOF
:
4545 ERR( "unknown node type %u\n", node_type(writer
->current
) );
4546 return E_INVALIDARG
;
4550 static HRESULT
write_tree( struct writer
*writer
)
4554 if ((hr
= write_tree_node( writer
)) != S_OK
) return hr
;
4557 if (node_type( writer
->current
) == WS_XML_NODE_TYPE_EOF
) break;
4558 if (move_to_child_node( &writer
->current
))
4560 if ((hr
= write_tree_node( writer
)) != S_OK
) return hr
;
4563 if (move_to_next_node( &writer
->current
))
4565 if ((hr
= write_tree_node( writer
)) != S_OK
) return hr
;
4568 if (!move_to_parent_node( &writer
->current
) || !move_to_next_node( &writer
->current
))
4570 ERR( "invalid tree\n" );
4571 return WS_E_INVALID_FORMAT
;
4573 if ((hr
= write_tree_node( writer
)) != S_OK
) return hr
;
4578 static void write_rewind( struct writer
*writer
)
4580 writer
->write_pos
= 0;
4581 writer
->current
= writer
->root
;
4582 writer
->state
= WRITER_STATE_INITIAL
;
4585 /**************************************************************************
4586 * WsCopyNode [webservices.@]
4588 HRESULT WINAPI
WsCopyNode( WS_XML_WRITER
*handle
, WS_XML_READER
*reader
, WS_ERROR
*error
)
4590 struct writer
*writer
= (struct writer
*)handle
;
4591 struct node
*parent
, *current
, *node
= NULL
;
4594 TRACE( "%p %p %p\n", handle
, reader
, error
);
4595 if (error
) FIXME( "ignoring error parameter\n" );
4597 if (!writer
) return E_INVALIDARG
;
4599 EnterCriticalSection( &writer
->cs
);
4601 if (writer
->magic
!= WRITER_MAGIC
)
4603 LeaveCriticalSection( &writer
->cs
);
4604 return E_INVALIDARG
;
4607 if (!(parent
= find_parent( writer
)))
4609 LeaveCriticalSection( &writer
->cs
);
4610 return WS_E_INVALID_FORMAT
;
4613 if ((hr
= copy_node( reader
, &node
)) != S_OK
) goto done
;
4614 current
= writer
->current
;
4615 write_insert_node( writer
, parent
, node
);
4617 write_rewind( writer
);
4618 if ((hr
= write_tree( writer
)) != S_OK
) goto done
;
4619 writer
->current
= current
;
4621 WsMoveReader( reader
, WS_MOVE_TO_NEXT_NODE
, NULL
, NULL
);
4624 LeaveCriticalSection( &writer
->cs
);
4628 static HRESULT
write_param( struct writer
*writer
, const WS_FIELD_DESCRIPTION
*desc
, const void *value
)
4630 return write_type_field( writer
, desc
, value
, 0 );
4633 static ULONG
get_array_len( const WS_PARAMETER_DESCRIPTION
*params
, ULONG count
, ULONG index
, const void **args
)
4636 for (i
= 0; i
< count
; i
++)
4638 if (params
[i
].inputMessageIndex
!= index
|| params
[i
].parameterType
!= WS_PARAMETER_TYPE_ARRAY_COUNT
)
4640 if (args
[i
]) ret
= *(const ULONG
*)args
[i
];
4646 static HRESULT
write_param_array( struct writer
*writer
, const WS_FIELD_DESCRIPTION
*desc
, const void *value
,
4649 return write_type_repeating_element( writer
, desc
, value
, len
);
4652 HRESULT
write_input_params( WS_XML_WRITER
*handle
, const WS_ELEMENT_DESCRIPTION
*desc
,
4653 const WS_PARAMETER_DESCRIPTION
*params
, ULONG count
, const void **args
)
4655 struct writer
*writer
= (struct writer
*)handle
;
4656 const WS_STRUCT_DESCRIPTION
*desc_struct
;
4657 const WS_FIELD_DESCRIPTION
*desc_field
;
4661 if (desc
->type
!= WS_STRUCT_TYPE
|| !(desc_struct
= desc
->typeDescription
)) return E_INVALIDARG
;
4663 EnterCriticalSection( &writer
->cs
);
4665 if (writer
->magic
!= WRITER_MAGIC
)
4667 LeaveCriticalSection( &writer
->cs
);
4668 return E_INVALIDARG
;
4671 if ((hr
= write_element_node( writer
, NULL
, desc
->elementLocalName
, desc
->elementNs
)) != S_OK
) goto done
;
4673 for (i
= 0; i
< count
; i
++)
4675 if (params
[i
].inputMessageIndex
== INVALID_PARAMETER_INDEX
) continue;
4676 if (params
[i
].parameterType
== WS_PARAMETER_TYPE_MESSAGES
)
4678 FIXME( "messages type not supported\n" );
4682 if ((hr
= get_param_desc( desc_struct
, params
[i
].inputMessageIndex
, &desc_field
)) != S_OK
) goto done
;
4683 if (params
[i
].parameterType
== WS_PARAMETER_TYPE_NORMAL
)
4685 if ((hr
= write_param( writer
, desc_field
, args
[i
] )) != S_OK
) goto done
;
4687 else if (params
[i
].parameterType
== WS_PARAMETER_TYPE_ARRAY
)
4689 const void *ptr
= *(const void **)args
[i
];
4690 ULONG len
= get_array_len( params
, count
, params
[i
].inputMessageIndex
, args
);
4691 if ((hr
= write_param_array( writer
, desc_field
, ptr
, len
)) != S_OK
) goto done
;
4695 hr
= write_endelement_node( writer
);
4698 LeaveCriticalSection( &writer
->cs
);