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
;
725 case WS_XML_TEXT_TYPE_DATETIME
:
726 return RECORD_DATETIME_TEXT
;
729 FIXME( "unhandled text type %u\n", text
->textType
);
734 static INT64
get_text_value_int( const WS_XML_TEXT
*text
)
736 switch (text
->textType
)
738 case WS_XML_TEXT_TYPE_INT32
:
740 const WS_XML_INT32_TEXT
*text_int32
= (const WS_XML_INT32_TEXT
*)text
;
741 return text_int32
->value
;
743 case WS_XML_TEXT_TYPE_INT64
:
745 const WS_XML_INT64_TEXT
*text_int64
= (const WS_XML_INT64_TEXT
*)text
;
746 return text_int64
->value
;
748 case WS_XML_TEXT_TYPE_UINT64
:
750 const WS_XML_UINT64_TEXT
*text_uint64
= (const WS_XML_UINT64_TEXT
*)text
;
751 return text_uint64
->value
;
753 case WS_XML_TEXT_TYPE_DOUBLE
:
755 const WS_XML_DOUBLE_TEXT
*text_double
= (const WS_XML_DOUBLE_TEXT
*)text
;
756 return text_double
->value
;
759 ERR( "unhandled text type %u\n", text
->textType
);
765 static HRESULT
write_attribute_value_bin( struct writer
*writer
, const WS_XML_TEXT
*text
)
767 enum record_type type
= get_attr_text_record_type( text
);
770 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
771 write_char( writer
, type
);
775 case RECORD_CHARS8_TEXT
:
777 WS_XML_UTF8_TEXT
*text_utf8
= (WS_XML_UTF8_TEXT
*)text
;
780 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
781 write_char( writer
, 0 );
784 if ((hr
= write_grow_buffer( writer
, 1 + text_utf8
->value
.length
)) != S_OK
) return hr
;
785 write_char( writer
, text_utf8
->value
.length
);
786 write_bytes( writer
, text_utf8
->value
.bytes
, text_utf8
->value
.length
);
789 case RECORD_CHARS16_TEXT
:
791 WS_XML_UTF8_TEXT
*text_utf8
= (WS_XML_UTF8_TEXT
*)text
;
792 UINT16 len
= text_utf8
->value
.length
;
793 if ((hr
= write_grow_buffer( writer
, sizeof(len
) + len
)) != S_OK
) return hr
;
794 write_bytes( writer
, (const BYTE
*)&len
, sizeof(len
) );
795 write_bytes( writer
, text_utf8
->value
.bytes
, len
);
798 case RECORD_BYTES8_TEXT
:
800 WS_XML_BASE64_TEXT
*text_base64
= (WS_XML_BASE64_TEXT
*)text
;
801 if ((hr
= write_grow_buffer( writer
, 1 + text_base64
->length
)) != S_OK
) return hr
;
802 write_char( writer
, text_base64
->length
);
803 write_bytes( writer
, text_base64
->bytes
, text_base64
->length
);
806 case RECORD_BYTES16_TEXT
:
808 WS_XML_BASE64_TEXT
*text_base64
= (WS_XML_BASE64_TEXT
*)text
;
809 UINT16 len
= text_base64
->length
;
810 if ((hr
= write_grow_buffer( writer
, sizeof(len
) + len
)) != S_OK
) return hr
;
811 write_bytes( writer
, (const BYTE
*)&len
, sizeof(len
) );
812 write_bytes( writer
, text_base64
->bytes
, len
);
815 case RECORD_ZERO_TEXT
:
816 case RECORD_ONE_TEXT
:
817 case RECORD_FALSE_TEXT
:
818 case RECORD_TRUE_TEXT
:
821 case RECORD_INT8_TEXT
:
823 INT8 val
= get_text_value_int( text
);
824 if ((hr
= write_grow_buffer( writer
, sizeof(val
) )) != S_OK
) return hr
;
825 write_char( writer
, val
);
828 case RECORD_INT16_TEXT
:
830 INT16 val
= get_text_value_int( text
);
831 if ((hr
= write_grow_buffer( writer
, sizeof(val
) )) != S_OK
) return hr
;
832 write_bytes( writer
, (const BYTE
*)&val
, sizeof(val
) );
835 case RECORD_INT32_TEXT
:
837 INT32 val
= get_text_value_int( text
);
838 if ((hr
= write_grow_buffer( writer
, sizeof(val
) )) != S_OK
) return hr
;
839 write_bytes( writer
, (const BYTE
*)&val
, sizeof(val
) );
842 case RECORD_INT64_TEXT
:
844 INT64 val
= get_text_value_int( text
);
845 if ((hr
= write_grow_buffer( writer
, sizeof(val
) )) != S_OK
) return hr
;
846 write_bytes( writer
, (const BYTE
*)&val
, sizeof(val
) );
849 case RECORD_UINT64_TEXT
:
851 WS_XML_UINT64_TEXT
*text_uint64
= (WS_XML_UINT64_TEXT
*)text
;
852 if ((hr
= write_grow_buffer( writer
, sizeof(text_uint64
->value
) )) != S_OK
) return hr
;
853 write_bytes( writer
, (const BYTE
*)&text_uint64
->value
, sizeof(text_uint64
->value
) );
856 case RECORD_DOUBLE_TEXT
:
858 WS_XML_DOUBLE_TEXT
*text_double
= (WS_XML_DOUBLE_TEXT
*)text
;
859 if ((hr
= write_grow_buffer( writer
, sizeof(text_double
->value
) )) != S_OK
) return hr
;
860 write_bytes( writer
, (const BYTE
*)&text_double
->value
, sizeof(text_double
->value
) );
863 case RECORD_GUID_TEXT
:
865 WS_XML_GUID_TEXT
*text_guid
= (WS_XML_GUID_TEXT
*)text
;
866 if ((hr
= write_grow_buffer( writer
, sizeof(text_guid
->value
) )) != S_OK
) return hr
;
867 write_bytes( writer
, (const BYTE
*)&text_guid
->value
, sizeof(text_guid
->value
) );
870 case RECORD_UNIQUE_ID_TEXT
:
872 WS_XML_UNIQUE_ID_TEXT
*text_unique_id
= (WS_XML_UNIQUE_ID_TEXT
*)text
;
873 if ((hr
= write_grow_buffer( writer
, sizeof(text_unique_id
->value
) )) != S_OK
) return hr
;
874 write_bytes( writer
, (const BYTE
*)&text_unique_id
->value
, sizeof(text_unique_id
->value
) );
877 case RECORD_DATETIME_TEXT
:
879 WS_XML_DATETIME_TEXT
*text_datetime
= (WS_XML_DATETIME_TEXT
*)text
;
880 UINT64 val
= text_datetime
->value
.ticks
;
882 assert( val
<= TICKS_MAX
);
883 if (text_datetime
->value
.format
== WS_DATETIME_FORMAT_UTC
) val
|= (UINT64
)1 << 62;
884 else if (text_datetime
->value
.format
== WS_DATETIME_FORMAT_LOCAL
) val
|= (UINT64
)1 << 63;
886 if ((hr
= write_grow_buffer( writer
, sizeof(val
) )) != S_OK
) return hr
;
887 write_bytes( writer
, (const BYTE
*)&val
, sizeof(val
) );
891 FIXME( "unhandled record type %02x\n", type
);
896 static BOOL
lookup_string_id( struct writer
*writer
, const WS_XML_STRING
*str
, ULONG
*id
)
898 if (writer
->dict
&& str
->dictionary
== writer
->dict
)
906 writer
->dict_cb( writer
->dict_cb_state
, str
, &found
, id
, NULL
);
907 if (found
) *id
= (*id
<< 1) | 1;
913 static enum record_type
get_attr_record_type( const WS_XML_ATTRIBUTE
*attr
, BOOL use_dict
)
915 if (!attr
->prefix
|| !attr
->prefix
->length
)
917 if (use_dict
) return RECORD_SHORT_DICTIONARY_ATTRIBUTE
;
918 return RECORD_SHORT_ATTRIBUTE
;
920 if (attr
->prefix
->length
== 1 && attr
->prefix
->bytes
[0] >= 'a' && attr
->prefix
->bytes
[0] <= 'z')
922 if (use_dict
) return RECORD_PREFIX_DICTIONARY_ATTRIBUTE_A
+ attr
->prefix
->bytes
[0] - 'a';
923 return RECORD_PREFIX_ATTRIBUTE_A
+ attr
->prefix
->bytes
[0] - 'a';
925 if (use_dict
) return RECORD_DICTIONARY_ATTRIBUTE
;
926 return RECORD_ATTRIBUTE
;
929 static HRESULT
write_attribute_bin( struct writer
*writer
, const WS_XML_ATTRIBUTE
*attr
)
932 enum record_type type
= get_attr_record_type( attr
, lookup_string_id(writer
, attr
->localName
, &id
) );
935 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
936 write_char( writer
, type
);
938 if (type
>= RECORD_PREFIX_ATTRIBUTE_A
&& type
<= RECORD_PREFIX_ATTRIBUTE_Z
)
940 if ((hr
= write_string( writer
, attr
->localName
->bytes
, attr
->localName
->length
)) != S_OK
) return hr
;
941 return write_attribute_value_bin( writer
, attr
->value
);
943 if (type
>= RECORD_PREFIX_DICTIONARY_ATTRIBUTE_A
&& type
<= RECORD_PREFIX_DICTIONARY_ATTRIBUTE_Z
)
945 if ((hr
= write_dict_string( writer
, id
)) != S_OK
) return hr
;
946 return write_attribute_value_bin( writer
, attr
->value
);
951 case RECORD_SHORT_ATTRIBUTE
:
952 if ((hr
= write_string( writer
, attr
->localName
->bytes
, attr
->localName
->length
)) != S_OK
) return hr
;
955 case RECORD_ATTRIBUTE
:
956 if ((hr
= write_string( writer
, attr
->prefix
->bytes
, attr
->prefix
->length
)) != S_OK
) return hr
;
957 if ((hr
= write_string( writer
, attr
->localName
->bytes
, attr
->localName
->length
)) != S_OK
) return hr
;
960 case RECORD_SHORT_DICTIONARY_ATTRIBUTE
:
961 if ((hr
= write_dict_string( writer
, id
)) != S_OK
) return hr
;
964 case RECORD_DICTIONARY_ATTRIBUTE
:
965 if ((hr
= write_string( writer
, attr
->prefix
->bytes
, attr
->prefix
->length
)) != S_OK
) return hr
;
966 if ((hr
= write_dict_string( writer
, id
)) != S_OK
) return hr
;
970 ERR( "unhandled record type %02x\n", type
);
971 return WS_E_NOT_SUPPORTED
;
974 return write_attribute_value_bin( writer
, attr
->value
);
977 static HRESULT
write_attribute( struct writer
*writer
, const WS_XML_ATTRIBUTE
*attr
)
979 switch (writer
->output_enc
)
981 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_attribute_text( writer
, attr
);
982 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return write_attribute_bin( writer
, attr
);
984 ERR( "unhandled encoding %u\n", writer
->output_enc
);
985 return WS_E_NOT_SUPPORTED
;
989 static inline BOOL
is_current_namespace( struct writer
*writer
, const WS_XML_STRING
*ns
)
991 return (WsXmlStringEquals( writer
->current_ns
, ns
, NULL
) == S_OK
);
994 /**************************************************************************
995 * WsGetPrefixFromNamespace [webservices.@]
997 HRESULT WINAPI
WsGetPrefixFromNamespace( WS_XML_WRITER
*handle
, const WS_XML_STRING
*ns
,
998 BOOL required
, const WS_XML_STRING
**prefix
,
1001 struct writer
*writer
= (struct writer
*)handle
;
1002 WS_XML_ELEMENT_NODE
*elem
;
1006 TRACE( "%p %s %d %p %p\n", handle
, debugstr_xmlstr(ns
), required
, prefix
, error
);
1007 if (error
) FIXME( "ignoring error parameter\n" );
1009 if (!writer
|| !ns
|| !prefix
) return E_INVALIDARG
;
1011 EnterCriticalSection( &writer
->cs
);
1013 if (writer
->magic
!= WRITER_MAGIC
)
1015 LeaveCriticalSection( &writer
->cs
);
1016 return E_INVALIDARG
;
1019 elem
= &writer
->current
->hdr
;
1020 if (elem
->prefix
&& is_current_namespace( writer
, ns
))
1022 *prefix
= elem
->prefix
;
1028 if (required
) hr
= WS_E_INVALID_FORMAT
;
1036 LeaveCriticalSection( &writer
->cs
);
1040 static HRESULT
write_namespace_attribute_text( struct writer
*writer
, const WS_XML_ATTRIBUTE
*attr
)
1042 unsigned char quote
= attr
->singleQuote
? '\'' : '"';
1046 /* ' xmlns:prefix="namespace"' */
1048 size
= attr
->ns
->length
+ 9 /* ' xmlns=""' */;
1049 if (attr
->prefix
) size
+= attr
->prefix
->length
+ 1 /* ':' */;
1050 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
1052 write_bytes( writer
, (const BYTE
*)" xmlns", 6 );
1055 write_char( writer
, ':' );
1056 write_bytes( writer
, attr
->prefix
->bytes
, attr
->prefix
->length
);
1058 write_char( writer
, '=' );
1059 write_char( writer
, quote
);
1060 write_bytes( writer
, attr
->ns
->bytes
, attr
->ns
->length
);
1061 write_char( writer
, quote
);
1066 static enum record_type
get_xmlns_record_type( const WS_XML_ATTRIBUTE
*attr
, BOOL use_dict
)
1068 if (!attr
->prefix
|| !attr
->prefix
->length
)
1070 if (use_dict
) return RECORD_SHORT_DICTIONARY_XMLNS_ATTRIBUTE
;
1071 return RECORD_SHORT_XMLNS_ATTRIBUTE
;
1073 if (use_dict
) return RECORD_DICTIONARY_XMLNS_ATTRIBUTE
;
1074 return RECORD_XMLNS_ATTRIBUTE
;
1077 static HRESULT
write_namespace_attribute_bin( struct writer
*writer
, const WS_XML_ATTRIBUTE
*attr
)
1080 enum record_type type
= get_xmlns_record_type( attr
, lookup_string_id(writer
, attr
->ns
, &id
) );
1083 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
1084 write_char( writer
, type
);
1088 case RECORD_SHORT_XMLNS_ATTRIBUTE
:
1091 case RECORD_XMLNS_ATTRIBUTE
:
1092 if ((hr
= write_string( writer
, attr
->prefix
->bytes
, attr
->prefix
->length
)) != S_OK
) return hr
;
1095 case RECORD_SHORT_DICTIONARY_XMLNS_ATTRIBUTE
:
1096 return write_dict_string( writer
, id
);
1098 case RECORD_DICTIONARY_XMLNS_ATTRIBUTE
:
1099 if ((hr
= write_string( writer
, attr
->prefix
->bytes
, attr
->prefix
->length
)) != S_OK
) return hr
;
1100 return write_dict_string( writer
, id
);
1103 ERR( "unhandled record type %02x\n", type
);
1104 return WS_E_NOT_SUPPORTED
;
1107 return write_string( writer
, attr
->ns
->bytes
, attr
->ns
->length
);
1110 static HRESULT
write_namespace_attribute( struct writer
*writer
, const WS_XML_ATTRIBUTE
*attr
)
1112 switch (writer
->output_enc
)
1114 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_namespace_attribute_text( writer
, attr
);
1115 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return write_namespace_attribute_bin( writer
, attr
);
1117 ERR( "unhandled encoding %u\n", writer
->output_enc
);
1118 return WS_E_NOT_SUPPORTED
;
1122 static HRESULT
add_namespace_attribute( struct writer
*writer
, const WS_XML_STRING
*prefix
,
1123 const WS_XML_STRING
*ns
, BOOL single
)
1125 WS_XML_ATTRIBUTE
*attr
;
1126 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
1129 if (!(attr
= heap_alloc_zero( sizeof(*attr
) ))) return E_OUTOFMEMORY
;
1131 attr
->singleQuote
= !!single
;
1133 if (prefix
&& !(attr
->prefix
= dup_xml_string( prefix
)))
1135 free_attribute( attr
);
1136 return E_OUTOFMEMORY
;
1138 if (!(attr
->ns
= dup_xml_string( ns
)))
1140 free_attribute( attr
);
1141 return E_OUTOFMEMORY
;
1143 if ((hr
= append_attribute( elem
, attr
)) != S_OK
)
1145 free_attribute( attr
);
1151 static inline BOOL
str_equal( const WS_XML_STRING
*str1
, const WS_XML_STRING
*str2
)
1153 if (!str1
&& !str2
) return TRUE
;
1154 return WsXmlStringEquals( str1
, str2
, NULL
) == S_OK
;
1157 static BOOL
namespace_in_scope( const WS_XML_ELEMENT_NODE
*elem
, const WS_XML_STRING
*prefix
,
1158 const WS_XML_STRING
*ns
)
1161 const struct node
*node
;
1163 for (node
= (const struct node
*)elem
; node
; node
= node
->parent
)
1165 if (node_type( node
) != WS_XML_NODE_TYPE_ELEMENT
) break;
1168 for (i
= 0; i
< elem
->attributeCount
; i
++)
1170 if (!elem
->attributes
[i
]->isXmlNs
) continue;
1171 if (str_equal( elem
->attributes
[i
]->prefix
, prefix
) &&
1172 str_equal( elem
->attributes
[i
]->ns
, ns
)) return TRUE
;
1178 static HRESULT
set_current_namespace( struct writer
*writer
, const WS_XML_STRING
*ns
)
1181 if (!(str
= dup_xml_string( ns
))) return E_OUTOFMEMORY
;
1182 free_xml_string( writer
->current_ns
);
1183 writer
->current_ns
= str
;
1187 static HRESULT
set_namespaces( struct writer
*writer
)
1189 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
1193 if (elem
->ns
->length
&& !namespace_in_scope( elem
, elem
->prefix
, elem
->ns
))
1195 if ((hr
= add_namespace_attribute( writer
, elem
->prefix
, elem
->ns
, FALSE
)) != S_OK
) return hr
;
1196 if ((hr
= set_current_namespace( writer
, elem
->ns
)) != S_OK
) return hr
;
1199 for (i
= 0; i
< elem
->attributeCount
; i
++)
1201 const WS_XML_ATTRIBUTE
*attr
= elem
->attributes
[i
];
1202 if (!attr
->ns
->length
|| namespace_in_scope( elem
, attr
->prefix
, attr
->ns
)) continue;
1203 if ((hr
= add_namespace_attribute( writer
, attr
->prefix
, attr
->ns
, FALSE
)) != S_OK
) return hr
;
1209 /**************************************************************************
1210 * WsWriteEndAttribute [webservices.@]
1212 HRESULT WINAPI
WsWriteEndAttribute( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
1214 struct writer
*writer
= (struct writer
*)handle
;
1216 TRACE( "%p %p\n", handle
, error
);
1217 if (error
) FIXME( "ignoring error parameter\n" );
1219 if (!writer
) return E_INVALIDARG
;
1221 EnterCriticalSection( &writer
->cs
);
1223 if (writer
->magic
!= WRITER_MAGIC
)
1225 LeaveCriticalSection( &writer
->cs
);
1226 return E_INVALIDARG
;
1229 writer
->state
= WRITER_STATE_STARTELEMENT
;
1231 LeaveCriticalSection( &writer
->cs
);
1235 static HRESULT
write_attributes( struct writer
*writer
, const WS_XML_ELEMENT_NODE
*elem
)
1239 for (i
= 0; i
< elem
->attributeCount
; i
++)
1241 if (elem
->attributes
[i
]->isXmlNs
) continue;
1242 if ((hr
= write_attribute( writer
, elem
->attributes
[i
] )) != S_OK
) return hr
;
1244 for (i
= 0; i
< elem
->attributeCount
; i
++)
1246 if (!elem
->attributes
[i
]->isXmlNs
|| !elem
->attributes
[i
]->prefix
) continue;
1247 if ((hr
= write_namespace_attribute( writer
, elem
->attributes
[i
] )) != S_OK
) return hr
;
1249 for (i
= 0; i
< elem
->attributeCount
; i
++)
1251 if (!elem
->attributes
[i
]->isXmlNs
|| elem
->attributes
[i
]->prefix
) continue;
1252 if ((hr
= write_namespace_attribute( writer
, elem
->attributes
[i
] )) != S_OK
) return hr
;
1257 static HRESULT
write_startelement_text( struct writer
*writer
)
1259 const WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
1263 /* '<prefix:localname prefix:attr="value"... xmlns:prefix="ns"'... */
1265 size
= elem
->localName
->length
+ 1 /* '<' */;
1266 if (elem
->prefix
&& elem
->prefix
->length
) size
+= elem
->prefix
->length
+ 1 /* ':' */;
1267 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
1269 write_char( writer
, '<' );
1270 if (elem
->prefix
&& elem
->prefix
->length
)
1272 write_bytes( writer
, elem
->prefix
->bytes
, elem
->prefix
->length
);
1273 write_char( writer
, ':' );
1275 write_bytes( writer
, elem
->localName
->bytes
, elem
->localName
->length
);
1276 return write_attributes( writer
, elem
);
1279 static enum record_type
get_elem_record_type( const WS_XML_ELEMENT_NODE
*elem
, BOOL use_dict
)
1281 if (!elem
->prefix
|| !elem
->prefix
->length
)
1283 if (use_dict
) return RECORD_SHORT_DICTIONARY_ELEMENT
;
1284 return RECORD_SHORT_ELEMENT
;
1286 if (elem
->prefix
->length
== 1 && elem
->prefix
->bytes
[0] >= 'a' && elem
->prefix
->bytes
[0] <= 'z')
1288 if (use_dict
) return RECORD_PREFIX_DICTIONARY_ELEMENT_A
+ elem
->prefix
->bytes
[0] - 'a';
1289 return RECORD_PREFIX_ELEMENT_A
+ elem
->prefix
->bytes
[0] - 'a';
1291 if (use_dict
) return RECORD_DICTIONARY_ELEMENT
;
1292 return RECORD_ELEMENT
;
1295 static HRESULT
write_startelement_bin( struct writer
*writer
)
1297 const WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
1299 enum record_type type
= get_elem_record_type( elem
, lookup_string_id(writer
, elem
->localName
, &id
) );
1302 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
1303 write_char( writer
, type
);
1305 if (type
>= RECORD_PREFIX_ELEMENT_A
&& type
<= RECORD_PREFIX_ELEMENT_Z
)
1307 if ((hr
= write_string( writer
, elem
->localName
->bytes
, elem
->localName
->length
)) != S_OK
) return hr
;
1308 return write_attributes( writer
, elem
);
1310 if (type
>= RECORD_PREFIX_DICTIONARY_ELEMENT_A
&& type
<= RECORD_PREFIX_DICTIONARY_ELEMENT_Z
)
1312 if ((hr
= write_dict_string( writer
, id
)) != S_OK
) return hr
;
1313 return write_attributes( writer
, elem
);
1318 case RECORD_SHORT_ELEMENT
:
1319 if ((hr
= write_string( writer
, elem
->localName
->bytes
, elem
->localName
->length
)) != S_OK
) return hr
;
1322 case RECORD_ELEMENT
:
1323 if ((hr
= write_string( writer
, elem
->prefix
->bytes
, elem
->prefix
->length
)) != S_OK
) return hr
;
1324 if ((hr
= write_string( writer
, elem
->localName
->bytes
, elem
->localName
->length
)) != S_OK
) return hr
;
1327 case RECORD_SHORT_DICTIONARY_ELEMENT
:
1328 if ((hr
= write_dict_string( writer
, id
)) != S_OK
) return hr
;
1331 case RECORD_DICTIONARY_ELEMENT
:
1332 if ((hr
= write_string( writer
, elem
->prefix
->bytes
, elem
->prefix
->length
)) != S_OK
) return hr
;
1333 if ((hr
= write_dict_string( writer
, id
)) != S_OK
) return hr
;
1337 ERR( "unhandled record type %02x\n", type
);
1338 return WS_E_NOT_SUPPORTED
;
1341 return write_attributes( writer
, elem
);
1344 static HRESULT
write_startelement( struct writer
*writer
)
1346 switch (writer
->output_enc
)
1348 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_startelement_text( writer
);
1349 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return write_startelement_bin( writer
);
1351 ERR( "unhandled encoding %u\n", writer
->output_enc
);
1352 return WS_E_NOT_SUPPORTED
;
1356 static struct node
*write_find_startelement( struct writer
*writer
)
1359 for (node
= writer
->current
; node
; node
= node
->parent
)
1361 if (node_type( node
) == WS_XML_NODE_TYPE_ELEMENT
) return node
;
1366 static inline BOOL
is_empty_element( const struct node
*node
)
1368 const struct node
*head
= LIST_ENTRY( list_head( &node
->children
), struct node
, entry
);
1369 return node_type( head
) == WS_XML_NODE_TYPE_END_ELEMENT
;
1372 static HRESULT
write_endelement_text( struct writer
*writer
, const WS_XML_ELEMENT_NODE
*elem
)
1379 if (elem
->isEmpty
&& writer
->state
!= WRITER_STATE_ENDSTARTELEMENT
)
1381 if ((hr
= write_grow_buffer( writer
, 2 )) != S_OK
) return hr
;
1382 write_char( writer
, '/' );
1383 write_char( writer
, '>' );
1387 /* '</prefix:localname>' */
1389 size
= elem
->localName
->length
+ 3 /* '</>' */;
1390 if (elem
->prefix
&& elem
->prefix
->length
) size
+= elem
->prefix
->length
+ 1 /* ':' */;
1391 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
1393 write_char( writer
, '<' );
1394 write_char( writer
, '/' );
1395 if (elem
->prefix
&& elem
->prefix
->length
)
1397 write_bytes( writer
, elem
->prefix
->bytes
, elem
->prefix
->length
);
1398 write_char( writer
, ':' );
1400 write_bytes( writer
, elem
->localName
->bytes
, elem
->localName
->length
);
1401 write_char( writer
, '>' );
1405 static HRESULT
write_endelement_bin( struct writer
*writer
)
1408 if (node_type( writer
->current
) == WS_XML_NODE_TYPE_TEXT
) return S_OK
;
1409 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
1410 write_char( writer
, RECORD_ENDELEMENT
);
1414 static HRESULT
write_endelement( struct writer
*writer
, const WS_XML_ELEMENT_NODE
*elem
)
1416 switch (writer
->output_enc
)
1418 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_endelement_text( writer
, elem
);
1419 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return write_endelement_bin( writer
);
1421 ERR( "unhandled encoding %u\n", writer
->output_enc
);
1422 return WS_E_NOT_SUPPORTED
;
1426 static HRESULT
write_close_element( struct writer
*writer
, struct node
*node
)
1428 WS_XML_ELEMENT_NODE
*elem
= &node
->hdr
;
1429 elem
->isEmpty
= is_empty_element( node
);
1430 return write_endelement( writer
, elem
);
1433 static HRESULT
write_endelement_node( struct writer
*writer
)
1438 if (!(node
= write_find_startelement( writer
))) return WS_E_INVALID_FORMAT
;
1439 if (writer
->state
== WRITER_STATE_STARTELEMENT
)
1441 if ((hr
= set_namespaces( writer
)) != S_OK
) return hr
;
1442 if ((hr
= write_startelement( writer
)) != S_OK
) return hr
;
1444 if ((hr
= write_close_element( writer
, node
)) != S_OK
) return hr
;
1445 writer
->current
= node
->parent
;
1446 writer
->state
= WRITER_STATE_ENDELEMENT
;
1450 /**************************************************************************
1451 * WsWriteEndElement [webservices.@]
1453 HRESULT WINAPI
WsWriteEndElement( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
1455 struct writer
*writer
= (struct writer
*)handle
;
1458 TRACE( "%p %p\n", handle
, error
);
1459 if (error
) FIXME( "ignoring error parameter\n" );
1461 if (!writer
) return E_INVALIDARG
;
1463 EnterCriticalSection( &writer
->cs
);
1465 if (writer
->magic
!= WRITER_MAGIC
)
1467 LeaveCriticalSection( &writer
->cs
);
1468 return E_INVALIDARG
;
1471 hr
= write_endelement_node( writer
);
1473 LeaveCriticalSection( &writer
->cs
);
1477 static HRESULT
write_endstartelement_text( struct writer
*writer
)
1480 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
1481 write_char( writer
, '>' );
1485 static HRESULT
write_endstartelement( struct writer
*writer
)
1487 switch (writer
->output_enc
)
1489 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_endstartelement_text( writer
);
1490 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return S_OK
;
1492 ERR( "unhandled encoding %u\n", writer
->output_enc
);
1493 return WS_E_NOT_SUPPORTED
;
1497 /**************************************************************************
1498 * WsWriteEndStartElement [webservices.@]
1500 HRESULT WINAPI
WsWriteEndStartElement( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
1502 struct writer
*writer
= (struct writer
*)handle
;
1505 TRACE( "%p %p\n", handle
, error
);
1506 if (error
) FIXME( "ignoring error parameter\n" );
1508 if (!writer
) return E_INVALIDARG
;
1510 EnterCriticalSection( &writer
->cs
);
1512 if (writer
->magic
!= WRITER_MAGIC
)
1514 LeaveCriticalSection( &writer
->cs
);
1515 return E_INVALIDARG
;
1518 if (writer
->state
!= WRITER_STATE_STARTELEMENT
)
1520 LeaveCriticalSection( &writer
->cs
);
1521 return WS_E_INVALID_OPERATION
;
1524 if ((hr
= set_namespaces( writer
)) != S_OK
) goto done
;
1525 if ((hr
= write_startelement( writer
)) != S_OK
) goto done
;
1526 if ((hr
= write_endstartelement( writer
)) != S_OK
) goto done
;
1527 writer
->state
= WRITER_STATE_ENDSTARTELEMENT
;
1530 LeaveCriticalSection( &writer
->cs
);
1534 static HRESULT
write_add_attribute( struct writer
*writer
, const WS_XML_STRING
*prefix
,
1535 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
1538 WS_XML_ATTRIBUTE
*attr
;
1539 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
1542 if (!(attr
= heap_alloc_zero( sizeof(*attr
) ))) return E_OUTOFMEMORY
;
1544 if (!prefix
&& ns
->length
) prefix
= elem
->prefix
;
1546 attr
->singleQuote
= !!single
;
1547 if (prefix
&& !(attr
->prefix
= dup_xml_string( prefix
)))
1549 free_attribute( attr
);
1550 return E_OUTOFMEMORY
;
1552 if (!(attr
->localName
= dup_xml_string( localname
)))
1554 free_attribute( attr
);
1555 return E_OUTOFMEMORY
;
1557 if (!(attr
->ns
= dup_xml_string( ns
)))
1559 free_attribute( attr
);
1560 return E_OUTOFMEMORY
;
1562 if ((hr
= append_attribute( elem
, attr
)) != S_OK
)
1564 free_attribute( attr
);
1570 /**************************************************************************
1571 * WsWriteStartAttribute [webservices.@]
1573 HRESULT WINAPI
WsWriteStartAttribute( WS_XML_WRITER
*handle
, const WS_XML_STRING
*prefix
,
1574 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
1575 BOOL single
, WS_ERROR
*error
)
1577 struct writer
*writer
= (struct writer
*)handle
;
1580 TRACE( "%p %s %s %s %d %p\n", handle
, debugstr_xmlstr(prefix
), debugstr_xmlstr(localname
),
1581 debugstr_xmlstr(ns
), single
, error
);
1582 if (error
) FIXME( "ignoring error parameter\n" );
1584 if (!writer
|| !localname
|| !ns
) return E_INVALIDARG
;
1586 EnterCriticalSection( &writer
->cs
);
1588 if (writer
->magic
!= WRITER_MAGIC
)
1590 LeaveCriticalSection( &writer
->cs
);
1591 return E_INVALIDARG
;
1594 if (writer
->state
!= WRITER_STATE_STARTELEMENT
)
1596 LeaveCriticalSection( &writer
->cs
);
1597 return WS_E_INVALID_OPERATION
;
1600 if ((hr
= write_add_attribute( writer
, prefix
, localname
, ns
, single
)) == S_OK
)
1601 writer
->state
= WRITER_STATE_STARTATTRIBUTE
;
1603 LeaveCriticalSection( &writer
->cs
);
1607 /* flush current start element if necessary */
1608 static HRESULT
write_flush( struct writer
*writer
)
1610 if (writer
->state
== WRITER_STATE_STARTELEMENT
)
1613 if ((hr
= set_namespaces( writer
)) != S_OK
) return hr
;
1614 if ((hr
= write_startelement( writer
)) != S_OK
) return hr
;
1615 if ((hr
= write_endstartelement( writer
)) != S_OK
) return hr
;
1616 writer
->state
= WRITER_STATE_ENDSTARTELEMENT
;
1621 static HRESULT
write_add_cdata_node( struct writer
*writer
)
1623 struct node
*node
, *parent
;
1624 if (!(parent
= find_parent( writer
))) return WS_E_INVALID_FORMAT
;
1625 if (!(node
= alloc_node( WS_XML_NODE_TYPE_CDATA
))) return E_OUTOFMEMORY
;
1626 write_insert_node( writer
, parent
, node
);
1630 static HRESULT
write_add_endcdata_node( struct writer
*writer
)
1633 if (!(node
= alloc_node( WS_XML_NODE_TYPE_END_CDATA
))) return E_OUTOFMEMORY
;
1634 node
->parent
= writer
->current
;
1635 list_add_tail( &node
->parent
->children
, &node
->entry
);
1639 static HRESULT
write_cdata( struct writer
*writer
)
1642 if ((hr
= write_grow_buffer( writer
, 9 )) != S_OK
) return hr
;
1643 write_bytes( writer
, (const BYTE
*)"<![CDATA[", 9 );
1647 static HRESULT
write_cdata_node( struct writer
*writer
)
1650 if ((hr
= write_flush( writer
)) != S_OK
) return hr
;
1651 if ((hr
= write_add_cdata_node( writer
)) != S_OK
) return hr
;
1652 if ((hr
= write_add_endcdata_node( writer
)) != S_OK
) return hr
;
1653 if ((hr
= write_cdata( writer
)) != S_OK
) return hr
;
1654 writer
->state
= WRITER_STATE_STARTCDATA
;
1658 /**************************************************************************
1659 * WsWriteStartCData [webservices.@]
1661 HRESULT WINAPI
WsWriteStartCData( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
1663 struct writer
*writer
= (struct writer
*)handle
;
1666 TRACE( "%p %p\n", handle
, error
);
1667 if (error
) FIXME( "ignoring error parameter\n" );
1669 if (!writer
) return E_INVALIDARG
;
1671 EnterCriticalSection( &writer
->cs
);
1673 if (writer
->magic
!= WRITER_MAGIC
)
1675 LeaveCriticalSection( &writer
->cs
);
1676 return E_INVALIDARG
;
1679 hr
= write_cdata_node( writer
);
1681 LeaveCriticalSection( &writer
->cs
);
1685 static HRESULT
write_endcdata( struct writer
*writer
)
1688 if ((hr
= write_grow_buffer( writer
, 3 )) != S_OK
) return hr
;
1689 write_bytes( writer
, (const BYTE
*)"]]>", 3 );
1693 static HRESULT
write_endcdata_node( struct writer
*writer
)
1696 if ((hr
= write_endcdata( writer
)) != S_OK
) return hr
;
1697 writer
->current
= writer
->current
->parent
;
1698 writer
->state
= WRITER_STATE_ENDCDATA
;
1702 /**************************************************************************
1703 * WsWriteEndCData [webservices.@]
1705 HRESULT WINAPI
WsWriteEndCData( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
1707 struct writer
*writer
= (struct writer
*)handle
;
1710 TRACE( "%p %p\n", handle
, error
);
1711 if (error
) FIXME( "ignoring error parameter\n" );
1713 if (!writer
) return E_INVALIDARG
;
1715 EnterCriticalSection( &writer
->cs
);
1717 if (writer
->magic
!= WRITER_MAGIC
)
1719 LeaveCriticalSection( &writer
->cs
);
1720 return E_INVALIDARG
;
1723 if (writer
->state
!= WRITER_STATE_TEXT
)
1725 LeaveCriticalSection( &writer
->cs
);
1726 return WS_E_INVALID_OPERATION
;
1729 hr
= write_endcdata_node( writer
);
1731 LeaveCriticalSection( &writer
->cs
);
1735 static HRESULT
write_add_element_node( struct writer
*writer
, const WS_XML_STRING
*prefix
,
1736 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
)
1738 struct node
*node
, *parent
;
1739 WS_XML_ELEMENT_NODE
*elem
;
1741 if (!(parent
= find_parent( writer
))) return WS_E_INVALID_FORMAT
;
1743 if (!prefix
&& node_type( parent
) == WS_XML_NODE_TYPE_ELEMENT
)
1745 elem
= &parent
->hdr
;
1746 if (WsXmlStringEquals( ns
, elem
->ns
, NULL
) == S_OK
) prefix
= elem
->prefix
;
1749 if (!(node
= alloc_node( WS_XML_NODE_TYPE_ELEMENT
))) return E_OUTOFMEMORY
;
1752 if (prefix
&& !(elem
->prefix
= dup_xml_string( prefix
)))
1755 return E_OUTOFMEMORY
;
1757 if (!(elem
->localName
= dup_xml_string( localname
)))
1760 return E_OUTOFMEMORY
;
1762 if (!(elem
->ns
= dup_xml_string( ns
)))
1765 return E_OUTOFMEMORY
;
1767 write_insert_node( writer
, parent
, node
);
1771 static HRESULT
write_add_endelement_node( struct writer
*writer
, struct node
*parent
)
1774 if (!(node
= alloc_node( WS_XML_NODE_TYPE_END_ELEMENT
))) return E_OUTOFMEMORY
;
1775 node
->parent
= parent
;
1776 list_add_tail( &parent
->children
, &node
->entry
);
1780 static HRESULT
write_element_node( struct writer
*writer
, const WS_XML_STRING
*prefix
,
1781 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
)
1784 if ((hr
= write_flush( writer
)) != S_OK
) return hr
;
1785 if ((hr
= write_add_element_node( writer
, prefix
, localname
, ns
)) != S_OK
) return hr
;
1786 if ((hr
= write_add_endelement_node( writer
, writer
->current
)) != S_OK
) return hr
;
1787 writer
->state
= WRITER_STATE_STARTELEMENT
;
1791 /**************************************************************************
1792 * WsWriteStartElement [webservices.@]
1794 HRESULT WINAPI
WsWriteStartElement( WS_XML_WRITER
*handle
, const WS_XML_STRING
*prefix
,
1795 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
1798 struct writer
*writer
= (struct writer
*)handle
;
1801 TRACE( "%p %s %s %s %p\n", handle
, debugstr_xmlstr(prefix
), debugstr_xmlstr(localname
),
1802 debugstr_xmlstr(ns
), error
);
1803 if (error
) FIXME( "ignoring error parameter\n" );
1805 if (!writer
|| !localname
|| !ns
) return E_INVALIDARG
;
1807 EnterCriticalSection( &writer
->cs
);
1809 if (writer
->magic
!= WRITER_MAGIC
)
1811 LeaveCriticalSection( &writer
->cs
);
1812 return E_INVALIDARG
;
1815 hr
= write_element_node( writer
, prefix
, localname
, ns
);
1817 LeaveCriticalSection( &writer
->cs
);
1821 static ULONG
format_bool( const BOOL
*ptr
, unsigned char *buf
)
1823 static const unsigned char bool_true
[] = {'t','r','u','e'}, bool_false
[] = {'f','a','l','s','e'};
1826 memcpy( buf
, bool_true
, sizeof(bool_true
) );
1827 return sizeof(bool_true
);
1829 memcpy( buf
, bool_false
, sizeof(bool_false
) );
1830 return sizeof(bool_false
);
1833 static ULONG
format_int32( const INT32
*ptr
, unsigned char *buf
)
1835 return wsprintfA( (char *)buf
, "%d", *ptr
);
1838 static ULONG
format_int64( const INT64
*ptr
, unsigned char *buf
)
1840 return wsprintfA( (char *)buf
, "%I64d", *ptr
);
1843 static ULONG
format_uint64( const UINT64
*ptr
, unsigned char *buf
)
1845 return wsprintfA( (char *)buf
, "%I64u", *ptr
);
1848 static ULONG
format_double( const double *ptr
, unsigned char *buf
)
1851 static const long double precision
= 0.0000000000000001;
1852 unsigned char *p
= buf
;
1853 long double val
= *ptr
;
1854 int neg
, mag
, mag2
, use_exp
;
1858 memcpy( buf
, "NaN", 3 );
1865 memcpy( buf
, "-INF", 4 );
1868 memcpy( buf
, "INF", 3 );
1877 if ((neg
= val
< 0))
1883 mag
= log10l( val
);
1884 use_exp
= (mag
>= 15 || (neg
&& mag
>= 1) || mag
<= -1);
1887 if (mag
< 0) mag
-= 1;
1888 val
= val
/ powl( 10.0, mag
);
1892 else if (mag
< 1) mag
= 0;
1894 while (val
> precision
|| mag
>= 0)
1896 long double weight
= powl( 10.0, mag
);
1897 if (weight
> 0 && !isinf( weight
))
1899 int digit
= floorl( val
/ weight
);
1900 val
-= digit
* weight
;
1901 *(p
++) = '0' + digit
;
1903 if (!mag
&& val
> precision
) *(p
++) = '.';
1911 if (mag2
> 0) *(p
++) = '+';
1920 *(p
++) = '0' + mag2
% 10;
1924 for (i
= -mag
, j
= -1; i
< j
; i
++, j
--)
1934 FIXME( "powl not found at build time\n" );
1939 static inline int year_size( int year
)
1941 return leap_year( year
) ? 366 : 365;
1945 static ULONG
format_datetime( const WS_DATETIME
*ptr
, unsigned char *buf
)
1947 static const char fmt
[] = "%04u-%02u-%02uT%02u:%02u:%02u";
1948 int day
, hour
, min
, sec
, sec_frac
, month
= 0, year
= 1, tz_hour
;
1949 unsigned __int64 ticks
, day_ticks
;
1952 if (ptr
->format
== WS_DATETIME_FORMAT_LOCAL
&&
1953 ptr
->ticks
>= TICKS_1601_01_01
+ TZ_OFFSET
* TICKS_PER_HOUR
)
1955 ticks
= ptr
->ticks
- TZ_OFFSET
* TICKS_PER_HOUR
;
1956 tz_hour
= TZ_OFFSET
;
1963 day
= ticks
/ TICKS_PER_DAY
;
1964 day_ticks
= ticks
% TICKS_PER_DAY
;
1965 hour
= day_ticks
/ TICKS_PER_HOUR
;
1966 min
= (day_ticks
% TICKS_PER_HOUR
) / TICKS_PER_MIN
;
1967 sec
= (day_ticks
% TICKS_PER_MIN
) / TICKS_PER_SEC
;
1968 sec_frac
= day_ticks
% TICKS_PER_SEC
;
1970 while (day
>= year_size( year
))
1972 day
-= year_size( year
);
1975 while (day
>= month_days
[leap_year( year
)][month
])
1977 day
-= month_days
[leap_year( year
)][month
];
1981 len
= sprintf( (char *)buf
, fmt
, year
, month
+ 1, day
+ 1, hour
, min
, sec
);
1984 static const char fmt_frac
[] = ".%07u";
1985 len
+= sprintf( (char *)buf
+ len
, fmt_frac
, sec_frac
);
1986 while (buf
[len
- 1] == '0') len
--;
1988 if (ptr
->format
== WS_DATETIME_FORMAT_UTC
)
1992 else if (ptr
->format
== WS_DATETIME_FORMAT_LOCAL
)
1994 static const char fmt_tz
[] = "%c%02u:00";
1995 len
+= sprintf( (char *)buf
+ len
, fmt_tz
, tz_hour
? '-' : '+', tz_hour
);
2001 static ULONG
format_guid( const GUID
*ptr
, unsigned char *buf
)
2003 static const char fmt
[] = "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x";
2004 return sprintf( (char *)buf
, fmt
, ptr
->Data1
, ptr
->Data2
, ptr
->Data3
,
2005 ptr
->Data4
[0], ptr
->Data4
[1], ptr
->Data4
[2], ptr
->Data4
[3],
2006 ptr
->Data4
[4], ptr
->Data4
[5], ptr
->Data4
[6], ptr
->Data4
[7] );
2009 static ULONG
format_urn( const GUID
*ptr
, unsigned char *buf
)
2011 static const char fmt
[] = "urn:uuid:%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x";
2012 return sprintf( (char *)buf
, fmt
, ptr
->Data1
, ptr
->Data2
, ptr
->Data3
,
2013 ptr
->Data4
[0], ptr
->Data4
[1], ptr
->Data4
[2], ptr
->Data4
[3],
2014 ptr
->Data4
[4], ptr
->Data4
[5], ptr
->Data4
[6], ptr
->Data4
[7] );
2017 static ULONG
format_qname( const WS_XML_STRING
*prefix
, const WS_XML_STRING
*localname
, unsigned char *buf
)
2020 if (prefix
&& prefix
->length
)
2022 memcpy( buf
, prefix
->bytes
, prefix
->length
);
2023 len
+= prefix
->length
;
2026 memcpy( buf
+ len
, localname
->bytes
, localname
->length
);
2027 return len
+ localname
->length
;
2030 static ULONG
encode_base64( const unsigned char *bin
, ULONG len
, unsigned char *buf
)
2032 static const char base64
[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
2037 buf
[i
++] = base64
[(bin
[0] & 0xfc) >> 2];
2038 x
= (bin
[0] & 3) << 4;
2041 buf
[i
++] = base64
[x
];
2046 buf
[i
++] = base64
[x
| ((bin
[1] & 0xf0) >> 4)];
2047 x
= (bin
[1] & 0x0f) << 2;
2050 buf
[i
++] = base64
[x
];
2054 buf
[i
++] = base64
[x
| ((bin
[2] & 0xc0) >> 6)];
2055 buf
[i
++] = base64
[bin
[2] & 0x3f];
2062 static HRESULT
text_to_utf8text( const WS_XML_TEXT
*text
, const WS_XML_UTF8_TEXT
*old
, ULONG
*offset
,
2063 WS_XML_UTF8_TEXT
**ret
)
2065 ULONG len_old
= old
? old
->value
.length
: 0;
2066 if (offset
) *offset
= len_old
;
2068 switch (text
->textType
)
2070 case WS_XML_TEXT_TYPE_UTF8
:
2072 const WS_XML_UTF8_TEXT
*src
= (const WS_XML_UTF8_TEXT
*)text
;
2074 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ src
->value
.length
))) return E_OUTOFMEMORY
;
2075 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
2076 memcpy( (*ret
)->value
.bytes
+ len_old
, src
->value
.bytes
, src
->value
.length
);
2079 case WS_XML_TEXT_TYPE_UTF16
:
2081 const WS_XML_UTF16_TEXT
*src
= (const WS_XML_UTF16_TEXT
*)text
;
2082 const WCHAR
*str
= (const WCHAR
*)src
->bytes
;
2083 ULONG len
= src
->byteCount
/ sizeof(WCHAR
), len_utf8
;
2085 if (src
->byteCount
% sizeof(WCHAR
)) return E_INVALIDARG
;
2086 len_utf8
= WideCharToMultiByte( CP_UTF8
, 0, str
, len
, NULL
, 0, NULL
, NULL
);
2087 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len_utf8
))) return E_OUTOFMEMORY
;
2088 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
2089 WideCharToMultiByte( CP_UTF8
, 0, str
, len
, (char *)(*ret
)->value
.bytes
+ len_old
, len_utf8
, NULL
, NULL
);
2092 case WS_XML_TEXT_TYPE_BASE64
:
2094 const WS_XML_BASE64_TEXT
*base64
= (const WS_XML_BASE64_TEXT
*)text
;
2095 ULONG len
= ((4 * base64
->length
/ 3) + 3) & ~3;
2097 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
2098 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
2099 (*ret
)->value
.length
= encode_base64( base64
->bytes
, base64
->length
, (*ret
)->value
.bytes
+ len_old
) + len_old
;
2102 case WS_XML_TEXT_TYPE_BOOL
:
2104 const WS_XML_BOOL_TEXT
*bool_text
= (const WS_XML_BOOL_TEXT
*)text
;
2106 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ 5 ))) return E_OUTOFMEMORY
;
2107 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
2108 (*ret
)->value
.length
= format_bool( &bool_text
->value
, (*ret
)->value
.bytes
+ len_old
) + len_old
;
2111 case WS_XML_TEXT_TYPE_INT32
:
2113 const WS_XML_INT32_TEXT
*int32_text
= (const WS_XML_INT32_TEXT
*)text
;
2114 unsigned char buf
[12]; /* "-2147483648" */
2115 ULONG len
= format_int32( &int32_text
->value
, buf
);
2117 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
2118 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
2119 memcpy( (*ret
)->value
.bytes
+ len_old
, buf
, len
);
2122 case WS_XML_TEXT_TYPE_INT64
:
2124 const WS_XML_INT64_TEXT
*int64_text
= (const WS_XML_INT64_TEXT
*)text
;
2125 unsigned char buf
[21]; /* "-9223372036854775808" */
2126 ULONG len
= format_int64( &int64_text
->value
, buf
);
2128 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
2129 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
2130 memcpy( (*ret
)->value
.bytes
+ len_old
, buf
, len
);
2133 case WS_XML_TEXT_TYPE_UINT64
:
2135 const WS_XML_UINT64_TEXT
*uint64_text
= (const WS_XML_UINT64_TEXT
*)text
;
2136 unsigned char buf
[21]; /* "18446744073709551615" */
2137 ULONG len
= format_uint64( &uint64_text
->value
, buf
);
2139 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
2140 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
2141 memcpy( (*ret
)->value
.bytes
+ len_old
, buf
, len
);
2144 case WS_XML_TEXT_TYPE_DOUBLE
:
2146 const WS_XML_DOUBLE_TEXT
*double_text
= (const WS_XML_DOUBLE_TEXT
*)text
;
2147 unsigned char buf
[32]; /* "-1.1111111111111111E-308", oversized to address Valgrind limitations */
2148 unsigned short fpword
;
2151 if (!set_fpword( 0x37f, &fpword
)) return E_NOTIMPL
;
2152 len
= format_double( &double_text
->value
, buf
);
2153 restore_fpword( fpword
);
2154 if (!len
) return E_NOTIMPL
;
2156 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
2157 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
2158 memcpy( (*ret
)->value
.bytes
+ len_old
, buf
, len
);
2161 case WS_XML_TEXT_TYPE_GUID
:
2163 const WS_XML_GUID_TEXT
*id
= (const WS_XML_GUID_TEXT
*)text
;
2165 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ 37 ))) return E_OUTOFMEMORY
;
2166 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
2167 (*ret
)->value
.length
= format_guid( &id
->value
, (*ret
)->value
.bytes
+ len_old
) + len_old
;
2170 case WS_XML_TEXT_TYPE_UNIQUE_ID
:
2172 const WS_XML_UNIQUE_ID_TEXT
*id
= (const WS_XML_UNIQUE_ID_TEXT
*)text
;
2174 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ 46 ))) return E_OUTOFMEMORY
;
2175 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
2176 (*ret
)->value
.length
= format_urn( &id
->value
, (*ret
)->value
.bytes
+ len_old
) + len_old
;
2179 case WS_XML_TEXT_TYPE_DATETIME
:
2181 const WS_XML_DATETIME_TEXT
*dt
= (const WS_XML_DATETIME_TEXT
*)text
;
2183 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ 34 ))) return E_OUTOFMEMORY
;
2184 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
2185 (*ret
)->value
.length
= format_datetime( &dt
->value
, (*ret
)->value
.bytes
+ len_old
) + len_old
;
2188 case WS_XML_TEXT_TYPE_QNAME
:
2190 const WS_XML_QNAME_TEXT
*qn
= (const WS_XML_QNAME_TEXT
*)text
;
2191 ULONG len
= qn
->localName
->length
;
2193 if (qn
->prefix
&& qn
->prefix
->length
) len
+= qn
->prefix
->length
+ 1;
2194 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
2195 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
2196 (*ret
)->value
.length
= format_qname( qn
->prefix
, qn
->localName
, (*ret
)->value
.bytes
+ len_old
) + len_old
;
2200 FIXME( "unhandled text type %u\n", text
->textType
);
2205 static HRESULT
text_to_text( const WS_XML_TEXT
*text
, const WS_XML_TEXT
*old
, ULONG
*offset
, WS_XML_TEXT
**ret
)
2207 if (offset
) *offset
= 0;
2208 switch (text
->textType
)
2210 case WS_XML_TEXT_TYPE_UTF8
:
2212 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)text
;
2213 const WS_XML_UTF8_TEXT
*utf8_old
= (const WS_XML_UTF8_TEXT
*)old
;
2214 WS_XML_UTF8_TEXT
*new;
2215 ULONG len
= utf8
->value
.length
, len_old
= utf8_old
? utf8_old
->value
.length
: 0;
2217 if (!(new = alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
2218 if (utf8_old
) memcpy( new->value
.bytes
, utf8_old
->value
.bytes
, len_old
);
2219 memcpy( new->value
.bytes
+ len_old
, utf8
->value
.bytes
, len
);
2220 if (offset
) *offset
= len_old
;
2224 case WS_XML_TEXT_TYPE_UTF16
:
2226 const WS_XML_UTF16_TEXT
*utf16
= (const WS_XML_UTF16_TEXT
*)text
;
2227 const WS_XML_UTF8_TEXT
*utf8_old
= (const WS_XML_UTF8_TEXT
*)old
;
2228 WS_XML_UTF8_TEXT
*new;
2229 const WCHAR
*str
= (const WCHAR
*)utf16
->bytes
;
2230 ULONG len
= utf16
->byteCount
/ sizeof(WCHAR
), len_utf8
, len_old
= utf8_old
? utf8_old
->value
.length
: 0;
2232 if (utf16
->byteCount
% sizeof(WCHAR
)) return E_INVALIDARG
;
2233 len_utf8
= WideCharToMultiByte( CP_UTF8
, 0, str
, len
, NULL
, 0, NULL
, NULL
);
2234 if (!(new = alloc_utf8_text( NULL
, len_old
+ len_utf8
))) return E_OUTOFMEMORY
;
2235 if (old
) memcpy( new->value
.bytes
, utf8_old
->value
.bytes
, len_old
);
2236 WideCharToMultiByte( CP_UTF8
, 0, str
, len
, (char *)new->value
.bytes
+ len_old
, len_utf8
, NULL
, NULL
);
2237 if (offset
) *offset
= len_old
;
2241 case WS_XML_TEXT_TYPE_BASE64
:
2243 const WS_XML_BASE64_TEXT
*base64
= (const WS_XML_BASE64_TEXT
*)text
;
2244 const WS_XML_BASE64_TEXT
*base64_old
= (const WS_XML_BASE64_TEXT
*)old
;
2245 WS_XML_BASE64_TEXT
*new;
2246 ULONG len
= base64
->length
, len_old
= base64_old
? base64_old
->length
: 0;
2248 if (!(new = alloc_base64_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
2249 if (base64_old
) memcpy( new->bytes
, base64_old
->bytes
, len_old
);
2250 memcpy( new->bytes
+ len_old
, base64
->bytes
, len
);
2251 if (offset
) *offset
= len_old
;
2255 case WS_XML_TEXT_TYPE_BOOL
:
2257 const WS_XML_BOOL_TEXT
*bool_text
= (const WS_XML_BOOL_TEXT
*)text
;
2258 WS_XML_BOOL_TEXT
*new;
2260 if (!(new = alloc_bool_text( bool_text
->value
))) return E_OUTOFMEMORY
;
2264 case WS_XML_TEXT_TYPE_INT32
:
2266 const WS_XML_INT32_TEXT
*int32_text
= (const WS_XML_INT32_TEXT
*)text
;
2267 WS_XML_INT32_TEXT
*new;
2269 if (!(new = alloc_int32_text( int32_text
->value
))) return E_OUTOFMEMORY
;
2273 case WS_XML_TEXT_TYPE_INT64
:
2275 const WS_XML_INT64_TEXT
*int64_text
= (const WS_XML_INT64_TEXT
*)text
;
2276 WS_XML_INT64_TEXT
*new;
2278 if (!(new = alloc_int64_text( int64_text
->value
))) return E_OUTOFMEMORY
;
2282 case WS_XML_TEXT_TYPE_UINT64
:
2284 const WS_XML_UINT64_TEXT
*uint64_text
= (const WS_XML_UINT64_TEXT
*)text
;
2285 WS_XML_UINT64_TEXT
*new;
2287 if (!(new = alloc_uint64_text( uint64_text
->value
))) return E_OUTOFMEMORY
;
2291 case WS_XML_TEXT_TYPE_DOUBLE
:
2293 const WS_XML_DOUBLE_TEXT
*double_text
= (const WS_XML_DOUBLE_TEXT
*)text
;
2294 WS_XML_DOUBLE_TEXT
*new;
2296 if (!(new = alloc_double_text( double_text
->value
))) return E_OUTOFMEMORY
;
2300 case WS_XML_TEXT_TYPE_GUID
:
2302 const WS_XML_GUID_TEXT
*id
= (const WS_XML_GUID_TEXT
*)text
;
2303 WS_XML_GUID_TEXT
*new;
2305 if (!(new = alloc_guid_text( &id
->value
))) return E_OUTOFMEMORY
;
2309 case WS_XML_TEXT_TYPE_UNIQUE_ID
:
2311 const WS_XML_UNIQUE_ID_TEXT
*id
= (const WS_XML_UNIQUE_ID_TEXT
*)text
;
2312 WS_XML_UNIQUE_ID_TEXT
*new;
2314 if (!(new = alloc_unique_id_text( &id
->value
))) return E_OUTOFMEMORY
;
2318 case WS_XML_TEXT_TYPE_DATETIME
:
2320 const WS_XML_DATETIME_TEXT
*dt
= (const WS_XML_DATETIME_TEXT
*)text
;
2321 WS_XML_DATETIME_TEXT
*new;
2323 if (!(new = alloc_datetime_text( &dt
->value
))) return E_OUTOFMEMORY
;
2328 FIXME( "unhandled text type %u\n", text
->textType
);
2333 static HRESULT
write_set_attribute_value( struct writer
*writer
, const WS_XML_TEXT
*value
)
2335 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
2338 switch (value
->textType
)
2340 case WS_XML_TEXT_TYPE_UTF8
:
2341 case WS_XML_TEXT_TYPE_UTF16
:
2342 case WS_XML_TEXT_TYPE_BASE64
:
2345 case WS_XML_TEXT_TYPE_BOOL
:
2346 case WS_XML_TEXT_TYPE_INT32
:
2347 case WS_XML_TEXT_TYPE_INT64
:
2348 case WS_XML_TEXT_TYPE_UINT64
:
2349 case WS_XML_TEXT_TYPE_DOUBLE
:
2350 case WS_XML_TEXT_TYPE_GUID
:
2351 case WS_XML_TEXT_TYPE_UNIQUE_ID
:
2352 case WS_XML_TEXT_TYPE_DATETIME
:
2353 if (elem
->attributes
[elem
->attributeCount
- 1]->value
) return WS_E_INVALID_OPERATION
;
2357 FIXME( "unhandled text type %u\n", value
->textType
);
2361 switch (writer
->output_enc
)
2363 case WS_XML_WRITER_ENCODING_TYPE_TEXT
:
2365 WS_XML_UTF8_TEXT
*new, *old
= (WS_XML_UTF8_TEXT
*)elem
->attributes
[elem
->attributeCount
- 1]->value
;
2366 if ((hr
= text_to_utf8text( value
, old
, NULL
, &new )) != S_OK
) return hr
;
2368 elem
->attributes
[elem
->attributeCount
- 1]->value
= &new->text
;
2371 case WS_XML_WRITER_ENCODING_TYPE_BINARY
:
2373 WS_XML_TEXT
*new, *old
= elem
->attributes
[elem
->attributeCount
- 1]->value
;
2374 if ((hr
= text_to_text( value
, old
, NULL
, &new )) != S_OK
) return hr
;
2376 elem
->attributes
[elem
->attributeCount
- 1]->value
= new;
2380 FIXME( "unhandled output encoding %u\n", writer
->output_enc
);
2387 static HRESULT
write_add_text_node( struct writer
*writer
, const WS_XML_TEXT
*value
)
2390 WS_XML_TEXT_NODE
*text
;
2393 if (node_type( writer
->current
) != WS_XML_NODE_TYPE_ELEMENT
&&
2394 node_type( writer
->current
) != WS_XML_NODE_TYPE_BOF
&&
2395 node_type( writer
->current
) != WS_XML_NODE_TYPE_CDATA
) return WS_E_INVALID_FORMAT
;
2397 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return E_OUTOFMEMORY
;
2398 text
= (WS_XML_TEXT_NODE
*)node
;
2400 switch (writer
->output_enc
)
2402 case WS_XML_WRITER_ENCODING_TYPE_TEXT
:
2404 WS_XML_UTF8_TEXT
*new;
2405 if ((hr
= text_to_utf8text( value
, NULL
, NULL
, &new )) != S_OK
)
2410 text
->text
= &new->text
;
2413 case WS_XML_WRITER_ENCODING_TYPE_BINARY
:
2416 if ((hr
= text_to_text( value
, NULL
, NULL
, &new )) != S_OK
)
2425 FIXME( "unhandled output encoding %u\n", writer
->output_enc
);
2430 write_insert_node( writer
, writer
->current
, node
);
2434 static HRESULT
write_text_text( struct writer
*writer
, const WS_XML_TEXT
*text
, ULONG offset
)
2436 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)text
;
2439 if (node_type( writer
->current
->parent
) == WS_XML_NODE_TYPE_ELEMENT
)
2441 const struct escape
*escapes
[3] = { &escape_lt
, &escape_gt
, &escape_amp
};
2442 return write_bytes_escape( writer
, utf8
->value
.bytes
+ offset
, utf8
->value
.length
- offset
, escapes
, 3 );
2444 else if (node_type( writer
->current
->parent
) == WS_XML_NODE_TYPE_CDATA
)
2446 if ((hr
= write_grow_buffer( writer
, utf8
->value
.length
- offset
)) != S_OK
) return hr
;
2447 write_bytes( writer
, utf8
->value
.bytes
+ offset
, utf8
->value
.length
- offset
);
2451 return WS_E_INVALID_FORMAT
;
2454 static enum record_type
get_text_record_type( const WS_XML_TEXT
*text
)
2456 switch (text
->textType
)
2458 case WS_XML_TEXT_TYPE_UTF8
:
2460 const WS_XML_UTF8_TEXT
*text_utf8
= (const WS_XML_UTF8_TEXT
*)text
;
2461 if (text_utf8
->value
.length
<= MAX_UINT8
) return RECORD_CHARS8_TEXT_WITH_ENDELEMENT
;
2462 if (text_utf8
->value
.length
<= MAX_UINT16
) return RECORD_CHARS16_TEXT_WITH_ENDELEMENT
;
2463 return RECORD_CHARS32_TEXT_WITH_ENDELEMENT
;
2465 case WS_XML_TEXT_TYPE_BASE64
:
2467 const WS_XML_BASE64_TEXT
*text_base64
= (const WS_XML_BASE64_TEXT
*)text
;
2468 ULONG rem
= text_base64
->length
% 3, len
= text_base64
->length
- rem
;
2469 if (len
<= MAX_UINT8
) return RECORD_BYTES8_TEXT
;
2470 if (len
<= MAX_UINT16
) return RECORD_BYTES16_TEXT
;
2471 return RECORD_BYTES32_TEXT
;
2473 case WS_XML_TEXT_TYPE_BOOL
:
2475 const WS_XML_BOOL_TEXT
*text_bool
= (const WS_XML_BOOL_TEXT
*)text
;
2476 return text_bool
->value
? RECORD_TRUE_TEXT_WITH_ENDELEMENT
: RECORD_FALSE_TEXT_WITH_ENDELEMENT
;
2478 case WS_XML_TEXT_TYPE_INT32
:
2480 const WS_XML_INT32_TEXT
*text_int32
= (const WS_XML_INT32_TEXT
*)text
;
2481 if (!text_int32
->value
) return RECORD_ZERO_TEXT_WITH_ENDELEMENT
;
2482 if (text_int32
->value
== 1) return RECORD_ONE_TEXT_WITH_ENDELEMENT
;
2483 if (text_int32
->value
>= MIN_INT8
&& text_int32
->value
<= MAX_INT8
) return RECORD_INT8_TEXT_WITH_ENDELEMENT
;
2484 if (text_int32
->value
>= MIN_INT16
&& text_int32
->value
<= MAX_INT16
) return RECORD_INT16_TEXT_WITH_ENDELEMENT
;
2485 return RECORD_INT32_TEXT_WITH_ENDELEMENT
;
2487 case WS_XML_TEXT_TYPE_INT64
:
2489 const WS_XML_INT64_TEXT
*text_int64
= (const WS_XML_INT64_TEXT
*)text
;
2490 if (!text_int64
->value
) return RECORD_ZERO_TEXT_WITH_ENDELEMENT
;
2491 if (text_int64
->value
== 1) return RECORD_ONE_TEXT_WITH_ENDELEMENT
;
2492 if (text_int64
->value
>= MIN_INT8
&& text_int64
->value
<= MAX_INT8
) return RECORD_INT8_TEXT_WITH_ENDELEMENT
;
2493 if (text_int64
->value
>= MIN_INT16
&& text_int64
->value
<= MAX_INT16
) return RECORD_INT16_TEXT_WITH_ENDELEMENT
;
2494 if (text_int64
->value
>= MIN_INT32
&& text_int64
->value
<= MAX_INT32
) return RECORD_INT32_TEXT_WITH_ENDELEMENT
;
2495 return RECORD_INT64_TEXT_WITH_ENDELEMENT
;
2497 case WS_XML_TEXT_TYPE_UINT64
:
2499 const WS_XML_UINT64_TEXT
*text_uint64
= (const WS_XML_UINT64_TEXT
*)text
;
2500 if (!text_uint64
->value
) return RECORD_ZERO_TEXT_WITH_ENDELEMENT
;
2501 if (text_uint64
->value
== 1) return RECORD_ONE_TEXT_WITH_ENDELEMENT
;
2502 if (text_uint64
->value
<= MAX_INT8
) return RECORD_INT8_TEXT_WITH_ENDELEMENT
;
2503 if (text_uint64
->value
<= MAX_INT16
) return RECORD_INT16_TEXT_WITH_ENDELEMENT
;
2504 if (text_uint64
->value
<= MAX_INT32
) return RECORD_INT32_TEXT_WITH_ENDELEMENT
;
2505 if (text_uint64
->value
<= MAX_INT64
) return RECORD_INT64_TEXT_WITH_ENDELEMENT
;
2506 return RECORD_UINT64_TEXT_WITH_ENDELEMENT
;
2508 case WS_XML_TEXT_TYPE_DOUBLE
:
2510 const WS_XML_DOUBLE_TEXT
*text_double
= (const WS_XML_DOUBLE_TEXT
*)text
;
2511 if (!text_double
->value
) return RECORD_ZERO_TEXT_WITH_ENDELEMENT
;
2512 if (text_double
->value
== 1) return RECORD_ONE_TEXT_WITH_ENDELEMENT
;
2513 if (isinf( text_double
->value
) || (INT64
)text_double
->value
!= text_double
->value
)
2514 return RECORD_DOUBLE_TEXT_WITH_ENDELEMENT
;
2515 if (text_double
->value
<= MAX_INT8
) return RECORD_INT8_TEXT_WITH_ENDELEMENT
;
2516 if (text_double
->value
<= MAX_INT16
) return RECORD_INT16_TEXT_WITH_ENDELEMENT
;
2517 if (text_double
->value
<= MAX_INT32
) return RECORD_INT32_TEXT_WITH_ENDELEMENT
;
2518 return RECORD_INT64_TEXT_WITH_ENDELEMENT
;
2520 case WS_XML_TEXT_TYPE_GUID
:
2521 return RECORD_GUID_TEXT_WITH_ENDELEMENT
;
2523 case WS_XML_TEXT_TYPE_UNIQUE_ID
:
2524 return RECORD_UNIQUE_ID_TEXT_WITH_ENDELEMENT
;
2526 case WS_XML_TEXT_TYPE_DATETIME
:
2527 return RECORD_DATETIME_TEXT_WITH_ENDELEMENT
;
2530 FIXME( "unhandled text type %u\n", text
->textType
);
2535 static HRESULT
write_text_bin( struct writer
*writer
, const WS_XML_TEXT
*text
, ULONG offset
)
2537 enum record_type type
= get_text_record_type( text
);
2542 FIXME( "no support for appending text in binary mode\n" );
2548 case RECORD_CHARS8_TEXT_WITH_ENDELEMENT
:
2550 const WS_XML_UTF8_TEXT
*text_utf8
= (const WS_XML_UTF8_TEXT
*)text
;
2551 UINT8 len
= text_utf8
->value
.length
;
2553 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(len
) + len
)) != S_OK
) return hr
;
2554 write_char( writer
, type
);
2555 write_char( writer
, len
);
2556 write_bytes( writer
, text_utf8
->value
.bytes
, len
);
2559 case RECORD_CHARS16_TEXT_WITH_ENDELEMENT
:
2561 const WS_XML_UTF8_TEXT
*text_utf8
= (const WS_XML_UTF8_TEXT
*)text
;
2562 UINT16 len
= text_utf8
->value
.length
;
2564 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(len
) + len
)) != S_OK
) return hr
;
2565 write_char( writer
, type
);
2566 write_bytes( writer
, (const BYTE
*)&len
, sizeof(len
) );
2567 write_bytes( writer
, text_utf8
->value
.bytes
, len
);
2570 case RECORD_BYTES8_TEXT
:
2572 const WS_XML_BASE64_TEXT
*text_base64
= (const WS_XML_BASE64_TEXT
*)text
;
2573 UINT8 rem
= text_base64
->length
% 3, len
= text_base64
->length
- rem
;
2577 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(len
) + len
)) != S_OK
) return hr
;
2578 write_char( writer
, rem
? RECORD_BYTES8_TEXT
: RECORD_BYTES8_TEXT_WITH_ENDELEMENT
);
2579 write_char( writer
, len
);
2580 write_bytes( writer
, text_base64
->bytes
, len
);
2584 if ((hr
= write_grow_buffer( writer
, 3 )) != S_OK
) return hr
;
2585 write_char( writer
, RECORD_BYTES8_TEXT_WITH_ENDELEMENT
);
2586 write_char( writer
, rem
);
2587 write_bytes( writer
, (const BYTE
*)text_base64
->bytes
+ len
, rem
);
2591 case RECORD_BYTES16_TEXT
:
2593 const WS_XML_BASE64_TEXT
*text_base64
= (const WS_XML_BASE64_TEXT
*)text
;
2594 UINT16 rem
= text_base64
->length
% 3, len
= text_base64
->length
- rem
;
2598 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(len
) + len
)) != S_OK
) return hr
;
2599 write_char( writer
, rem
? RECORD_BYTES16_TEXT
: RECORD_BYTES16_TEXT_WITH_ENDELEMENT
);
2600 write_bytes( writer
, (const BYTE
*)&len
, sizeof(len
) );
2601 write_bytes( writer
, text_base64
->bytes
, len
);
2605 if ((hr
= write_grow_buffer( writer
, 3 )) != S_OK
) return hr
;
2606 write_char( writer
, RECORD_BYTES8_TEXT_WITH_ENDELEMENT
);
2607 write_char( writer
, rem
);
2608 write_bytes( writer
, (const BYTE
*)text_base64
->bytes
+ len
, rem
);
2612 case RECORD_ZERO_TEXT_WITH_ENDELEMENT
:
2613 case RECORD_ONE_TEXT_WITH_ENDELEMENT
:
2614 case RECORD_FALSE_TEXT_WITH_ENDELEMENT
:
2615 case RECORD_TRUE_TEXT_WITH_ENDELEMENT
:
2617 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
2618 write_char( writer
, type
);
2621 case RECORD_INT8_TEXT_WITH_ENDELEMENT
:
2623 INT8 val
= get_text_value_int( text
);
2624 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(val
) )) != S_OK
) return hr
;
2625 write_char( writer
, type
);
2626 write_char( writer
, val
);
2629 case RECORD_INT16_TEXT_WITH_ENDELEMENT
:
2631 INT16 val
= get_text_value_int( text
);
2632 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(val
) )) != S_OK
) return hr
;
2633 write_char( writer
, type
);
2634 write_bytes( writer
, (const BYTE
*)&val
, sizeof(val
) );
2637 case RECORD_INT32_TEXT_WITH_ENDELEMENT
:
2639 INT32 val
= get_text_value_int( text
);
2640 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(val
) )) != S_OK
) return hr
;
2641 write_char( writer
, type
);
2642 write_bytes( writer
, (const BYTE
*)&val
, sizeof(val
) );
2645 case RECORD_INT64_TEXT_WITH_ENDELEMENT
:
2647 INT64 val
= get_text_value_int( text
);
2648 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(val
) )) != S_OK
) return hr
;
2649 write_char( writer
, type
);
2650 write_bytes( writer
, (const BYTE
*)&val
, sizeof(val
) );
2653 case RECORD_UINT64_TEXT_WITH_ENDELEMENT
:
2655 WS_XML_UINT64_TEXT
*text_uint64
= (WS_XML_UINT64_TEXT
*)text
;
2656 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(text_uint64
->value
) )) != S_OK
) return hr
;
2657 write_char( writer
, type
);
2658 write_bytes( writer
, (const BYTE
*)&text_uint64
->value
, sizeof(text_uint64
->value
) );
2661 case RECORD_DOUBLE_TEXT_WITH_ENDELEMENT
:
2663 WS_XML_DOUBLE_TEXT
*text_double
= (WS_XML_DOUBLE_TEXT
*)text
;
2664 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(text_double
->value
) )) != S_OK
) return hr
;
2665 write_char( writer
, type
);
2666 write_bytes( writer
, (const BYTE
*)&text_double
->value
, sizeof(text_double
->value
) );
2669 case RECORD_GUID_TEXT_WITH_ENDELEMENT
:
2671 WS_XML_GUID_TEXT
*text_guid
= (WS_XML_GUID_TEXT
*)text
;
2672 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(text_guid
->value
) )) != S_OK
) return hr
;
2673 write_char( writer
, type
);
2674 write_bytes( writer
, (const BYTE
*)&text_guid
->value
, sizeof(text_guid
->value
) );
2677 case RECORD_UNIQUE_ID_TEXT_WITH_ENDELEMENT
:
2679 WS_XML_UNIQUE_ID_TEXT
*text_unique_id
= (WS_XML_UNIQUE_ID_TEXT
*)text
;
2680 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(text_unique_id
->value
) )) != S_OK
) return hr
;
2681 write_char( writer
, type
);
2682 write_bytes( writer
, (const BYTE
*)&text_unique_id
->value
, sizeof(text_unique_id
->value
) );
2685 case RECORD_DATETIME_TEXT_WITH_ENDELEMENT
:
2687 WS_XML_DATETIME_TEXT
*text_datetime
= (WS_XML_DATETIME_TEXT
*)text
;
2688 UINT64 val
= text_datetime
->value
.ticks
;
2690 assert( val
<= TICKS_MAX
);
2691 if (text_datetime
->value
.format
== WS_DATETIME_FORMAT_UTC
) val
|= (UINT64
)1 << 62;
2692 else if (text_datetime
->value
.format
== WS_DATETIME_FORMAT_LOCAL
) val
|= (UINT64
)1 << 63;
2694 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(val
) )) != S_OK
) return hr
;
2695 write_char( writer
, type
);
2696 write_bytes( writer
, (const BYTE
*)&val
, sizeof(val
) );
2700 FIXME( "unhandled record type %02x\n", type
);
2705 static HRESULT
write_text( struct writer
*writer
, const WS_XML_TEXT
*text
, ULONG offset
)
2707 if (!writer
->current
->parent
) return WS_E_INVALID_FORMAT
;
2709 switch (writer
->output_enc
)
2711 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_text_text( writer
, text
, offset
);
2712 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return write_text_bin( writer
, text
, offset
);
2714 ERR( "unhandled encoding %u\n", writer
->output_enc
);
2715 return WS_E_NOT_SUPPORTED
;
2719 static HRESULT
write_text_node( struct writer
*writer
, const WS_XML_TEXT
*text
)
2721 WS_XML_TEXT_NODE
*node
= (WS_XML_TEXT_NODE
*)writer
->current
;
2725 if ((hr
= write_flush( writer
)) != S_OK
) return hr
;
2726 if (node_type( writer
->current
) != WS_XML_NODE_TYPE_TEXT
)
2728 if ((hr
= write_add_text_node( writer
, text
)) != S_OK
) return hr
;
2729 node
= (WS_XML_TEXT_NODE
*)writer
->current
;
2733 switch (writer
->output_enc
)
2735 case WS_XML_WRITER_ENCODING_TYPE_TEXT
:
2737 WS_XML_UTF8_TEXT
*new, *old
= (WS_XML_UTF8_TEXT
*)node
->text
;
2738 offset
= old
->value
.length
;
2739 if ((hr
= text_to_utf8text( text
, old
, &offset
, &new )) != S_OK
) return hr
;
2741 node
->text
= &new->text
;
2744 case WS_XML_WRITER_ENCODING_TYPE_BINARY
:
2746 WS_XML_TEXT
*new, *old
= node
->text
;
2747 if ((hr
= text_to_text( text
, old
, &offset
, &new )) != S_OK
) return hr
;
2753 FIXME( "unhandled output encoding %u\n", writer
->output_enc
);
2758 if ((hr
= write_text( writer
, node
->text
, offset
)) != S_OK
) return hr
;
2760 writer
->state
= WRITER_STATE_TEXT
;
2764 /**************************************************************************
2765 * WsWriteText [webservices.@]
2767 HRESULT WINAPI
WsWriteText( WS_XML_WRITER
*handle
, const WS_XML_TEXT
*text
, WS_ERROR
*error
)
2769 struct writer
*writer
= (struct writer
*)handle
;
2772 TRACE( "%p %p %p\n", handle
, text
, error
);
2773 if (error
) FIXME( "ignoring error parameter\n" );
2775 if (!writer
|| !text
) return E_INVALIDARG
;
2777 EnterCriticalSection( &writer
->cs
);
2779 if (writer
->magic
!= WRITER_MAGIC
)
2781 LeaveCriticalSection( &writer
->cs
);
2782 return E_INVALIDARG
;
2785 if (writer
->state
== WRITER_STATE_STARTATTRIBUTE
) hr
= write_set_attribute_value( writer
, text
);
2786 else hr
= write_text_node( writer
, text
);
2788 LeaveCriticalSection( &writer
->cs
);
2792 /**************************************************************************
2793 * WsWriteBytes [webservices.@]
2795 HRESULT WINAPI
WsWriteBytes( WS_XML_WRITER
*handle
, const void *bytes
, ULONG count
, WS_ERROR
*error
)
2797 struct writer
*writer
= (struct writer
*)handle
;
2798 WS_XML_BASE64_TEXT base64
;
2801 TRACE( "%p %p %u %p\n", handle
, bytes
, count
, error
);
2802 if (error
) FIXME( "ignoring error parameter\n" );
2804 if (!writer
) return E_INVALIDARG
;
2806 EnterCriticalSection( &writer
->cs
);
2808 if (writer
->magic
!= WRITER_MAGIC
)
2810 LeaveCriticalSection( &writer
->cs
);
2811 return E_INVALIDARG
;
2814 if (!writer
->output_type
)
2816 LeaveCriticalSection( &writer
->cs
);
2817 return WS_E_INVALID_OPERATION
;
2820 base64
.text
.textType
= WS_XML_TEXT_TYPE_BASE64
;
2821 base64
.bytes
= (BYTE
*)bytes
;
2822 base64
.length
= count
;
2824 if (writer
->state
== WRITER_STATE_STARTATTRIBUTE
) hr
= write_set_attribute_value( writer
, &base64
.text
);
2825 else hr
= write_text_node( writer
, &base64
.text
);
2827 LeaveCriticalSection( &writer
->cs
);
2831 /**************************************************************************
2832 * WsWriteChars [webservices.@]
2834 HRESULT WINAPI
WsWriteChars( WS_XML_WRITER
*handle
, const WCHAR
*chars
, ULONG count
, WS_ERROR
*error
)
2836 struct writer
*writer
= (struct writer
*)handle
;
2837 WS_XML_UTF16_TEXT utf16
;
2840 TRACE( "%p %s %u %p\n", handle
, debugstr_wn(chars
, count
), count
, error
);
2841 if (error
) FIXME( "ignoring error parameter\n" );
2843 if (!writer
) return E_INVALIDARG
;
2845 EnterCriticalSection( &writer
->cs
);
2847 if (writer
->magic
!= WRITER_MAGIC
)
2849 LeaveCriticalSection( &writer
->cs
);
2850 return E_INVALIDARG
;
2853 if (!writer
->output_type
)
2855 LeaveCriticalSection( &writer
->cs
);
2856 return WS_E_INVALID_OPERATION
;
2859 utf16
.text
.textType
= WS_XML_TEXT_TYPE_UTF16
;
2860 utf16
.bytes
= (BYTE
*)chars
;
2861 utf16
.byteCount
= count
* sizeof(WCHAR
);
2863 if (writer
->state
== WRITER_STATE_STARTATTRIBUTE
) hr
= write_set_attribute_value( writer
, &utf16
.text
);
2864 else hr
= write_text_node( writer
, &utf16
.text
);
2866 LeaveCriticalSection( &writer
->cs
);
2870 /**************************************************************************
2871 * WsWriteCharsUtf8 [webservices.@]
2873 HRESULT WINAPI
WsWriteCharsUtf8( WS_XML_WRITER
*handle
, const BYTE
*bytes
, ULONG count
, WS_ERROR
*error
)
2875 struct writer
*writer
= (struct writer
*)handle
;
2876 WS_XML_UTF8_TEXT utf8
;
2879 TRACE( "%p %s %u %p\n", handle
, debugstr_an((const char *)bytes
, count
), count
, error
);
2880 if (error
) FIXME( "ignoring error parameter\n" );
2882 if (!writer
) return E_INVALIDARG
;
2884 EnterCriticalSection( &writer
->cs
);
2886 if (writer
->magic
!= WRITER_MAGIC
)
2888 LeaveCriticalSection( &writer
->cs
);
2889 return E_INVALIDARG
;
2892 if (!writer
->output_type
)
2894 LeaveCriticalSection( &writer
->cs
);
2895 return WS_E_INVALID_OPERATION
;
2898 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
2899 utf8
.value
.bytes
= (BYTE
*)bytes
;
2900 utf8
.value
.length
= count
;
2902 if (writer
->state
== WRITER_STATE_STARTATTRIBUTE
) hr
= write_set_attribute_value( writer
, &utf8
.text
);
2903 else hr
= write_text_node( writer
, &utf8
.text
);
2905 LeaveCriticalSection( &writer
->cs
);
2909 static HRESULT
write_type_text( struct writer
*writer
, WS_TYPE_MAPPING mapping
, const WS_XML_TEXT
*text
)
2913 case WS_ELEMENT_TYPE_MAPPING
:
2914 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
2915 return write_text_node( writer
, text
);
2917 case WS_ATTRIBUTE_TYPE_MAPPING
:
2918 return write_set_attribute_value( writer
, text
);
2920 case WS_ANY_ELEMENT_TYPE_MAPPING
:
2921 switch (writer
->state
)
2923 case WRITER_STATE_STARTATTRIBUTE
:
2924 return write_set_attribute_value( writer
, text
);
2926 case WRITER_STATE_STARTELEMENT
:
2927 return write_text_node( writer
, text
);
2930 FIXME( "writer state %u not handled\n", writer
->state
);
2935 FIXME( "mapping %u not implemented\n", mapping
);
2940 static HRESULT
write_add_nil_attribute( struct writer
*writer
)
2942 static const WS_XML_STRING prefix
= {1, (BYTE
*)"a"};
2943 static const WS_XML_STRING localname
= {3, (BYTE
*)"nil"};
2944 static const WS_XML_STRING ns
= {41, (BYTE
*)"http://www.w3.org/2001/XMLSchema-instance"};
2945 static const WS_XML_UTF8_TEXT value
= {{WS_XML_TEXT_TYPE_UTF8
}, {4, (BYTE
*)"true"}};
2948 if ((hr
= write_add_attribute( writer
, &prefix
, &localname
, &ns
, FALSE
)) != S_OK
) return hr
;
2949 if ((hr
= write_set_attribute_value( writer
, &value
.text
)) != S_OK
) return hr
;
2950 return add_namespace_attribute( writer
, &prefix
, &ns
, FALSE
);
2953 static HRESULT
get_value_ptr( WS_WRITE_OPTION option
, const void *value
, ULONG size
, ULONG expected_size
,
2958 case WS_WRITE_REQUIRED_VALUE
:
2959 case WS_WRITE_NILLABLE_VALUE
:
2960 if (!value
|| size
!= expected_size
) return E_INVALIDARG
;
2964 case WS_WRITE_REQUIRED_POINTER
:
2965 if (size
!= sizeof(const void *) || !(*ptr
= *(const void **)value
)) return E_INVALIDARG
;
2968 case WS_WRITE_NILLABLE_POINTER
:
2969 if (size
!= sizeof(const void *)) return E_INVALIDARG
;
2970 *ptr
= *(const void **)value
;
2974 return E_INVALIDARG
;
2978 static HRESULT
write_type_bool( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
2979 const WS_BOOL_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
2980 const BOOL
*value
, ULONG size
)
2982 WS_XML_BOOL_TEXT text_bool
;
2988 FIXME( "description not supported\n" );
2992 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
2993 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(BOOL
), (const void **)&ptr
)) != S_OK
) return hr
;
2994 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
2996 text_bool
.text
.textType
= WS_XML_TEXT_TYPE_BOOL
;
2997 text_bool
.value
= *ptr
;
2998 return write_type_text( writer
, mapping
, &text_bool
.text
);
3001 static HRESULT
write_type_int8( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3002 const WS_INT8_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3003 const BOOL
*value
, ULONG size
)
3005 WS_XML_INT32_TEXT text_int32
;
3011 FIXME( "description not supported\n" );
3015 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3016 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(INT8
), (const void **)&ptr
)) != S_OK
) return hr
;
3017 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3019 text_int32
.text
.textType
= WS_XML_TEXT_TYPE_INT32
;
3020 text_int32
.value
= *ptr
;
3021 return write_type_text( writer
, mapping
, &text_int32
.text
);
3024 static HRESULT
write_type_int16( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3025 const WS_INT16_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3026 const BOOL
*value
, ULONG size
)
3028 WS_XML_INT32_TEXT text_int32
;
3034 FIXME( "description not supported\n" );
3038 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3039 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(INT16
), (const void **)&ptr
)) != S_OK
) return hr
;
3040 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3042 text_int32
.text
.textType
= WS_XML_TEXT_TYPE_INT32
;
3043 text_int32
.value
= *ptr
;
3044 return write_type_text( writer
, mapping
, &text_int32
.text
);
3047 static HRESULT
write_type_int32( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3048 const WS_INT32_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3049 const void *value
, ULONG size
)
3051 WS_XML_INT32_TEXT text_int32
;
3057 FIXME( "description not supported\n" );
3061 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3062 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(INT32
), (const void **)&ptr
)) != S_OK
) return hr
;
3063 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3065 text_int32
.text
.textType
= WS_XML_TEXT_TYPE_INT32
;
3066 text_int32
.value
= *ptr
;
3067 return write_type_text( writer
, mapping
, &text_int32
.text
);
3070 static HRESULT
write_type_int64( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3071 const WS_INT64_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3072 const void *value
, ULONG size
)
3074 WS_XML_INT64_TEXT text_int64
;
3080 FIXME( "description not supported\n" );
3084 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3085 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(INT64
), (const void **)&ptr
)) != S_OK
) return hr
;
3086 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3088 text_int64
.text
.textType
= WS_XML_TEXT_TYPE_INT64
;
3089 text_int64
.value
= *ptr
;
3090 return write_type_text( writer
, mapping
, &text_int64
.text
);
3093 static HRESULT
write_type_uint8( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3094 const WS_UINT8_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3095 const void *value
, ULONG size
)
3097 WS_XML_UINT64_TEXT text_uint64
;
3103 FIXME( "description not supported\n" );
3107 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3108 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(UINT8
), (const void **)&ptr
)) != S_OK
) return hr
;
3109 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3111 text_uint64
.text
.textType
= WS_XML_TEXT_TYPE_UINT64
;
3112 text_uint64
.value
= *ptr
;
3113 return write_type_text( writer
, mapping
, &text_uint64
.text
);
3116 static HRESULT
write_type_uint16( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3117 const WS_UINT16_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3118 const void *value
, ULONG size
)
3120 WS_XML_UINT64_TEXT text_uint64
;
3126 FIXME( "description not supported\n" );
3130 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3131 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(UINT16
), (const void **)&ptr
)) != S_OK
) return hr
;
3132 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3134 text_uint64
.text
.textType
= WS_XML_TEXT_TYPE_UINT64
;
3135 text_uint64
.value
= *ptr
;
3136 return write_type_text( writer
, mapping
, &text_uint64
.text
);
3139 static HRESULT
write_type_uint32( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3140 const WS_UINT32_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3141 const void *value
, ULONG size
)
3143 WS_XML_UINT64_TEXT text_uint64
;
3149 FIXME( "description not supported\n" );
3153 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3154 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(UINT32
), (const void **)&ptr
)) != S_OK
) return hr
;
3155 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3157 text_uint64
.text
.textType
= WS_XML_TEXT_TYPE_UINT64
;
3158 text_uint64
.value
= *ptr
;
3159 return write_type_text( writer
, mapping
, &text_uint64
.text
);
3162 static HRESULT
write_type_uint64( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3163 const WS_UINT64_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3164 const void *value
, ULONG size
)
3166 WS_XML_UINT64_TEXT text_uint64
;
3172 FIXME( "description not supported\n" );
3176 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3177 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(UINT64
), (const void **)&ptr
)) != S_OK
) return hr
;
3178 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3180 text_uint64
.text
.textType
= WS_XML_TEXT_TYPE_UINT64
;
3181 text_uint64
.value
= *ptr
;
3182 return write_type_text( writer
, mapping
, &text_uint64
.text
);
3185 static HRESULT
write_type_double( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3186 const WS_DOUBLE_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3187 const void *value
, ULONG size
)
3189 WS_XML_DOUBLE_TEXT text_double
;
3195 FIXME( "description not supported\n" );
3199 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3200 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(double), (const void **)&ptr
)) != S_OK
) return hr
;
3201 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3203 text_double
.text
.textType
= WS_XML_TEXT_TYPE_DOUBLE
;
3204 text_double
.value
= *ptr
;
3205 return write_type_text( writer
, mapping
, &text_double
.text
);
3208 static HRESULT
write_type_datetime( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3209 const WS_DATETIME_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3210 const void *value
, ULONG size
)
3212 WS_XML_DATETIME_TEXT text_datetime
;
3213 const WS_DATETIME
*ptr
;
3218 FIXME( "description not supported\n" );
3222 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3223 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(WS_DATETIME
), (const void **)&ptr
)) != S_OK
) return hr
;
3224 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3225 if (ptr
->ticks
> TICKS_MAX
|| ptr
->format
> WS_DATETIME_FORMAT_NONE
) return WS_E_INVALID_FORMAT
;
3227 text_datetime
.text
.textType
= WS_XML_TEXT_TYPE_DATETIME
;
3228 text_datetime
.value
= *ptr
;
3229 return write_type_text( writer
, mapping
, &text_datetime
.text
);
3232 static HRESULT
write_type_guid( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3233 const WS_GUID_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3234 const void *value
, ULONG size
)
3236 WS_XML_GUID_TEXT text_guid
;
3242 FIXME( "description not supported\n" );
3246 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3247 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(GUID
), (const void **)&ptr
)) != S_OK
) return hr
;
3248 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3250 text_guid
.text
.textType
= WS_XML_TEXT_TYPE_GUID
;
3251 text_guid
.value
= *ptr
;
3252 return write_type_text( writer
, mapping
, &text_guid
.text
);
3255 static HRESULT
write_type_unique_id( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3256 const WS_UNIQUE_ID_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3257 const void *value
, ULONG size
)
3259 WS_XML_UNIQUE_ID_TEXT text_unique_id
;
3260 WS_XML_UTF16_TEXT text_utf16
;
3261 const WS_UNIQUE_ID
*ptr
;
3266 FIXME( "description not supported\n" );
3270 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3271 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(*ptr
), (const void **)&ptr
)) != S_OK
) return hr
;
3272 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3274 if (ptr
->uri
.length
)
3276 text_utf16
.text
.textType
= WS_XML_TEXT_TYPE_UTF16
;
3277 text_utf16
.bytes
= (BYTE
*)ptr
->uri
.chars
;
3278 text_utf16
.byteCount
= ptr
->uri
.length
* sizeof(WCHAR
);
3279 return write_type_text( writer
, mapping
, &text_utf16
.text
);
3282 text_unique_id
.text
.textType
= WS_XML_TEXT_TYPE_UNIQUE_ID
;
3283 text_unique_id
.value
= ptr
->guid
;
3284 return write_type_text( writer
, mapping
, &text_unique_id
.text
);
3287 static HRESULT
write_type_string( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3288 const WS_STRING_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3289 const void *value
, ULONG size
)
3291 WS_XML_UTF16_TEXT utf16
;
3292 const WS_STRING
*ptr
;
3297 FIXME( "description not supported\n" );
3301 if (!option
) return E_INVALIDARG
;
3302 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(WS_STRING
), (const void **)&ptr
)) != S_OK
) return hr
;
3303 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3304 if (!ptr
->length
) return S_OK
;
3306 utf16
.text
.textType
= WS_XML_TEXT_TYPE_UTF16
;
3307 utf16
.bytes
= (BYTE
*)ptr
->chars
;
3308 utf16
.byteCount
= ptr
->length
* sizeof(WCHAR
);
3309 return write_type_text( writer
, mapping
, &utf16
.text
);
3312 static HRESULT
write_type_wsz( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3313 const WS_WSZ_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3314 const void *value
, ULONG size
)
3316 WS_XML_UTF16_TEXT utf16
;
3323 FIXME( "description not supported\n" );
3327 if (!option
|| option
== WS_WRITE_REQUIRED_VALUE
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3328 if ((hr
= get_value_ptr( option
, value
, size
, 0, (const void **)&ptr
)) != S_OK
) return hr
;
3329 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3330 if (!(len
= strlenW( ptr
))) return S_OK
;
3332 utf16
.text
.textType
= WS_XML_TEXT_TYPE_UTF16
;
3333 utf16
.bytes
= (BYTE
*)ptr
;
3334 utf16
.byteCount
= len
* sizeof(WCHAR
);
3335 return write_type_text( writer
, mapping
, &utf16
.text
);
3338 static HRESULT
write_type_bytes( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3339 const WS_BYTES_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3340 const void *value
, ULONG size
)
3342 WS_XML_BASE64_TEXT base64
;
3343 const WS_BYTES
*ptr
;
3348 FIXME( "description not supported\n" );
3352 if (!option
) return E_INVALIDARG
;
3353 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(WS_BYTES
), (const void **)&ptr
)) != S_OK
) return hr
;
3354 if ((option
== WS_WRITE_NILLABLE_VALUE
&& is_nil_value( value
, size
)) ||
3355 (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
)) return write_add_nil_attribute( writer
);
3356 if (!ptr
->length
) return S_OK
;
3358 base64
.text
.textType
= WS_XML_TEXT_TYPE_BASE64
;
3359 base64
.bytes
= ptr
->bytes
;
3360 base64
.length
= ptr
->length
;
3361 return write_type_text( writer
, mapping
, &base64
.text
);
3364 static HRESULT
write_type_xml_string( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3365 const WS_XML_STRING_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3366 const void *value
, ULONG size
)
3368 WS_XML_UTF8_TEXT utf8
;
3369 const WS_XML_STRING
*ptr
;
3374 FIXME( "description not supported\n" );
3378 if (!option
) return E_INVALIDARG
;
3379 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(WS_XML_STRING
), (const void **)&ptr
)) != S_OK
) return hr
;
3380 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3381 if (option
== WS_WRITE_NILLABLE_VALUE
&& is_nil_value( value
, size
)) return write_add_nil_attribute( writer
);
3382 if (!ptr
->length
) return S_OK
;
3384 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
3385 utf8
.value
.bytes
= ptr
->bytes
;
3386 utf8
.value
.length
= ptr
->length
;
3387 return write_type_text( writer
, mapping
, &utf8
.text
);
3390 static HRESULT
find_prefix( struct writer
*writer
, const WS_XML_STRING
*ns
, const WS_XML_STRING
**prefix
)
3392 const struct node
*node
;
3393 for (node
= writer
->current
; node_type( node
) == WS_XML_NODE_TYPE_ELEMENT
; node
= node
->parent
)
3395 const WS_XML_ELEMENT_NODE
*elem
= &node
->hdr
;
3397 for (i
= 0; i
< elem
->attributeCount
; i
++)
3399 if (!elem
->attributes
[i
]->isXmlNs
) continue;
3400 if (WsXmlStringEquals( elem
->attributes
[i
]->ns
, ns
, NULL
) != S_OK
) continue;
3401 *prefix
= elem
->attributes
[i
]->prefix
;
3405 return WS_E_INVALID_FORMAT
;
3408 static HRESULT
write_type_qname( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3409 const WS_XML_QNAME_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3410 const void *value
, ULONG size
)
3412 WS_XML_QNAME_TEXT qname
;
3413 const WS_XML_QNAME
*ptr
;
3414 const WS_XML_STRING
*prefix
;
3419 FIXME( "description not supported\n" );
3423 if (!option
) return E_INVALIDARG
;
3424 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(*ptr
), (const void **)&ptr
)) != S_OK
) return hr
;
3425 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3426 if (option
== WS_WRITE_NILLABLE_VALUE
&& is_nil_value( value
, size
)) return write_add_nil_attribute( writer
);
3428 if (((hr
= find_prefix( writer
, &ptr
->ns
, &prefix
)) != S_OK
)) return hr
;
3430 qname
.text
.textType
= WS_XML_TEXT_TYPE_QNAME
;
3431 qname
.prefix
= (WS_XML_STRING
*)prefix
;
3432 qname
.localName
= (WS_XML_STRING
*)&ptr
->localName
;
3433 qname
.ns
= (WS_XML_STRING
*)&ptr
->ns
;
3434 return write_type_text( writer
, mapping
, &qname
.text
);
3437 static WS_WRITE_OPTION
get_field_write_option( WS_TYPE type
, ULONG options
)
3439 if (options
& WS_FIELD_POINTER
)
3441 if (options
& (WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
)) return WS_WRITE_NILLABLE_POINTER
;
3442 return WS_WRITE_REQUIRED_POINTER
;
3453 case WS_UINT16_TYPE
:
3454 case WS_UINT32_TYPE
:
3455 case WS_UINT64_TYPE
:
3456 case WS_DOUBLE_TYPE
:
3457 case WS_DATETIME_TYPE
:
3459 case WS_UNIQUE_ID_TYPE
:
3460 case WS_STRING_TYPE
:
3462 case WS_XML_STRING_TYPE
:
3463 case WS_XML_QNAME_TYPE
:
3464 case WS_STRUCT_TYPE
:
3466 if (options
& (WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
)) return WS_WRITE_NILLABLE_VALUE
;
3467 return WS_WRITE_REQUIRED_VALUE
;
3470 case WS_DESCRIPTION_TYPE
:
3471 if (options
& (WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
)) return WS_WRITE_NILLABLE_POINTER
;
3472 return WS_WRITE_REQUIRED_POINTER
;
3475 FIXME( "unhandled type %u\n", type
);
3480 static HRESULT
write_type( struct writer
*, WS_TYPE_MAPPING
, WS_TYPE
, const void *, WS_WRITE_OPTION
,
3481 const void *, ULONG
);
3483 static HRESULT
write_type_repeating_element( struct writer
*writer
, const WS_FIELD_DESCRIPTION
*desc
,
3484 const char *buf
, ULONG count
)
3487 ULONG i
, size
, offset
= 0;
3488 WS_WRITE_OPTION option
;
3490 if (!(option
= get_field_write_option( desc
->type
, desc
->options
))) return E_INVALIDARG
;
3492 /* wrapper element */
3493 if (desc
->localName
&& ((hr
= write_element_node( writer
, NULL
, desc
->localName
, desc
->ns
)) != S_OK
))
3496 if (option
== WS_WRITE_REQUIRED_VALUE
|| option
== WS_WRITE_NILLABLE_VALUE
)
3497 size
= get_type_size( desc
->type
, desc
->typeDescription
);
3499 size
= sizeof(const void *);
3501 for (i
= 0; i
< count
; i
++)
3503 if ((hr
= write_element_node( writer
, NULL
, desc
->itemLocalName
, desc
->itemNs
)) != S_OK
) return hr
;
3504 if ((hr
= write_type( writer
, WS_ELEMENT_TYPE_MAPPING
, desc
->type
, desc
->typeDescription
, option
,
3505 buf
+ offset
, size
)) != S_OK
) return hr
;
3506 if ((hr
= write_endelement_node( writer
)) != S_OK
) return hr
;
3510 if (desc
->localName
) hr
= write_endelement_node( writer
);
3514 static HRESULT
write_type_field( struct writer
*, const WS_FIELD_DESCRIPTION
*, const char *, ULONG
);
3516 static HRESULT
write_type_union( struct writer
*writer
, const WS_UNION_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3517 const void *value
, ULONG size
)
3524 if ((hr
= get_value_ptr( option
, value
, size
, desc
->size
, &ptr
)) != S_OK
) return hr
;
3526 if (size
< sizeof(enum_value
)) return E_INVALIDARG
;
3527 if ((enum_value
= *(int *)(char *)ptr
+ desc
->enumOffset
) == desc
->noneEnumValue
)
3531 case WS_WRITE_REQUIRED_VALUE
:
3532 return WS_E_INVALID_FORMAT
;
3534 case WS_WRITE_NILLABLE_VALUE
:
3538 ERR( "unhandled write option %u\n", option
);
3539 return E_INVALIDARG
;
3543 for (i
= 0; i
< desc
->fieldCount
; i
++)
3545 if (desc
->fields
[i
]->value
== enum_value
)
3547 offset
= desc
->fields
[i
]->field
.offset
;
3548 return write_type_field( writer
, &desc
->fields
[i
]->field
, ptr
, offset
);
3552 return E_INVALIDARG
;
3555 static HRESULT
write_type_field( struct writer
*writer
, const WS_FIELD_DESCRIPTION
*desc
, const char *buf
,
3559 WS_TYPE_MAPPING mapping
;
3560 WS_WRITE_OPTION option
;
3561 ULONG count
, size
, field_options
= desc
->options
;
3562 const char *ptr
= buf
+ offset
;
3564 if (field_options
& ~(WS_FIELD_POINTER
|WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
))
3566 FIXME( "options 0x%x not supported\n", desc
->options
);
3570 /* zero-terminated strings are always pointers */
3571 if (desc
->type
== WS_WSZ_TYPE
) field_options
|= WS_FIELD_POINTER
;
3573 if (field_options
& WS_FIELD_POINTER
)
3574 size
= sizeof(const void *);
3576 size
= get_type_size( desc
->type
, desc
->typeDescription
);
3578 if (is_nil_value( ptr
, size
))
3580 if (field_options
& WS_FIELD_OPTIONAL
) return S_OK
;
3581 if (field_options
& WS_FIELD_NILLABLE
)
3583 if (field_options
& WS_FIELD_POINTER
) option
= WS_WRITE_NILLABLE_POINTER
;
3584 else option
= WS_WRITE_NILLABLE_VALUE
;
3588 if (field_options
& WS_FIELD_POINTER
) option
= WS_WRITE_REQUIRED_POINTER
;
3589 else option
= WS_WRITE_REQUIRED_VALUE
;
3594 if (field_options
& WS_FIELD_POINTER
) option
= WS_WRITE_REQUIRED_POINTER
;
3595 else option
= WS_WRITE_REQUIRED_VALUE
;
3598 switch (desc
->mapping
)
3600 case WS_ATTRIBUTE_FIELD_MAPPING
:
3601 if (!desc
->localName
|| !desc
->ns
) return E_INVALIDARG
;
3602 if ((hr
= write_add_attribute( writer
, NULL
, desc
->localName
, desc
->ns
, FALSE
)) != S_OK
)
3604 writer
->state
= WRITER_STATE_STARTATTRIBUTE
;
3606 mapping
= WS_ATTRIBUTE_TYPE_MAPPING
;
3609 case WS_ELEMENT_FIELD_MAPPING
:
3610 if ((hr
= write_element_node( writer
, NULL
, desc
->localName
, desc
->ns
)) != S_OK
) return hr
;
3611 mapping
= WS_ELEMENT_TYPE_MAPPING
;
3614 case WS_ELEMENT_CHOICE_FIELD_MAPPING
:
3615 if (desc
->type
!= WS_UNION_TYPE
|| !desc
->typeDescription
) return E_INVALIDARG
;
3616 option
= (field_options
& WS_FIELD_OPTIONAL
) ? WS_WRITE_NILLABLE_VALUE
: WS_WRITE_REQUIRED_VALUE
;
3617 return write_type_union( writer
, desc
->typeDescription
, option
, ptr
, size
);
3619 case WS_REPEATING_ELEMENT_FIELD_MAPPING
:
3620 count
= *(const ULONG
*)(buf
+ desc
->countOffset
);
3621 return write_type_repeating_element( writer
, desc
, *(const char **)ptr
, count
);
3623 case WS_TEXT_FIELD_MAPPING
:
3624 switch (writer
->state
)
3626 case WRITER_STATE_STARTELEMENT
:
3627 mapping
= WS_ELEMENT_CONTENT_TYPE_MAPPING
;
3630 case WRITER_STATE_STARTATTRIBUTE
:
3631 mapping
= WS_ATTRIBUTE_TYPE_MAPPING
;
3635 FIXME( "unhandled writer state %u\n", writer
->state
);
3641 FIXME( "field mapping %u not supported\n", desc
->mapping
);
3645 if ((hr
= write_type( writer
, mapping
, desc
->type
, desc
->typeDescription
, option
, ptr
, size
)) != S_OK
)
3650 case WS_ATTRIBUTE_TYPE_MAPPING
:
3651 writer
->state
= WRITER_STATE_STARTELEMENT
;
3654 case WS_ELEMENT_TYPE_MAPPING
:
3655 if ((hr
= write_endelement_node( writer
)) != S_OK
) return hr
;
3664 static HRESULT
write_type_struct( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3665 const WS_STRUCT_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3666 const void *value
, ULONG size
)
3672 if (!desc
) return E_INVALIDARG
;
3673 if (desc
->structOptions
) FIXME( "struct options 0x%x not supported\n", desc
->structOptions
);
3675 if ((hr
= get_value_ptr( option
, value
, size
, desc
->size
, &ptr
)) != S_OK
) return hr
;
3677 for (i
= 0; i
< desc
->fieldCount
; i
++)
3679 offset
= desc
->fields
[i
]->offset
;
3680 if ((hr
= write_type_field( writer
, desc
->fields
[i
], ptr
, offset
)) != S_OK
) return hr
;
3686 static HRESULT
write_type( struct writer
*writer
, WS_TYPE_MAPPING mapping
, WS_TYPE type
,
3687 const void *desc
, WS_WRITE_OPTION option
, const void *value
,
3693 return write_type_bool( writer
, mapping
, desc
, option
, value
, size
);
3696 return write_type_int8( writer
, mapping
, desc
, option
, value
, size
);
3699 return write_type_int16( writer
, mapping
, desc
, option
, value
, size
);
3702 return write_type_int32( writer
, mapping
, desc
, option
, value
, size
);
3705 return write_type_int64( writer
, mapping
, desc
, option
, value
, size
);
3708 return write_type_uint8( writer
, mapping
, desc
, option
, value
, size
);
3710 case WS_UINT16_TYPE
:
3711 return write_type_uint16( writer
, mapping
, desc
, option
, value
, size
);
3713 case WS_UINT32_TYPE
:
3714 return write_type_uint32( writer
, mapping
, desc
, option
, value
, size
);
3716 case WS_UINT64_TYPE
:
3717 return write_type_uint64( writer
, mapping
, desc
, option
, value
, size
);
3719 case WS_DOUBLE_TYPE
:
3720 return write_type_double( writer
, mapping
, desc
, option
, value
, size
);
3722 case WS_DATETIME_TYPE
:
3723 return write_type_datetime( writer
, mapping
, desc
, option
, value
, size
);
3726 return write_type_guid( writer
, mapping
, desc
, option
, value
, size
);
3728 case WS_UNIQUE_ID_TYPE
:
3729 return write_type_unique_id( writer
, mapping
, desc
, option
, value
, size
);
3731 case WS_STRING_TYPE
:
3732 return write_type_string( writer
, mapping
, desc
, option
, value
, size
);
3735 return write_type_wsz( writer
, mapping
, desc
, option
, value
, size
);
3738 return write_type_bytes( writer
, mapping
, desc
, option
, value
, size
);
3740 case WS_XML_STRING_TYPE
:
3741 return write_type_xml_string( writer
, mapping
, desc
, option
, value
, size
);
3743 case WS_XML_QNAME_TYPE
:
3744 return write_type_qname( writer
, mapping
, desc
, option
, value
, size
);
3746 case WS_STRUCT_TYPE
:
3747 return write_type_struct( writer
, mapping
, desc
, option
, value
, size
);
3750 FIXME( "type %u not supported\n", type
);
3755 /**************************************************************************
3756 * WsWriteAttribute [webservices.@]
3758 HRESULT WINAPI
WsWriteAttribute( WS_XML_WRITER
*handle
, const WS_ATTRIBUTE_DESCRIPTION
*desc
,
3759 WS_WRITE_OPTION option
, const void *value
, ULONG size
,
3762 struct writer
*writer
= (struct writer
*)handle
;
3765 TRACE( "%p %p %u %p %u %p\n", handle
, desc
, option
, value
, size
, error
);
3766 if (error
) FIXME( "ignoring error parameter\n" );
3768 if (!writer
|| !desc
|| !desc
->attributeLocalName
|| !desc
->attributeNs
|| !value
)
3769 return E_INVALIDARG
;
3771 EnterCriticalSection( &writer
->cs
);
3773 if (writer
->magic
!= WRITER_MAGIC
)
3775 LeaveCriticalSection( &writer
->cs
);
3776 return E_INVALIDARG
;
3779 if (writer
->state
!= WRITER_STATE_STARTELEMENT
)
3781 LeaveCriticalSection( &writer
->cs
);
3782 return WS_E_INVALID_OPERATION
;
3785 if ((hr
= write_add_attribute( writer
, NULL
, desc
->attributeLocalName
, desc
->attributeNs
, FALSE
)) != S_OK
)
3787 LeaveCriticalSection( &writer
->cs
);
3790 writer
->state
= WRITER_STATE_STARTATTRIBUTE
;
3792 hr
= write_type( writer
, WS_ATTRIBUTE_TYPE_MAPPING
, desc
->type
, desc
->typeDescription
, option
, value
, size
);
3794 LeaveCriticalSection( &writer
->cs
);
3798 /**************************************************************************
3799 * WsWriteElement [webservices.@]
3801 HRESULT WINAPI
WsWriteElement( WS_XML_WRITER
*handle
, const WS_ELEMENT_DESCRIPTION
*desc
,
3802 WS_WRITE_OPTION option
, const void *value
, ULONG size
,
3805 struct writer
*writer
= (struct writer
*)handle
;
3808 TRACE( "%p %p %u %p %u %p\n", handle
, desc
, option
, value
, size
, error
);
3809 if (error
) FIXME( "ignoring error parameter\n" );
3811 if (!writer
|| !desc
|| !desc
->elementLocalName
|| !desc
->elementNs
|| !value
)
3812 return E_INVALIDARG
;
3814 EnterCriticalSection( &writer
->cs
);
3816 if (writer
->magic
!= WRITER_MAGIC
)
3818 LeaveCriticalSection( &writer
->cs
);
3819 return E_INVALIDARG
;
3822 if ((hr
= write_element_node( writer
, NULL
, desc
->elementLocalName
, desc
->elementNs
)) != S_OK
) goto done
;
3824 if ((hr
= write_type( writer
, WS_ANY_ELEMENT_TYPE_MAPPING
, desc
->type
, desc
->typeDescription
,
3825 option
, value
, size
)) != S_OK
) goto done
;
3827 hr
= write_endelement_node( writer
);
3830 LeaveCriticalSection( &writer
->cs
);
3834 /**************************************************************************
3835 * WsWriteType [webservices.@]
3837 HRESULT WINAPI
WsWriteType( WS_XML_WRITER
*handle
, WS_TYPE_MAPPING mapping
, WS_TYPE type
,
3838 const void *desc
, WS_WRITE_OPTION option
, const void *value
,
3839 ULONG size
, WS_ERROR
*error
)
3841 struct writer
*writer
= (struct writer
*)handle
;
3844 TRACE( "%p %u %u %p %u %p %u %p\n", handle
, mapping
, type
, desc
, option
, value
,
3846 if (error
) FIXME( "ignoring error parameter\n" );
3848 if (!writer
|| !value
) return E_INVALIDARG
;
3850 EnterCriticalSection( &writer
->cs
);
3852 if (writer
->magic
!= WRITER_MAGIC
)
3854 LeaveCriticalSection( &writer
->cs
);
3855 return E_INVALIDARG
;
3860 case WS_ATTRIBUTE_TYPE_MAPPING
:
3861 if (writer
->state
!= WRITER_STATE_STARTATTRIBUTE
) hr
= WS_E_INVALID_FORMAT
;
3862 else hr
= write_type( writer
, mapping
, type
, desc
, option
, value
, size
);
3865 case WS_ELEMENT_TYPE_MAPPING
:
3866 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
3867 if (writer
->state
!= WRITER_STATE_STARTELEMENT
) hr
= WS_E_INVALID_FORMAT
;
3868 else hr
= write_type( writer
, mapping
, type
, desc
, option
, value
, size
);
3871 case WS_ANY_ELEMENT_TYPE_MAPPING
:
3872 hr
= write_type( writer
, mapping
, type
, desc
, option
, value
, size
);
3876 FIXME( "mapping %u not implemented\n", mapping
);
3880 LeaveCriticalSection( &writer
->cs
);
3884 WS_TYPE
map_value_type( WS_VALUE_TYPE type
)
3888 case WS_BOOL_VALUE_TYPE
: return WS_BOOL_TYPE
;
3889 case WS_INT8_VALUE_TYPE
: return WS_INT8_TYPE
;
3890 case WS_INT16_VALUE_TYPE
: return WS_INT16_TYPE
;
3891 case WS_INT32_VALUE_TYPE
: return WS_INT32_TYPE
;
3892 case WS_INT64_VALUE_TYPE
: return WS_INT64_TYPE
;
3893 case WS_UINT8_VALUE_TYPE
: return WS_UINT8_TYPE
;
3894 case WS_UINT16_VALUE_TYPE
: return WS_UINT16_TYPE
;
3895 case WS_UINT32_VALUE_TYPE
: return WS_UINT32_TYPE
;
3896 case WS_UINT64_VALUE_TYPE
: return WS_UINT64_TYPE
;
3897 case WS_FLOAT_VALUE_TYPE
: return WS_FLOAT_TYPE
;
3898 case WS_DOUBLE_VALUE_TYPE
: return WS_DOUBLE_TYPE
;
3899 case WS_DECIMAL_VALUE_TYPE
: return WS_DECIMAL_TYPE
;
3900 case WS_DATETIME_VALUE_TYPE
: return WS_DATETIME_TYPE
;
3901 case WS_TIMESPAN_VALUE_TYPE
: return WS_TIMESPAN_TYPE
;
3902 case WS_GUID_VALUE_TYPE
: return WS_GUID_TYPE
;
3904 FIXME( "unhandled type %u\n", type
);
3909 /**************************************************************************
3910 * WsWriteValue [webservices.@]
3912 HRESULT WINAPI
WsWriteValue( WS_XML_WRITER
*handle
, WS_VALUE_TYPE value_type
, const void *value
,
3913 ULONG size
, WS_ERROR
*error
)
3915 struct writer
*writer
= (struct writer
*)handle
;
3916 WS_TYPE_MAPPING mapping
;
3920 TRACE( "%p %u %p %u %p\n", handle
, value_type
, value
, size
, error
);
3921 if (error
) FIXME( "ignoring error parameter\n" );
3923 if (!writer
|| !value
|| (type
= map_value_type( value_type
)) == ~0u) return E_INVALIDARG
;
3925 EnterCriticalSection( &writer
->cs
);
3927 if (writer
->magic
!= WRITER_MAGIC
)
3929 LeaveCriticalSection( &writer
->cs
);
3930 return E_INVALIDARG
;
3933 switch (writer
->state
)
3935 case WRITER_STATE_STARTATTRIBUTE
:
3936 mapping
= WS_ATTRIBUTE_TYPE_MAPPING
;
3939 case WRITER_STATE_STARTELEMENT
:
3940 mapping
= WS_ELEMENT_TYPE_MAPPING
;
3944 hr
= WS_E_INVALID_FORMAT
;
3947 if (hr
== S_OK
) hr
= write_type( writer
, mapping
, type
, NULL
, WS_WRITE_REQUIRED_VALUE
, value
, size
);
3949 LeaveCriticalSection( &writer
->cs
);
3953 /**************************************************************************
3954 * WsWriteArray [webservices.@]
3956 HRESULT WINAPI
WsWriteArray( WS_XML_WRITER
*handle
, const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3957 WS_VALUE_TYPE value_type
, const void *array
, ULONG size
, ULONG offset
,
3958 ULONG count
, WS_ERROR
*error
)
3960 struct writer
*writer
= (struct writer
*)handle
;
3965 TRACE( "%p %s %s %u %p %u %u %u %p\n", handle
, debugstr_xmlstr(localname
), debugstr_xmlstr(ns
),
3966 value_type
, array
, size
, offset
, count
, error
);
3967 if (error
) FIXME( "ignoring error parameter\n" );
3969 if (!writer
) return E_INVALIDARG
;
3971 EnterCriticalSection( &writer
->cs
);
3973 if (writer
->magic
!= WRITER_MAGIC
)
3975 LeaveCriticalSection( &writer
->cs
);
3976 return E_INVALIDARG
;
3979 if (!writer
->output_type
)
3981 LeaveCriticalSection( &writer
->cs
);
3982 return WS_E_INVALID_OPERATION
;
3985 if (!localname
|| !ns
|| (type
= map_value_type( value_type
)) == ~0u)
3987 LeaveCriticalSection( &writer
->cs
);
3988 return E_INVALIDARG
;
3991 type_size
= get_type_size( type
, NULL
);
3992 if (size
% type_size
|| (offset
+ count
) * type_size
> size
|| (count
&& !array
))
3994 LeaveCriticalSection( &writer
->cs
);
3995 return E_INVALIDARG
;
3998 for (i
= offset
; i
< count
; i
++)
4000 const char *ptr
= (const char *)array
+ (offset
+ i
) * type_size
;
4001 if ((hr
= write_element_node( writer
, NULL
, localname
, ns
)) != S_OK
) goto done
;
4002 if ((hr
= write_type( writer
, WS_ELEMENT_TYPE_MAPPING
, type
, NULL
, WS_WRITE_REQUIRED_POINTER
,
4003 &ptr
, sizeof(ptr
) )) != S_OK
) goto done
;
4004 if ((hr
= write_endelement_node( writer
)) != S_OK
) goto done
;
4008 LeaveCriticalSection( &writer
->cs
);
4012 /**************************************************************************
4013 * WsWriteXmlBuffer [webservices.@]
4015 HRESULT WINAPI
WsWriteXmlBuffer( WS_XML_WRITER
*handle
, WS_XML_BUFFER
*buffer
, WS_ERROR
*error
)
4017 struct writer
*writer
= (struct writer
*)handle
;
4018 struct xmlbuf
*xmlbuf
= (struct xmlbuf
*)buffer
;
4021 TRACE( "%p %p %p\n", handle
, buffer
, error
);
4022 if (error
) FIXME( "ignoring error parameter\n" );
4024 if (!writer
|| !xmlbuf
) return E_INVALIDARG
;
4026 EnterCriticalSection( &writer
->cs
);
4028 if (writer
->magic
!= WRITER_MAGIC
)
4030 LeaveCriticalSection( &writer
->cs
);
4031 return E_INVALIDARG
;
4034 if (xmlbuf
->encoding
!= writer
->output_enc
|| xmlbuf
->charset
!= writer
->output_charset
)
4036 FIXME( "no support for different encoding and/or charset\n" );
4041 if ((hr
= write_flush( writer
)) != S_OK
) goto done
;
4042 if ((hr
= write_grow_buffer( writer
, xmlbuf
->bytes
.length
)) != S_OK
) goto done
;
4043 write_bytes( writer
, xmlbuf
->bytes
.bytes
, xmlbuf
->bytes
.length
);
4046 LeaveCriticalSection( &writer
->cs
);
4050 /**************************************************************************
4051 * WsWriteXmlBufferToBytes [webservices.@]
4053 HRESULT WINAPI
WsWriteXmlBufferToBytes( WS_XML_WRITER
*handle
, WS_XML_BUFFER
*buffer
,
4054 const WS_XML_WRITER_ENCODING
*encoding
,
4055 const WS_XML_WRITER_PROPERTY
*properties
, ULONG count
,
4056 WS_HEAP
*heap
, void **bytes
, ULONG
*size
, WS_ERROR
*error
)
4058 struct writer
*writer
= (struct writer
*)handle
;
4059 struct xmlbuf
*xmlbuf
= (struct xmlbuf
*)buffer
;
4064 TRACE( "%p %p %p %p %u %p %p %p %p\n", handle
, buffer
, encoding
, properties
, count
, heap
,
4065 bytes
, size
, error
);
4066 if (error
) FIXME( "ignoring error parameter\n" );
4068 if (!writer
|| !xmlbuf
|| !heap
|| !bytes
) return E_INVALIDARG
;
4070 if (encoding
&& encoding
->encodingType
!= WS_XML_WRITER_ENCODING_TYPE_TEXT
)
4072 FIXME( "encoding type %u not supported\n", encoding
->encodingType
);
4076 EnterCriticalSection( &writer
->cs
);
4078 if (writer
->magic
!= WRITER_MAGIC
)
4080 LeaveCriticalSection( &writer
->cs
);
4081 return E_INVALIDARG
;
4084 for (i
= 0; i
< count
; i
++)
4086 hr
= prop_set( writer
->prop
, writer
->prop_count
, properties
[i
].id
, properties
[i
].value
,
4087 properties
[i
].valueSize
);
4088 if (hr
!= S_OK
) goto done
;
4091 if (!(buf
= ws_alloc( heap
, xmlbuf
->bytes
.length
))) hr
= WS_E_QUOTA_EXCEEDED
;
4094 memcpy( buf
, xmlbuf
->bytes
.bytes
, xmlbuf
->bytes
.length
);
4096 *size
= xmlbuf
->bytes
.length
;
4100 LeaveCriticalSection( &writer
->cs
);
4104 /**************************************************************************
4105 * WsWriteXmlnsAttribute [webservices.@]
4107 HRESULT WINAPI
WsWriteXmlnsAttribute( WS_XML_WRITER
*handle
, const WS_XML_STRING
*prefix
,
4108 const WS_XML_STRING
*ns
, BOOL single
, WS_ERROR
*error
)
4110 struct writer
*writer
= (struct writer
*)handle
;
4113 TRACE( "%p %s %s %d %p\n", handle
, debugstr_xmlstr(prefix
), debugstr_xmlstr(ns
),
4115 if (error
) FIXME( "ignoring error parameter\n" );
4117 if (!writer
|| !ns
) return E_INVALIDARG
;
4119 EnterCriticalSection( &writer
->cs
);
4121 if (writer
->magic
!= WRITER_MAGIC
)
4123 LeaveCriticalSection( &writer
->cs
);
4124 return E_INVALIDARG
;
4127 if (writer
->state
!= WRITER_STATE_STARTELEMENT
)
4129 LeaveCriticalSection( &writer
->cs
);
4130 return WS_E_INVALID_OPERATION
;
4133 if (!namespace_in_scope( &writer
->current
->hdr
, prefix
, ns
))
4134 hr
= add_namespace_attribute( writer
, prefix
, ns
, single
);
4136 LeaveCriticalSection( &writer
->cs
);
4140 static HRESULT
write_qualified_name( struct writer
*writer
, const WS_XML_STRING
*prefix
,
4141 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
)
4143 WS_XML_QNAME_TEXT qname
= {{WS_XML_TEXT_TYPE_QNAME
}};
4146 if ((hr
= write_flush( writer
)) != S_OK
) return hr
;
4147 if (!prefix
&& ((hr
= find_prefix( writer
, ns
, &prefix
)) != S_OK
)) return hr
;
4149 qname
.prefix
= (WS_XML_STRING
*)prefix
;
4150 qname
.localName
= (WS_XML_STRING
*)localname
;
4151 qname
.ns
= (WS_XML_STRING
*)ns
;
4153 if ((hr
= write_add_text_node( writer
, &qname
.text
)) != S_OK
) return hr
;
4154 return write_text( writer
, ((const WS_XML_TEXT_NODE
*)writer
->current
)->text
, 0 );
4157 /**************************************************************************
4158 * WsWriteQualifiedName [webservices.@]
4160 HRESULT WINAPI
WsWriteQualifiedName( WS_XML_WRITER
*handle
, const WS_XML_STRING
*prefix
,
4161 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4164 struct writer
*writer
= (struct writer
*)handle
;
4167 TRACE( "%p %s %s %s %p\n", handle
, debugstr_xmlstr(prefix
), debugstr_xmlstr(localname
),
4168 debugstr_xmlstr(ns
), error
);
4169 if (error
) FIXME( "ignoring error parameter\n" );
4171 if (!writer
) return E_INVALIDARG
;
4173 EnterCriticalSection( &writer
->cs
);
4175 if (writer
->magic
!= WRITER_MAGIC
)
4177 LeaveCriticalSection( &writer
->cs
);
4178 return E_INVALIDARG
;
4181 if (!writer
->output_type
)
4183 LeaveCriticalSection( &writer
->cs
);
4184 return WS_E_INVALID_OPERATION
;
4187 if (writer
->state
!= WRITER_STATE_STARTELEMENT
)
4189 LeaveCriticalSection( &writer
->cs
);
4190 return WS_E_INVALID_FORMAT
;
4193 if (!localname
|| (!prefix
&& !ns
))
4195 LeaveCriticalSection( &writer
->cs
);
4196 return E_INVALIDARG
;
4199 hr
= write_qualified_name( writer
, prefix
, localname
, ns
);
4201 LeaveCriticalSection( &writer
->cs
);
4205 static HRESULT
write_move_to( struct writer
*writer
, WS_MOVE_TO move
, BOOL
*found
)
4207 BOOL success
= FALSE
;
4208 struct node
*node
= writer
->current
;
4212 case WS_MOVE_TO_ROOT_ELEMENT
:
4213 success
= move_to_root_element( writer
->root
, &node
);
4216 case WS_MOVE_TO_NEXT_ELEMENT
:
4217 success
= move_to_next_element( &node
);
4220 case WS_MOVE_TO_PREVIOUS_ELEMENT
:
4221 success
= move_to_prev_element( &node
);
4224 case WS_MOVE_TO_CHILD_ELEMENT
:
4225 success
= move_to_child_element( &node
);
4228 case WS_MOVE_TO_END_ELEMENT
:
4229 success
= move_to_end_element( &node
);
4232 case WS_MOVE_TO_PARENT_ELEMENT
:
4233 success
= move_to_parent_element( &node
);
4236 case WS_MOVE_TO_FIRST_NODE
:
4237 success
= move_to_first_node( &node
);
4240 case WS_MOVE_TO_NEXT_NODE
:
4241 success
= move_to_next_node( &node
);
4244 case WS_MOVE_TO_PREVIOUS_NODE
:
4245 success
= move_to_prev_node( &node
);
4248 case WS_MOVE_TO_CHILD_NODE
:
4249 success
= move_to_child_node( &node
);
4252 case WS_MOVE_TO_BOF
:
4253 success
= move_to_bof( writer
->root
, &node
);
4256 case WS_MOVE_TO_EOF
:
4257 success
= move_to_eof( writer
->root
, &node
);
4261 FIXME( "unhandled move %u\n", move
);
4265 if (success
&& node
== writer
->root
) return E_INVALIDARG
;
4266 writer
->current
= node
;
4273 return success
? S_OK
: WS_E_INVALID_FORMAT
;
4276 /**************************************************************************
4277 * WsMoveWriter [webservices.@]
4279 HRESULT WINAPI
WsMoveWriter( WS_XML_WRITER
*handle
, WS_MOVE_TO move
, BOOL
*found
, WS_ERROR
*error
)
4281 struct writer
*writer
= (struct writer
*)handle
;
4284 TRACE( "%p %u %p %p\n", handle
, move
, found
, error
);
4285 if (error
) FIXME( "ignoring error parameter\n" );
4287 if (!writer
) return E_INVALIDARG
;
4289 EnterCriticalSection( &writer
->cs
);
4291 if (writer
->magic
!= WRITER_MAGIC
)
4293 LeaveCriticalSection( &writer
->cs
);
4294 return E_INVALIDARG
;
4297 if (!writer
->output_type
)
4299 LeaveCriticalSection( &writer
->cs
);
4300 return WS_E_INVALID_OPERATION
;
4303 hr
= write_move_to( writer
, move
, found
);
4305 LeaveCriticalSection( &writer
->cs
);
4309 /**************************************************************************
4310 * WsGetWriterPosition [webservices.@]
4312 HRESULT WINAPI
WsGetWriterPosition( WS_XML_WRITER
*handle
, WS_XML_NODE_POSITION
*pos
, WS_ERROR
*error
)
4314 struct writer
*writer
= (struct writer
*)handle
;
4316 TRACE( "%p %p %p\n", handle
, pos
, error
);
4317 if (error
) FIXME( "ignoring error parameter\n" );
4319 if (!writer
|| !pos
) return E_INVALIDARG
;
4321 EnterCriticalSection( &writer
->cs
);
4323 if (writer
->magic
!= WRITER_MAGIC
)
4325 LeaveCriticalSection( &writer
->cs
);
4326 return E_INVALIDARG
;
4329 if (!writer
->output_type
)
4331 LeaveCriticalSection( &writer
->cs
);
4332 return WS_E_INVALID_OPERATION
;
4335 pos
->buffer
= (WS_XML_BUFFER
*)writer
->output_buf
;
4336 pos
->node
= writer
->current
;
4338 LeaveCriticalSection( &writer
->cs
);
4342 /**************************************************************************
4343 * WsSetWriterPosition [webservices.@]
4345 HRESULT WINAPI
WsSetWriterPosition( WS_XML_WRITER
*handle
, const WS_XML_NODE_POSITION
*pos
, WS_ERROR
*error
)
4347 struct writer
*writer
= (struct writer
*)handle
;
4349 TRACE( "%p %p %p\n", handle
, pos
, error
);
4350 if (error
) FIXME( "ignoring error parameter\n" );
4352 if (!writer
|| !pos
) return E_INVALIDARG
;
4354 EnterCriticalSection( &writer
->cs
);
4356 if (writer
->magic
!= WRITER_MAGIC
|| (struct xmlbuf
*)pos
->buffer
!= writer
->output_buf
)
4358 LeaveCriticalSection( &writer
->cs
);
4359 return E_INVALIDARG
;
4362 if (!writer
->output_type
)
4364 LeaveCriticalSection( &writer
->cs
);
4365 return WS_E_INVALID_OPERATION
;
4368 writer
->current
= pos
->node
;
4370 LeaveCriticalSection( &writer
->cs
);
4374 static HRESULT
write_add_comment_node( struct writer
*writer
, const WS_XML_STRING
*value
)
4376 struct node
*node
, *parent
;
4377 WS_XML_COMMENT_NODE
*comment
;
4379 if (!(parent
= find_parent( writer
))) return WS_E_INVALID_FORMAT
;
4380 if (!(node
= alloc_node( WS_XML_NODE_TYPE_COMMENT
))) return E_OUTOFMEMORY
;
4381 comment
= (WS_XML_COMMENT_NODE
*)node
;
4383 if (value
->length
&& !(comment
->value
.bytes
= heap_alloc( value
->length
)))
4386 return E_OUTOFMEMORY
;
4388 memcpy( comment
->value
.bytes
, value
->bytes
, value
->length
);
4389 comment
->value
.length
= value
->length
;
4391 write_insert_node( writer
, parent
, node
);
4395 static HRESULT
write_comment_text( struct writer
*writer
)
4397 const WS_XML_COMMENT_NODE
*comment
= (const WS_XML_COMMENT_NODE
*)writer
->current
;
4400 if ((hr
= write_grow_buffer( writer
, comment
->value
.length
+ 7 )) != S_OK
) return hr
;
4401 write_bytes( writer
, (const BYTE
*)"<!--", 4 );
4402 write_bytes( writer
, comment
->value
.bytes
, comment
->value
.length
);
4403 write_bytes( writer
, (const BYTE
*)"-->", 3 );
4407 static HRESULT
write_comment_bin( struct writer
*writer
)
4409 const WS_XML_COMMENT_NODE
*comment
= (const WS_XML_COMMENT_NODE
*)writer
->current
;
4412 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
4413 write_char( writer
, RECORD_COMMENT
);
4414 return write_string( writer
, comment
->value
.bytes
, comment
->value
.length
);
4417 static HRESULT
write_comment( struct writer
*writer
)
4419 switch (writer
->output_enc
)
4421 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_comment_text( writer
);
4422 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return write_comment_bin( writer
);
4424 ERR( "unhandled encoding %u\n", writer
->output_enc
);
4425 return WS_E_NOT_SUPPORTED
;
4429 static HRESULT
write_comment_node( struct writer
*writer
, const WS_XML_STRING
*value
)
4432 if ((hr
= write_flush( writer
)) != S_OK
) return hr
;
4433 if ((hr
= write_add_comment_node( writer
, value
)) != S_OK
) return hr
;
4434 if ((hr
= write_comment( writer
)) != S_OK
) return hr
;
4435 writer
->state
= WRITER_STATE_COMMENT
;
4439 static HRESULT
write_set_attributes( struct writer
*writer
, WS_XML_ATTRIBUTE
**attrs
, ULONG count
)
4444 for (i
= 0; i
< count
; i
++)
4446 if ((hr
= write_add_attribute( writer
, attrs
[i
]->prefix
, attrs
[i
]->localName
, attrs
[i
]->ns
,
4447 attrs
[i
]->singleQuote
)) != S_OK
) return hr
;
4448 if ((hr
= write_set_attribute_value( writer
, attrs
[i
]->value
)) != S_OK
) return hr
;
4453 static HRESULT
write_node( struct writer
*writer
, const WS_XML_NODE
*node
)
4457 switch (node
->nodeType
)
4459 case WS_XML_NODE_TYPE_ELEMENT
:
4461 const WS_XML_ELEMENT_NODE
*elem
= (const WS_XML_ELEMENT_NODE
*)node
;
4462 if ((hr
= write_element_node( writer
, elem
->prefix
, elem
->localName
, elem
->ns
)) != S_OK
) return hr
;
4463 return write_set_attributes( writer
, elem
->attributes
, elem
->attributeCount
);
4465 case WS_XML_NODE_TYPE_TEXT
:
4467 const WS_XML_TEXT_NODE
*text
= (const WS_XML_TEXT_NODE
*)node
;
4468 return write_text_node( writer
, text
->text
);
4470 case WS_XML_NODE_TYPE_END_ELEMENT
:
4471 return write_endelement_node( writer
);
4473 case WS_XML_NODE_TYPE_COMMENT
:
4475 const WS_XML_COMMENT_NODE
*comment
= (const WS_XML_COMMENT_NODE
*)node
;
4476 return write_comment_node( writer
, &comment
->value
);
4478 case WS_XML_NODE_TYPE_CDATA
:
4479 return write_cdata_node( writer
);
4481 case WS_XML_NODE_TYPE_END_CDATA
:
4482 return write_endcdata_node( writer
);
4484 case WS_XML_NODE_TYPE_EOF
:
4485 case WS_XML_NODE_TYPE_BOF
:
4489 WARN( "unknown node type %u\n", node
->nodeType
);
4490 return E_INVALIDARG
;
4494 /**************************************************************************
4495 * WsWriteNode [webservices.@]
4497 HRESULT WINAPI
WsWriteNode( WS_XML_WRITER
*handle
, const WS_XML_NODE
*node
, WS_ERROR
*error
)
4499 struct writer
*writer
= (struct writer
*)handle
;
4502 TRACE( "%p %p %p\n", handle
, node
, error
);
4503 if (error
) FIXME( "ignoring error parameter\n" );
4505 if (!writer
|| !node
) return E_INVALIDARG
;
4507 EnterCriticalSection( &writer
->cs
);
4509 if (writer
->magic
!= WRITER_MAGIC
)
4511 LeaveCriticalSection( &writer
->cs
);
4512 return E_INVALIDARG
;
4515 if (!writer
->output_type
)
4517 LeaveCriticalSection( &writer
->cs
);
4518 return WS_E_INVALID_OPERATION
;
4521 hr
= write_node( writer
, node
);
4523 LeaveCriticalSection( &writer
->cs
);
4527 static HRESULT
write_tree_node( struct writer
*writer
)
4531 switch (node_type( writer
->current
))
4533 case WS_XML_NODE_TYPE_ELEMENT
:
4534 if (writer
->state
== WRITER_STATE_STARTELEMENT
&& (hr
= write_endstartelement( writer
)) != S_OK
)
4536 if ((hr
= write_startelement( writer
)) != S_OK
) return hr
;
4537 writer
->state
= WRITER_STATE_STARTELEMENT
;
4540 case WS_XML_NODE_TYPE_TEXT
:
4541 if (writer
->state
== WRITER_STATE_STARTELEMENT
&& (hr
= write_endstartelement( writer
)) != S_OK
)
4543 if ((hr
= write_text( writer
, ((const WS_XML_TEXT_NODE
*)writer
->current
)->text
, 0 )) != S_OK
) return hr
;
4544 writer
->state
= WRITER_STATE_TEXT
;
4547 case WS_XML_NODE_TYPE_END_ELEMENT
:
4548 if ((hr
= write_close_element( writer
, writer
->current
->parent
)) != S_OK
) return hr
;
4549 writer
->state
= WRITER_STATE_ENDELEMENT
;
4552 case WS_XML_NODE_TYPE_COMMENT
:
4553 if (writer
->state
== WRITER_STATE_STARTELEMENT
&& (hr
= write_endstartelement( writer
)) != S_OK
)
4555 if ((hr
= write_comment( writer
)) != S_OK
) return hr
;
4556 writer
->state
= WRITER_STATE_COMMENT
;
4559 case WS_XML_NODE_TYPE_CDATA
:
4560 if (writer
->state
== WRITER_STATE_STARTELEMENT
&& (hr
= write_endstartelement( writer
)) != S_OK
)
4562 if ((hr
= write_cdata( writer
)) != S_OK
) return hr
;
4563 writer
->state
= WRITER_STATE_STARTCDATA
;
4566 case WS_XML_NODE_TYPE_END_CDATA
:
4567 if ((hr
= write_endcdata( writer
)) != S_OK
) return hr
;
4568 writer
->state
= WRITER_STATE_ENDCDATA
;
4571 case WS_XML_NODE_TYPE_EOF
:
4572 case WS_XML_NODE_TYPE_BOF
:
4576 ERR( "unknown node type %u\n", node_type(writer
->current
) );
4577 return E_INVALIDARG
;
4581 static HRESULT
write_tree( struct writer
*writer
)
4585 if ((hr
= write_tree_node( writer
)) != S_OK
) return hr
;
4588 if (node_type( writer
->current
) == WS_XML_NODE_TYPE_EOF
) break;
4589 if (move_to_child_node( &writer
->current
))
4591 if ((hr
= write_tree_node( writer
)) != S_OK
) return hr
;
4594 if (move_to_next_node( &writer
->current
))
4596 if ((hr
= write_tree_node( writer
)) != S_OK
) return hr
;
4599 if (!move_to_parent_node( &writer
->current
) || !move_to_next_node( &writer
->current
))
4601 ERR( "invalid tree\n" );
4602 return WS_E_INVALID_FORMAT
;
4604 if ((hr
= write_tree_node( writer
)) != S_OK
) return hr
;
4609 static void write_rewind( struct writer
*writer
)
4611 writer
->write_pos
= 0;
4612 writer
->current
= writer
->root
;
4613 writer
->state
= WRITER_STATE_INITIAL
;
4616 /**************************************************************************
4617 * WsCopyNode [webservices.@]
4619 HRESULT WINAPI
WsCopyNode( WS_XML_WRITER
*handle
, WS_XML_READER
*reader
, WS_ERROR
*error
)
4621 struct writer
*writer
= (struct writer
*)handle
;
4622 struct node
*parent
, *current
, *node
= NULL
;
4625 TRACE( "%p %p %p\n", handle
, reader
, error
);
4626 if (error
) FIXME( "ignoring error parameter\n" );
4628 if (!writer
) return E_INVALIDARG
;
4630 EnterCriticalSection( &writer
->cs
);
4632 if (writer
->magic
!= WRITER_MAGIC
)
4634 LeaveCriticalSection( &writer
->cs
);
4635 return E_INVALIDARG
;
4638 if (!(parent
= find_parent( writer
)))
4640 LeaveCriticalSection( &writer
->cs
);
4641 return WS_E_INVALID_FORMAT
;
4644 if ((hr
= copy_node( reader
, &node
)) != S_OK
) goto done
;
4645 current
= writer
->current
;
4646 write_insert_node( writer
, parent
, node
);
4648 write_rewind( writer
);
4649 if ((hr
= write_tree( writer
)) != S_OK
) goto done
;
4650 writer
->current
= current
;
4652 WsMoveReader( reader
, WS_MOVE_TO_NEXT_NODE
, NULL
, NULL
);
4655 LeaveCriticalSection( &writer
->cs
);
4659 static HRESULT
write_param( struct writer
*writer
, const WS_FIELD_DESCRIPTION
*desc
, const void *value
)
4661 return write_type_field( writer
, desc
, value
, 0 );
4664 static ULONG
get_array_len( const WS_PARAMETER_DESCRIPTION
*params
, ULONG count
, ULONG index
, const void **args
)
4667 for (i
= 0; i
< count
; i
++)
4669 if (params
[i
].inputMessageIndex
!= index
|| params
[i
].parameterType
!= WS_PARAMETER_TYPE_ARRAY_COUNT
)
4671 if (args
[i
]) ret
= *(const ULONG
*)args
[i
];
4677 static HRESULT
write_param_array( struct writer
*writer
, const WS_FIELD_DESCRIPTION
*desc
, const void *value
,
4680 return write_type_repeating_element( writer
, desc
, value
, len
);
4683 HRESULT
write_input_params( WS_XML_WRITER
*handle
, const WS_ELEMENT_DESCRIPTION
*desc
,
4684 const WS_PARAMETER_DESCRIPTION
*params
, ULONG count
, const void **args
)
4686 struct writer
*writer
= (struct writer
*)handle
;
4687 const WS_STRUCT_DESCRIPTION
*desc_struct
;
4688 const WS_FIELD_DESCRIPTION
*desc_field
;
4692 if (desc
->type
!= WS_STRUCT_TYPE
|| !(desc_struct
= desc
->typeDescription
)) return E_INVALIDARG
;
4694 EnterCriticalSection( &writer
->cs
);
4696 if (writer
->magic
!= WRITER_MAGIC
)
4698 LeaveCriticalSection( &writer
->cs
);
4699 return E_INVALIDARG
;
4702 if ((hr
= write_element_node( writer
, NULL
, desc
->elementLocalName
, desc
->elementNs
)) != S_OK
) goto done
;
4704 for (i
= 0; i
< count
; i
++)
4706 if (params
[i
].inputMessageIndex
== INVALID_PARAMETER_INDEX
) continue;
4707 if (params
[i
].parameterType
== WS_PARAMETER_TYPE_MESSAGES
)
4709 FIXME( "messages type not supported\n" );
4713 if ((hr
= get_param_desc( desc_struct
, params
[i
].inputMessageIndex
, &desc_field
)) != S_OK
) goto done
;
4714 if (params
[i
].parameterType
== WS_PARAMETER_TYPE_NORMAL
)
4716 if ((hr
= write_param( writer
, desc_field
, args
[i
] )) != S_OK
) goto done
;
4718 else if (params
[i
].parameterType
== WS_PARAMETER_TYPE_ARRAY
)
4720 const void *ptr
= *(const void **)args
[i
];
4721 ULONG len
= get_array_len( params
, count
, params
[i
].inputMessageIndex
, args
);
4722 if ((hr
= write_param_array( writer
, desc_field
, ptr
, len
)) != S_OK
) goto done
;
4726 hr
= write_endelement_node( writer
);
4729 LeaveCriticalSection( &writer
->cs
);