webservices: Add support for appending byte records in the reader.
[wine.git] / dlls / webservices / reader.c
blobbf05352d8c984e0b14626bba295515aeb64484d3
1 /*
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
19 #include <stdarg.h>
20 #include <assert.h>
22 #include "windef.h"
23 #include "winbase.h"
24 #include "winnls.h"
25 #include "webservices.h"
27 #include "wine/debug.h"
28 #include "wine/list.h"
29 #include "webservices_private.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(webservices);
33 ULONG prop_size( const struct prop_desc *desc, ULONG count )
35 ULONG i, ret = count * sizeof(struct prop);
36 for (i = 0; i < count; i++) ret += desc[i].size;
37 return ret;
40 void prop_init( const struct prop_desc *desc, ULONG count, struct prop *prop, void *data )
42 ULONG i;
43 char *ptr = data;
44 for (i = 0; i < count; i++)
46 prop[i].value = ptr;
47 prop[i].size = desc[i].size;
48 prop[i].readonly = desc[i].readonly;
49 prop[i].writeonly = desc[i].writeonly;
50 ptr += prop[i].size;
54 HRESULT prop_set( const struct prop *prop, ULONG count, ULONG id, const void *value, ULONG size )
56 if (id >= count || size != prop[id].size || prop[id].readonly) return E_INVALIDARG;
57 memcpy( prop[id].value, value, size );
58 return S_OK;
61 HRESULT prop_get( const struct prop *prop, ULONG count, ULONG id, void *buf, ULONG size )
63 if (id >= count || size != prop[id].size || prop[id].writeonly) return E_INVALIDARG;
64 memcpy( buf, prop[id].value, prop[id].size );
65 return S_OK;
68 struct node *alloc_node( WS_XML_NODE_TYPE type )
70 struct node *ret;
72 if (!(ret = heap_alloc_zero( sizeof(*ret) ))) return NULL;
73 ret->hdr.node.nodeType = type;
74 list_init( &ret->entry );
75 list_init( &ret->children );
76 return ret;
79 void free_attribute( WS_XML_ATTRIBUTE *attr )
81 if (!attr) return;
82 free_xml_string( attr->prefix );
83 free_xml_string( attr->localName );
84 free_xml_string( attr->ns );
85 heap_free( attr->value );
86 heap_free( attr );
89 void free_node( struct node *node )
91 if (!node) return;
92 switch (node_type( node ))
94 case WS_XML_NODE_TYPE_ELEMENT:
96 WS_XML_ELEMENT_NODE *elem = &node->hdr;
97 ULONG i;
99 for (i = 0; i < elem->attributeCount; i++) free_attribute( elem->attributes[i] );
100 heap_free( elem->attributes );
101 free_xml_string( elem->prefix );
102 free_xml_string( elem->localName );
103 free_xml_string( elem->ns );
104 break;
106 case WS_XML_NODE_TYPE_TEXT:
108 WS_XML_TEXT_NODE *text = (WS_XML_TEXT_NODE *)node;
109 heap_free( text->text );
110 break;
112 case WS_XML_NODE_TYPE_COMMENT:
114 WS_XML_COMMENT_NODE *comment = (WS_XML_COMMENT_NODE *)node;
115 heap_free( comment->value.bytes );
116 break;
118 case WS_XML_NODE_TYPE_CDATA:
119 case WS_XML_NODE_TYPE_END_CDATA:
120 case WS_XML_NODE_TYPE_END_ELEMENT:
121 case WS_XML_NODE_TYPE_EOF:
122 case WS_XML_NODE_TYPE_BOF:
123 break;
125 default:
126 ERR( "unhandled type %u\n", node_type( node ) );
127 break;
129 heap_free( node );
132 void destroy_nodes( struct node *node )
134 struct list *ptr;
136 if (!node) return;
137 while ((ptr = list_head( &node->children )))
139 struct node *child = LIST_ENTRY( ptr, struct node, entry );
140 list_remove( &child->entry );
141 destroy_nodes( child );
143 free_node( node );
146 static WS_XML_ATTRIBUTE *dup_attribute( const WS_XML_ATTRIBUTE *src )
148 WS_XML_ATTRIBUTE *dst;
149 const WS_XML_STRING *prefix = src->prefix;
150 const WS_XML_STRING *localname = src->localName;
151 const WS_XML_STRING *ns = src->localName;
152 const WS_XML_TEXT *text = src->value;
154 if (!(dst = heap_alloc( sizeof(*dst) ))) return NULL;
155 dst->singleQuote = src->singleQuote;
156 dst->isXmlNs = src->isXmlNs;
158 if (!prefix) dst->prefix = NULL;
159 else if (!(dst->prefix = dup_xml_string( prefix ))) goto error;
160 if (!(dst->localName = dup_xml_string( localname ))) goto error;
161 if (!(dst->ns = dup_xml_string( ns ))) goto error;
163 if (text)
165 WS_XML_UTF8_TEXT *utf8;
166 const WS_XML_UTF8_TEXT *utf8_src = (const WS_XML_UTF8_TEXT *)text;
167 if (!(utf8 = alloc_utf8_text( utf8_src->value.bytes, utf8_src->value.length ))) goto error;
168 dst->value = &utf8->text;
171 return dst;
173 error:
174 free_attribute( dst );
175 return NULL;
178 static WS_XML_ATTRIBUTE **dup_attributes( WS_XML_ATTRIBUTE * const *src, ULONG count )
180 WS_XML_ATTRIBUTE **dst;
181 ULONG i;
183 if (!(dst = heap_alloc( sizeof(*dst) * count ))) return NULL;
184 for (i = 0; i < count; i++)
186 if (!(dst[i] = dup_attribute( src[i] )))
188 for (; i > 0; i--) free_attribute( dst[i - 1] );
189 heap_free( dst );
190 return NULL;
193 return dst;
196 static struct node *dup_element_node( const WS_XML_ELEMENT_NODE *src )
198 struct node *node;
199 WS_XML_ELEMENT_NODE *dst;
200 ULONG count = src->attributeCount;
201 WS_XML_ATTRIBUTE **attrs = src->attributes;
202 const WS_XML_STRING *prefix = (src->prefix && src->prefix->length) ? src->prefix : NULL;
203 const WS_XML_STRING *localname = src->localName;
204 const WS_XML_STRING *ns = src->ns;
206 if (!(node = alloc_node( WS_XML_NODE_TYPE_ELEMENT ))) return NULL;
207 dst = &node->hdr;
209 if (count && !(dst->attributes = dup_attributes( attrs, count ))) goto error;
210 dst->attributeCount = count;
212 if (prefix && !(dst->prefix = dup_xml_string( prefix ))) goto error;
213 if (localname && !(dst->localName = dup_xml_string( localname ))) goto error;
214 if (ns && !(dst->ns = dup_xml_string( ns ))) goto error;
215 return node;
217 error:
218 free_node( node );
219 return NULL;
222 static struct node *dup_text_node( const WS_XML_TEXT_NODE *src )
224 struct node *node;
225 WS_XML_TEXT_NODE *dst;
227 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
228 dst = (WS_XML_TEXT_NODE *)node;
230 if (src->text)
232 WS_XML_UTF8_TEXT *utf8;
233 const WS_XML_UTF8_TEXT *utf8_src = (const WS_XML_UTF8_TEXT *)src->text;
234 if (!(utf8 = alloc_utf8_text( utf8_src->value.bytes, utf8_src->value.length )))
236 free_node( node );
237 return NULL;
239 dst->text = &utf8->text;
241 return node;
244 static struct node *dup_comment_node( const WS_XML_COMMENT_NODE *src )
246 struct node *node;
247 WS_XML_COMMENT_NODE *dst;
249 if (!(node = alloc_node( WS_XML_NODE_TYPE_COMMENT ))) return NULL;
250 dst = (WS_XML_COMMENT_NODE *)node;
252 if (src->value.length && !(dst->value.bytes = heap_alloc( src->value.length )))
254 free_node( node );
255 return NULL;
257 memcpy( dst->value.bytes, src->value.bytes, src->value.length );
258 dst->value.length = src->value.length;
259 return node;
262 static struct node *dup_node( const struct node *src )
264 switch (node_type( src ))
266 case WS_XML_NODE_TYPE_ELEMENT:
267 return dup_element_node( &src->hdr );
269 case WS_XML_NODE_TYPE_TEXT:
270 return dup_text_node( (const WS_XML_TEXT_NODE *)src );
272 case WS_XML_NODE_TYPE_COMMENT:
273 return dup_comment_node( (const WS_XML_COMMENT_NODE *)src );
275 case WS_XML_NODE_TYPE_CDATA:
276 case WS_XML_NODE_TYPE_END_CDATA:
277 case WS_XML_NODE_TYPE_END_ELEMENT:
278 case WS_XML_NODE_TYPE_EOF:
279 case WS_XML_NODE_TYPE_BOF:
280 return alloc_node( node_type( src ) );
282 default:
283 ERR( "unhandled type %u\n", node_type( src ) );
284 break;
286 return NULL;
289 static HRESULT dup_tree( struct node **dst, const struct node *src )
291 struct node *parent;
292 const struct node *child;
294 if (!*dst && !(*dst = dup_node( src ))) return E_OUTOFMEMORY;
295 parent = *dst;
297 LIST_FOR_EACH_ENTRY( child, &src->children, struct node, entry )
299 HRESULT hr = E_OUTOFMEMORY;
300 struct node *new_child;
302 if (!(new_child = dup_node( child )) || (hr = dup_tree( &new_child, child )) != S_OK)
304 destroy_nodes( *dst );
305 return hr;
307 new_child->parent = parent;
308 list_add_tail( &parent->children, &new_child->entry );
310 return S_OK;
313 static const struct prop_desc reader_props[] =
315 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_MAX_DEPTH */
316 { sizeof(BOOL), FALSE }, /* WS_XML_READER_PROPERTY_ALLOW_FRAGMENT */
317 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_MAX_ATTRIBUTES */
318 { sizeof(BOOL), FALSE }, /* WS_XML_READER_PROPERTY_READ_DECLARATION */
319 { sizeof(WS_CHARSET), FALSE }, /* WS_XML_READER_PROPERTY_CHARSET */
320 { sizeof(ULONGLONG), TRUE }, /* WS_XML_READER_PROPERTY_ROW */
321 { sizeof(ULONGLONG), TRUE }, /* WS_XML_READER_PROPERTY_COLUMN */
322 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_UTF8_TRIM_SIZE */
323 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_STREAM_BUFFER_SIZE */
324 { sizeof(BOOL), TRUE }, /* WS_XML_READER_PROPERTY_IN_ATTRIBUTE */
325 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_STREAM_MAX_ROOT_MIME_PART_SIZE */
326 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_STREAM_MAX_MIME_HEADERS_SIZE */
327 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_MAX_MIME_PARTS */
328 { sizeof(BOOL), FALSE }, /* WS_XML_READER_PROPERTY_ALLOW_INVALID_CHARACTER_REFERENCES */
329 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_MAX_NAMESPACES */
332 enum reader_state
334 READER_STATE_INITIAL,
335 READER_STATE_BOF,
336 READER_STATE_STARTELEMENT,
337 READER_STATE_STARTATTRIBUTE,
338 READER_STATE_STARTCDATA,
339 READER_STATE_CDATA,
340 READER_STATE_TEXT,
341 READER_STATE_ENDELEMENT,
342 READER_STATE_ENDCDATA,
343 READER_STATE_COMMENT,
344 READER_STATE_EOF
347 struct prefix
349 WS_XML_STRING *str;
350 WS_XML_STRING *ns;
353 struct reader
355 ULONG magic;
356 CRITICAL_SECTION cs;
357 ULONG read_size;
358 ULONG read_pos;
359 const unsigned char *read_bufptr;
360 enum reader_state state;
361 struct node *root;
362 struct node *current;
363 ULONG current_attr;
364 struct node *last;
365 struct prefix *prefixes;
366 ULONG nb_prefixes;
367 ULONG nb_prefixes_allocated;
368 WS_XML_READER_ENCODING_TYPE input_enc;
369 WS_CHARSET input_charset;
370 WS_XML_READER_INPUT_TYPE input_type;
371 struct xmlbuf *input_buf;
372 const unsigned char *input_data;
373 ULONG input_size;
374 ULONG text_conv_offset;
375 const WS_XML_DICTIONARY *dict_static;
376 WS_XML_DICTIONARY *dict;
377 ULONG prop_count;
378 struct prop prop[sizeof(reader_props)/sizeof(reader_props[0])];
381 #define READER_MAGIC (('R' << 24) | ('E' << 16) | ('A' << 8) | 'D')
383 static struct reader *alloc_reader(void)
385 static const ULONG count = sizeof(reader_props)/sizeof(reader_props[0]);
386 struct reader *ret;
387 ULONG size = sizeof(*ret) + prop_size( reader_props, count );
389 if (!(ret = heap_alloc_zero( size ))) return NULL;
390 if (!(ret->prefixes = heap_alloc_zero( sizeof(*ret->prefixes) )))
392 heap_free( ret );
393 return NULL;
395 ret->nb_prefixes = ret->nb_prefixes_allocated = 1;
397 ret->magic = READER_MAGIC;
398 InitializeCriticalSection( &ret->cs );
399 ret->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": reader.cs");
401 prop_init( reader_props, count, ret->prop, &ret[1] );
402 ret->prop_count = count;
403 return ret;
406 static void clear_prefixes( struct prefix *prefixes, ULONG count )
408 ULONG i;
409 for (i = 0; i < count; i++)
411 free_xml_string( prefixes[i].str );
412 prefixes[i].str = NULL;
413 free_xml_string( prefixes[i].ns );
414 prefixes[i].ns = NULL;
418 static HRESULT set_prefix( struct prefix *prefix, const WS_XML_STRING *str, const WS_XML_STRING *ns )
420 if (str)
422 free_xml_string( prefix->str );
423 if (!(prefix->str = dup_xml_string( str ))) return E_OUTOFMEMORY;
425 if (prefix->ns) free_xml_string( prefix->ns );
426 if (!(prefix->ns = dup_xml_string( ns ))) return E_OUTOFMEMORY;
427 return S_OK;
430 static HRESULT bind_prefix( struct reader *reader, const WS_XML_STRING *prefix, const WS_XML_STRING *ns )
432 ULONG i;
433 HRESULT hr;
435 for (i = 0; i < reader->nb_prefixes; i++)
437 if (WsXmlStringEquals( prefix, reader->prefixes[i].str, NULL ) == S_OK)
438 return set_prefix( &reader->prefixes[i], NULL, ns );
440 if (i >= reader->nb_prefixes_allocated)
442 ULONG new_size = reader->nb_prefixes_allocated * sizeof(*reader->prefixes) * 2;
443 struct prefix *tmp = heap_realloc_zero( reader->prefixes, new_size );
444 if (!tmp) return E_OUTOFMEMORY;
445 reader->prefixes = tmp;
446 reader->nb_prefixes_allocated *= 2;
448 if ((hr = set_prefix( &reader->prefixes[i], prefix, ns )) != S_OK) return hr;
449 reader->nb_prefixes++;
450 return S_OK;
453 static const WS_XML_STRING *get_namespace( struct reader *reader, const WS_XML_STRING *prefix )
455 ULONG i;
456 for (i = 0; i < reader->nb_prefixes; i++)
458 if (WsXmlStringEquals( prefix, reader->prefixes[i].str, NULL ) == S_OK)
459 return reader->prefixes[i].ns;
461 return NULL;
464 static void read_insert_eof( struct reader *reader, struct node *eof )
466 if (!reader->root) reader->root = eof;
467 else
469 eof->parent = reader->root;
470 list_add_tail( &reader->root->children, &eof->entry );
472 reader->current = reader->last = eof;
475 static void read_insert_bof( struct reader *reader, struct node *bof )
477 reader->root->parent = bof;
478 list_add_tail( &bof->children, &reader->root->entry );
479 reader->current = reader->last = reader->root = bof;
482 static void read_insert_node( struct reader *reader, struct node *parent, struct node *node )
484 node->parent = parent;
485 list_add_before( list_tail( &parent->children ), &node->entry );
486 reader->current = reader->last = node;
489 static void free_reader( struct reader *reader )
491 destroy_nodes( reader->root );
492 clear_prefixes( reader->prefixes, reader->nb_prefixes );
493 heap_free( reader->prefixes );
494 reader->cs.DebugInfo->Spare[0] = 0;
495 DeleteCriticalSection( &reader->cs );
496 heap_free( reader );
499 static HRESULT init_reader( struct reader *reader )
501 static const WS_XML_STRING empty = {0, NULL};
502 struct node *node;
503 HRESULT hr;
505 reader->state = READER_STATE_INITIAL;
506 destroy_nodes( reader->root );
507 reader->root = reader->current = NULL;
508 reader->current_attr = 0;
509 clear_prefixes( reader->prefixes, reader->nb_prefixes );
510 reader->nb_prefixes = 1;
511 if ((hr = bind_prefix( reader, &empty, &empty )) != S_OK) return hr;
513 if (!(node = alloc_node( WS_XML_NODE_TYPE_EOF ))) return E_OUTOFMEMORY;
514 read_insert_eof( reader, node );
515 reader->input_enc = WS_XML_READER_ENCODING_TYPE_TEXT;
516 reader->input_charset = WS_CHARSET_UTF8;
517 reader->dict_static = NULL;
518 reader->dict = NULL;
519 return S_OK;
522 /**************************************************************************
523 * WsCreateReader [webservices.@]
525 HRESULT WINAPI WsCreateReader( const WS_XML_READER_PROPERTY *properties, ULONG count,
526 WS_XML_READER **handle, WS_ERROR *error )
528 struct reader *reader;
529 ULONG i, max_depth = 32, max_attrs = 128, max_ns = 32;
530 BOOL read_decl = TRUE;
531 HRESULT hr;
533 TRACE( "%p %u %p %p\n", properties, count, handle, error );
534 if (error) FIXME( "ignoring error parameter\n" );
536 if (!handle) return E_INVALIDARG;
537 if (!(reader = alloc_reader())) return E_OUTOFMEMORY;
539 prop_set( reader->prop, reader->prop_count, WS_XML_READER_PROPERTY_MAX_DEPTH, &max_depth, sizeof(max_depth) );
540 prop_set( reader->prop, reader->prop_count, WS_XML_READER_PROPERTY_MAX_ATTRIBUTES, &max_attrs, sizeof(max_attrs) );
541 prop_set( reader->prop, reader->prop_count, WS_XML_READER_PROPERTY_READ_DECLARATION, &read_decl, sizeof(read_decl) );
542 prop_set( reader->prop, reader->prop_count, WS_XML_READER_PROPERTY_MAX_NAMESPACES, &max_ns, sizeof(max_ns) );
544 for (i = 0; i < count; i++)
546 hr = prop_set( reader->prop, reader->prop_count, properties[i].id, properties[i].value,
547 properties[i].valueSize );
548 if (hr != S_OK)
550 free_reader( reader );
551 return hr;
555 if ((hr = init_reader( reader )) != S_OK)
557 free_reader( reader );
558 return hr;
561 *handle = (WS_XML_READER *)reader;
562 return S_OK;
565 /**************************************************************************
566 * WsFreeReader [webservices.@]
568 void WINAPI WsFreeReader( WS_XML_READER *handle )
570 struct reader *reader = (struct reader *)handle;
572 TRACE( "%p\n", handle );
574 if (!reader) return;
576 EnterCriticalSection( &reader->cs );
578 if (reader->magic != READER_MAGIC)
580 LeaveCriticalSection( &reader->cs );
581 return;
584 reader->magic = 0;
586 LeaveCriticalSection( &reader->cs );
587 free_reader( reader );
590 /**************************************************************************
591 * WsFillReader [webservices.@]
593 HRESULT WINAPI WsFillReader( WS_XML_READER *handle, ULONG min_size, const WS_ASYNC_CONTEXT *ctx,
594 WS_ERROR *error )
596 struct reader *reader = (struct reader *)handle;
598 TRACE( "%p %u %p %p\n", handle, min_size, ctx, error );
599 if (error) FIXME( "ignoring error parameter\n" );
601 if (!reader) return E_INVALIDARG;
603 EnterCriticalSection( &reader->cs );
605 if (reader->magic != READER_MAGIC)
607 LeaveCriticalSection( &reader->cs );
608 return E_INVALIDARG;
611 /* FIXME: add support for stream input */
612 reader->read_size = min( min_size, reader->input_size );
613 reader->read_pos = 0;
615 LeaveCriticalSection( &reader->cs );
616 return S_OK;
619 /**************************************************************************
620 * WsGetNamespaceFromPrefix [webservices.@]
622 HRESULT WINAPI WsGetNamespaceFromPrefix( WS_XML_READER *handle, const WS_XML_STRING *prefix,
623 BOOL required, const WS_XML_STRING **ns, WS_ERROR *error )
625 static const WS_XML_STRING xml = {3, (BYTE *)"xml"};
626 static const WS_XML_STRING xmlns = {5, (BYTE *)"xmlns"};
627 static const WS_XML_STRING empty_ns = {0, NULL};
628 static const WS_XML_STRING xml_ns = {36, (BYTE *)"http://www.w3.org/XML/1998/namespace"};
629 static const WS_XML_STRING xmlns_ns = {29, (BYTE *)"http://www.w3.org/2000/xmlns/"};
630 struct reader *reader = (struct reader *)handle;
631 BOOL found = FALSE;
633 TRACE( "%p %s %d %p %p\n", handle, debugstr_xmlstr(prefix), required, ns, error );
634 if (error) FIXME( "ignoring error parameter\n" );
636 if (!reader || !prefix || !ns) return E_INVALIDARG;
638 EnterCriticalSection( &reader->cs );
640 if (reader->magic != READER_MAGIC)
642 LeaveCriticalSection( &reader->cs );
643 return E_INVALIDARG;
646 if (reader->state != READER_STATE_STARTELEMENT)
648 LeaveCriticalSection( &reader->cs );
649 return WS_E_INVALID_OPERATION;
652 if (!prefix->length)
654 *ns = &empty_ns;
655 found = TRUE;
657 else if (WsXmlStringEquals( prefix, &xml, NULL ) == S_OK)
659 *ns = &xml_ns;
660 found = TRUE;
662 else if (WsXmlStringEquals( prefix, &xmlns, NULL ) == S_OK)
664 *ns = &xmlns_ns;
665 found = TRUE;
667 else
669 WS_XML_ELEMENT_NODE *elem = &reader->current->hdr;
670 ULONG i;
672 for (i = 0; i < elem->attributeCount; i++)
674 if (!elem->attributes[i]->isXmlNs) continue;
675 if (WsXmlStringEquals( prefix, elem->attributes[i]->prefix, NULL ) == S_OK)
677 *ns = elem->attributes[i]->ns;
678 found = TRUE;
679 break;
684 LeaveCriticalSection( &reader->cs );
686 if (!found)
688 if (required) return WS_E_INVALID_FORMAT;
689 *ns = NULL;
690 return S_FALSE;
693 return S_OK;
696 /**************************************************************************
697 * WsGetReaderNode [webservices.@]
699 HRESULT WINAPI WsGetReaderNode( WS_XML_READER *handle, const WS_XML_NODE **node,
700 WS_ERROR *error )
702 struct reader *reader = (struct reader *)handle;
704 TRACE( "%p %p %p\n", handle, node, error );
705 if (error) FIXME( "ignoring error parameter\n" );
707 if (!reader || !node) return E_INVALIDARG;
709 EnterCriticalSection( &reader->cs );
711 if (reader->magic != READER_MAGIC)
713 LeaveCriticalSection( &reader->cs );
714 return E_INVALIDARG;
717 *node = &reader->current->hdr.node;
719 LeaveCriticalSection( &reader->cs );
720 return S_OK;
723 static HRESULT get_charset( struct reader *reader, void *buf, ULONG size )
725 if (!buf || size != sizeof(reader->input_charset)) return E_INVALIDARG;
726 if (!reader->input_charset) return WS_E_INVALID_FORMAT;
727 *(WS_CHARSET *)buf = reader->input_charset;
728 return S_OK;
731 /**************************************************************************
732 * WsGetReaderProperty [webservices.@]
734 HRESULT WINAPI WsGetReaderProperty( WS_XML_READER *handle, WS_XML_READER_PROPERTY_ID id,
735 void *buf, ULONG size, WS_ERROR *error )
737 struct reader *reader = (struct reader *)handle;
738 HRESULT hr;
740 TRACE( "%p %u %p %u %p\n", handle, id, buf, size, error );
741 if (error) FIXME( "ignoring error parameter\n" );
743 if (!reader) return E_INVALIDARG;
745 EnterCriticalSection( &reader->cs );
747 if (reader->magic != READER_MAGIC)
749 LeaveCriticalSection( &reader->cs );
750 return E_INVALIDARG;
753 if (!reader->input_type)
755 LeaveCriticalSection( &reader->cs );
756 return WS_E_INVALID_OPERATION;
759 if (id == WS_XML_READER_PROPERTY_CHARSET) hr = get_charset( reader, buf, size );
760 else hr = prop_get( reader->prop, reader->prop_count, id, buf, size );
762 LeaveCriticalSection( &reader->cs );
763 return hr;
766 /**************************************************************************
767 * WsGetXmlAttribute [webservices.@]
769 HRESULT WINAPI WsGetXmlAttribute( WS_XML_READER *handle, const WS_XML_STRING *attr,
770 WS_HEAP *heap, WCHAR **str, ULONG *len, WS_ERROR *error )
772 FIXME( "%p %s %p %p %p %p: stub\n", handle, debugstr_xmlstr(attr), heap, str, len, error );
773 return E_NOTIMPL;
776 WS_XML_UTF8_TEXT *alloc_utf8_text( const BYTE *data, ULONG len )
778 WS_XML_UTF8_TEXT *ret;
780 if (!(ret = heap_alloc( sizeof(*ret) + len ))) return NULL;
781 ret->text.textType = WS_XML_TEXT_TYPE_UTF8;
782 ret->value.length = len;
783 ret->value.bytes = len ? (BYTE *)(ret + 1) : NULL;
784 ret->value.dictionary = NULL;
785 ret->value.id = 0;
786 if (data) memcpy( ret->value.bytes, data, len );
787 return ret;
790 static WS_XML_BASE64_TEXT *alloc_base64_text( const BYTE *data, ULONG len )
792 WS_XML_BASE64_TEXT *ret;
794 if (!(ret = heap_alloc( sizeof(*ret) + len ))) return NULL;
795 ret->text.textType = WS_XML_TEXT_TYPE_BASE64;
796 ret->length = len;
797 ret->bytes = len ? (BYTE *)(ret + 1) : NULL;
798 if (data) memcpy( ret->bytes, data, len );
799 return ret;
802 static inline BOOL read_end_of_data( struct reader *reader )
804 return reader->read_pos >= reader->read_size;
807 static inline const unsigned char *read_current_ptr( struct reader *reader )
809 return &reader->read_bufptr[reader->read_pos];
812 static inline HRESULT read_peek( struct reader *reader, unsigned char *byte )
814 if (reader->read_pos >= reader->read_size) return WS_E_INVALID_FORMAT;
815 *byte = reader->read_bufptr[reader->read_pos];
816 return S_OK;
819 static inline HRESULT read_byte( struct reader *reader, unsigned char *byte )
821 if (reader->read_pos >= reader->read_size) return WS_E_INVALID_FORMAT;
822 *byte = reader->read_bufptr[reader->read_pos++];
823 return S_OK;
826 static inline HRESULT read_bytes( struct reader *reader, unsigned char *bytes, unsigned int len )
828 if (reader->read_pos + len > reader->read_size) return WS_E_INVALID_FORMAT;
829 memcpy( bytes, reader->read_bufptr + reader->read_pos, len );
830 reader->read_pos += len;
831 return S_OK;
834 /* UTF-8 support based on libs/wine/utf8.c */
836 /* number of following bytes in sequence based on first byte value (for bytes above 0x7f) */
837 static const char utf8_length[128] =
839 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x80-0x8f */
840 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x90-0x9f */
841 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xa0-0xaf */
842 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xb0-0xbf */
843 0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xc0-0xcf */
844 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xd0-0xdf */
845 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, /* 0xe0-0xef */
846 3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0 /* 0xf0-0xff */
849 /* first byte mask depending on UTF-8 sequence length */
850 static const unsigned char utf8_mask[4] = { 0x7f, 0x1f, 0x0f, 0x07 };
852 /* minimum Unicode value depending on UTF-8 sequence length */
853 static const unsigned int utf8_minval[4] = { 0x0, 0x80, 0x800, 0x10000 };
855 static inline unsigned int read_utf8_char( struct reader *reader, unsigned int *skip )
857 unsigned int len, res;
858 unsigned char ch = reader->read_bufptr[reader->read_pos];
859 const unsigned char *end;
861 if (reader->read_pos >= reader->read_size) return 0;
863 if (ch < 0x80)
865 *skip = 1;
866 return ch;
868 len = utf8_length[ch - 0x80];
869 if (reader->read_pos + len >= reader->read_size) return 0;
870 end = reader->read_bufptr + reader->read_pos + len + 1;
871 res = ch & utf8_mask[len];
873 switch (len)
875 case 3:
876 if ((ch = end[-3] ^ 0x80) >= 0x40) break;
877 res = (res << 6) | ch;
878 case 2:
879 if ((ch = end[-2] ^ 0x80) >= 0x40) break;
880 res = (res << 6) | ch;
881 case 1:
882 if ((ch = end[-1] ^ 0x80) >= 0x40) break;
883 res = (res << 6) | ch;
884 if (res < utf8_minval[len]) break;
885 *skip = len + 1;
886 return res;
889 return 0;
892 static inline void read_skip( struct reader *reader, unsigned int count )
894 if (reader->read_pos + count > reader->read_size) return;
895 reader->read_pos += count;
898 static inline void read_rewind( struct reader *reader, unsigned int count )
900 reader->read_pos -= count;
903 static inline BOOL read_isnamechar( unsigned int ch )
905 /* FIXME: incomplete */
906 return (ch >= 'A' && ch <= 'Z') ||
907 (ch >= 'a' && ch <= 'z') ||
908 (ch >= '0' && ch <= '9') ||
909 ch == '_' || ch == '-' || ch == '.' || ch == ':';
912 static inline BOOL read_isspace( unsigned int ch )
914 return ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n';
917 static inline void read_skip_whitespace( struct reader *reader )
919 while (reader->read_pos < reader->read_size && read_isspace( reader->read_bufptr[reader->read_pos] ))
920 reader->read_pos++;
923 static inline int read_cmp( struct reader *reader, const char *str, int len )
925 const unsigned char *ptr = read_current_ptr( reader );
927 if (len < 0) len = strlen( str );
928 if (reader->read_pos + len > reader->read_size) return -1;
929 while (len--)
931 if (*str != *ptr) return *ptr - *str;
932 str++; ptr++;
934 return 0;
937 static HRESULT read_xmldecl( struct reader *reader )
939 if (!reader->read_size) return WS_E_INVALID_FORMAT;
941 if (read_cmp( reader, "<", 1 ) || read_cmp( reader, "<?", 2 ))
943 reader->state = READER_STATE_BOF;
944 return S_OK;
946 if (read_cmp( reader, "<?xml ", 6 )) return WS_E_INVALID_FORMAT;
947 read_skip( reader, 6 );
949 /* FIXME: parse attributes */
950 while (reader->read_pos < reader->read_size && reader->read_bufptr[reader->read_pos] != '?')
951 reader->read_pos++;
953 if (read_cmp( reader, "?>", 2 )) return WS_E_INVALID_FORMAT;
954 read_skip( reader, 2 );
956 reader->state = READER_STATE_BOF;
957 return S_OK;
960 HRESULT append_attribute( WS_XML_ELEMENT_NODE *elem, WS_XML_ATTRIBUTE *attr )
962 if (elem->attributeCount)
964 WS_XML_ATTRIBUTE **tmp;
965 if (!(tmp = heap_realloc( elem->attributes, (elem->attributeCount + 1) * sizeof(attr) )))
966 return E_OUTOFMEMORY;
967 elem->attributes = tmp;
969 else if (!(elem->attributes = heap_alloc( sizeof(attr) ))) return E_OUTOFMEMORY;
970 elem->attributes[elem->attributeCount++] = attr;
971 return S_OK;
974 static inline void init_xml_string( BYTE *bytes, ULONG len, WS_XML_STRING *str )
976 str->length = len;
977 str->bytes = bytes;
978 str->dictionary = NULL;
979 str->id = 0;
982 static HRESULT split_qname( const BYTE *str, ULONG len, WS_XML_STRING *prefix, WS_XML_STRING *localname )
984 BYTE *prefix_bytes = NULL, *localname_bytes = (BYTE *)str, *ptr = (BYTE *)str;
985 ULONG prefix_len = 0, localname_len = len;
987 while (len--)
989 if (*ptr == ':')
991 if (ptr == str) return WS_E_INVALID_FORMAT;
992 prefix_bytes = (BYTE *)str;
993 prefix_len = ptr - str;
994 localname_bytes = ptr + 1;
995 localname_len = len;
996 break;
998 ptr++;
1000 if (!localname_len) return WS_E_INVALID_FORMAT;
1002 init_xml_string( prefix_bytes, prefix_len, prefix );
1003 init_xml_string( localname_bytes, localname_len, localname );
1004 return S_OK;
1007 static HRESULT parse_qname( const BYTE *str, ULONG len, WS_XML_STRING **prefix_ret, WS_XML_STRING **localname_ret )
1009 WS_XML_STRING prefix, localname;
1010 HRESULT hr;
1012 if ((hr = split_qname( str, len, &prefix, &localname )) != S_OK) return hr;
1013 if (!(*prefix_ret = alloc_xml_string( NULL, prefix.length ))) return E_OUTOFMEMORY;
1014 if (!(*localname_ret = dup_xml_string( &localname )))
1016 free_xml_string( *prefix_ret );
1017 return E_OUTOFMEMORY;
1019 memcpy( (*prefix_ret)->bytes, prefix.bytes, prefix.length );
1020 if (prefix.length && add_xml_string( *prefix_ret ) != S_OK) WARN( "prefix not added to dictionary\n" );
1021 return S_OK;
1024 static int codepoint_to_utf8( int cp, unsigned char *dst )
1026 if (!cp) return -1;
1027 if (cp < 0x80)
1029 *dst = cp;
1030 return 1;
1032 if (cp < 0x800)
1034 dst[1] = 0x80 | (cp & 0x3f);
1035 cp >>= 6;
1036 dst[0] = 0xc0 | cp;
1037 return 2;
1039 if ((cp >= 0xd800 && cp <= 0xdfff) || cp == 0xfffe || cp == 0xffff) return -1;
1040 if (cp < 0x10000)
1042 dst[2] = 0x80 | (cp & 0x3f);
1043 cp >>= 6;
1044 dst[1] = 0x80 | (cp & 0x3f);
1045 cp >>= 6;
1046 dst[0] = 0xe0 | cp;
1047 return 3;
1049 if (cp >= 0x110000) return -1;
1050 dst[3] = 0x80 | (cp & 0x3f);
1051 cp >>= 6;
1052 dst[2] = 0x80 | (cp & 0x3f);
1053 cp >>= 6;
1054 dst[1] = 0x80 | (cp & 0x3f);
1055 cp >>= 6;
1056 dst[0] = 0xf0 | cp;
1057 return 4;
1060 static HRESULT decode_text( const unsigned char *str, ULONG len, unsigned char *ret, ULONG *ret_len )
1062 const unsigned char *p = str;
1063 unsigned char *q = ret;
1065 *ret_len = 0;
1066 while (len)
1068 if (*p == '&')
1070 p++; len--;
1071 if (!len) return WS_E_INVALID_FORMAT;
1073 if (len >= 3 && !memcmp( p, "lt;", 3 ))
1075 *q++ = '<';
1076 p += 3;
1077 len -= 3;
1079 else if (len >= 3 && !memcmp( p, "gt;", 3 ))
1081 *q++ = '>';
1082 p += 3;
1083 len -= 3;
1085 else if (len >= 5 && !memcmp( p, "quot;", 5 ))
1087 *q++ = '"';
1088 p += 5;
1089 len -= 5;
1091 else if (len >= 4 && !memcmp( p, "amp;", 4 ))
1093 *q++ = '&';
1094 p += 4;
1095 len -= 4;
1097 else if (len >= 5 && !memcmp( p, "apos;", 5 ))
1099 *q++ = '\'';
1100 p += 5;
1101 len -= 5;
1103 else if (*p == '#')
1105 ULONG start, nb_digits, i;
1106 int len_utf8, cp = 0;
1108 p++; len--;
1109 if (!len) return WS_E_INVALID_FORMAT;
1110 if (*p == 'x')
1112 p++; len--;
1114 start = len;
1115 while (len && isxdigit( *p )) { p++; len--; };
1116 if (!len) return WS_E_INVALID_FORMAT;
1118 p -= nb_digits = start - len;
1119 if (!nb_digits || nb_digits > 6 || p[nb_digits] != ';') return WS_E_INVALID_FORMAT;
1120 for (i = 0; i < nb_digits; i++)
1122 cp *= 16;
1123 if (*p >= '0' && *p <= '9') cp += *p - '0';
1124 else if (*p >= 'a' && *p <= 'f') cp += *p - 'a' + 10;
1125 else cp += *p - 'A' + 10;
1126 p++;
1129 else if (isdigit( *p ))
1131 while (len && *p == '0') { p++; len--; };
1132 if (!len) return WS_E_INVALID_FORMAT;
1134 start = len;
1135 while (len && isdigit( *p )) { p++; len--; };
1136 if (!len) return WS_E_INVALID_FORMAT;
1138 p -= nb_digits = start - len;
1139 if (!nb_digits || nb_digits > 7 || p[nb_digits] != ';') return WS_E_INVALID_FORMAT;
1140 for (i = 0; i < nb_digits; i++)
1142 cp *= 10;
1143 cp += *p - '0';
1144 p++;
1147 else return WS_E_INVALID_FORMAT;
1148 p++; len--;
1149 if ((len_utf8 = codepoint_to_utf8( cp, q )) < 0) return WS_E_INVALID_FORMAT;
1150 *ret_len += len_utf8;
1151 q += len_utf8;
1152 continue;
1154 else return WS_E_INVALID_FORMAT;
1156 else
1158 *q++ = *p++;
1159 len--;
1161 *ret_len += 1;
1163 return S_OK;
1166 static HRESULT read_attribute_value_text( struct reader *reader, WS_XML_ATTRIBUTE *attr )
1168 WS_XML_UTF8_TEXT *utf8 = NULL;
1169 unsigned int len, ch, skip, quote;
1170 const unsigned char *start;
1171 HRESULT hr = E_OUTOFMEMORY;
1173 read_skip_whitespace( reader );
1174 if (read_cmp( reader, "=", 1 )) return WS_E_INVALID_FORMAT;
1175 read_skip( reader, 1 );
1177 read_skip_whitespace( reader );
1178 if (read_cmp( reader, "\"", 1 ) && read_cmp( reader, "'", 1 )) return WS_E_INVALID_FORMAT;
1179 quote = read_utf8_char( reader, &skip );
1180 read_skip( reader, 1 );
1182 len = 0;
1183 start = read_current_ptr( reader );
1184 for (;;)
1186 if (!(ch = read_utf8_char( reader, &skip ))) return WS_E_INVALID_FORMAT;
1187 if (ch == quote) break;
1188 read_skip( reader, skip );
1189 len += skip;
1191 read_skip( reader, 1 );
1193 if (attr->isXmlNs)
1195 if (!(attr->ns = alloc_xml_string( start, len ))) goto error;
1196 if ((hr = bind_prefix( reader, attr->prefix, attr->ns )) != S_OK) goto error;
1197 if (!(utf8 = alloc_utf8_text( NULL, 0 )))
1199 hr = E_OUTOFMEMORY;
1200 goto error;
1203 else
1205 if (!(utf8 = alloc_utf8_text( NULL, len ))) goto error;
1206 if ((hr = decode_text( start, len, utf8->value.bytes, &utf8->value.length )) != S_OK) goto error;
1209 attr->value = &utf8->text;
1210 attr->singleQuote = (quote == '\'');
1211 return S_OK;
1213 error:
1214 heap_free( utf8 );
1215 return hr;
1218 static inline BOOL is_text_type( unsigned char type )
1220 return (type >= RECORD_ZERO_TEXT && type <= RECORD_QNAME_DICTIONARY_TEXT_WITH_ENDELEMENT);
1223 static HRESULT read_int31( struct reader *reader, ULONG *len )
1225 unsigned char byte;
1226 HRESULT hr;
1228 if ((hr = read_byte( reader, &byte )) != S_OK) return hr;
1229 *len = byte & 0x7f;
1230 if (!(byte & 0x80)) return S_OK;
1232 if ((hr = read_byte( reader, &byte )) != S_OK) return hr;
1233 *len += (byte & 0x7f) << 7;
1234 if (!(byte & 0x80)) return S_OK;
1236 if ((hr = read_byte( reader, &byte )) != S_OK) return hr;
1237 *len += (byte & 0x7f) << 14;
1238 if (!(byte & 0x80)) return S_OK;
1240 if ((hr = read_byte( reader, &byte )) != S_OK) return hr;
1241 *len += (byte & 0x7f) << 21;
1242 if (!(byte & 0x80)) return S_OK;
1244 if ((hr = read_byte( reader, &byte )) != S_OK) return hr;
1245 *len += (byte & 0x07) << 28;
1246 return S_OK;
1249 static HRESULT read_string( struct reader *reader, WS_XML_STRING **str )
1251 ULONG len;
1252 HRESULT hr;
1253 if ((hr = read_int31( reader, &len )) != S_OK) return hr;
1254 if (!(*str = alloc_xml_string( NULL, len ))) return E_OUTOFMEMORY;
1255 if ((hr = read_bytes( reader, (*str)->bytes, len )) == S_OK)
1257 if (add_xml_string( *str ) != S_OK) WARN( "string not added to dictionary\n" );
1258 return S_OK;
1260 free_xml_string( *str );
1261 return hr;
1264 static HRESULT read_dict_string( struct reader *reader, WS_XML_STRING **str )
1266 const WS_XML_DICTIONARY *dict;
1267 HRESULT hr;
1268 ULONG id;
1270 if ((hr = read_int31( reader, &id )) != S_OK) return hr;
1271 dict = (id & 1) ? reader->dict : reader->dict_static;
1272 if (!dict || (id >>= 1) >= dict->stringCount) return WS_E_INVALID_FORMAT;
1273 if (!(*str = alloc_xml_string( NULL, 0 ))) return E_OUTOFMEMORY;
1274 *(*str) = dict->strings[id];
1275 return S_OK;
1278 static HRESULT read_datetime( struct reader *reader, WS_DATETIME *ret )
1280 UINT64 val;
1281 HRESULT hr;
1283 if ((hr = read_bytes( reader, (unsigned char *)&val, sizeof(val) )) != S_OK) return hr;
1285 if ((val & 0x03) == 1) ret->format = WS_DATETIME_FORMAT_UTC;
1286 else if ((val & 0x03) == 2) ret->format = WS_DATETIME_FORMAT_LOCAL;
1287 else ret->format = WS_DATETIME_FORMAT_NONE;
1289 if ((ret->ticks = val >> 2) > TICKS_MAX) return WS_E_INVALID_FORMAT;
1290 return S_OK;
1293 static HRESULT lookup_string( struct reader *reader, ULONG id, const WS_XML_STRING **ret )
1295 const WS_XML_DICTIONARY *dict = (id & 1) ? reader->dict : reader->dict_static;
1296 if (!dict || (id >>= 1) >= dict->stringCount) return WS_E_INVALID_FORMAT;
1297 *ret = &dict->strings[id];
1298 return S_OK;
1301 static HRESULT read_attribute_value_bin( struct reader *reader, WS_XML_ATTRIBUTE *attr )
1303 static const unsigned char zero[] = {'0'}, one[] = {'1'};
1304 static const unsigned char false[] = {'f','a','l','s','e'}, true[] = {'t','r','u','e'};
1305 WS_XML_UTF8_TEXT *utf8 = NULL;
1306 WS_XML_BASE64_TEXT *base64;
1307 const WS_XML_STRING *str;
1308 unsigned char type, buf[46];
1309 BOOL val_bool;
1310 INT8 val_int8;
1311 INT16 val_int16;
1312 INT32 val_int32;
1313 INT64 val_int64;
1314 double val_double;
1315 UINT8 val_uint8;
1316 UINT16 val_uint16;
1317 UINT64 val_uint64;
1318 WS_DATETIME datetime;
1319 ULONG len, id;
1320 GUID uuid;
1321 HRESULT hr;
1323 if ((hr = read_byte( reader, &type )) != S_OK) return hr;
1324 if (!is_text_type( type )) return WS_E_INVALID_FORMAT;
1326 switch (type)
1328 case RECORD_ZERO_TEXT:
1329 if (!(utf8 = alloc_utf8_text( zero, sizeof(zero) ))) return E_OUTOFMEMORY;
1330 break;
1332 case RECORD_ONE_TEXT:
1333 if (!(utf8 = alloc_utf8_text( one, sizeof(one) ))) return E_OUTOFMEMORY;
1334 break;
1336 case RECORD_FALSE_TEXT:
1337 if (!(utf8 = alloc_utf8_text( false, sizeof(false) ))) return E_OUTOFMEMORY;
1338 break;
1340 case RECORD_TRUE_TEXT:
1341 if (!(utf8 = alloc_utf8_text( true, sizeof(true) ))) return E_OUTOFMEMORY;
1342 break;
1344 case RECORD_INT8_TEXT:
1345 if ((hr = read_byte( reader, (unsigned char *)&val_int8 )) != S_OK) return hr;
1346 len = format_int8( &val_int8, buf );
1347 if (!(utf8 = alloc_utf8_text( buf, len ))) return E_OUTOFMEMORY;
1348 break;
1350 case RECORD_INT16_TEXT:
1351 if ((hr = read_bytes( reader, (unsigned char *)&val_int16, sizeof(val_int16) )) != S_OK) return hr;
1352 len = format_int16( &val_int16, buf );
1353 if (!(utf8 = alloc_utf8_text( buf, len ))) return E_OUTOFMEMORY;
1354 break;
1356 case RECORD_INT32_TEXT:
1357 if ((hr = read_bytes( reader, (unsigned char *)&val_int32, sizeof(val_int32) )) != S_OK) return hr;
1358 len = format_int32( &val_int32, buf );
1359 if (!(utf8 = alloc_utf8_text( buf, len ))) return E_OUTOFMEMORY;
1360 break;
1362 case RECORD_INT64_TEXT:
1363 if ((hr = read_bytes( reader, (unsigned char *)&val_int64, sizeof(val_int64) )) != S_OK) return hr;
1364 len = format_int64( &val_int64, buf );
1365 if (!(utf8 = alloc_utf8_text( buf, len ))) return E_OUTOFMEMORY;
1366 break;
1368 case RECORD_DOUBLE_TEXT:
1369 if ((hr = read_bytes( reader, (unsigned char *)&val_double, sizeof(val_double) )) != S_OK) return hr;
1370 len = format_double( &val_double, buf );
1371 if (!(utf8 = alloc_utf8_text( buf, len ))) return E_OUTOFMEMORY;
1372 break;
1374 case RECORD_DATETIME_TEXT:
1375 if ((hr = read_datetime( reader, &datetime )) != S_OK) return hr;
1376 len = format_datetime( &datetime, buf );
1377 if (!(utf8 = alloc_utf8_text( buf, len ))) return E_OUTOFMEMORY;
1378 break;
1380 case RECORD_CHARS8_TEXT:
1381 if ((hr = read_byte( reader, (unsigned char *)&val_uint8 )) != S_OK) return hr;
1382 len = val_uint8;
1383 break;
1385 case RECORD_CHARS16_TEXT:
1386 if ((hr = read_bytes( reader, (unsigned char *)&val_uint16, sizeof(val_uint16) )) != S_OK) return hr;
1387 len = val_uint16;
1388 break;
1390 case RECORD_CHARS32_TEXT:
1391 if ((hr = read_bytes( reader, (unsigned char *)&val_int32, sizeof(val_int32) )) != S_OK) return hr;
1392 if (val_int32 < 0) return WS_E_INVALID_FORMAT;
1393 len = val_int32;
1394 break;
1396 case RECORD_BYTES8_TEXT:
1397 if ((hr = read_byte( reader, (unsigned char *)&val_uint8 )) != S_OK) return hr;
1398 if (!(base64 = alloc_base64_text( NULL, val_uint8 ))) return E_OUTOFMEMORY;
1399 if ((hr = read_bytes( reader, base64->bytes, val_uint8 )) != S_OK)
1401 heap_free( base64 );
1402 return hr;
1404 break;
1406 case RECORD_BYTES16_TEXT:
1407 if ((hr = read_bytes( reader, (unsigned char *)&val_uint16, sizeof(val_uint16) )) != S_OK) return hr;
1408 if (!(base64 = alloc_base64_text( NULL, val_uint16 ))) return E_OUTOFMEMORY;
1409 if ((hr = read_bytes( reader, base64->bytes, val_uint16 )) != S_OK)
1411 heap_free( base64 );
1412 return hr;
1414 break;
1416 case RECORD_BYTES32_TEXT:
1417 if ((hr = read_bytes( reader, (unsigned char *)&val_int32, sizeof(val_int32) )) != S_OK) return hr;
1418 if (val_int32 < 0) return WS_E_INVALID_FORMAT;
1419 if (!(base64 = alloc_base64_text( NULL, val_int32 ))) return E_OUTOFMEMORY;
1420 if ((hr = read_bytes( reader, base64->bytes, val_int32 )) != S_OK)
1422 heap_free( base64 );
1423 return hr;
1425 break;
1427 case RECORD_EMPTY_TEXT:
1428 len = 0;
1429 break;
1431 case RECORD_DICTIONARY_TEXT:
1432 if ((hr = read_int31( reader, &id )) != S_OK) return hr;
1433 if ((hr = lookup_string( reader, id, &str )) != S_OK) return hr;
1434 if (!(utf8 = alloc_utf8_text( str->bytes, str->length ))) return E_OUTOFMEMORY;
1435 break;
1437 case RECORD_UNIQUEID_TEXT:
1438 if ((hr = read_bytes( reader, (unsigned char *)&uuid, sizeof(uuid) )) != S_OK) return hr;
1439 len = format_urn( &uuid, buf );
1440 if (!(utf8 = alloc_utf8_text( buf, len ))) return E_OUTOFMEMORY;
1441 break;
1443 case RECORD_UUID_TEXT:
1444 if ((hr = read_bytes( reader, (unsigned char *)&uuid, sizeof(uuid) )) != S_OK) return hr;
1445 len = format_guid( &uuid, buf );
1446 if (!(utf8 = alloc_utf8_text( buf, len ))) return E_OUTOFMEMORY;
1447 break;
1449 case RECORD_UINT64_TEXT:
1450 if ((hr = read_bytes( reader, (unsigned char *)&val_uint64, sizeof(val_uint64) )) != S_OK) return hr;
1451 len = format_uint64( &val_uint64, buf );
1452 if (!(utf8 = alloc_utf8_text( buf, len ))) return E_OUTOFMEMORY;
1453 break;
1455 case RECORD_BOOL_TEXT:
1456 if ((hr = read_bytes( reader, (unsigned char *)&val_bool, sizeof(val_bool) )) != S_OK) return hr;
1457 len = format_bool( &val_bool, buf );
1458 if (!(utf8 = alloc_utf8_text( buf, len ))) return E_OUTOFMEMORY;
1459 break;
1461 default:
1462 ERR( "unhandled record type %02x\n", type );
1463 return WS_E_NOT_SUPPORTED;
1466 if (type >= RECORD_BYTES8_TEXT && type <= RECORD_BYTES32_TEXT)
1468 attr->value = &base64->text;
1469 return S_OK;
1472 if (!utf8)
1474 if (!(utf8 = alloc_utf8_text( NULL, len ))) return E_OUTOFMEMORY;
1475 if (!len) utf8->value.bytes = (BYTE *)(utf8 + 1); /* quirk */
1476 if ((hr = read_bytes( reader, utf8->value.bytes, len )) != S_OK)
1478 heap_free( utf8 );
1479 return hr;
1483 attr->value = &utf8->text;
1484 return S_OK;
1487 static HRESULT read_attribute_text( struct reader *reader, WS_XML_ATTRIBUTE **ret )
1489 static const WS_XML_STRING xmlns = {5, (BYTE *)"xmlns"};
1490 WS_XML_ATTRIBUTE *attr;
1491 unsigned int len = 0, ch, skip;
1492 const unsigned char *start;
1493 WS_XML_STRING *prefix, *localname;
1494 HRESULT hr = WS_E_INVALID_FORMAT;
1496 if (!(attr = heap_alloc_zero( sizeof(*attr) ))) return E_OUTOFMEMORY;
1498 start = read_current_ptr( reader );
1499 for (;;)
1501 if (!(ch = read_utf8_char( reader, &skip ))) goto error;
1502 if (!read_isnamechar( ch )) break;
1503 read_skip( reader, skip );
1504 len += skip;
1506 if (!len) goto error;
1508 if ((hr = parse_qname( start, len, &prefix, &localname )) != S_OK) goto error;
1509 if (WsXmlStringEquals( prefix, &xmlns, NULL ) == S_OK)
1511 free_xml_string( prefix );
1512 attr->isXmlNs = 1;
1513 if (!(attr->prefix = alloc_xml_string( localname->bytes, localname->length )))
1515 free_xml_string( localname );
1516 hr = E_OUTOFMEMORY;
1517 goto error;
1519 attr->localName = localname;
1521 else if (!prefix->length && WsXmlStringEquals( localname, &xmlns, NULL ) == S_OK)
1523 attr->isXmlNs = 1;
1524 attr->prefix = prefix;
1525 attr->localName = localname;
1527 else
1529 attr->prefix = prefix;
1530 attr->localName = localname;
1533 if ((hr = read_attribute_value_text( reader, attr )) != S_OK) goto error;
1535 *ret = attr;
1536 return S_OK;
1538 error:
1539 free_attribute( attr );
1540 return hr;
1543 static inline BOOL is_attribute_type( unsigned char type )
1545 return (type >= RECORD_SHORT_ATTRIBUTE && type <= RECORD_PREFIX_ATTRIBUTE_Z);
1548 static HRESULT read_attribute_bin( struct reader *reader, WS_XML_ATTRIBUTE **ret )
1550 WS_XML_ATTRIBUTE *attr;
1551 unsigned char type = 0;
1552 HRESULT hr;
1554 if ((hr = read_byte( reader, &type )) != S_OK) return hr;
1555 if (!is_attribute_type( type )) return WS_E_INVALID_FORMAT;
1556 if (!(attr = heap_alloc_zero( sizeof(*attr) ))) return E_OUTOFMEMORY;
1558 if (type >= RECORD_PREFIX_ATTRIBUTE_A && type <= RECORD_PREFIX_ATTRIBUTE_Z)
1560 unsigned char ch = type - RECORD_PREFIX_ATTRIBUTE_A + 'a';
1561 if (!(attr->prefix = alloc_xml_string( &ch, 1 )))
1563 hr = E_OUTOFMEMORY;
1564 goto error;
1566 if ((hr = read_string( reader, &attr->localName )) != S_OK) goto error;
1567 if ((hr = read_attribute_value_bin( reader, attr )) != S_OK) goto error;
1569 else if (type >= RECORD_PREFIX_DICTIONARY_ATTRIBUTE_A && type <= RECORD_PREFIX_DICTIONARY_ATTRIBUTE_Z)
1571 unsigned char ch = type - RECORD_PREFIX_DICTIONARY_ATTRIBUTE_A + 'a';
1572 if (!(attr->prefix = alloc_xml_string( &ch, 1 )))
1574 hr = E_OUTOFMEMORY;
1575 goto error;
1577 if ((hr = read_dict_string( reader, &attr->localName )) != S_OK) goto error;
1578 if ((hr = read_attribute_value_bin( reader, attr )) != S_OK) goto error;
1580 else
1582 switch (type)
1584 case RECORD_SHORT_ATTRIBUTE:
1585 if (!(attr->prefix = alloc_xml_string( NULL, 0 )))
1587 hr = E_OUTOFMEMORY;
1588 goto error;
1590 if ((hr = read_string( reader, &attr->localName )) != S_OK) goto error;
1591 if ((hr = read_attribute_value_bin( reader, attr )) != S_OK) goto error;
1592 break;
1594 case RECORD_ATTRIBUTE:
1595 if ((hr = read_string( reader, &attr->prefix )) != S_OK) goto error;
1596 if ((hr = read_string( reader, &attr->localName )) != S_OK) goto error;
1597 if ((hr = read_attribute_value_bin( reader, attr )) != S_OK) goto error;
1598 break;
1600 case RECORD_SHORT_DICTIONARY_ATTRIBUTE:
1601 if (!(attr->prefix = alloc_xml_string( NULL, 0 )))
1603 hr = E_OUTOFMEMORY;
1604 goto error;
1606 if ((hr = read_dict_string( reader, &attr->localName )) != S_OK) goto error;
1607 if ((hr = read_attribute_value_bin( reader, attr )) != S_OK) goto error;
1608 break;
1610 case RECORD_DICTIONARY_ATTRIBUTE:
1611 if ((hr = read_string( reader, &attr->prefix )) != S_OK) goto error;
1612 if ((hr = read_dict_string( reader, &attr->localName )) != S_OK) goto error;
1613 if ((hr = read_attribute_value_bin( reader, attr )) != S_OK) goto error;
1614 break;
1616 case RECORD_SHORT_XMLNS_ATTRIBUTE:
1617 if (!(attr->prefix = alloc_xml_string( NULL, 0 )))
1619 hr = E_OUTOFMEMORY;
1620 goto error;
1622 if ((hr = read_string( reader, &attr->ns )) != S_OK) goto error;
1623 if ((hr = bind_prefix( reader, attr->prefix, attr->ns )) != S_OK) goto error;
1624 attr->isXmlNs = 1;
1625 break;
1627 case RECORD_XMLNS_ATTRIBUTE:
1628 if ((hr = read_string( reader, &attr->prefix )) != S_OK) goto error;
1629 if ((hr = read_string( reader, &attr->ns )) != S_OK) goto error;
1630 if ((hr = bind_prefix( reader, attr->prefix, attr->ns )) != S_OK) goto error;
1631 attr->isXmlNs = 1;
1632 break;
1634 case RECORD_SHORT_DICTIONARY_XMLNS_ATTRIBUTE:
1635 if (!(attr->prefix = alloc_xml_string( NULL, 0 )))
1637 hr = E_OUTOFMEMORY;
1638 goto error;
1640 if ((hr = read_dict_string( reader, &attr->ns )) != S_OK) goto error;
1641 if ((hr = bind_prefix( reader, attr->prefix, attr->ns )) != S_OK) goto error;
1642 attr->isXmlNs = 1;
1643 break;
1645 case RECORD_DICTIONARY_XMLNS_ATTRIBUTE:
1646 if ((hr = read_string( reader, &attr->prefix )) != S_OK) goto error;
1647 if ((hr = read_dict_string( reader, &attr->ns )) != S_OK) goto error;
1648 if ((hr = bind_prefix( reader, attr->prefix, attr->ns )) != S_OK) goto error;
1649 attr->isXmlNs = 1;
1650 break;
1652 default:
1653 ERR( "unhandled record type %02x\n", type );
1654 return WS_E_NOT_SUPPORTED;
1658 *ret = attr;
1659 return S_OK;
1661 error:
1662 free_attribute( attr );
1663 return hr;
1666 static inline struct node *find_parent( struct reader *reader )
1668 if (node_type( reader->current ) == WS_XML_NODE_TYPE_END_ELEMENT)
1670 if (is_valid_parent( reader->current->parent->parent )) return reader->current->parent->parent;
1671 return NULL;
1673 if (is_valid_parent( reader->current )) return reader->current;
1674 if (is_valid_parent( reader->current->parent )) return reader->current->parent;
1675 return NULL;
1678 static HRESULT set_namespaces( struct reader *reader, WS_XML_ELEMENT_NODE *elem )
1680 static const WS_XML_STRING xml = {3, (BYTE *)"xml"};
1681 const WS_XML_STRING *ns;
1682 ULONG i;
1684 if (!(ns = get_namespace( reader, elem->prefix ))) return WS_E_INVALID_FORMAT;
1685 if (!(elem->ns = dup_xml_string( ns ))) return E_OUTOFMEMORY;
1687 for (i = 0; i < elem->attributeCount; i++)
1689 WS_XML_ATTRIBUTE *attr = elem->attributes[i];
1690 if (attr->isXmlNs || WsXmlStringEquals( attr->prefix, &xml, NULL ) == S_OK) continue;
1691 if (!(ns = get_namespace( reader, attr->prefix ))) return WS_E_INVALID_FORMAT;
1692 if (!(attr->ns = alloc_xml_string( NULL, ns->length ))) return E_OUTOFMEMORY;
1693 if (attr->ns->length) memcpy( attr->ns->bytes, ns->bytes, ns->length );
1695 return S_OK;
1698 static WS_XML_ELEMENT_NODE *alloc_element_pair(void)
1700 struct node *node, *end;
1701 if (!(node = alloc_node( WS_XML_NODE_TYPE_ELEMENT ))) return NULL;
1702 if (!(end = alloc_node( WS_XML_NODE_TYPE_END_ELEMENT )))
1704 free_node( node );
1705 return NULL;
1707 list_add_tail( &node->children, &end->entry );
1708 end->parent = node;
1709 return &node->hdr;
1712 static HRESULT read_attributes_text( struct reader *reader, WS_XML_ELEMENT_NODE *elem )
1714 WS_XML_ATTRIBUTE *attr;
1715 HRESULT hr;
1717 reader->current_attr = 0;
1718 for (;;)
1720 read_skip_whitespace( reader );
1721 if (!read_cmp( reader, ">", 1 ) || !read_cmp( reader, "/>", 2 )) break;
1722 if ((hr = read_attribute_text( reader, &attr )) != S_OK) return hr;
1723 if ((hr = append_attribute( elem, attr )) != S_OK)
1725 free_attribute( attr );
1726 return hr;
1728 reader->current_attr++;
1730 return S_OK;
1733 static HRESULT read_element_text( struct reader *reader )
1735 unsigned int len = 0, ch, skip;
1736 const unsigned char *start;
1737 struct node *node = NULL, *parent;
1738 WS_XML_ELEMENT_NODE *elem;
1739 HRESULT hr = WS_E_INVALID_FORMAT;
1741 if (read_end_of_data( reader ))
1743 reader->current = LIST_ENTRY( list_tail( &reader->root->children ), struct node, entry );
1744 reader->last = reader->current;
1745 reader->state = READER_STATE_EOF;
1746 return S_OK;
1749 if (read_cmp( reader, "<", 1 )) return WS_E_INVALID_FORMAT;
1750 read_skip( reader, 1 );
1751 if (!read_isnamechar( read_utf8_char( reader, &skip )))
1753 read_rewind( reader, 1 );
1754 return WS_E_INVALID_FORMAT;
1757 if (!(elem = alloc_element_pair())) return E_OUTOFMEMORY;
1758 node = (struct node *)elem;
1760 start = read_current_ptr( reader );
1761 for (;;)
1763 if (!(ch = read_utf8_char( reader, &skip ))) goto error;
1764 if (!read_isnamechar( ch )) break;
1765 read_skip( reader, skip );
1766 len += skip;
1768 if (!len) goto error;
1770 if (!(parent = find_parent( reader ))) goto error;
1771 if ((hr = parse_qname( start, len, &elem->prefix, &elem->localName )) != S_OK) goto error;
1772 if ((hr = read_attributes_text( reader, elem )) != S_OK) goto error;
1773 if ((hr = set_namespaces( reader, elem )) != S_OK) goto error;
1775 read_insert_node( reader, parent, node );
1776 reader->state = READER_STATE_STARTELEMENT;
1777 return S_OK;
1779 error:
1780 destroy_nodes( node );
1781 return hr;
1784 static inline BOOL is_element_type( unsigned char type )
1786 return (type >= RECORD_SHORT_ELEMENT && type <= RECORD_PREFIX_ELEMENT_Z);
1789 static HRESULT read_attributes_bin( struct reader *reader, WS_XML_ELEMENT_NODE *elem )
1791 WS_XML_ATTRIBUTE *attr;
1792 unsigned char type;
1793 HRESULT hr;
1795 reader->current_attr = 0;
1796 for (;;)
1798 if ((hr = read_peek( reader, &type )) != S_OK) return hr;
1799 if (!is_attribute_type( type )) break;
1800 if ((hr = read_attribute_bin( reader, &attr )) != S_OK) return hr;
1801 if ((hr = append_attribute( elem, attr )) != S_OK)
1803 free_attribute( attr );
1804 return hr;
1806 reader->current_attr++;
1808 return S_OK;
1811 static HRESULT read_element_bin( struct reader *reader )
1813 struct node *node = NULL, *parent;
1814 WS_XML_ELEMENT_NODE *elem;
1815 unsigned char type;
1816 HRESULT hr;
1818 if ((hr = read_byte( reader, &type )) != S_OK) return hr;
1819 if (!is_element_type( type )) return WS_E_INVALID_FORMAT;
1821 if (!(elem = alloc_element_pair())) return E_OUTOFMEMORY;
1822 node = (struct node *)elem;
1824 if (type >= RECORD_PREFIX_ELEMENT_A && type <= RECORD_PREFIX_ELEMENT_Z)
1826 unsigned char ch = type - RECORD_PREFIX_ELEMENT_A + 'a';
1827 if (!(elem->prefix = alloc_xml_string( &ch, 1 )))
1829 hr = E_OUTOFMEMORY;
1830 goto error;
1832 if ((hr = read_string( reader, &elem->localName )) != S_OK) goto error;
1834 else if (type >= RECORD_PREFIX_DICTIONARY_ELEMENT_A && type <= RECORD_PREFIX_DICTIONARY_ELEMENT_Z)
1836 unsigned char ch = type - RECORD_PREFIX_DICTIONARY_ELEMENT_A + 'a';
1837 if (!(elem->prefix = alloc_xml_string( &ch, 1 )))
1839 hr = E_OUTOFMEMORY;
1840 goto error;
1842 if ((hr = read_dict_string( reader, &elem->localName )) != S_OK) goto error;
1844 else
1846 switch (type)
1848 case RECORD_SHORT_ELEMENT:
1849 if (!(elem->prefix = alloc_xml_string( NULL, 0 )))
1851 hr = E_OUTOFMEMORY;
1852 goto error;
1854 if ((hr = read_string( reader, &elem->localName )) != S_OK) goto error;
1855 break;
1857 case RECORD_ELEMENT:
1858 if ((hr = read_string( reader, &elem->prefix )) != S_OK) goto error;
1859 if ((hr = read_string( reader, &elem->localName )) != S_OK) goto error;
1860 break;
1862 case RECORD_SHORT_DICTIONARY_ELEMENT:
1863 if (!(elem->prefix = alloc_xml_string( NULL, 0 )))
1865 hr = E_OUTOFMEMORY;
1866 goto error;
1868 if ((hr = read_dict_string( reader, &elem->localName )) != S_OK) goto error;
1869 break;
1871 case RECORD_DICTIONARY_ELEMENT:
1872 if ((hr = read_string( reader, &elem->prefix )) != S_OK) goto error;
1873 if ((hr = read_dict_string( reader, &elem->localName )) != S_OK) goto error;
1874 break;
1876 default:
1877 ERR( "unhandled record type %02x\n", type );
1878 return WS_E_NOT_SUPPORTED;
1882 if (!(parent = find_parent( reader )))
1884 hr = WS_E_INVALID_FORMAT;
1885 goto error;
1888 if ((hr = read_attributes_bin( reader, elem )) != S_OK) goto error;
1889 if ((hr = set_namespaces( reader, elem )) != S_OK) goto error;
1891 read_insert_node( reader, parent, node );
1892 reader->state = READER_STATE_STARTELEMENT;
1893 return S_OK;
1895 error:
1896 destroy_nodes( node );
1897 return hr;
1900 static HRESULT read_text_text( struct reader *reader )
1902 unsigned int len = 0, ch, skip;
1903 const unsigned char *start;
1904 struct node *node, *parent;
1905 WS_XML_TEXT_NODE *text;
1906 WS_XML_UTF8_TEXT *utf8;
1907 HRESULT hr;
1909 start = read_current_ptr( reader );
1910 for (;;)
1912 if (read_end_of_data( reader )) break;
1913 if (!(ch = read_utf8_char( reader, &skip ))) return WS_E_INVALID_FORMAT;
1914 if (ch == '<') break;
1915 read_skip( reader, skip );
1916 len += skip;
1919 if (!(parent = find_parent( reader ))) return WS_E_INVALID_FORMAT;
1921 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return E_OUTOFMEMORY;
1922 text = (WS_XML_TEXT_NODE *)node;
1923 if (!(utf8 = alloc_utf8_text( NULL, len )))
1925 heap_free( node );
1926 return E_OUTOFMEMORY;
1928 if ((hr = decode_text( start, len, utf8->value.bytes, &utf8->value.length )) != S_OK)
1930 heap_free( utf8 );
1931 heap_free( node );
1932 return hr;
1934 text->text = &utf8->text;
1936 read_insert_node( reader, parent, node );
1937 reader->state = READER_STATE_TEXT;
1938 reader->text_conv_offset = 0;
1939 return S_OK;
1942 static struct node *alloc_utf8_text_node( const BYTE *data, ULONG len, WS_XML_UTF8_TEXT **ret )
1944 struct node *node;
1945 WS_XML_UTF8_TEXT *utf8;
1946 WS_XML_TEXT_NODE *text;
1948 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
1949 if (!(utf8 = alloc_utf8_text( data, len )))
1951 heap_free( node );
1952 return NULL;
1954 text = (WS_XML_TEXT_NODE *)node;
1955 text->text = &utf8->text;
1956 if (ret) *ret = utf8;
1957 return node;
1960 static struct node *alloc_base64_text_node( const BYTE *data, ULONG len, WS_XML_BASE64_TEXT **ret )
1962 struct node *node;
1963 WS_XML_BASE64_TEXT *base64;
1964 WS_XML_TEXT_NODE *text;
1966 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
1967 if (!(base64 = alloc_base64_text( data, len )))
1969 heap_free( node );
1970 return NULL;
1972 text = (WS_XML_TEXT_NODE *)node;
1973 text->text = &base64->text;
1974 if (ret) *ret = base64;
1975 return node;
1978 static HRESULT append_text_bytes( struct reader *reader, WS_XML_TEXT_NODE *node, ULONG len )
1980 WS_XML_BASE64_TEXT *new, *old = (WS_XML_BASE64_TEXT *)node->text;
1981 HRESULT hr;
1983 if (!(new = alloc_base64_text( NULL, old->length + len ))) return E_OUTOFMEMORY;
1984 memcpy( new->bytes, old->bytes, old->length );
1985 if ((hr = read_bytes( reader, new->bytes + old->length, len )) != S_OK) return hr;
1986 heap_free( old );
1987 node->text = &new->text;
1988 return S_OK;
1991 static HRESULT read_text_bytes( struct reader *reader, unsigned char type )
1993 struct node *node = NULL, *parent;
1994 WS_XML_BASE64_TEXT *base64;
1995 HRESULT hr;
1996 ULONG len;
1998 if (!(parent = find_parent( reader ))) return WS_E_INVALID_FORMAT;
1999 for (;;)
2001 switch (type)
2003 case RECORD_BYTES8_TEXT:
2004 case RECORD_BYTES8_TEXT_WITH_ENDELEMENT:
2006 UINT8 len_uint8;
2007 if ((hr = read_byte( reader, (unsigned char *)&len_uint8 )) != S_OK) goto error;
2008 len = len_uint8;
2009 break;
2011 case RECORD_BYTES16_TEXT:
2012 case RECORD_BYTES16_TEXT_WITH_ENDELEMENT:
2014 UINT16 len_uint16;
2015 if ((hr = read_bytes( reader, (unsigned char *)&len_uint16, sizeof(len_uint16) )) != S_OK) goto error;
2016 len = len_uint16;
2017 break;
2019 case RECORD_BYTES32_TEXT:
2020 case RECORD_BYTES32_TEXT_WITH_ENDELEMENT:
2022 INT32 len_int32;
2023 if ((hr = read_bytes( reader, (unsigned char *)&len_int32, sizeof(len_int32) )) != S_OK) goto error;
2024 if (len_int32 < 0)
2026 hr = WS_E_INVALID_FORMAT;
2027 goto error;
2029 len = len_int32;
2030 break;
2032 default:
2033 ERR( "unexpected type %u\n", type );
2034 hr = E_INVALIDARG;
2035 goto error;
2038 if (!node)
2040 if (!(node = alloc_base64_text_node( NULL, len, &base64 ))) return E_OUTOFMEMORY;
2041 if ((hr = read_bytes( reader, base64->bytes, len )) != S_OK) goto error;
2043 else if ((hr = append_text_bytes( reader, (WS_XML_TEXT_NODE *)node, len )) != S_OK) goto error;
2045 if (type & 1)
2047 node->flags |= NODE_FLAG_TEXT_WITH_IMPLICIT_END_ELEMENT;
2048 break;
2050 if ((hr = read_peek( reader, &type )) != S_OK) goto error;
2051 if (type < RECORD_BYTES8_TEXT || type > RECORD_BYTES32_TEXT_WITH_ENDELEMENT) break;
2052 read_skip( reader, 1 );
2055 read_insert_node( reader, parent, node );
2056 reader->state = READER_STATE_TEXT;
2057 reader->text_conv_offset = 0;
2058 return S_OK;
2060 error:
2061 free_node( node );
2062 return hr;
2065 static HRESULT read_text_bin( struct reader *reader )
2067 static const unsigned char zero[] = {'0'}, one[] = {'1'};
2068 static const unsigned char false[] = {'f','a','l','s','e'}, true[] = {'t','r','u','e'};
2069 unsigned char type, buf[46];
2070 struct node *node = NULL, *parent;
2071 WS_XML_UTF8_TEXT *utf8;
2072 const WS_XML_STRING *str;
2073 BOOL val_bool;
2074 INT8 val_int8;
2075 INT16 val_int16;
2076 INT32 val_int32;
2077 INT64 val_int64;
2078 double val_double;
2079 UINT8 val_uint8;
2080 UINT16 val_uint16;
2081 UINT64 val_uint64;
2082 WS_DATETIME datetime;
2083 ULONG len, id;
2084 GUID uuid;
2085 HRESULT hr;
2087 if ((hr = read_byte( reader, &type )) != S_OK) return hr;
2088 if (!is_text_type( type ) || !(parent = find_parent( reader ))) return WS_E_INVALID_FORMAT;
2090 switch (type)
2092 case RECORD_ZERO_TEXT:
2093 case RECORD_ZERO_TEXT_WITH_ENDELEMENT:
2094 if (!(node = alloc_utf8_text_node( zero, sizeof(zero), NULL ))) return E_OUTOFMEMORY;
2095 break;
2097 case RECORD_ONE_TEXT:
2098 case RECORD_ONE_TEXT_WITH_ENDELEMENT:
2099 if (!(node = alloc_utf8_text_node( one, sizeof(one), NULL ))) return E_OUTOFMEMORY;
2100 break;
2102 case RECORD_FALSE_TEXT:
2103 case RECORD_FALSE_TEXT_WITH_ENDELEMENT:
2104 if (!(node = alloc_utf8_text_node( false, sizeof(false), NULL ))) return E_OUTOFMEMORY;
2105 break;
2107 case RECORD_TRUE_TEXT:
2108 case RECORD_TRUE_TEXT_WITH_ENDELEMENT:
2109 if (!(node = alloc_utf8_text_node( true, sizeof(true), NULL ))) return E_OUTOFMEMORY;
2110 break;
2112 case RECORD_INT8_TEXT:
2113 case RECORD_INT8_TEXT_WITH_ENDELEMENT:
2114 if ((hr = read_byte( reader, (unsigned char *)&val_int8 )) != S_OK) return hr;
2115 len = format_int8( &val_int8, buf );
2116 if (!(node = alloc_utf8_text_node( buf, len, NULL ))) return E_OUTOFMEMORY;
2117 break;
2119 case RECORD_INT16_TEXT:
2120 case RECORD_INT16_TEXT_WITH_ENDELEMENT:
2121 if ((hr = read_bytes( reader, (unsigned char *)&val_int16, sizeof(val_int16) )) != S_OK) return hr;
2122 len = format_int16( &val_int16, buf );
2123 if (!(node = alloc_utf8_text_node( buf, len, NULL ))) return E_OUTOFMEMORY;
2124 break;
2126 case RECORD_INT32_TEXT:
2127 case RECORD_INT32_TEXT_WITH_ENDELEMENT:
2128 if ((hr = read_bytes( reader, (unsigned char *)&val_int32, sizeof(val_int32) )) != S_OK) return hr;
2129 len = format_int32( &val_int32, buf );
2130 if (!(node = alloc_utf8_text_node( buf, len, NULL ))) return E_OUTOFMEMORY;
2131 break;
2133 case RECORD_INT64_TEXT:
2134 case RECORD_INT64_TEXT_WITH_ENDELEMENT:
2135 if ((hr = read_bytes( reader, (unsigned char *)&val_int64, sizeof(val_int64) )) != S_OK) return hr;
2136 len = format_int64( &val_int64, buf );
2137 if (!(node = alloc_utf8_text_node( buf, len, NULL ))) return E_OUTOFMEMORY;
2138 break;
2140 case RECORD_DOUBLE_TEXT:
2141 case RECORD_DOUBLE_TEXT_WITH_ENDELEMENT:
2142 if ((hr = read_bytes( reader, (unsigned char *)&val_double, sizeof(val_double) )) != S_OK) return hr;
2143 len = format_double( &val_double, buf );
2144 if (!(node = alloc_utf8_text_node( buf, len, NULL ))) return E_OUTOFMEMORY;
2145 break;
2147 case RECORD_DATETIME_TEXT:
2148 case RECORD_DATETIME_TEXT_WITH_ENDELEMENT:
2149 if ((hr = read_datetime( reader, &datetime )) != S_OK) return hr;
2150 len = format_datetime( &datetime, buf );
2151 if (!(node = alloc_utf8_text_node( buf, len, NULL ))) return E_OUTOFMEMORY;
2152 break;
2154 case RECORD_CHARS8_TEXT:
2155 case RECORD_CHARS8_TEXT_WITH_ENDELEMENT:
2156 if ((hr = read_byte( reader, (unsigned char *)&val_uint8 )) != S_OK) return hr;
2157 len = val_uint8;
2158 break;
2160 case RECORD_CHARS16_TEXT:
2161 case RECORD_CHARS16_TEXT_WITH_ENDELEMENT:
2162 if ((hr = read_bytes( reader, (unsigned char *)&val_uint16, sizeof(val_uint16) )) != S_OK) return hr;
2163 len = val_uint16;
2164 break;
2166 case RECORD_CHARS32_TEXT:
2167 case RECORD_CHARS32_TEXT_WITH_ENDELEMENT:
2168 if ((hr = read_bytes( reader, (unsigned char *)&val_int32, sizeof(val_int32) )) != S_OK) return hr;
2169 if (val_int32 < 0) return WS_E_INVALID_FORMAT;
2170 len = val_int32;
2171 break;
2173 case RECORD_BYTES8_TEXT:
2174 case RECORD_BYTES8_TEXT_WITH_ENDELEMENT:
2175 case RECORD_BYTES16_TEXT:
2176 case RECORD_BYTES16_TEXT_WITH_ENDELEMENT:
2177 case RECORD_BYTES32_TEXT:
2178 case RECORD_BYTES32_TEXT_WITH_ENDELEMENT:
2179 return read_text_bytes( reader, type );
2181 case RECORD_EMPTY_TEXT:
2182 case RECORD_EMPTY_TEXT_WITH_ENDELEMENT:
2183 len = 0;
2184 break;
2186 case RECORD_DICTIONARY_TEXT:
2187 case RECORD_DICTIONARY_TEXT_WITH_ENDELEMENT:
2188 if ((hr = read_int31( reader, &id )) != S_OK) return hr;
2189 if ((hr = lookup_string( reader, id, &str )) != S_OK) return hr;
2190 if (!(node = alloc_utf8_text_node( str->bytes, str->length, NULL ))) return E_OUTOFMEMORY;
2191 break;
2193 case RECORD_UNIQUEID_TEXT:
2194 case RECORD_UNIQUEID_TEXT_WITH_ENDELEMENT:
2195 if ((hr = read_bytes( reader, (unsigned char *)&uuid, sizeof(uuid) )) != S_OK) return hr;
2196 len = format_urn( &uuid, buf );
2197 if (!(node = alloc_utf8_text_node( buf, len, NULL ))) return E_OUTOFMEMORY;
2198 break;
2200 case RECORD_UUID_TEXT:
2201 case RECORD_UUID_TEXT_WITH_ENDELEMENT:
2202 if ((hr = read_bytes( reader, (unsigned char *)&uuid, sizeof(uuid) )) != S_OK) return hr;
2203 len = format_guid( &uuid, buf );
2204 if (!(node = alloc_utf8_text_node( buf, len, NULL ))) return E_OUTOFMEMORY;
2205 break;
2207 case RECORD_UINT64_TEXT:
2208 case RECORD_UINT64_TEXT_WITH_ENDELEMENT:
2209 if ((hr = read_bytes( reader, (unsigned char *)&val_uint64, sizeof(val_uint64) )) != S_OK) return hr;
2210 len = format_uint64( &val_uint64, buf );
2211 if (!(node = alloc_utf8_text_node( buf, len, NULL ))) return E_OUTOFMEMORY;
2212 break;
2214 case RECORD_BOOL_TEXT:
2215 case RECORD_BOOL_TEXT_WITH_ENDELEMENT:
2216 if ((hr = read_bytes( reader, (unsigned char *)&val_bool, sizeof(val_bool) )) != S_OK) return hr;
2217 len = format_bool( &val_bool, buf );
2218 if (!(node = alloc_utf8_text_node( buf, len, NULL ))) return E_OUTOFMEMORY;
2219 break;
2221 default:
2222 ERR( "unhandled record type %02x\n", type );
2223 return WS_E_NOT_SUPPORTED;
2226 if (!node)
2228 if (!(node = alloc_utf8_text_node( NULL, len, &utf8 ))) return E_OUTOFMEMORY;
2229 if ((hr = read_bytes( reader, utf8->value.bytes, len )) != S_OK)
2231 free_node( node );
2232 return hr;
2236 if (type & 1) node->flags |= NODE_FLAG_TEXT_WITH_IMPLICIT_END_ELEMENT;
2237 read_insert_node( reader, parent, node );
2238 reader->state = READER_STATE_TEXT;
2239 reader->text_conv_offset = 0;
2240 return S_OK;
2243 static HRESULT read_node_text( struct reader * );
2245 static HRESULT read_startelement_text( struct reader *reader )
2247 read_skip_whitespace( reader );
2248 if (!read_cmp( reader, "/>", 2 ))
2250 read_skip( reader, 2 );
2251 reader->current = LIST_ENTRY( list_tail( &reader->current->children ), struct node, entry );
2252 reader->last = reader->current;
2253 reader->state = READER_STATE_ENDELEMENT;
2254 return S_OK;
2256 else if (!read_cmp( reader, ">", 1 ))
2258 read_skip( reader, 1 );
2259 return read_node_text( reader );
2261 return WS_E_INVALID_FORMAT;
2264 static HRESULT read_node_bin( struct reader * );
2266 static HRESULT read_startelement_bin( struct reader *reader )
2268 if (node_type( reader->current ) != WS_XML_NODE_TYPE_ELEMENT) return WS_E_INVALID_FORMAT;
2269 return read_node_bin( reader );
2272 static HRESULT read_startelement( struct reader *reader )
2274 switch (reader->input_enc)
2276 case WS_XML_READER_ENCODING_TYPE_TEXT: return read_startelement_text( reader );
2277 case WS_XML_READER_ENCODING_TYPE_BINARY: return read_startelement_bin( reader );
2278 default:
2279 ERR( "unhandled encoding %u\n", reader->input_enc );
2280 return WS_E_NOT_SUPPORTED;
2284 static HRESULT read_to_startelement_text( struct reader *reader, BOOL *found )
2286 HRESULT hr;
2288 switch (reader->state)
2290 case READER_STATE_INITIAL:
2291 if ((hr = read_xmldecl( reader )) != S_OK) return hr;
2292 break;
2294 case READER_STATE_STARTELEMENT:
2295 if (found) *found = TRUE;
2296 return S_OK;
2298 default:
2299 break;
2302 read_skip_whitespace( reader );
2303 if ((hr = read_element_text( reader )) == S_OK && found)
2305 if (reader->state == READER_STATE_STARTELEMENT)
2306 *found = TRUE;
2307 else
2308 *found = FALSE;
2311 return hr;
2314 static HRESULT read_to_startelement_bin( struct reader *reader, BOOL *found )
2316 HRESULT hr;
2318 if (reader->state == READER_STATE_STARTELEMENT)
2320 if (found) *found = TRUE;
2321 return S_OK;
2324 if ((hr = read_element_bin( reader )) == S_OK && found)
2326 if (reader->state == READER_STATE_STARTELEMENT)
2327 *found = TRUE;
2328 else
2329 *found = FALSE;
2332 return hr;
2335 static HRESULT read_to_startelement( struct reader *reader, BOOL *found )
2337 switch (reader->input_enc)
2339 case WS_XML_READER_ENCODING_TYPE_TEXT: return read_to_startelement_text( reader, found );
2340 case WS_XML_READER_ENCODING_TYPE_BINARY: return read_to_startelement_bin( reader, found );
2341 default:
2342 ERR( "unhandled encoding %u\n", reader->input_enc );
2343 return WS_E_NOT_SUPPORTED;
2347 static int cmp_name( const unsigned char *name1, ULONG len1, const unsigned char *name2, ULONG len2 )
2349 ULONG i;
2350 if (len1 != len2) return 1;
2351 for (i = 0; i < len1; i++) { if (toupper( name1[i] ) != toupper( name2[i] )) return 1; }
2352 return 0;
2355 static struct node *find_startelement( struct reader *reader, const WS_XML_STRING *prefix,
2356 const WS_XML_STRING *localname )
2358 struct node *parent;
2359 const WS_XML_STRING *str;
2361 for (parent = reader->current; parent; parent = parent->parent)
2363 if (node_type( parent ) == WS_XML_NODE_TYPE_ELEMENT)
2365 str = parent->hdr.prefix;
2366 if (cmp_name( str->bytes, str->length, prefix->bytes, prefix->length )) continue;
2367 str = parent->hdr.localName;
2368 if (cmp_name( str->bytes, str->length, localname->bytes, localname->length )) continue;
2369 return parent;
2372 return NULL;
2375 static HRESULT read_endelement_text( struct reader *reader )
2377 struct node *parent;
2378 unsigned int len = 0, ch, skip;
2379 const unsigned char *start;
2380 WS_XML_STRING prefix, localname;
2381 HRESULT hr;
2383 if (read_cmp( reader, "</", 2 )) return WS_E_INVALID_FORMAT;
2384 read_skip( reader, 2 );
2386 start = read_current_ptr( reader );
2387 for (;;)
2389 if (!(ch = read_utf8_char( reader, &skip ))) return WS_E_INVALID_FORMAT;
2390 if (ch == '>')
2392 read_skip( reader, 1 );
2393 break;
2395 if (!read_isnamechar( ch )) return WS_E_INVALID_FORMAT;
2396 read_skip( reader, skip );
2397 len += skip;
2400 if ((hr = split_qname( start, len, &prefix, &localname )) != S_OK) return hr;
2401 if (!(parent = find_startelement( reader, &prefix, &localname ))) return WS_E_INVALID_FORMAT;
2403 reader->current = LIST_ENTRY( list_tail( &parent->children ), struct node, entry );
2404 reader->last = reader->current;
2405 reader->state = READER_STATE_ENDELEMENT;
2406 return S_OK;
2409 static HRESULT read_endelement_bin( struct reader *reader )
2411 struct node *parent;
2412 unsigned char type;
2413 HRESULT hr;
2415 if (!(reader->current->flags & NODE_FLAG_TEXT_WITH_IMPLICIT_END_ELEMENT))
2417 if ((hr = read_byte( reader, &type )) != S_OK) return hr;
2418 if (type != RECORD_ENDELEMENT) return WS_E_INVALID_FORMAT;
2420 if (!(parent = find_parent( reader ))) return WS_E_INVALID_FORMAT;
2422 reader->current = LIST_ENTRY( list_tail( &parent->children ), struct node, entry );
2423 reader->last = reader->current;
2424 reader->state = READER_STATE_ENDELEMENT;
2425 return S_OK;
2428 static HRESULT read_endelement( struct reader *reader )
2430 if (reader->state == READER_STATE_EOF) return WS_E_INVALID_FORMAT;
2432 if (read_end_of_data( reader ))
2434 reader->current = LIST_ENTRY( list_tail( &reader->root->children ), struct node, entry );
2435 reader->last = reader->current;
2436 reader->state = READER_STATE_EOF;
2437 return S_OK;
2440 switch (reader->input_enc)
2442 case WS_XML_READER_ENCODING_TYPE_TEXT: return read_endelement_text( reader );
2443 case WS_XML_READER_ENCODING_TYPE_BINARY: return read_endelement_bin( reader );
2444 default:
2445 ERR( "unhandled encoding %u\n", reader->input_enc );
2446 return WS_E_NOT_SUPPORTED;
2450 static HRESULT read_comment_text( struct reader *reader )
2452 unsigned int len = 0, ch, skip;
2453 const unsigned char *start;
2454 struct node *node, *parent;
2455 WS_XML_COMMENT_NODE *comment;
2457 if (read_cmp( reader, "<!--", 4 )) return WS_E_INVALID_FORMAT;
2458 read_skip( reader, 4 );
2460 start = read_current_ptr( reader );
2461 for (;;)
2463 if (!read_cmp( reader, "-->", 3 ))
2465 read_skip( reader, 3 );
2466 break;
2468 if (!(ch = read_utf8_char( reader, &skip ))) return WS_E_INVALID_FORMAT;
2469 read_skip( reader, skip );
2470 len += skip;
2473 if (!(parent = find_parent( reader ))) return WS_E_INVALID_FORMAT;
2475 if (!(node = alloc_node( WS_XML_NODE_TYPE_COMMENT ))) return E_OUTOFMEMORY;
2476 comment = (WS_XML_COMMENT_NODE *)node;
2477 if (!(comment->value.bytes = heap_alloc( len )))
2479 heap_free( node );
2480 return E_OUTOFMEMORY;
2482 memcpy( comment->value.bytes, start, len );
2483 comment->value.length = len;
2485 read_insert_node( reader, parent, node );
2486 reader->state = READER_STATE_COMMENT;
2487 return S_OK;
2490 static HRESULT read_comment_bin( struct reader *reader )
2492 struct node *node, *parent;
2493 WS_XML_COMMENT_NODE *comment;
2494 unsigned char type;
2495 ULONG len;
2496 HRESULT hr;
2498 if ((hr = read_byte( reader, &type )) != S_OK) return hr;
2499 if (type != RECORD_COMMENT) return WS_E_INVALID_FORMAT;
2500 if ((hr = read_int31( reader, &len )) != S_OK) return hr;
2502 if (!(parent = find_parent( reader ))) return WS_E_INVALID_FORMAT;
2504 if (!(node = alloc_node( WS_XML_NODE_TYPE_COMMENT ))) return E_OUTOFMEMORY;
2505 comment = (WS_XML_COMMENT_NODE *)node;
2506 if (!(comment->value.bytes = heap_alloc( len )))
2508 heap_free( node );
2509 return E_OUTOFMEMORY;
2511 if ((hr = read_bytes( reader, comment->value.bytes, len )) != S_OK)
2513 free_node( node );
2514 return E_OUTOFMEMORY;
2516 comment->value.length = len;
2518 read_insert_node( reader, parent, node );
2519 reader->state = READER_STATE_COMMENT;
2520 return S_OK;
2523 static HRESULT read_startcdata( struct reader *reader )
2525 struct node *node, *endnode, *parent;
2527 if (read_cmp( reader, "<![CDATA[", 9 )) return WS_E_INVALID_FORMAT;
2528 read_skip( reader, 9 );
2530 if (!(parent = find_parent( reader ))) return WS_E_INVALID_FORMAT;
2532 if (!(node = alloc_node( WS_XML_NODE_TYPE_CDATA ))) return E_OUTOFMEMORY;
2533 if (!(endnode = alloc_node( WS_XML_NODE_TYPE_END_CDATA )))
2535 heap_free( node );
2536 return E_OUTOFMEMORY;
2538 list_add_tail( &node->children, &endnode->entry );
2539 endnode->parent = node;
2541 read_insert_node( reader, parent, node );
2542 reader->state = READER_STATE_STARTCDATA;
2543 return S_OK;
2546 static HRESULT read_cdata( struct reader *reader )
2548 unsigned int len = 0, ch, skip;
2549 const unsigned char *start;
2550 struct node *node;
2551 WS_XML_TEXT_NODE *text;
2552 WS_XML_UTF8_TEXT *utf8;
2554 start = read_current_ptr( reader );
2555 for (;;)
2557 if (!read_cmp( reader, "]]>", 3 )) break;
2558 if (!(ch = read_utf8_char( reader, &skip ))) return WS_E_INVALID_FORMAT;
2559 read_skip( reader, skip );
2560 len += skip;
2563 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return E_OUTOFMEMORY;
2564 text = (WS_XML_TEXT_NODE *)node;
2565 if (!(utf8 = alloc_utf8_text( start, len )))
2567 heap_free( node );
2568 return E_OUTOFMEMORY;
2570 text->text = &utf8->text;
2572 read_insert_node( reader, reader->current, node );
2573 reader->state = READER_STATE_CDATA;
2574 return S_OK;
2577 static HRESULT read_endcdata( struct reader *reader )
2579 struct node *parent;
2581 if (read_cmp( reader, "]]>", 3 )) return WS_E_INVALID_FORMAT;
2582 read_skip( reader, 3 );
2584 if (node_type( reader->current ) == WS_XML_NODE_TYPE_TEXT) parent = reader->current->parent;
2585 else parent = reader->current;
2587 reader->current = LIST_ENTRY( list_tail( &parent->children ), struct node, entry );
2588 reader->last = reader->current;
2589 reader->state = READER_STATE_ENDCDATA;
2590 return S_OK;
2593 static HRESULT read_node_text( struct reader *reader )
2595 HRESULT hr;
2597 for (;;)
2599 if (read_end_of_data( reader ))
2601 reader->current = LIST_ENTRY( list_tail( &reader->root->children ), struct node, entry );
2602 reader->last = reader->current;
2603 reader->state = READER_STATE_EOF;
2604 return S_OK;
2606 if (reader->state == READER_STATE_STARTCDATA) return read_cdata( reader );
2607 else if (reader->state == READER_STATE_CDATA) return read_endcdata( reader );
2608 else if (!read_cmp( reader, "<?", 2 ))
2610 hr = read_xmldecl( reader );
2611 if (FAILED( hr )) return hr;
2613 else if (!read_cmp( reader, "</", 2 )) return read_endelement_text( reader );
2614 else if (!read_cmp( reader, "<![CDATA[", 9 )) return read_startcdata( reader );
2615 else if (!read_cmp( reader, "<!--", 4 )) return read_comment_text( reader );
2616 else if (!read_cmp( reader, "<", 1 )) return read_element_text( reader );
2617 else if (!read_cmp( reader, "/>", 2 ) || !read_cmp( reader, ">", 1 )) return read_startelement_text( reader );
2618 else return read_text_text( reader );
2622 static HRESULT read_node_bin( struct reader *reader )
2624 unsigned char type;
2625 HRESULT hr;
2627 if (reader->current->flags & NODE_FLAG_TEXT_WITH_IMPLICIT_END_ELEMENT)
2629 reader->current = LIST_ENTRY( list_tail( &reader->current->parent->children ), struct node, entry );
2630 reader->last = reader->current;
2631 reader->state = READER_STATE_ENDELEMENT;
2632 return S_OK;
2634 if (read_end_of_data( reader ))
2636 reader->current = LIST_ENTRY( list_tail( &reader->root->children ), struct node, entry );
2637 reader->last = reader->current;
2638 reader->state = READER_STATE_EOF;
2639 return S_OK;
2642 if ((hr = read_peek( reader, &type )) != S_OK) return hr;
2643 if (type == RECORD_ENDELEMENT)
2645 return read_endelement_bin( reader );
2647 else if (type == RECORD_COMMENT)
2649 return read_comment_bin( reader );
2651 else if (type >= RECORD_SHORT_ELEMENT && type <= RECORD_PREFIX_ELEMENT_Z)
2653 return read_element_bin( reader );
2655 else if (type >= RECORD_ZERO_TEXT && type <= RECORD_QNAME_DICTIONARY_TEXT_WITH_ENDELEMENT)
2657 return read_text_bin( reader );
2659 FIXME( "unhandled record type %02x\n", type );
2660 return WS_E_NOT_SUPPORTED;
2663 static HRESULT read_node( struct reader *reader )
2665 switch (reader->input_enc)
2667 case WS_XML_READER_ENCODING_TYPE_TEXT: return read_node_text( reader );
2668 case WS_XML_READER_ENCODING_TYPE_BINARY: return read_node_bin( reader );
2669 default:
2670 ERR( "unhandled encoding %u\n", reader->input_enc );
2671 return WS_E_NOT_SUPPORTED;
2675 HRESULT copy_node( WS_XML_READER *handle, struct node **node )
2677 struct reader *reader = (struct reader *)handle;
2678 const struct list *ptr;
2679 const struct node *start;
2680 HRESULT hr;
2682 EnterCriticalSection( &reader->cs );
2684 if (reader->magic != READER_MAGIC)
2686 LeaveCriticalSection( &reader->cs );
2687 return E_INVALIDARG;
2690 if (reader->current != reader->root) ptr = &reader->current->entry;
2691 else /* copy whole tree */
2693 if (!read_end_of_data( reader ))
2695 for (;;)
2697 if ((hr = read_node( reader )) != S_OK) goto done;
2698 if (node_type( reader->current ) == WS_XML_NODE_TYPE_EOF) break;
2701 ptr = list_head( &reader->root->children );
2704 start = LIST_ENTRY( ptr, struct node, entry );
2705 if (node_type( start ) == WS_XML_NODE_TYPE_EOF) hr = WS_E_INVALID_OPERATION;
2706 else hr = dup_tree( node, start );
2708 done:
2709 LeaveCriticalSection( &reader->cs );
2710 return hr;
2713 /**************************************************************************
2714 * WsReadEndElement [webservices.@]
2716 HRESULT WINAPI WsReadEndElement( WS_XML_READER *handle, WS_ERROR *error )
2718 struct reader *reader = (struct reader *)handle;
2719 HRESULT hr;
2721 TRACE( "%p %p\n", handle, error );
2722 if (error) FIXME( "ignoring error parameter\n" );
2724 if (!reader) return E_INVALIDARG;
2726 EnterCriticalSection( &reader->cs );
2728 if (reader->magic != READER_MAGIC)
2730 LeaveCriticalSection( &reader->cs );
2731 return E_INVALIDARG;
2734 hr = read_endelement( reader );
2736 LeaveCriticalSection( &reader->cs );
2737 return hr;
2740 /**************************************************************************
2741 * WsReadNode [webservices.@]
2743 HRESULT WINAPI WsReadNode( WS_XML_READER *handle, WS_ERROR *error )
2745 struct reader *reader = (struct reader *)handle;
2746 HRESULT hr;
2748 TRACE( "%p %p\n", handle, error );
2749 if (error) FIXME( "ignoring error parameter\n" );
2751 if (!reader) return E_INVALIDARG;
2753 EnterCriticalSection( &reader->cs );
2755 if (reader->magic != READER_MAGIC)
2757 LeaveCriticalSection( &reader->cs );
2758 return E_INVALIDARG;
2761 hr = read_node( reader );
2763 LeaveCriticalSection( &reader->cs );
2764 return hr;
2767 static HRESULT skip_node( struct reader *reader )
2769 const struct node *parent;
2770 HRESULT hr;
2772 if (node_type( reader->current ) == WS_XML_NODE_TYPE_EOF) return WS_E_INVALID_OPERATION;
2773 if (node_type( reader->current ) == WS_XML_NODE_TYPE_ELEMENT) parent = reader->current;
2774 else parent = NULL;
2776 for (;;)
2778 if ((hr = read_node( reader ) != S_OK) || !parent) break;
2779 if (node_type( reader->current ) != WS_XML_NODE_TYPE_END_ELEMENT) continue;
2780 if (reader->current->parent == parent) return read_node( reader );
2783 return hr;
2786 /**************************************************************************
2787 * WsSkipNode [webservices.@]
2789 HRESULT WINAPI WsSkipNode( WS_XML_READER *handle, WS_ERROR *error )
2791 struct reader *reader = (struct reader *)handle;
2792 HRESULT hr;
2794 TRACE( "%p %p\n", handle, error );
2795 if (error) FIXME( "ignoring error parameter\n" );
2797 if (!reader) return E_INVALIDARG;
2799 EnterCriticalSection( &reader->cs );
2801 if (reader->magic != READER_MAGIC)
2803 LeaveCriticalSection( &reader->cs );
2804 return E_INVALIDARG;
2807 hr = skip_node( reader );
2809 LeaveCriticalSection( &reader->cs );
2810 return hr;
2813 /**************************************************************************
2814 * WsReadStartElement [webservices.@]
2816 HRESULT WINAPI WsReadStartElement( WS_XML_READER *handle, WS_ERROR *error )
2818 struct reader *reader = (struct reader *)handle;
2819 HRESULT hr;
2821 TRACE( "%p %p\n", handle, error );
2822 if (error) FIXME( "ignoring error parameter\n" );
2824 if (!reader) return E_INVALIDARG;
2826 EnterCriticalSection( &reader->cs );
2828 if (reader->magic != READER_MAGIC)
2830 LeaveCriticalSection( &reader->cs );
2831 return E_INVALIDARG;
2834 hr = read_startelement( reader );
2836 LeaveCriticalSection( &reader->cs );
2837 return hr;
2840 /**************************************************************************
2841 * WsReadToStartElement [webservices.@]
2843 HRESULT WINAPI WsReadToStartElement( WS_XML_READER *handle, const WS_XML_STRING *localname,
2844 const WS_XML_STRING *ns, BOOL *found, WS_ERROR *error )
2846 struct reader *reader = (struct reader *)handle;
2847 HRESULT hr;
2849 TRACE( "%p %s %s %p %p\n", handle, debugstr_xmlstr(localname), debugstr_xmlstr(ns), found, error );
2850 if (error) FIXME( "ignoring error parameter\n" );
2852 if (!reader) return E_INVALIDARG;
2853 if (localname || ns) FIXME( "name and/or namespace not verified\n" );
2855 EnterCriticalSection( &reader->cs );
2857 if (reader->magic != READER_MAGIC)
2859 LeaveCriticalSection( &reader->cs );
2860 return E_INVALIDARG;
2863 hr = read_to_startelement( reader, found );
2865 LeaveCriticalSection( &reader->cs );
2866 return hr;
2869 BOOL move_to_root_element( struct node *root, struct node **current )
2871 struct list *ptr;
2872 struct node *node;
2874 if (!(ptr = list_head( &root->children ))) return FALSE;
2875 node = LIST_ENTRY( ptr, struct node, entry );
2876 if (node_type( node ) == WS_XML_NODE_TYPE_ELEMENT)
2878 *current = node;
2879 return TRUE;
2881 while ((ptr = list_next( &root->children, &node->entry )))
2883 struct node *next = LIST_ENTRY( ptr, struct node, entry );
2884 if (node_type( next ) == WS_XML_NODE_TYPE_ELEMENT)
2886 *current = next;
2887 return TRUE;
2889 node = next;
2891 return FALSE;
2894 BOOL move_to_next_element( struct node **current )
2896 struct list *ptr;
2897 struct node *node = *current, *parent = (*current)->parent;
2899 if (!parent) return FALSE;
2900 while ((ptr = list_next( &parent->children, &node->entry )))
2902 struct node *next = LIST_ENTRY( ptr, struct node, entry );
2903 if (node_type( next ) == WS_XML_NODE_TYPE_ELEMENT)
2905 *current = next;
2906 return TRUE;
2908 node = next;
2910 return FALSE;
2913 BOOL move_to_prev_element( struct node **current )
2915 struct list *ptr;
2916 struct node *node = *current, *parent = (*current)->parent;
2918 if (!parent) return FALSE;
2919 while ((ptr = list_prev( &parent->children, &node->entry )))
2921 struct node *prev = LIST_ENTRY( ptr, struct node, entry );
2922 if (node_type( prev ) == WS_XML_NODE_TYPE_ELEMENT)
2924 *current = prev;
2925 return TRUE;
2927 node = prev;
2929 return FALSE;
2932 BOOL move_to_child_element( struct node **current )
2934 struct list *ptr;
2935 struct node *child, *node = *current;
2937 if (!(ptr = list_head( &node->children ))) return FALSE;
2938 child = LIST_ENTRY( ptr, struct node, entry );
2939 if (node_type( child ) == WS_XML_NODE_TYPE_ELEMENT)
2941 *current = child;
2942 return TRUE;
2944 while ((ptr = list_next( &node->children, &child->entry )))
2946 struct node *next = LIST_ENTRY( ptr, struct node, entry );
2947 if (node_type( next ) == WS_XML_NODE_TYPE_ELEMENT)
2949 *current = next;
2950 return TRUE;
2952 child = next;
2954 return FALSE;
2957 BOOL move_to_end_element( struct node **current )
2959 struct list *ptr;
2960 struct node *node = *current;
2962 if (node_type( node ) != WS_XML_NODE_TYPE_ELEMENT) return FALSE;
2964 if ((ptr = list_tail( &node->children )))
2966 struct node *tail = LIST_ENTRY( ptr, struct node, entry );
2967 if (node_type( tail ) == WS_XML_NODE_TYPE_END_ELEMENT)
2969 *current = tail;
2970 return TRUE;
2973 return FALSE;
2976 BOOL move_to_parent_element( struct node **current )
2978 struct node *parent = (*current)->parent;
2980 if (parent && (node_type( parent ) == WS_XML_NODE_TYPE_ELEMENT ||
2981 node_type( parent ) == WS_XML_NODE_TYPE_BOF))
2983 *current = parent;
2984 return TRUE;
2986 return FALSE;
2989 BOOL move_to_first_node( struct node **current )
2991 struct list *ptr;
2992 struct node *node = *current;
2994 if ((ptr = list_head( &node->parent->children )))
2996 *current = LIST_ENTRY( ptr, struct node, entry );
2997 return TRUE;
2999 return FALSE;
3002 BOOL move_to_next_node( struct node **current )
3004 struct list *ptr;
3005 struct node *node = *current;
3007 if ((ptr = list_next( &node->parent->children, &node->entry )))
3009 *current = LIST_ENTRY( ptr, struct node, entry );
3010 return TRUE;
3012 return FALSE;
3015 BOOL move_to_prev_node( struct node **current )
3017 struct list *ptr;
3018 struct node *node = *current;
3020 if ((ptr = list_prev( &node->parent->children, &node->entry )))
3022 *current = LIST_ENTRY( ptr, struct node, entry );
3023 return TRUE;
3025 return FALSE;
3028 BOOL move_to_bof( struct node *root, struct node **current )
3030 *current = root;
3031 return TRUE;
3034 BOOL move_to_eof( struct node *root, struct node **current )
3036 struct list *ptr;
3037 if ((ptr = list_tail( &root->children )))
3039 *current = LIST_ENTRY( ptr, struct node, entry );
3040 return TRUE;
3042 return FALSE;
3045 BOOL move_to_child_node( struct node **current )
3047 struct list *ptr;
3048 struct node *node = *current;
3050 if ((ptr = list_head( &node->children )))
3052 *current = LIST_ENTRY( ptr, struct node, entry );
3053 return TRUE;
3055 return FALSE;
3058 BOOL move_to_parent_node( struct node **current )
3060 struct node *parent = (*current)->parent;
3061 if (!parent) return FALSE;
3062 *current = parent;
3063 return TRUE;
3066 static HRESULT read_move_to( struct reader *reader, WS_MOVE_TO move, BOOL *found )
3068 BOOL success = FALSE;
3069 HRESULT hr = S_OK;
3071 if (!read_end_of_data( reader ))
3073 struct node *saved_current = reader->current;
3074 while (reader->state != READER_STATE_EOF && (hr = read_node( reader )) == S_OK) { /* nothing */ };
3075 if (hr != S_OK) return hr;
3076 reader->current = saved_current;
3078 switch (move)
3080 case WS_MOVE_TO_ROOT_ELEMENT:
3081 success = move_to_root_element( reader->root, &reader->current );
3082 break;
3084 case WS_MOVE_TO_NEXT_ELEMENT:
3085 success = move_to_next_element( &reader->current );
3086 break;
3088 case WS_MOVE_TO_PREVIOUS_ELEMENT:
3089 success = move_to_prev_element( &reader->current );
3090 break;
3092 case WS_MOVE_TO_CHILD_ELEMENT:
3093 success = move_to_child_element( &reader->current );
3094 break;
3096 case WS_MOVE_TO_END_ELEMENT:
3097 success = move_to_end_element( &reader->current );
3098 break;
3100 case WS_MOVE_TO_PARENT_ELEMENT:
3101 success = move_to_parent_element( &reader->current );
3102 break;
3104 case WS_MOVE_TO_FIRST_NODE:
3105 success = move_to_first_node( &reader->current );
3106 break;
3108 case WS_MOVE_TO_NEXT_NODE:
3109 success = move_to_next_node( &reader->current );
3110 break;
3112 case WS_MOVE_TO_PREVIOUS_NODE:
3113 success = move_to_prev_node( &reader->current );
3114 break;
3116 case WS_MOVE_TO_CHILD_NODE:
3117 success = move_to_child_node( &reader->current );
3118 break;
3120 case WS_MOVE_TO_BOF:
3121 success = move_to_bof( reader->root, &reader->current );
3122 break;
3124 case WS_MOVE_TO_EOF:
3125 success = move_to_eof( reader->root, &reader->current );
3126 break;
3128 default:
3129 FIXME( "unhandled move %u\n", move );
3130 return E_NOTIMPL;
3133 if (found)
3135 *found = success;
3136 return S_OK;
3138 return success ? S_OK : WS_E_INVALID_FORMAT;
3141 /**************************************************************************
3142 * WsMoveReader [webservices.@]
3144 HRESULT WINAPI WsMoveReader( WS_XML_READER *handle, WS_MOVE_TO move, BOOL *found, WS_ERROR *error )
3146 struct reader *reader = (struct reader *)handle;
3147 HRESULT hr;
3149 TRACE( "%p %u %p %p\n", handle, move, found, error );
3150 if (error) FIXME( "ignoring error parameter\n" );
3152 if (!reader) return E_INVALIDARG;
3154 EnterCriticalSection( &reader->cs );
3156 if (reader->magic != READER_MAGIC)
3158 LeaveCriticalSection( &reader->cs );
3159 return E_INVALIDARG;
3162 if (!reader->input_type)
3164 LeaveCriticalSection( &reader->cs );
3165 return WS_E_INVALID_OPERATION;
3168 hr = read_move_to( reader, move, found );
3170 LeaveCriticalSection( &reader->cs );
3171 return hr;
3174 /**************************************************************************
3175 * WsReadStartAttribute [webservices.@]
3177 HRESULT WINAPI WsReadStartAttribute( WS_XML_READER *handle, ULONG index, WS_ERROR *error )
3179 struct reader *reader = (struct reader *)handle;
3180 const WS_XML_ELEMENT_NODE *elem;
3182 TRACE( "%p %u %p\n", handle, index, error );
3183 if (error) FIXME( "ignoring error parameter\n" );
3185 if (!reader) return E_INVALIDARG;
3187 EnterCriticalSection( &reader->cs );
3189 if (reader->magic != READER_MAGIC)
3191 LeaveCriticalSection( &reader->cs );
3192 return E_INVALIDARG;
3195 elem = &reader->current->hdr;
3196 if (reader->state != READER_STATE_STARTELEMENT || index >= elem->attributeCount)
3198 LeaveCriticalSection( &reader->cs );
3199 return WS_E_INVALID_FORMAT;
3202 reader->current_attr = index;
3203 reader->state = READER_STATE_STARTATTRIBUTE;
3205 LeaveCriticalSection( &reader->cs );
3206 return S_OK;
3209 /**************************************************************************
3210 * WsReadEndAttribute [webservices.@]
3212 HRESULT WINAPI WsReadEndAttribute( WS_XML_READER *handle, WS_ERROR *error )
3214 struct reader *reader = (struct reader *)handle;
3216 TRACE( "%p %p\n", handle, error );
3217 if (error) FIXME( "ignoring error parameter\n" );
3219 if (!reader) return E_INVALIDARG;
3221 EnterCriticalSection( &reader->cs );
3223 if (reader->magic != READER_MAGIC)
3225 LeaveCriticalSection( &reader->cs );
3226 return E_INVALIDARG;
3229 if (reader->state != READER_STATE_STARTATTRIBUTE)
3231 LeaveCriticalSection( &reader->cs );
3232 return WS_E_INVALID_FORMAT;
3235 reader->state = READER_STATE_STARTELEMENT;
3237 LeaveCriticalSection( &reader->cs );
3238 return S_OK;
3241 static WCHAR *xmltext_to_widechar( WS_HEAP *heap, const WS_XML_TEXT *text )
3243 WCHAR *ret;
3245 switch (text->textType)
3247 case WS_XML_TEXT_TYPE_UTF8:
3249 const WS_XML_UTF8_TEXT *utf8 = (const WS_XML_UTF8_TEXT *)text;
3250 int len = MultiByteToWideChar( CP_UTF8, 0, (char *)utf8->value.bytes, utf8->value.length, NULL, 0 );
3251 if (!(ret = ws_alloc( heap, (len + 1) * sizeof(WCHAR) ))) return NULL;
3252 MultiByteToWideChar( CP_UTF8, 0, (char *)utf8->value.bytes, utf8->value.length, ret, len );
3253 ret[len] = 0;
3254 break;
3256 default:
3257 FIXME( "unhandled type %u\n", text->textType );
3258 return NULL;
3261 return ret;
3264 #define MAX_INT8 0x7f
3265 #define MIN_INT8 (-MAX_INT8 - 1)
3266 #define MAX_INT16 0x7fff
3267 #define MIN_INT16 (-MAX_INT16 - 1)
3268 #define MAX_INT32 0x7fffffff
3269 #define MIN_INT32 (-MAX_INT32 - 1)
3270 #define MAX_INT64 (((INT64)0x7fffffff << 32) | 0xffffffff)
3271 #define MIN_INT64 (-MAX_INT64 - 1)
3272 #define MAX_UINT8 0xff
3273 #define MAX_UINT16 0xffff
3274 #define MAX_UINT32 0xffffffff
3275 #define MAX_UINT64 (((UINT64)0xffffffff << 32) | 0xffffffff)
3277 static HRESULT str_to_int64( const unsigned char *str, ULONG len, INT64 min, INT64 max, INT64 *ret )
3279 BOOL negative = FALSE;
3280 const unsigned char *ptr = str;
3282 *ret = 0;
3283 while (len && read_isspace( *ptr )) { ptr++; len--; }
3284 while (len && read_isspace( ptr[len - 1] )) { len--; }
3285 if (!len) return WS_E_INVALID_FORMAT;
3287 if (*ptr == '-')
3289 negative = TRUE;
3290 ptr++;
3291 len--;
3293 if (!len) return WS_E_INVALID_FORMAT;
3295 while (len--)
3297 int val;
3299 if (!isdigit( *ptr )) return WS_E_INVALID_FORMAT;
3300 val = *ptr - '0';
3301 if (negative) val = -val;
3303 if ((!negative && (*ret > max / 10 || *ret * 10 > max - val)) ||
3304 (negative && (*ret < min / 10 || *ret * 10 < min - val)))
3306 return WS_E_NUMERIC_OVERFLOW;
3308 *ret = *ret * 10 + val;
3309 ptr++;
3312 return S_OK;
3315 static HRESULT str_to_uint64( const unsigned char *str, ULONG len, UINT64 max, UINT64 *ret )
3317 const unsigned char *ptr = str;
3319 *ret = 0;
3320 while (len && read_isspace( *ptr )) { ptr++; len--; }
3321 while (len && read_isspace( ptr[len - 1] )) { len--; }
3322 if (!len) return WS_E_INVALID_FORMAT;
3324 while (len--)
3326 unsigned int val;
3328 if (!isdigit( *ptr )) return WS_E_INVALID_FORMAT;
3329 val = *ptr - '0';
3331 if ((*ret > max / 10 || *ret * 10 > max - val)) return WS_E_NUMERIC_OVERFLOW;
3332 *ret = *ret * 10 + val;
3333 ptr++;
3336 return S_OK;
3339 BOOL set_fpword( unsigned short new, unsigned short *old )
3341 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
3342 unsigned short fpword;
3344 __asm__ __volatile__( "fstcw %0" : "=m" (fpword) );
3345 *old = fpword;
3346 fpword = new;
3347 __asm__ __volatile__( "fldcw %0" : : "m" (fpword) );
3348 return TRUE;
3349 #else
3350 FIXME( "not implemented\n" );
3351 return FALSE;
3352 #endif
3355 void restore_fpword( unsigned short fpword )
3357 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
3358 __asm__ __volatile__( "fldcw %0" : : "m" (fpword) );
3359 #else
3360 FIXME( "not implemented\n" );
3361 #endif
3364 static HRESULT str_to_double( const unsigned char *str, ULONG len, double *ret )
3366 static const unsigned __int64 nan = 0xfff8000000000000;
3367 static const unsigned __int64 inf = 0x7ff0000000000000;
3368 static const unsigned __int64 inf_min = 0xfff0000000000000;
3369 HRESULT hr = WS_E_INVALID_FORMAT;
3370 const unsigned char *p = str, *q;
3371 int sign = 1, exp_sign = 1, exp = 0, exp_tmp = 0, neg_exp, i, nb_digits, have_digits;
3372 unsigned __int64 val = 0, tmp;
3373 long double exp_val = 1.0, exp_mul = 10.0;
3374 unsigned short fpword;
3376 while (len && read_isspace( *p )) { p++; len--; }
3377 while (len && read_isspace( p[len - 1] )) { len--; }
3378 if (!len) return WS_E_INVALID_FORMAT;
3380 if (len == 3 && !memcmp( p, "NaN", 3 ))
3382 *(unsigned __int64 *)ret = nan;
3383 return S_OK;
3385 else if (len == 3 && !memcmp( p, "INF", 3 ))
3387 *(unsigned __int64 *)ret = inf;
3388 return S_OK;
3390 else if (len == 4 && !memcmp( p, "-INF", 4 ))
3392 *(unsigned __int64 *)ret = inf_min;
3393 return S_OK;
3396 *ret = 0.0;
3397 if (*p == '-')
3399 sign = -1;
3400 p++; len--;
3402 else if (*p == '+') { p++; len--; };
3403 if (!len) return S_OK;
3405 if (!set_fpword( 0x37f, &fpword )) return E_NOTIMPL;
3407 q = p;
3408 while (len && isdigit( *q )) { q++; len--; }
3409 have_digits = nb_digits = q - p;
3410 for (i = 0; i < nb_digits; i++)
3412 tmp = val * 10 + p[i] - '0';
3413 if (val > MAX_UINT64 / 10 || tmp < val)
3415 for (; i < nb_digits; i++) exp++;
3416 break;
3418 val = tmp;
3421 if (len)
3423 if (*q == '.')
3425 p = ++q; len--;
3426 while (len && isdigit( *q )) { q++; len--; };
3427 have_digits |= nb_digits = q - p;
3428 for (i = 0; i < nb_digits; i++)
3430 tmp = val * 10 + p[i] - '0';
3431 if (val > MAX_UINT64 / 10 || tmp < val) break;
3432 val = tmp;
3433 exp--;
3436 if (len > 1 && tolower(*q) == 'e')
3438 if (!have_digits) goto done;
3439 p = ++q; len--;
3440 if (*p == '-')
3442 exp_sign = -1;
3443 p++; len--;
3445 else if (*p == '+') { p++; len--; };
3447 q = p;
3448 while (len && isdigit( *q )) { q++; len--; };
3449 nb_digits = q - p;
3450 if (!nb_digits || len) goto done;
3451 for (i = 0; i < nb_digits; i++)
3453 if (exp_tmp > MAX_INT32 / 10 || (exp_tmp = exp_tmp * 10 + p[i] - '0') < 0)
3454 exp_tmp = MAX_INT32;
3456 exp_tmp *= exp_sign;
3458 if (exp < 0 && exp_tmp < 0 && exp + exp_tmp >= 0) exp = MIN_INT32;
3459 else if (exp > 0 && exp_tmp > 0 && exp + exp_tmp < 0) exp = MAX_INT32;
3460 else exp += exp_tmp;
3463 if (!have_digits || len) goto done;
3465 if ((neg_exp = exp < 0)) exp = -exp;
3466 for (; exp; exp >>= 1)
3468 if (exp & 1) exp_val *= exp_mul;
3469 exp_mul *= exp_mul;
3472 *ret = sign * (neg_exp ? val / exp_val : val * exp_val);
3473 hr = S_OK;
3475 done:
3476 restore_fpword( fpword );
3477 return hr;
3480 static HRESULT str_to_guid( const unsigned char *str, ULONG len, GUID *ret )
3482 static const unsigned char hex[] =
3484 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x00 */
3485 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x10 */
3486 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x20 */
3487 0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0, /* 0x30 */
3488 0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0, /* 0x40 */
3489 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x50 */
3490 0,10,11,12,13,14,15 /* 0x60 */
3492 const unsigned char *p = str;
3493 ULONG i;
3495 while (len && read_isspace( *p )) { p++; len--; }
3496 while (len && read_isspace( p[len - 1] )) { len--; }
3497 if (len != 36) return WS_E_INVALID_FORMAT;
3499 if (p[8] != '-' || p[13] != '-' || p[18] != '-' || p[23] != '-')
3500 return WS_E_INVALID_FORMAT;
3502 for (i = 0; i < 36; i++)
3504 if (i == 8 || i == 13 || i == 18 || i == 23) continue;
3505 if (p[i] > 'f' || (!hex[p[i]] && p[i] != '0')) return WS_E_INVALID_FORMAT;
3508 ret->Data1 = hex[p[0]] << 28 | hex[p[1]] << 24 | hex[p[2]] << 20 | hex[p[3]] << 16 |
3509 hex[p[4]] << 12 | hex[p[5]] << 8 | hex[p[6]] << 4 | hex[p[7]];
3511 ret->Data2 = hex[p[9]] << 12 | hex[p[10]] << 8 | hex[p[11]] << 4 | hex[p[12]];
3512 ret->Data3 = hex[p[14]] << 12 | hex[p[15]] << 8 | hex[p[16]] << 4 | hex[p[17]];
3514 ret->Data4[0] = hex[p[19]] << 4 | hex[p[20]];
3515 ret->Data4[1] = hex[p[21]] << 4 | hex[p[22]];
3516 ret->Data4[2] = hex[p[24]] << 4 | hex[p[25]];
3517 ret->Data4[3] = hex[p[26]] << 4 | hex[p[27]];
3518 ret->Data4[4] = hex[p[28]] << 4 | hex[p[29]];
3519 ret->Data4[5] = hex[p[30]] << 4 | hex[p[31]];
3520 ret->Data4[6] = hex[p[32]] << 4 | hex[p[33]];
3521 ret->Data4[7] = hex[p[34]] << 4 | hex[p[35]];
3523 return S_OK;
3526 static HRESULT str_to_string( const unsigned char *str, ULONG len, WS_HEAP *heap, WS_STRING *ret )
3528 int len_utf16 = MultiByteToWideChar( CP_UTF8, 0, (const char *)str, len, NULL, 0 );
3529 if (!(ret->chars = ws_alloc( heap, len_utf16 * sizeof(WCHAR) ))) return WS_E_QUOTA_EXCEEDED;
3530 MultiByteToWideChar( CP_UTF8, 0, (const char *)str, len, ret->chars, len_utf16 );
3531 ret->length = len_utf16;
3532 return S_OK;
3535 static HRESULT str_to_unique_id( const unsigned char *str, ULONG len, WS_HEAP *heap, WS_UNIQUE_ID *ret )
3537 if (len == 45 && !memcmp( str, "urn:uuid:", 9 ))
3539 ret->uri.length = 0;
3540 ret->uri.chars = NULL;
3541 return str_to_guid( str + 9, len - 9, &ret->guid );
3544 memset( &ret->guid, 0, sizeof(ret->guid) );
3545 return str_to_string( str, len, heap, &ret->uri );
3548 static inline unsigned char decode_char( unsigned char c )
3550 if (c >= 'A' && c <= 'Z') return c - 'A';
3551 if (c >= 'a' && c <= 'z') return c - 'a' + 26;
3552 if (c >= '0' && c <= '9') return c - '0' + 52;
3553 if (c == '+') return 62;
3554 if (c == '/') return 63;
3555 return 64;
3558 static ULONG decode_base64( const unsigned char *base64, ULONG len, unsigned char *buf )
3560 ULONG i = 0;
3561 unsigned char c0, c1, c2, c3;
3562 const unsigned char *p = base64;
3564 while (len > 4)
3566 if ((c0 = decode_char( p[0] )) > 63) return 0;
3567 if ((c1 = decode_char( p[1] )) > 63) return 0;
3568 if ((c2 = decode_char( p[2] )) > 63) return 0;
3569 if ((c3 = decode_char( p[3] )) > 63) return 0;
3570 buf[i + 0] = (c0 << 2) | (c1 >> 4);
3571 buf[i + 1] = (c1 << 4) | (c2 >> 2);
3572 buf[i + 2] = (c2 << 6) | c3;
3573 len -= 4;
3574 i += 3;
3575 p += 4;
3577 if (p[2] == '=')
3579 if ((c0 = decode_char( p[0] )) > 63) return 0;
3580 if ((c1 = decode_char( p[1] )) > 63) return 0;
3581 buf[i] = (c0 << 2) | (c1 >> 4);
3582 i++;
3584 else if (p[3] == '=')
3586 if ((c0 = decode_char( p[0] )) > 63) return 0;
3587 if ((c1 = decode_char( p[1] )) > 63) return 0;
3588 if ((c2 = decode_char( p[2] )) > 63) return 0;
3589 buf[i + 0] = (c0 << 2) | (c1 >> 4);
3590 buf[i + 1] = (c1 << 4) | (c2 >> 2);
3591 i += 2;
3593 else
3595 if ((c0 = decode_char( p[0] )) > 63) return 0;
3596 if ((c1 = decode_char( p[1] )) > 63) return 0;
3597 if ((c2 = decode_char( p[2] )) > 63) return 0;
3598 if ((c3 = decode_char( p[3] )) > 63) return 0;
3599 buf[i + 0] = (c0 << 2) | (c1 >> 4);
3600 buf[i + 1] = (c1 << 4) | (c2 >> 2);
3601 buf[i + 2] = (c2 << 6) | c3;
3602 i += 3;
3604 return i;
3607 static HRESULT str_to_bytes( const unsigned char *str, ULONG len, WS_HEAP *heap, WS_BYTES *ret )
3609 const unsigned char *p = str;
3611 while (len && read_isspace( *p )) { p++; len--; }
3612 while (len && read_isspace( p[len - 1] )) { len--; }
3614 if (len % 4) return WS_E_INVALID_FORMAT;
3615 if (!(ret->bytes = ws_alloc( heap, len * 3 / 4 ))) return WS_E_QUOTA_EXCEEDED;
3616 ret->length = decode_base64( p, len, ret->bytes );
3617 return S_OK;
3620 static HRESULT str_to_xml_string( const unsigned char *str, ULONG len, WS_HEAP *heap, WS_XML_STRING *ret )
3622 if (!(ret->bytes = ws_alloc( heap, len ))) return WS_E_QUOTA_EXCEEDED;
3623 memcpy( ret->bytes, str, len );
3624 ret->length = len;
3625 ret->dictionary = NULL;
3626 ret->id = 0;
3627 return S_OK;
3630 static HRESULT copy_xml_string( WS_HEAP *heap, const WS_XML_STRING *src, WS_XML_STRING *dst )
3632 if (!(dst->bytes = ws_alloc( heap, src->length ))) return WS_E_QUOTA_EXCEEDED;
3633 memcpy( dst->bytes, src->bytes, src->length );
3634 dst->length = src->length;
3635 return S_OK;
3638 static HRESULT str_to_qname( struct reader *reader, const unsigned char *str, ULONG len, WS_HEAP *heap,
3639 WS_XML_STRING *prefix_ret, WS_XML_STRING *localname_ret, WS_XML_STRING *ns_ret )
3641 const unsigned char *p = str;
3642 WS_XML_STRING prefix, localname;
3643 const WS_XML_STRING *ns;
3644 HRESULT hr;
3646 while (len && read_isspace( *p )) { p++; len--; }
3647 while (len && read_isspace( p[len - 1] )) { len--; }
3649 if ((hr = split_qname( p, len, &prefix, &localname )) != S_OK) return hr;
3650 if (!(ns = get_namespace( reader, &prefix ))) return WS_E_INVALID_FORMAT;
3652 if (prefix_ret && (hr = copy_xml_string( heap, &prefix, prefix_ret )) != S_OK) return hr;
3653 if ((hr = copy_xml_string( heap, &localname, localname_ret )) != S_OK)
3655 ws_free( heap, prefix_ret->bytes, prefix_ret->length );
3656 return hr;
3658 if ((hr = copy_xml_string( heap, ns, ns_ret )) != S_OK)
3660 ws_free( heap, prefix_ret->bytes, prefix_ret->length );
3661 ws_free( heap, localname_ret->bytes, localname_ret->length );
3662 return hr;
3664 return S_OK;
3667 static HRESULT read_qualified_name( struct reader *reader, WS_HEAP *heap, WS_XML_STRING *prefix,
3668 WS_XML_STRING *localname, WS_XML_STRING *ns )
3670 const WS_XML_TEXT_NODE *node = (const WS_XML_TEXT_NODE *)reader->current;
3671 const WS_XML_UTF8_TEXT *utf8 = (const WS_XML_UTF8_TEXT *)node->text;
3672 return str_to_qname( reader, utf8->value.bytes, utf8->value.length, heap, prefix, localname, ns );
3675 /**************************************************************************
3676 * WsReadQualifiedName [webservices.@]
3678 HRESULT WINAPI WsReadQualifiedName( WS_XML_READER *handle, WS_HEAP *heap, WS_XML_STRING *prefix,
3679 WS_XML_STRING *localname, WS_XML_STRING *ns,
3680 WS_ERROR *error )
3682 struct reader *reader = (struct reader *)handle;
3683 HRESULT hr;
3685 TRACE( "%p %p %p %p %p %p\n", handle, heap, prefix, localname, ns, error );
3686 if (error) FIXME( "ignoring error parameter\n" );
3688 if (!reader || !heap) return E_INVALIDARG;
3690 EnterCriticalSection( &reader->cs );
3692 if (reader->magic != READER_MAGIC)
3694 LeaveCriticalSection( &reader->cs );
3695 return E_INVALIDARG;
3698 if (!reader->input_type)
3700 LeaveCriticalSection( &reader->cs );
3701 return WS_E_INVALID_OPERATION;
3704 if (!localname)
3706 LeaveCriticalSection( &reader->cs );
3707 return E_INVALIDARG;
3710 if (reader->state != READER_STATE_TEXT)
3712 LeaveCriticalSection( &reader->cs );
3713 return WS_E_INVALID_FORMAT;
3716 hr = read_qualified_name( reader, heap, prefix, localname, ns );
3718 LeaveCriticalSection( &reader->cs );
3719 return hr;
3722 static const int month_offsets[2][12] =
3724 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},
3725 {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}
3728 static inline int valid_day( int year, int month, int day )
3730 return day > 0 && day <= month_days[leap_year( year )][month - 1];
3733 static inline int leap_days_before( int year )
3735 return (year - 1) / 4 - (year - 1) / 100 + (year - 1) / 400;
3738 static HRESULT str_to_datetime( const unsigned char *bytes, ULONG len, WS_DATETIME *ret )
3740 const unsigned char *p = bytes, *q;
3741 int year, month, day, hour, min, sec, sec_frac = 0, tz_hour, tz_min, tz_neg;
3743 while (len && read_isspace( *p )) { p++; len--; }
3744 while (len && read_isspace( p[len - 1] )) { len--; }
3746 q = p;
3747 while (len && isdigit( *q )) { q++; len--; };
3748 if (q - p != 4 || !len || *q != '-') return WS_E_INVALID_FORMAT;
3749 year = (p[0] - '0') * 1000 + (p[1] - '0') * 100 + (p[2] - '0') * 10 + p[3] - '0';
3750 if (year < 1) return WS_E_INVALID_FORMAT;
3752 p = ++q; len--;
3753 while (len && isdigit( *q )) { q++; len--; };
3754 if (q - p != 2 || !len || *q != '-') return WS_E_INVALID_FORMAT;
3755 month = (p[0] - '0') * 10 + p[1] - '0';
3756 if (month < 1 || month > 12) return WS_E_INVALID_FORMAT;
3758 p = ++q; len--;
3759 while (len && isdigit( *q )) { q++; len--; };
3760 if (q - p != 2 || !len || *q != 'T') return WS_E_INVALID_FORMAT;
3761 day = (p[0] - '0') * 10 + p[1] - '0';
3762 if (!valid_day( year, month, day )) return WS_E_INVALID_FORMAT;
3764 p = ++q; len--;
3765 while (len && isdigit( *q )) { q++; len--; };
3766 if (q - p != 2 || !len || *q != ':') return WS_E_INVALID_FORMAT;
3767 hour = (p[0] - '0') * 10 + p[1] - '0';
3768 if (hour > 24) return WS_E_INVALID_FORMAT;
3770 p = ++q; len--;
3771 while (len && isdigit( *q )) { q++; len--; };
3772 if (q - p != 2 || !len || *q != ':') return WS_E_INVALID_FORMAT;
3773 min = (p[0] - '0') * 10 + p[1] - '0';
3774 if (min > 59 || (min > 0 && hour == 24)) return WS_E_INVALID_FORMAT;
3776 p = ++q; len--;
3777 while (len && isdigit( *q )) { q++; len--; };
3778 if (q - p != 2 || !len) return WS_E_INVALID_FORMAT;
3779 sec = (p[0] - '0') * 10 + p[1] - '0';
3780 if (sec > 59 || (sec > 0 && hour == 24)) return WS_E_INVALID_FORMAT;
3782 if (*q == '.')
3784 unsigned int i, nb_digits, mul = TICKS_PER_SEC / 10;
3785 p = ++q; len--;
3786 while (len && isdigit( *q )) { q++; len--; };
3787 nb_digits = q - p;
3788 if (nb_digits < 1 || nb_digits > 7) return WS_E_INVALID_FORMAT;
3789 for (i = 0; i < nb_digits; i++)
3791 sec_frac += (p[i] - '0') * mul;
3792 mul /= 10;
3795 if (*q == 'Z')
3797 if (--len) return WS_E_INVALID_FORMAT;
3798 tz_hour = tz_min = tz_neg = 0;
3799 ret->format = WS_DATETIME_FORMAT_UTC;
3801 else if (*q == '+' || *q == '-')
3803 tz_neg = (*q == '-') ? 1 : 0;
3805 p = ++q; len--;
3806 while (len && isdigit( *q )) { q++; len--; };
3807 if (q - p != 2 || !len || *q != ':') return WS_E_INVALID_FORMAT;
3808 tz_hour = (p[0] - '0') * 10 + p[1] - '0';
3809 if (tz_hour > 14) return WS_E_INVALID_FORMAT;
3811 p = ++q; len--;
3812 while (len && isdigit( *q )) { q++; len--; };
3813 if (q - p != 2 || len) return WS_E_INVALID_FORMAT;
3814 tz_min = (p[0] - '0') * 10 + p[1] - '0';
3815 if (tz_min > 59 || (tz_min > 0 && tz_hour == 14)) return WS_E_INVALID_FORMAT;
3817 ret->format = WS_DATETIME_FORMAT_LOCAL;
3819 else return WS_E_INVALID_FORMAT;
3821 ret->ticks = ((year - 1) * 365 + leap_days_before( year )) * TICKS_PER_DAY;
3822 ret->ticks += month_offsets[leap_year( year )][month - 1] * TICKS_PER_DAY;
3823 ret->ticks += (day - 1) * TICKS_PER_DAY;
3824 ret->ticks += hour * TICKS_PER_HOUR;
3825 ret->ticks += min * TICKS_PER_MIN;
3826 ret->ticks += sec * TICKS_PER_SEC;
3827 ret->ticks += sec_frac;
3829 if (tz_neg)
3831 if (tz_hour * TICKS_PER_HOUR + tz_min * TICKS_PER_MIN + ret->ticks > TICKS_MAX)
3832 return WS_E_INVALID_FORMAT;
3833 ret->ticks += tz_hour * TICKS_PER_HOUR;
3834 ret->ticks += tz_min * TICKS_PER_MIN;
3836 else
3838 if (tz_hour * TICKS_PER_HOUR + tz_min * TICKS_PER_MIN > ret->ticks)
3839 return WS_E_INVALID_FORMAT;
3840 ret->ticks -= tz_hour * TICKS_PER_HOUR;
3841 ret->ticks -= tz_min * TICKS_PER_MIN;
3844 return S_OK;
3847 /**************************************************************************
3848 * WsDateTimeToFileTime [webservices.@]
3850 HRESULT WINAPI WsDateTimeToFileTime( const WS_DATETIME *dt, FILETIME *ft, WS_ERROR *error )
3852 unsigned __int64 ticks;
3854 TRACE( "%p %p %p\n", dt, ft, error );
3855 if (error) FIXME( "ignoring error parameter\n" );
3857 if (!dt || !ft) return E_INVALIDARG;
3859 if (dt->ticks < TICKS_1601_01_01) return WS_E_INVALID_FORMAT;
3860 ticks = dt->ticks - TICKS_1601_01_01;
3861 ft->dwHighDateTime = ticks >> 32;
3862 ft->dwLowDateTime = (DWORD)ticks;
3863 return S_OK;
3866 /**************************************************************************
3867 * WsFileTimeToDateTime [webservices.@]
3869 HRESULT WINAPI WsFileTimeToDateTime( const FILETIME *ft, WS_DATETIME *dt, WS_ERROR *error )
3871 unsigned __int64 ticks;
3873 TRACE( "%p %p %p\n", ft, dt, error );
3874 if (error) FIXME( "ignoring error parameter\n" );
3876 if (!dt || !ft) return E_INVALIDARG;
3878 ticks = ((unsigned __int64)ft->dwHighDateTime << 32) | ft->dwLowDateTime;
3879 if (ticks > MAX_UINT64 - TICKS_1601_01_01) return WS_E_NUMERIC_OVERFLOW;
3880 if (ticks + TICKS_1601_01_01 > TICKS_MAX) return WS_E_INVALID_FORMAT;
3881 dt->ticks = ticks + TICKS_1601_01_01;
3882 dt->format = WS_DATETIME_FORMAT_UTC;
3883 return S_OK;
3886 static BOOL find_attribute( struct reader *reader, const WS_XML_STRING *localname,
3887 const WS_XML_STRING *ns, ULONG *index )
3889 ULONG i;
3890 WS_XML_ELEMENT_NODE *elem = &reader->current->hdr;
3892 if (!localname)
3894 *index = reader->current_attr;
3895 return TRUE;
3897 for (i = 0; i < elem->attributeCount; i++)
3899 const WS_XML_STRING *localname2 = elem->attributes[i]->localName;
3900 const WS_XML_STRING *ns2 = elem->attributes[i]->ns;
3902 if (!cmp_name( localname->bytes, localname->length, localname2->bytes, localname2->length ) &&
3903 !cmp_name( ns->bytes, ns->length, ns2->bytes, ns2->length ))
3905 *index = i;
3906 return TRUE;
3909 return FALSE;
3912 /**************************************************************************
3913 * WsFindAttribute [webservices.@]
3915 HRESULT WINAPI WsFindAttribute( WS_XML_READER *handle, const WS_XML_STRING *localname,
3916 const WS_XML_STRING *ns, BOOL required, ULONG *index,
3917 WS_ERROR *error )
3919 struct reader *reader = (struct reader *)handle;
3920 HRESULT hr = S_OK;
3922 TRACE( "%p %s %s %d %p %p\n", handle, debugstr_xmlstr(localname), debugstr_xmlstr(ns),
3923 required, index, error );
3924 if (error) FIXME( "ignoring error parameter\n" );
3926 if (!reader || !localname || !ns || !index) return E_INVALIDARG;
3928 EnterCriticalSection( &reader->cs );
3930 if (reader->magic != READER_MAGIC)
3932 LeaveCriticalSection( &reader->cs );
3933 return E_INVALIDARG;
3936 if (node_type( reader->current ) != WS_XML_NODE_TYPE_ELEMENT)
3938 LeaveCriticalSection( &reader->cs );
3939 return WS_E_INVALID_OPERATION;
3942 if (!find_attribute( reader, localname, ns, index ))
3944 if (required) hr = WS_E_INVALID_FORMAT;
3945 else
3947 *index = ~0u;
3948 hr = S_FALSE;
3952 LeaveCriticalSection( &reader->cs );
3953 return hr;
3956 static HRESULT get_node_text( struct reader *reader, const WS_XML_TEXT **ret )
3958 WS_XML_TEXT_NODE *node = (WS_XML_TEXT_NODE *)&reader->current->hdr.node;
3959 *ret = node->text;
3960 return S_OK;
3963 static HRESULT get_attribute_text( struct reader *reader, ULONG index, const WS_XML_TEXT **ret )
3965 WS_XML_ELEMENT_NODE *elem = &reader->current->hdr;
3966 *ret = elem->attributes[index]->value;
3967 return S_OK;
3970 static BOOL match_element( const struct node *node, const WS_XML_STRING *localname, const WS_XML_STRING *ns )
3972 const WS_XML_ELEMENT_NODE *elem = (const WS_XML_ELEMENT_NODE *)node;
3973 if (node_type( node ) != WS_XML_NODE_TYPE_ELEMENT) return FALSE;
3974 return WsXmlStringEquals( localname, elem->localName, NULL ) == S_OK &&
3975 WsXmlStringEquals( ns, elem->ns, NULL ) == S_OK;
3978 static HRESULT read_next_node( struct reader *reader )
3980 if (reader->current == reader->last) return read_node( reader );
3981 if (move_to_child_node( &reader->current )) return S_OK;
3982 if (move_to_next_node( &reader->current )) return S_OK;
3983 if (!move_to_parent_node( &reader->current )) return WS_E_INVALID_FORMAT;
3984 if (move_to_next_node( &reader->current )) return S_OK;
3985 return WS_E_INVALID_FORMAT;
3988 static HRESULT get_text( struct reader *reader, WS_TYPE_MAPPING mapping, const WS_XML_STRING *localname,
3989 const WS_XML_STRING *ns, const WS_XML_TEXT **ret, BOOL *found )
3991 switch (mapping)
3993 case WS_ATTRIBUTE_TYPE_MAPPING:
3995 ULONG index;
3996 if (!(*found = find_attribute( reader, localname, ns, &index ))) return S_OK;
3997 return get_attribute_text( reader, index, ret );
3999 case WS_ELEMENT_TYPE_MAPPING:
4000 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
4001 case WS_ANY_ELEMENT_TYPE_MAPPING:
4003 *found = TRUE;
4004 if (localname)
4006 HRESULT hr;
4007 if (!match_element( reader->current, localname, ns ))
4009 *found = FALSE;
4010 return S_OK;
4012 if ((hr = read_next_node( reader )) != S_OK) return hr;
4013 if (node_type( reader->current ) != WS_XML_NODE_TYPE_TEXT)
4015 if (!move_to_parent_element( &reader->current )) return WS_E_INVALID_FORMAT;
4016 *found = FALSE;
4017 return S_OK;
4020 if (node_type( reader->current ) != WS_XML_NODE_TYPE_TEXT)
4022 *found = FALSE;
4023 return S_OK;
4025 return get_node_text( reader, ret );
4027 default:
4028 FIXME( "mapping %u not supported\n", mapping );
4029 return E_NOTIMPL;
4033 static const WS_XML_UTF8_TEXT *text_to_utf8( const WS_XML_TEXT *text )
4035 assert( text->textType == WS_XML_TEXT_TYPE_UTF8 );
4036 return (const WS_XML_UTF8_TEXT *)text;
4039 static const WS_XML_BASE64_TEXT *text_to_base64( const WS_XML_TEXT *text )
4041 assert( text->textType == WS_XML_TEXT_TYPE_BASE64 );
4042 return (const WS_XML_BASE64_TEXT *)text;
4045 static HRESULT read_type_bool( struct reader *reader, WS_TYPE_MAPPING mapping,
4046 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4047 const WS_BOOL_DESCRIPTION *desc, WS_READ_OPTION option,
4048 WS_HEAP *heap, void *ret, ULONG size )
4050 const WS_XML_TEXT *text;
4051 HRESULT hr;
4052 BOOL found, val = FALSE;
4054 if (desc)
4056 FIXME( "description not supported\n" );
4057 return E_NOTIMPL;
4059 if ((hr = get_text( reader, mapping, localname, ns, &text, &found )) != S_OK) return hr;
4060 if (found)
4062 const WS_XML_UTF8_TEXT *utf8 = text_to_utf8( text );
4063 ULONG len = utf8->value.length;
4064 if (len == 4 && !memcmp( utf8->value.bytes, "true", 4 )) val = TRUE;
4065 else if (len == 1 && !memcmp( utf8->value.bytes, "1", 1 )) val = TRUE;
4066 else if (len == 5 && !memcmp( utf8->value.bytes, "false", 5 )) val = FALSE;
4067 else if (len == 1 && !memcmp( utf8->value.bytes, "0", 1 )) val = FALSE;
4068 else return WS_E_INVALID_FORMAT;
4071 switch (option)
4073 case WS_READ_REQUIRED_VALUE:
4074 if (!found) return WS_E_INVALID_FORMAT;
4075 /* fall through */
4077 case WS_READ_NILLABLE_VALUE:
4078 if (size != sizeof(val)) return E_INVALIDARG;
4079 *(BOOL *)ret = val;
4080 break;
4082 case WS_READ_REQUIRED_POINTER:
4083 if (!found) return WS_E_INVALID_FORMAT;
4084 /* fall through */
4086 case WS_READ_OPTIONAL_POINTER:
4087 case WS_READ_NILLABLE_POINTER:
4089 BOOL *heap_val = NULL;
4090 if (size != sizeof(heap_val)) return E_INVALIDARG;
4091 if (found)
4093 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4094 *heap_val = val;
4096 *(BOOL **)ret = heap_val;
4097 break;
4099 default:
4100 FIXME( "read option %u not supported\n", option );
4101 return E_NOTIMPL;
4104 return S_OK;
4107 static HRESULT read_type_int8( struct reader *reader, WS_TYPE_MAPPING mapping,
4108 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4109 const WS_INT8_DESCRIPTION *desc, WS_READ_OPTION option,
4110 WS_HEAP *heap, void *ret, ULONG size )
4112 const WS_XML_TEXT *text;
4113 HRESULT hr;
4114 INT64 val = 0;
4115 BOOL found;
4117 if (desc)
4119 FIXME( "description not supported\n" );
4120 return E_NOTIMPL;
4122 if ((hr = get_text( reader, mapping, localname, ns, &text, &found )) != S_OK) return hr;
4123 if (found)
4125 const WS_XML_UTF8_TEXT *utf8 = text_to_utf8( text );
4126 if ((hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT8, MAX_INT8, &val )) != S_OK)
4127 return hr;
4130 switch (option)
4132 case WS_READ_REQUIRED_VALUE:
4133 if (!found) return WS_E_INVALID_FORMAT;
4134 /* fall through */
4136 case WS_READ_NILLABLE_VALUE:
4137 if (size != sizeof(INT8)) return E_INVALIDARG;
4138 *(INT8 *)ret = val;
4139 break;
4141 case WS_READ_REQUIRED_POINTER:
4142 if (!found) return WS_E_INVALID_FORMAT;
4143 /* fall through */
4145 case WS_READ_OPTIONAL_POINTER:
4146 case WS_READ_NILLABLE_POINTER:
4148 INT8 *heap_val = NULL;
4149 if (size != sizeof(heap_val)) return E_INVALIDARG;
4150 if (found)
4152 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4153 *heap_val = val;
4155 *(INT8 **)ret = heap_val;
4156 break;
4158 default:
4159 FIXME( "read option %u not supported\n", option );
4160 return E_NOTIMPL;
4163 return S_OK;
4166 static HRESULT read_type_int16( struct reader *reader, WS_TYPE_MAPPING mapping,
4167 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4168 const WS_INT16_DESCRIPTION *desc, WS_READ_OPTION option,
4169 WS_HEAP *heap, void *ret, ULONG size )
4171 const WS_XML_TEXT *text;
4172 HRESULT hr;
4173 INT64 val = 0;
4174 BOOL found;
4176 if (desc)
4178 FIXME( "description not supported\n" );
4179 return E_NOTIMPL;
4181 if ((hr = get_text( reader, mapping, localname, ns, &text, &found )) != S_OK) return hr;
4182 if (found)
4184 const WS_XML_UTF8_TEXT *utf8 = text_to_utf8( text );
4185 if ((hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT16, MAX_INT16, &val )) != S_OK)
4186 return hr;
4189 switch (option)
4191 case WS_READ_REQUIRED_VALUE:
4192 if (!found) return WS_E_INVALID_FORMAT;
4193 /* fall through */
4195 case WS_READ_NILLABLE_VALUE:
4196 if (size != sizeof(INT16)) return E_INVALIDARG;
4197 *(INT16 *)ret = val;
4198 break;
4200 case WS_READ_REQUIRED_POINTER:
4201 if (!found) return WS_E_INVALID_FORMAT;
4202 /* fall through */
4204 case WS_READ_OPTIONAL_POINTER:
4205 case WS_READ_NILLABLE_POINTER:
4207 INT16 *heap_val = NULL;
4208 if (size != sizeof(heap_val)) return E_INVALIDARG;
4209 if (found)
4211 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4212 *heap_val = val;
4214 *(INT16 **)ret = heap_val;
4215 break;
4217 default:
4218 FIXME( "read option %u not supported\n", option );
4219 return E_NOTIMPL;
4222 return S_OK;
4225 static HRESULT read_type_int32( struct reader *reader, WS_TYPE_MAPPING mapping,
4226 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4227 const WS_INT32_DESCRIPTION *desc, WS_READ_OPTION option,
4228 WS_HEAP *heap, void *ret, ULONG size )
4230 const WS_XML_TEXT *text;
4231 HRESULT hr;
4232 INT64 val = 0;
4233 BOOL found;
4235 if (desc)
4237 FIXME( "description not supported\n" );
4238 return E_NOTIMPL;
4240 if ((hr = get_text( reader, mapping, localname, ns, &text, &found )) != S_OK) return hr;
4241 if (found)
4243 const WS_XML_UTF8_TEXT *utf8 = text_to_utf8( text );
4244 if ((hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT32, MAX_INT32, &val )) != S_OK)
4245 return hr;
4248 switch (option)
4250 case WS_READ_REQUIRED_VALUE:
4251 if (!found) return WS_E_INVALID_FORMAT;
4252 /* fall through */
4254 case WS_READ_NILLABLE_VALUE:
4255 if (size != sizeof(INT32)) return E_INVALIDARG;
4256 *(INT32 *)ret = val;
4257 break;
4259 case WS_READ_REQUIRED_POINTER:
4260 if (!found) return WS_E_INVALID_FORMAT;
4261 /* fall through */
4263 case WS_READ_OPTIONAL_POINTER:
4264 case WS_READ_NILLABLE_POINTER:
4266 INT32 *heap_val = NULL;
4267 if (size != sizeof(heap_val)) return E_INVALIDARG;
4268 if (found)
4270 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4271 *heap_val = val;
4273 *(INT32 **)ret = heap_val;
4274 break;
4276 default:
4277 FIXME( "read option %u not supported\n", option );
4278 return E_NOTIMPL;
4281 return S_OK;
4284 static HRESULT read_type_int64( struct reader *reader, WS_TYPE_MAPPING mapping,
4285 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4286 const WS_INT64_DESCRIPTION *desc, WS_READ_OPTION option,
4287 WS_HEAP *heap, void *ret, ULONG size )
4289 const WS_XML_TEXT *text;
4290 HRESULT hr;
4291 INT64 val = 0;
4292 BOOL found;
4294 if (desc)
4296 FIXME( "description not supported\n" );
4297 return E_NOTIMPL;
4299 if ((hr = get_text( reader, mapping, localname, ns, &text, &found )) != S_OK) return hr;
4300 if (found)
4302 const WS_XML_UTF8_TEXT *utf8 = text_to_utf8( text );
4303 if ((hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT64, MAX_INT64, &val )) != S_OK)
4304 return hr;
4307 switch (option)
4309 case WS_READ_REQUIRED_VALUE:
4310 if (!found) return WS_E_INVALID_FORMAT;
4311 /* fall through */
4313 case WS_READ_NILLABLE_VALUE:
4314 if (size != sizeof(val)) return E_INVALIDARG;
4315 *(INT64 *)ret = val;
4316 break;
4318 case WS_READ_REQUIRED_POINTER:
4319 if (!found) return WS_E_INVALID_FORMAT;
4320 /* fall through */
4322 case WS_READ_OPTIONAL_POINTER:
4323 case WS_READ_NILLABLE_POINTER:
4325 INT64 *heap_val = NULL;
4326 if (size != sizeof(heap_val)) return E_INVALIDARG;
4327 if (found)
4329 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4330 *heap_val = val;
4332 *(INT64 **)ret = heap_val;
4333 break;
4335 default:
4336 FIXME( "read option %u not supported\n", option );
4337 return E_NOTIMPL;
4340 return S_OK;
4343 static HRESULT read_type_uint8( struct reader *reader, WS_TYPE_MAPPING mapping,
4344 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4345 const WS_UINT8_DESCRIPTION *desc, WS_READ_OPTION option,
4346 WS_HEAP *heap, void *ret, ULONG size )
4348 const WS_XML_TEXT *text;
4349 HRESULT hr;
4350 UINT64 val = 0;
4351 BOOL found;
4353 if (desc)
4355 FIXME( "description not supported\n" );
4356 return E_NOTIMPL;
4358 if ((hr = get_text( reader, mapping, localname, ns, &text, &found )) != S_OK) return hr;
4359 if (found)
4361 const WS_XML_UTF8_TEXT *utf8 = text_to_utf8( text );
4362 if ((hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT8, &val )) != S_OK)
4363 return hr;
4366 switch (option)
4368 case WS_READ_REQUIRED_VALUE:
4369 if (!found) return WS_E_INVALID_FORMAT;
4370 /* fall through */
4372 case WS_READ_NILLABLE_VALUE:
4373 if (size != sizeof(UINT8)) return E_INVALIDARG;
4374 *(UINT8 *)ret = val;
4375 break;
4377 case WS_READ_REQUIRED_POINTER:
4378 if (!found) return WS_E_INVALID_FORMAT;
4379 /* fall through */
4381 case WS_READ_OPTIONAL_POINTER:
4382 case WS_READ_NILLABLE_POINTER:
4384 UINT8 *heap_val = NULL;
4385 if (size != sizeof(heap_val)) return E_INVALIDARG;
4386 if (found)
4388 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4389 *heap_val = val;
4391 *(UINT8 **)ret = heap_val;
4392 break;
4394 default:
4395 FIXME( "read option %u not supported\n", option );
4396 return E_NOTIMPL;
4399 return S_OK;
4402 static HRESULT read_type_uint16( struct reader *reader, WS_TYPE_MAPPING mapping,
4403 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4404 const WS_UINT16_DESCRIPTION *desc, WS_READ_OPTION option,
4405 WS_HEAP *heap, void *ret, ULONG size )
4407 const WS_XML_TEXT *text;
4408 HRESULT hr;
4409 UINT64 val = 0;
4410 BOOL found;
4412 if (desc)
4414 FIXME( "description not supported\n" );
4415 return E_NOTIMPL;
4417 if ((hr = get_text( reader, mapping, localname, ns, &text, &found )) != S_OK) return hr;
4418 if (found)
4420 const WS_XML_UTF8_TEXT *utf8 = text_to_utf8( text );
4421 if ((hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT16, &val )) != S_OK)
4422 return hr;
4425 switch (option)
4427 case WS_READ_REQUIRED_VALUE:
4428 if (!found) return WS_E_INVALID_FORMAT;
4429 /* fall through */
4431 case WS_READ_NILLABLE_VALUE:
4432 if (size != sizeof(UINT16)) return E_INVALIDARG;
4433 *(UINT16 *)ret = val;
4434 break;
4436 case WS_READ_REQUIRED_POINTER:
4437 if (!found) return WS_E_INVALID_FORMAT;
4438 /* fall through */
4440 case WS_READ_OPTIONAL_POINTER:
4441 case WS_READ_NILLABLE_POINTER:
4443 UINT16 *heap_val = NULL;
4444 if (size != sizeof(heap_val)) return E_INVALIDARG;
4445 if (found)
4447 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4448 *heap_val = val;
4450 *(UINT16 **)ret = heap_val;
4451 break;
4453 default:
4454 FIXME( "read option %u not supported\n", option );
4455 return E_NOTIMPL;
4458 return S_OK;
4461 static HRESULT read_type_uint32( struct reader *reader, WS_TYPE_MAPPING mapping,
4462 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4463 const WS_UINT32_DESCRIPTION *desc, WS_READ_OPTION option,
4464 WS_HEAP *heap, void *ret, ULONG size )
4466 const WS_XML_TEXT *text;
4467 HRESULT hr;
4468 UINT64 val = 0;
4469 BOOL found;
4471 if (desc)
4473 FIXME( "description not supported\n" );
4474 return E_NOTIMPL;
4476 if ((hr = get_text( reader, mapping, localname, ns, &text, &found )) != S_OK) return hr;
4477 if (found)
4479 const WS_XML_UTF8_TEXT *utf8 = text_to_utf8( text );
4480 if ((hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT32, &val )) != S_OK)
4481 return hr;
4484 switch (option)
4486 case WS_READ_REQUIRED_VALUE:
4487 if (!found) return WS_E_INVALID_FORMAT;
4488 /* fall through */
4490 case WS_READ_NILLABLE_VALUE:
4491 if (size != sizeof(UINT32)) return E_INVALIDARG;
4492 *(UINT32 *)ret = val;
4493 break;
4495 case WS_READ_REQUIRED_POINTER:
4496 if (!found) return WS_E_INVALID_FORMAT;
4497 /* fall through */
4499 case WS_READ_OPTIONAL_POINTER:
4500 case WS_READ_NILLABLE_POINTER:
4502 UINT32 *heap_val = NULL;
4503 if (size != sizeof(heap_val)) return E_INVALIDARG;
4504 if (found)
4506 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4507 *heap_val = val;
4509 *(UINT32 **)ret = heap_val;
4510 break;
4512 default:
4513 FIXME( "read option %u not supported\n", option );
4514 return E_NOTIMPL;
4517 return S_OK;
4520 static HRESULT read_type_uint64( struct reader *reader, WS_TYPE_MAPPING mapping,
4521 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4522 const WS_UINT64_DESCRIPTION *desc, WS_READ_OPTION option,
4523 WS_HEAP *heap, void *ret, ULONG size )
4525 const WS_XML_TEXT *text;
4526 HRESULT hr;
4527 UINT64 val = 0;
4528 BOOL found;
4530 if (desc)
4532 FIXME( "description not supported\n" );
4533 return E_NOTIMPL;
4535 if ((hr = get_text( reader, mapping, localname, ns, &text, &found )) != S_OK) return hr;
4536 if (found)
4538 const WS_XML_UTF8_TEXT *utf8 = text_to_utf8( text );
4539 if ((hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT64, &val )) != S_OK)
4540 return hr;
4543 switch (option)
4545 case WS_READ_REQUIRED_VALUE:
4546 if (!found) return WS_E_INVALID_FORMAT;
4547 /* fall through */
4549 case WS_READ_NILLABLE_VALUE:
4550 if (size != sizeof(val)) return E_INVALIDARG;
4551 *(UINT64 *)ret = val;
4552 break;
4554 case WS_READ_REQUIRED_POINTER:
4555 if (!found) return WS_E_INVALID_FORMAT;
4556 /* fall through */
4558 case WS_READ_OPTIONAL_POINTER:
4559 case WS_READ_NILLABLE_POINTER:
4561 UINT64 *heap_val = NULL;
4562 if (size != sizeof(heap_val)) return E_INVALIDARG;
4563 if (found)
4565 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4566 *heap_val = val;
4568 *(UINT64 **)ret = heap_val;
4569 break;
4571 default:
4572 FIXME( "read option %u not supported\n", option );
4573 return E_NOTIMPL;
4576 return S_OK;
4579 static HRESULT read_type_double( struct reader *reader, WS_TYPE_MAPPING mapping,
4580 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4581 const WS_DOUBLE_DESCRIPTION *desc, WS_READ_OPTION option,
4582 WS_HEAP *heap, void *ret, ULONG size )
4584 const WS_XML_TEXT *text;
4585 HRESULT hr;
4586 double val = 0.0;
4587 BOOL found;
4589 if (desc) FIXME( "ignoring description\n" );
4591 if ((hr = get_text( reader, mapping, localname, ns, &text, &found )) != S_OK) return hr;
4592 if (found)
4594 const WS_XML_UTF8_TEXT *utf8 = text_to_utf8( text );
4595 if ((hr = str_to_double( utf8->value.bytes, utf8->value.length, &val )) != S_OK) return hr;
4598 switch (option)
4600 case WS_READ_REQUIRED_VALUE:
4601 if (!found) return WS_E_INVALID_FORMAT;
4602 /* fall through */
4604 case WS_READ_NILLABLE_VALUE:
4605 if (size != sizeof(val)) return E_INVALIDARG;
4606 *(double *)ret = val;
4607 break;
4609 case WS_READ_REQUIRED_POINTER:
4610 if (!found) return WS_E_INVALID_FORMAT;
4611 /* fall through */
4613 case WS_READ_OPTIONAL_POINTER:
4614 case WS_READ_NILLABLE_POINTER:
4616 double *heap_val = NULL;
4617 if (size != sizeof(heap_val)) return E_INVALIDARG;
4618 if (found)
4620 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4621 *heap_val = val;
4623 *(double **)ret = heap_val;
4624 break;
4626 default:
4627 FIXME( "read option %u not supported\n", option );
4628 return E_NOTIMPL;
4631 return S_OK;
4634 static HRESULT read_type_wsz( struct reader *reader, WS_TYPE_MAPPING mapping,
4635 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4636 const WS_WSZ_DESCRIPTION *desc, WS_READ_OPTION option,
4637 WS_HEAP *heap, WCHAR **ret, ULONG size )
4639 const WS_XML_TEXT *text;
4640 HRESULT hr;
4641 WCHAR *str = NULL;
4642 BOOL found;
4644 if (desc)
4646 FIXME( "description not supported\n" );
4647 return E_NOTIMPL;
4649 if ((hr = get_text( reader, mapping, localname, ns, &text, &found )) != S_OK) return hr;
4650 if (found && !(str = xmltext_to_widechar( heap, text ))) return WS_E_QUOTA_EXCEEDED;
4652 switch (option)
4654 case WS_READ_REQUIRED_POINTER:
4655 if (!str && !(str = ws_alloc_zero( heap, sizeof(*str) ))) return WS_E_QUOTA_EXCEEDED;
4656 /* fall through */
4658 case WS_READ_OPTIONAL_POINTER:
4659 case WS_READ_NILLABLE_POINTER:
4660 if (size != sizeof(str)) return E_INVALIDARG;
4661 *ret = str;
4662 break;
4664 default:
4665 FIXME( "read option %u not supported\n", option );
4666 return E_NOTIMPL;
4669 return S_OK;
4672 static HRESULT get_enum_value( const WS_XML_UTF8_TEXT *text, const WS_ENUM_DESCRIPTION *desc, int *ret )
4674 ULONG i;
4675 for (i = 0; i < desc->valueCount; i++)
4677 if (WsXmlStringEquals( &text->value, desc->values[i].name, NULL ) == S_OK)
4679 *ret = desc->values[i].value;
4680 return S_OK;
4683 return WS_E_INVALID_FORMAT;
4686 static HRESULT read_type_enum( struct reader *reader, WS_TYPE_MAPPING mapping,
4687 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4688 const WS_ENUM_DESCRIPTION *desc, WS_READ_OPTION option,
4689 WS_HEAP *heap, void *ret, ULONG size )
4691 const WS_XML_TEXT *text;
4692 HRESULT hr;
4693 int val = 0;
4694 BOOL found;
4696 if (!desc) return E_INVALIDARG;
4698 if ((hr = get_text( reader, mapping, localname, ns, &text, &found )) != S_OK) return hr;
4699 if (found)
4701 const WS_XML_UTF8_TEXT *utf8 = text_to_utf8( text );
4702 if ((hr = get_enum_value( utf8, desc, &val )) != S_OK) return hr;
4705 switch (option)
4707 case WS_READ_REQUIRED_VALUE:
4708 if (!found) return WS_E_INVALID_FORMAT;
4709 /* fall through */
4711 case WS_READ_NILLABLE_VALUE:
4712 if (size != sizeof(val)) return E_INVALIDARG;
4713 *(int *)ret = val;
4714 break;
4716 case WS_READ_REQUIRED_POINTER:
4717 if (!found) return WS_E_INVALID_FORMAT;
4718 /* fall through */
4720 case WS_READ_OPTIONAL_POINTER:
4721 case WS_READ_NILLABLE_POINTER:
4723 int *heap_val = NULL;
4724 if (size != sizeof(heap_val)) return E_INVALIDARG;
4725 if (found)
4727 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4728 *heap_val = val;
4730 *(int **)ret = heap_val;
4731 break;
4733 default:
4734 FIXME( "read option %u not supported\n", option );
4735 return E_NOTIMPL;
4738 return S_OK;
4741 static HRESULT read_type_datetime( struct reader *reader, WS_TYPE_MAPPING mapping,
4742 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4743 const WS_DATETIME_DESCRIPTION *desc, WS_READ_OPTION option,
4744 WS_HEAP *heap, void *ret, ULONG size )
4746 const WS_XML_TEXT *text;
4747 HRESULT hr;
4748 WS_DATETIME val = {0, WS_DATETIME_FORMAT_UTC};
4749 BOOL found;
4751 if (desc) FIXME( "ignoring description\n" );
4753 if ((hr = get_text( reader, mapping, localname, ns, &text, &found )) != S_OK) return hr;
4754 if (found)
4756 const WS_XML_UTF8_TEXT *utf8 = text_to_utf8( text );
4757 if ((hr = str_to_datetime( utf8->value.bytes, utf8->value.length, &val )) != S_OK) return hr;
4760 switch (option)
4762 case WS_READ_REQUIRED_VALUE:
4763 if (!found) return WS_E_INVALID_FORMAT;
4764 /* fall through */
4766 case WS_READ_NILLABLE_VALUE:
4767 if (size != sizeof(val)) return E_INVALIDARG;
4768 *(WS_DATETIME *)ret = val;
4769 break;
4771 case WS_READ_REQUIRED_POINTER:
4772 if (!found) return WS_E_INVALID_FORMAT;
4773 /* fall through */
4775 case WS_READ_OPTIONAL_POINTER:
4776 case WS_READ_NILLABLE_POINTER:
4778 WS_DATETIME *heap_val = NULL;
4779 if (size != sizeof(heap_val)) return E_INVALIDARG;
4780 if (found)
4782 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4783 *heap_val = val;
4785 *(WS_DATETIME **)ret = heap_val;
4786 break;
4788 default:
4789 FIXME( "read option %u not supported\n", option );
4790 return E_NOTIMPL;
4793 return S_OK;
4796 static HRESULT read_type_guid( struct reader *reader, WS_TYPE_MAPPING mapping,
4797 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4798 const WS_GUID_DESCRIPTION *desc, WS_READ_OPTION option,
4799 WS_HEAP *heap, void *ret, ULONG size )
4801 const WS_XML_TEXT *text;
4802 GUID val = {0};
4803 HRESULT hr;
4804 BOOL found;
4806 if (desc) FIXME( "ignoring description\n" );
4808 if ((hr = get_text( reader, mapping, localname, ns, &text, &found )) != S_OK) return hr;
4809 if (found)
4811 const WS_XML_UTF8_TEXT *utf8 = text_to_utf8( text );
4812 if ((hr = str_to_guid( utf8->value.bytes, utf8->value.length, &val )) != S_OK) return hr;
4815 switch (option)
4817 case WS_READ_REQUIRED_VALUE:
4818 if (!found) return WS_E_INVALID_FORMAT;
4819 /* fall through */
4821 case WS_READ_NILLABLE_VALUE:
4822 if (size != sizeof(val)) return E_INVALIDARG;
4823 *(GUID *)ret = val;
4824 break;
4826 case WS_READ_REQUIRED_POINTER:
4827 if (!found) return WS_E_INVALID_FORMAT;
4828 /* fall through */
4830 case WS_READ_OPTIONAL_POINTER:
4831 case WS_READ_NILLABLE_POINTER:
4833 GUID *heap_val = NULL;
4834 if (size != sizeof(heap_val)) return E_INVALIDARG;
4835 if (found)
4837 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4838 *heap_val = val;
4840 *(GUID **)ret = heap_val;
4841 break;
4843 default:
4844 FIXME( "read option %u not supported\n", option );
4845 return E_NOTIMPL;
4848 return S_OK;
4851 static HRESULT read_type_unique_id( struct reader *reader, WS_TYPE_MAPPING mapping,
4852 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4853 const WS_UNIQUE_ID_DESCRIPTION *desc, WS_READ_OPTION option,
4854 WS_HEAP *heap, void *ret, ULONG size )
4856 const WS_XML_TEXT *text;
4857 WS_UNIQUE_ID val = {{0}};
4858 HRESULT hr;
4859 BOOL found;
4861 if (desc) FIXME( "ignoring description\n" );
4863 if ((hr = get_text( reader, mapping, localname, ns, &text, &found )) != S_OK) return hr;
4864 if (found)
4866 const WS_XML_UTF8_TEXT *utf8 = text_to_utf8( text );
4867 if ((hr = str_to_unique_id( utf8->value.bytes, utf8->value.length, heap, &val )) != S_OK) return hr;
4870 switch (option)
4872 case WS_READ_REQUIRED_VALUE:
4873 if (!found) return WS_E_INVALID_FORMAT;
4874 /* fall through */
4876 case WS_READ_NILLABLE_VALUE:
4877 if (size != sizeof(val)) return E_INVALIDARG;
4878 *(WS_UNIQUE_ID *)ret = val;
4879 break;
4881 case WS_READ_REQUIRED_POINTER:
4882 if (!found) return WS_E_INVALID_FORMAT;
4883 /* fall through */
4885 case WS_READ_OPTIONAL_POINTER:
4886 case WS_READ_NILLABLE_POINTER:
4888 WS_UNIQUE_ID *heap_val = NULL;
4889 if (size != sizeof(heap_val)) return E_INVALIDARG;
4890 if (found)
4892 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4893 *heap_val = val;
4895 *(WS_UNIQUE_ID **)ret = heap_val;
4896 break;
4898 default:
4899 FIXME( "read option %u not supported\n", option );
4900 return E_NOTIMPL;
4903 return S_OK;
4906 static HRESULT read_type_string( struct reader *reader, WS_TYPE_MAPPING mapping,
4907 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4908 const WS_STRING_DESCRIPTION *desc, WS_READ_OPTION option,
4909 WS_HEAP *heap, void *ret, ULONG size )
4911 const WS_XML_TEXT *text;
4912 WS_STRING val = {0};
4913 HRESULT hr;
4914 BOOL found;
4916 if (desc) FIXME( "ignoring description\n" );
4918 if ((hr = get_text( reader, mapping, localname, ns, &text, &found )) != S_OK) return hr;
4919 if (found)
4921 const WS_XML_UTF8_TEXT *utf8 = text_to_utf8( text );
4922 if ((hr = str_to_string( utf8->value.bytes, utf8->value.length, heap, &val )) != S_OK)
4923 return hr;
4926 switch (option)
4928 case WS_READ_REQUIRED_VALUE:
4929 case WS_READ_NILLABLE_VALUE:
4930 if (size != sizeof(val)) return E_INVALIDARG;
4931 *(WS_STRING *)ret = val;
4932 break;
4934 case WS_READ_REQUIRED_POINTER:
4936 WS_STRING *heap_val;
4937 if (size != sizeof(heap_val)) return E_INVALIDARG;
4938 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4939 *heap_val = val;
4940 *(WS_STRING **)ret = heap_val;
4941 break;
4943 case WS_READ_OPTIONAL_POINTER:
4944 case WS_READ_NILLABLE_POINTER:
4946 WS_STRING *heap_val = NULL;
4947 if (size != sizeof(heap_val)) return E_INVALIDARG;
4948 if (found)
4950 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4951 *heap_val = val;
4953 *(WS_STRING **)ret = heap_val;
4954 break;
4956 default:
4957 FIXME( "read option %u not supported\n", option );
4958 return E_NOTIMPL;
4961 return S_OK;
4964 static HRESULT read_type_bytes( struct reader *reader, WS_TYPE_MAPPING mapping,
4965 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4966 const WS_BYTES_DESCRIPTION *desc, WS_READ_OPTION option,
4967 WS_HEAP *heap, void *ret, ULONG size )
4969 const WS_XML_TEXT *text;
4970 WS_BYTES val = {0};
4971 HRESULT hr;
4972 BOOL found;
4974 if (desc) FIXME( "ignoring description\n" );
4976 if ((hr = get_text( reader, mapping, localname, ns, &text, &found )) != S_OK) return hr;
4977 if (found)
4979 switch (reader->input_enc)
4981 case WS_XML_READER_ENCODING_TYPE_TEXT:
4983 const WS_XML_UTF8_TEXT *utf8 = text_to_utf8( text );
4984 if ((hr = str_to_bytes( utf8->value.bytes, utf8->value.length, heap, &val )) != S_OK)
4985 return hr;
4986 break;
4988 case WS_XML_READER_ENCODING_TYPE_BINARY:
4990 const WS_XML_BASE64_TEXT *base64 = text_to_base64( text );
4991 if (!(val.bytes = ws_alloc( heap, base64->length ))) return WS_E_QUOTA_EXCEEDED;
4992 memcpy( val.bytes, base64->bytes, base64->length );
4993 val.length = base64->length;
4994 break;
4996 default:
4997 FIXME( "unhandled input encoding %u\n", reader->input_enc );
4998 return WS_E_NOT_SUPPORTED;
5002 switch (option)
5004 case WS_READ_REQUIRED_VALUE:
5005 case WS_READ_NILLABLE_VALUE:
5006 if (size != sizeof(val)) return E_INVALIDARG;
5007 *(WS_BYTES *)ret = val;
5008 break;
5010 case WS_READ_REQUIRED_POINTER:
5012 WS_BYTES *heap_val;
5013 if (size != sizeof(heap_val)) return E_INVALIDARG;
5014 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5015 *heap_val = val;
5016 *(WS_BYTES **)ret = heap_val;
5017 break;
5019 case WS_READ_OPTIONAL_POINTER:
5020 case WS_READ_NILLABLE_POINTER:
5022 WS_BYTES *heap_val = NULL;
5023 if (size != sizeof(heap_val)) return E_INVALIDARG;
5024 if (found)
5026 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5027 *heap_val = val;
5029 *(WS_BYTES **)ret = heap_val;
5030 break;
5032 default:
5033 FIXME( "read option %u not supported\n", option );
5034 return E_NOTIMPL;
5037 return S_OK;
5040 static HRESULT read_type_xml_string( struct reader *reader, WS_TYPE_MAPPING mapping,
5041 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
5042 const WS_XML_STRING_DESCRIPTION *desc, WS_READ_OPTION option,
5043 WS_HEAP *heap, void *ret, ULONG size )
5045 const WS_XML_TEXT *text;
5046 WS_XML_STRING val = {0};
5047 HRESULT hr;
5048 BOOL found;
5050 if (desc) FIXME( "ignoring description\n" );
5052 if ((hr = get_text( reader, mapping, localname, ns, &text, &found )) != S_OK) return hr;
5053 if (found)
5055 const WS_XML_UTF8_TEXT *utf8 = text_to_utf8( text );
5056 if ((hr = str_to_xml_string( utf8->value.bytes, utf8->value.length, heap, &val )) != S_OK)
5057 return hr;
5060 switch (option)
5062 case WS_READ_REQUIRED_VALUE:
5063 case WS_READ_NILLABLE_VALUE:
5064 if (size != sizeof(val)) return E_INVALIDARG;
5065 *(WS_XML_STRING *)ret = val;
5066 break;
5068 case WS_READ_REQUIRED_POINTER:
5070 WS_XML_STRING *heap_val;
5071 if (size != sizeof(heap_val)) return E_INVALIDARG;
5072 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5073 *heap_val = val;
5074 *(WS_XML_STRING **)ret = heap_val;
5075 break;
5077 case WS_READ_OPTIONAL_POINTER:
5078 case WS_READ_NILLABLE_POINTER:
5080 WS_XML_STRING *heap_val = NULL;
5081 if (size != sizeof(heap_val)) return E_INVALIDARG;
5082 if (found)
5084 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5085 *heap_val = val;
5087 *(WS_XML_STRING **)ret = heap_val;
5088 break;
5090 default:
5091 FIXME( "read option %u not supported\n", option );
5092 return E_NOTIMPL;
5095 return S_OK;
5098 static HRESULT read_type_qname( struct reader *reader, WS_TYPE_MAPPING mapping,
5099 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
5100 const WS_XML_QNAME_DESCRIPTION *desc, WS_READ_OPTION option,
5101 WS_HEAP *heap, void *ret, ULONG size )
5103 const WS_XML_TEXT *text;
5104 WS_XML_QNAME val = {{0}};
5105 HRESULT hr;
5106 BOOL found;
5108 if (desc) FIXME( "ignoring description\n" );
5110 if (node_type( reader->current ) != WS_XML_NODE_TYPE_ELEMENT) return WS_E_INVALID_FORMAT;
5111 if ((hr = read_startelement( reader )) != S_OK) return hr;
5112 if (node_type( reader->current ) != WS_XML_NODE_TYPE_TEXT) return WS_E_INVALID_FORMAT;
5114 if ((hr = get_text( reader, mapping, localname, ns, &text, &found )) != S_OK) return hr;
5115 if (found)
5117 const WS_XML_UTF8_TEXT *utf8 = text_to_utf8( text );
5118 if ((hr = str_to_qname( reader, utf8->value.bytes, utf8->value.length, heap, NULL,
5119 &val.localName, &val.ns )) != S_OK) return hr;
5122 switch (option)
5124 case WS_READ_REQUIRED_VALUE:
5125 if (!found) return WS_E_INVALID_FORMAT;
5126 /* fall through */
5128 case WS_READ_NILLABLE_VALUE:
5129 if (size != sizeof(val)) return E_INVALIDARG;
5130 *(WS_XML_QNAME *)ret = val;
5131 break;
5133 case WS_READ_REQUIRED_POINTER:
5134 if (!found) return WS_E_INVALID_FORMAT;
5135 /* fall through */
5137 case WS_READ_OPTIONAL_POINTER:
5138 case WS_READ_NILLABLE_POINTER:
5140 WS_XML_QNAME *heap_val = NULL;
5141 if (size != sizeof(heap_val)) return E_INVALIDARG;
5142 if (found)
5144 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5145 *heap_val = val;
5147 *(WS_XML_QNAME **)ret = heap_val;
5148 break;
5150 default:
5151 FIXME( "read option %u not supported\n", option );
5152 return E_NOTIMPL;
5155 return S_OK;
5158 static BOOL is_empty_text_node( const struct node *node )
5160 const WS_XML_TEXT_NODE *text = (const WS_XML_TEXT_NODE *)node;
5162 if (node_type( node ) != WS_XML_NODE_TYPE_TEXT) return FALSE;
5163 switch (text->text->textType)
5165 case WS_XML_TEXT_TYPE_UTF8:
5167 ULONG i;
5168 const WS_XML_UTF8_TEXT *utf8 = text_to_utf8( text->text );
5169 for (i = 0; i < utf8->value.length; i++) if (!read_isspace( utf8->value.bytes[i] )) return FALSE;
5170 return TRUE;
5172 case WS_XML_TEXT_TYPE_BASE64:
5174 const WS_XML_BASE64_TEXT *base64 = text_to_base64( text->text );
5175 return !base64->length;
5177 default:
5178 ERR( "unhandled text type %u\n", text->text->textType );
5179 return FALSE;
5183 /* skips comment and empty text nodes */
5184 static HRESULT read_type_next_node( struct reader *reader )
5186 for (;;)
5188 HRESULT hr;
5189 WS_XML_NODE_TYPE type;
5191 if ((hr = read_next_node( reader )) != S_OK) return hr;
5192 type = node_type( reader->current );
5193 if (type == WS_XML_NODE_TYPE_COMMENT ||
5194 (type == WS_XML_NODE_TYPE_TEXT && is_empty_text_node( reader->current ))) continue;
5195 return S_OK;
5199 static HRESULT read_type_next_element_node( struct reader *reader, const WS_XML_STRING *localname,
5200 const WS_XML_STRING *ns )
5202 struct node *node;
5203 ULONG attr;
5204 HRESULT hr;
5206 if (!localname) return S_OK; /* assume reader is already correctly positioned */
5207 if (reader->current == reader->last)
5209 BOOL found;
5210 if ((hr = read_to_startelement( reader, &found )) != S_OK) return hr;
5211 if (!found) return WS_E_INVALID_FORMAT;
5213 if (match_element( reader->current, localname, ns )) return S_OK;
5215 node = reader->current;
5216 attr = reader->current_attr;
5218 if ((hr = read_type_next_node( reader )) != S_OK) return hr;
5219 if (match_element( reader->current, localname, ns )) return S_OK;
5221 reader->current = node;
5222 reader->current_attr = attr;
5224 return WS_E_INVALID_FORMAT;
5227 ULONG get_type_size( WS_TYPE type, const void *desc )
5229 switch (type)
5231 case WS_INT8_TYPE:
5232 case WS_UINT8_TYPE:
5233 return sizeof(INT8);
5235 case WS_INT16_TYPE:
5236 case WS_UINT16_TYPE:
5237 return sizeof(INT16);
5239 case WS_BOOL_TYPE:
5240 case WS_INT32_TYPE:
5241 case WS_UINT32_TYPE:
5242 case WS_ENUM_TYPE:
5243 return sizeof(INT32);
5245 case WS_INT64_TYPE:
5246 case WS_UINT64_TYPE:
5247 return sizeof(INT64);
5249 case WS_DOUBLE_TYPE:
5250 return sizeof(double);
5252 case WS_DATETIME_TYPE:
5253 return sizeof(WS_DATETIME);
5255 case WS_GUID_TYPE:
5256 return sizeof(GUID);
5258 case WS_STRING_TYPE:
5259 return sizeof(WS_STRING);
5261 case WS_WSZ_TYPE:
5262 return sizeof(WCHAR *);
5264 case WS_BYTES_TYPE:
5265 return sizeof(WS_BYTES);
5267 case WS_XML_STRING_TYPE:
5268 return sizeof(WS_XML_STRING);
5270 case WS_XML_QNAME_TYPE:
5271 return sizeof(WS_XML_QNAME);
5273 case WS_DESCRIPTION_TYPE:
5274 return sizeof(WS_STRUCT_DESCRIPTION *);
5276 case WS_STRUCT_TYPE:
5278 const WS_STRUCT_DESCRIPTION *desc_struct = desc;
5279 return desc_struct->size;
5281 case WS_UNION_TYPE:
5283 const WS_UNION_DESCRIPTION *desc_union = desc;
5284 return desc_union->size;
5286 default:
5287 ERR( "unhandled type %u\n", type );
5288 return 0;
5292 static WS_READ_OPTION get_field_read_option( WS_TYPE type, ULONG options )
5294 if (options & WS_FIELD_POINTER)
5296 if (options & WS_FIELD_NILLABLE) return WS_READ_NILLABLE_POINTER;
5297 if (options & WS_FIELD_OPTIONAL) return WS_READ_OPTIONAL_POINTER;
5298 return WS_READ_REQUIRED_POINTER;
5301 switch (type)
5303 case WS_BOOL_TYPE:
5304 case WS_INT8_TYPE:
5305 case WS_INT16_TYPE:
5306 case WS_INT32_TYPE:
5307 case WS_INT64_TYPE:
5308 case WS_UINT8_TYPE:
5309 case WS_UINT16_TYPE:
5310 case WS_UINT32_TYPE:
5311 case WS_UINT64_TYPE:
5312 case WS_DOUBLE_TYPE:
5313 case WS_DATETIME_TYPE:
5314 case WS_GUID_TYPE:
5315 case WS_UNIQUE_ID_TYPE:
5316 case WS_STRING_TYPE:
5317 case WS_BYTES_TYPE:
5318 case WS_XML_STRING_TYPE:
5319 case WS_XML_QNAME_TYPE:
5320 case WS_STRUCT_TYPE:
5321 case WS_ENUM_TYPE:
5322 case WS_UNION_TYPE:
5323 if (options & (WS_FIELD_OPTIONAL|WS_FIELD_NILLABLE)) return WS_READ_NILLABLE_VALUE;
5324 return WS_READ_REQUIRED_VALUE;
5326 case WS_WSZ_TYPE:
5327 case WS_DESCRIPTION_TYPE:
5328 if (options & WS_FIELD_NILLABLE) return WS_READ_NILLABLE_POINTER;
5329 if (options & WS_FIELD_OPTIONAL) return WS_READ_OPTIONAL_POINTER;
5330 return WS_READ_REQUIRED_POINTER;
5332 default:
5333 FIXME( "unhandled type %u\n", type );
5334 return 0;
5338 static HRESULT read_type( struct reader *, WS_TYPE_MAPPING, WS_TYPE, const WS_XML_STRING *,
5339 const WS_XML_STRING *, const void *, WS_READ_OPTION, WS_HEAP *,
5340 void *, ULONG );
5342 static HRESULT read_type_repeating_element( struct reader *reader, const WS_FIELD_DESCRIPTION *desc,
5343 WS_HEAP *heap, void **ret, ULONG *count )
5345 HRESULT hr;
5346 ULONG item_size, nb_items = 0, nb_allocated = 1, offset = 0;
5347 WS_READ_OPTION option;
5348 char *buf;
5350 if (!(option = get_field_read_option( desc->type, desc->options ))) return E_INVALIDARG;
5352 /* wrapper element */
5353 if (desc->localName && ((hr = read_type_next_element_node( reader, desc->localName, desc->ns )) != S_OK))
5354 return hr;
5356 if (option == WS_READ_REQUIRED_VALUE || option == WS_READ_NILLABLE_VALUE)
5357 item_size = get_type_size( desc->type, desc->typeDescription );
5358 else
5359 item_size = sizeof(void *);
5361 if (!(buf = ws_alloc_zero( heap, item_size ))) return WS_E_QUOTA_EXCEEDED;
5362 for (;;)
5364 if (nb_items >= nb_allocated)
5366 SIZE_T old_size = nb_allocated * item_size, new_size = old_size * 2;
5367 if (!(buf = ws_realloc_zero( heap, buf, old_size, new_size )))
5368 return WS_E_QUOTA_EXCEEDED;
5369 nb_allocated *= 2;
5371 hr = read_type( reader, WS_ELEMENT_TYPE_MAPPING, desc->type, desc->itemLocalName, desc->itemNs,
5372 desc->typeDescription, option, heap, buf + offset, item_size );
5373 if (hr == WS_E_INVALID_FORMAT) break;
5374 if (hr != S_OK)
5376 ws_free( heap, buf, nb_allocated * item_size );
5377 return hr;
5379 offset += item_size;
5380 nb_items++;
5383 if (desc->localName && ((hr = read_type_next_node( reader )) != S_OK)) return hr;
5385 if (desc->itemRange && (nb_items < desc->itemRange->minItemCount || nb_items > desc->itemRange->maxItemCount))
5387 TRACE( "number of items %u out of range (%u-%u)\n", nb_items, desc->itemRange->minItemCount,
5388 desc->itemRange->maxItemCount );
5389 ws_free( heap, buf, nb_allocated * item_size );
5390 return WS_E_INVALID_FORMAT;
5393 *count = nb_items;
5394 *ret = buf;
5396 return S_OK;
5399 static HRESULT read_type_text( struct reader *reader, const WS_FIELD_DESCRIPTION *desc,
5400 WS_READ_OPTION option, WS_HEAP *heap, void *ret, ULONG size )
5402 HRESULT hr;
5403 if (reader->current == reader->last)
5405 BOOL found;
5406 if ((hr = read_to_startelement( reader, &found )) != S_OK) return S_OK;
5407 if (!found) return WS_E_INVALID_FORMAT;
5409 if ((hr = read_next_node( reader )) != S_OK) return hr;
5410 if (node_type( reader->current ) != WS_XML_NODE_TYPE_TEXT) return WS_E_INVALID_FORMAT;
5412 return read_type( reader, WS_ANY_ELEMENT_TYPE_MAPPING, desc->type, NULL, NULL,
5413 desc->typeDescription, option, heap, ret, size );
5416 static HRESULT read_type_field( struct reader *, const WS_FIELD_DESCRIPTION *, WS_HEAP *, char *, ULONG );
5418 static HRESULT read_type_union( struct reader *reader, const WS_UNION_DESCRIPTION *desc, WS_READ_OPTION option,
5419 WS_HEAP *heap, void *ret, ULONG size )
5421 ULONG offset, i;
5422 HRESULT hr = WS_E_INVALID_FORMAT;
5424 switch (option)
5426 case WS_READ_REQUIRED_VALUE:
5427 case WS_READ_NILLABLE_VALUE:
5428 if (size != desc->size) return E_INVALIDARG;
5429 break;
5431 default:
5432 return E_INVALIDARG;
5435 if ((hr = read_type_next_node( reader )) != S_OK) return hr;
5436 if (node_type( reader->current ) != WS_XML_NODE_TYPE_ELEMENT) return WS_E_INVALID_FORMAT;
5437 for (i = 0; i < desc->fieldCount; i++)
5439 if (match_element( reader->current, desc->fields[i]->field.localName, desc->fields[i]->field.ns ))
5440 break;
5442 if (i == desc->fieldCount)
5444 if (!move_to_parent_element( &reader->current )) return WS_E_INVALID_FORMAT;
5445 *(int *)((char *)ret + desc->enumOffset) = desc->noneEnumValue;
5447 else
5449 offset = desc->fields[i]->field.offset;
5450 if ((hr = read_type_field( reader, &desc->fields[i]->field, heap, ret, offset )) == S_OK)
5451 *(int *)((char *)ret + desc->enumOffset) = desc->fields[i]->value;
5454 switch (option)
5456 case WS_READ_NILLABLE_VALUE:
5457 break;
5459 case WS_READ_REQUIRED_VALUE:
5460 if (hr != S_OK) return hr;
5461 break;
5463 default:
5464 return E_INVALIDARG;
5467 return S_OK;
5470 static HRESULT read_type_field( struct reader *reader, const WS_FIELD_DESCRIPTION *desc, WS_HEAP *heap, char *buf,
5471 ULONG offset )
5473 char *ptr;
5474 WS_READ_OPTION option;
5475 ULONG size;
5476 HRESULT hr;
5478 if (!desc) return E_INVALIDARG;
5479 if (desc->options & ~(WS_FIELD_POINTER|WS_FIELD_OPTIONAL|WS_FIELD_NILLABLE|WS_FIELD_NILLABLE_ITEM))
5481 FIXME( "options %08x not supported\n", desc->options );
5482 return E_NOTIMPL;
5484 if (!(option = get_field_read_option( desc->type, desc->options ))) return E_INVALIDARG;
5486 if (option == WS_READ_REQUIRED_VALUE || option == WS_READ_NILLABLE_VALUE)
5487 size = get_type_size( desc->type, desc->typeDescription );
5488 else
5489 size = sizeof(void *);
5491 ptr = buf + offset;
5492 switch (desc->mapping)
5494 case WS_TYPE_ATTRIBUTE_FIELD_MAPPING:
5495 FIXME( "WS_TYPE_ATTRIBUTE_FIELD_MAPPING not supported\n" );
5496 return S_OK;
5498 case WS_ATTRIBUTE_FIELD_MAPPING:
5499 hr = read_type( reader, WS_ATTRIBUTE_TYPE_MAPPING, desc->type, desc->localName, desc->ns,
5500 desc->typeDescription, option, heap, ptr, size );
5501 break;
5503 case WS_ELEMENT_FIELD_MAPPING:
5504 hr = read_type( reader, WS_ELEMENT_TYPE_MAPPING, desc->type, desc->localName, desc->ns,
5505 desc->typeDescription, option, heap, ptr, size );
5506 break;
5508 case WS_ELEMENT_CHOICE_FIELD_MAPPING:
5509 if (desc->type != WS_UNION_TYPE || !desc->typeDescription ||
5510 (desc->options & (WS_FIELD_POINTER|WS_FIELD_NILLABLE))) return E_INVALIDARG;
5511 hr = read_type_union( reader, desc->typeDescription, option, heap, ptr, size );
5512 break;
5514 case WS_REPEATING_ELEMENT_FIELD_MAPPING:
5516 ULONG count;
5517 hr = read_type_repeating_element( reader, desc, heap, (void **)ptr, &count );
5518 if (hr == S_OK) *(ULONG *)(buf + desc->countOffset) = count;
5519 break;
5521 case WS_TEXT_FIELD_MAPPING:
5522 hr = read_type_text( reader, desc, option, heap, ptr, size );
5523 break;
5525 default:
5526 FIXME( "unhandled field mapping %u\n", desc->mapping );
5527 return E_NOTIMPL;
5530 if (hr == WS_E_INVALID_FORMAT)
5532 switch (option)
5534 case WS_READ_REQUIRED_VALUE:
5535 case WS_READ_REQUIRED_POINTER:
5536 return WS_E_INVALID_FORMAT;
5538 case WS_READ_NILLABLE_VALUE:
5539 if (desc->defaultValue) memcpy( ptr, desc->defaultValue->value, desc->defaultValue->valueSize );
5540 return S_OK;
5542 case WS_READ_OPTIONAL_POINTER:
5543 case WS_READ_NILLABLE_POINTER:
5544 *(void **)ptr = NULL;
5545 return S_OK;
5547 default:
5548 ERR( "unhandled option %u\n", option );
5549 return E_NOTIMPL;
5553 return hr;
5556 static HRESULT read_type_struct( struct reader *reader, WS_TYPE_MAPPING mapping, const WS_XML_STRING *localname,
5557 const WS_XML_STRING *ns, const WS_STRUCT_DESCRIPTION *desc, WS_READ_OPTION option,
5558 WS_HEAP *heap, void *ret, ULONG size )
5560 ULONG i, offset;
5561 HRESULT hr;
5562 char *buf;
5564 if (!desc) return E_INVALIDARG;
5565 if (desc->structOptions & ~WS_STRUCT_IGNORE_TRAILING_ELEMENT_CONTENT)
5567 FIXME( "struct options %08x not supported\n",
5568 desc->structOptions & ~WS_STRUCT_IGNORE_TRAILING_ELEMENT_CONTENT );
5571 switch (option)
5573 case WS_READ_REQUIRED_POINTER:
5574 case WS_READ_OPTIONAL_POINTER:
5575 case WS_READ_NILLABLE_POINTER:
5576 if (size != sizeof(void *)) return E_INVALIDARG;
5577 if (!(buf = ws_alloc_zero( heap, desc->size ))) return WS_E_QUOTA_EXCEEDED;
5578 break;
5580 case WS_READ_REQUIRED_VALUE:
5581 case WS_READ_NILLABLE_VALUE:
5582 if (size != desc->size) return E_INVALIDARG;
5583 buf = ret;
5584 break;
5586 default:
5587 FIXME( "unhandled read option %u\n", option );
5588 return E_NOTIMPL;
5591 for (i = 0; i < desc->fieldCount; i++)
5593 offset = desc->fields[i]->offset;
5594 if ((hr = read_type_field( reader, desc->fields[i], heap, buf, offset )) != S_OK) break;
5597 switch (option)
5599 case WS_READ_REQUIRED_POINTER:
5600 if (hr != S_OK)
5602 ws_free( heap, buf, desc->size );
5603 return hr;
5605 *(char **)ret = buf;
5606 break;
5608 case WS_READ_OPTIONAL_POINTER:
5609 case WS_READ_NILLABLE_POINTER:
5610 if (is_nil_value( buf, desc->size ))
5612 ws_free( heap, buf, desc->size );
5613 buf = NULL;
5615 *(char **)ret = buf;
5616 break;
5618 case WS_READ_REQUIRED_VALUE:
5619 case WS_READ_NILLABLE_VALUE:
5620 if (hr != S_OK) return hr;
5621 break;
5623 default:
5624 ERR( "unhandled read option %u\n", option );
5625 return E_NOTIMPL;
5628 if (desc->structOptions & WS_STRUCT_IGNORE_TRAILING_ELEMENT_CONTENT)
5630 struct node *parent = find_parent( reader );
5631 parent->flags |= NODE_FLAG_IGNORE_TRAILING_ELEMENT_CONTENT;
5633 return S_OK;
5636 static HRESULT start_mapping( struct reader *reader, WS_TYPE_MAPPING mapping, const WS_XML_STRING *localname,
5637 const WS_XML_STRING *ns )
5639 switch (mapping)
5641 case WS_ELEMENT_TYPE_MAPPING:
5642 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
5643 return read_type_next_element_node( reader, localname, ns );
5645 case WS_ANY_ELEMENT_TYPE_MAPPING:
5646 case WS_ATTRIBUTE_TYPE_MAPPING:
5647 return S_OK;
5649 default:
5650 FIXME( "unhandled mapping %u\n", mapping );
5651 return E_NOTIMPL;
5655 static HRESULT read_type_endelement_node( struct reader *reader )
5657 const struct node *parent = find_parent( reader );
5658 HRESULT hr;
5660 for (;;)
5662 if ((hr = read_type_next_node( reader )) != S_OK) return hr;
5663 if (node_type( reader->current ) == WS_XML_NODE_TYPE_END_ELEMENT && reader->current->parent == parent)
5665 return S_OK;
5667 if (read_end_of_data( reader ) || !(parent->flags & NODE_FLAG_IGNORE_TRAILING_ELEMENT_CONTENT)) break;
5670 return WS_E_INVALID_FORMAT;
5673 static HRESULT end_mapping( struct reader *reader, WS_TYPE_MAPPING mapping )
5675 switch (mapping)
5677 case WS_ELEMENT_TYPE_MAPPING:
5678 return read_type_endelement_node( reader );
5680 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
5681 return read_type_next_node( reader );
5683 case WS_ATTRIBUTE_TYPE_MAPPING:
5684 default:
5685 return S_OK;
5689 static HRESULT is_nil_element( const WS_XML_ELEMENT_NODE *elem )
5691 static const WS_XML_STRING localname = {3, (BYTE *)"nil"};
5692 static const WS_XML_STRING ns = {41, (BYTE *)"http://www.w3.org/2001/XMLSchema-instance"};
5693 ULONG i;
5695 for (i = 0; i < elem->attributeCount; i++)
5697 const WS_XML_UTF8_TEXT *text = (WS_XML_UTF8_TEXT *)elem->attributes[i]->value;
5699 if (elem->attributes[i]->isXmlNs) continue;
5700 if (WsXmlStringEquals( elem->attributes[i]->localName, &localname, NULL ) == S_OK &&
5701 WsXmlStringEquals( elem->attributes[i]->ns, &ns, NULL ) == S_OK &&
5702 text->value.length == 4 && !memcmp( text->value.bytes, "true", 4 )) return TRUE;
5704 return FALSE;
5707 static HRESULT read_type( struct reader *reader, WS_TYPE_MAPPING mapping, WS_TYPE type,
5708 const WS_XML_STRING *localname, const WS_XML_STRING *ns, const void *desc,
5709 WS_READ_OPTION option, WS_HEAP *heap, void *value, ULONG size )
5711 HRESULT hr;
5713 if ((hr = start_mapping( reader, mapping, localname, ns )) != S_OK) return hr;
5715 if (mapping == WS_ELEMENT_TYPE_MAPPING && is_nil_element( &reader->current->hdr ))
5717 if (option != WS_READ_NILLABLE_POINTER && option != WS_READ_NILLABLE_VALUE) return WS_E_INVALID_FORMAT;
5718 return end_mapping( reader, mapping );
5721 switch (type)
5723 case WS_BOOL_TYPE:
5724 if ((hr = read_type_bool( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
5725 return hr;
5726 break;
5728 case WS_INT8_TYPE:
5729 if ((hr = read_type_int8( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
5730 return hr;
5731 break;
5733 case WS_INT16_TYPE:
5734 if ((hr = read_type_int16( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
5735 return hr;
5736 break;
5738 case WS_INT32_TYPE:
5739 if ((hr = read_type_int32( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
5740 return hr;
5741 break;
5743 case WS_INT64_TYPE:
5744 if ((hr = read_type_int64( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
5745 return hr;
5746 break;
5748 case WS_UINT8_TYPE:
5749 if ((hr = read_type_uint8( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
5750 return hr;
5751 break;
5753 case WS_UINT16_TYPE:
5754 if ((hr = read_type_uint16( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
5755 return hr;
5756 break;
5758 case WS_UINT32_TYPE:
5759 if ((hr = read_type_uint32( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
5760 return hr;
5761 break;
5763 case WS_UINT64_TYPE:
5764 if ((hr = read_type_uint64( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
5765 return hr;
5766 break;
5768 case WS_DOUBLE_TYPE:
5769 if ((hr = read_type_double( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
5770 return hr;
5771 break;
5773 case WS_DATETIME_TYPE:
5774 if ((hr = read_type_datetime( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
5775 return hr;
5776 break;
5778 case WS_GUID_TYPE:
5779 if ((hr = read_type_guid( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
5780 return hr;
5781 break;
5783 case WS_UNIQUE_ID_TYPE:
5784 if ((hr = read_type_unique_id( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
5785 return hr;
5786 break;
5788 case WS_STRING_TYPE:
5789 if ((hr = read_type_string( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
5790 return hr;
5791 break;
5793 case WS_WSZ_TYPE:
5794 if ((hr = read_type_wsz( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
5795 return hr;
5796 break;
5798 case WS_BYTES_TYPE:
5799 if ((hr = read_type_bytes( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
5800 return hr;
5801 break;
5803 case WS_XML_STRING_TYPE:
5804 if ((hr = read_type_xml_string( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
5805 return hr;
5806 break;
5808 case WS_XML_QNAME_TYPE:
5809 if ((hr = read_type_qname( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
5810 return hr;
5811 break;
5813 case WS_STRUCT_TYPE:
5814 if ((hr = read_type_struct( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
5815 return hr;
5816 break;
5818 case WS_ENUM_TYPE:
5819 if ((hr = read_type_enum( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
5820 return hr;
5821 break;
5823 default:
5824 FIXME( "type %u not supported\n", type );
5825 return E_NOTIMPL;
5828 return end_mapping( reader, mapping );
5831 /**************************************************************************
5832 * WsReadType [webservices.@]
5834 HRESULT WINAPI WsReadType( WS_XML_READER *handle, WS_TYPE_MAPPING mapping, WS_TYPE type,
5835 const void *desc, WS_READ_OPTION option, WS_HEAP *heap, void *value,
5836 ULONG size, WS_ERROR *error )
5838 struct reader *reader = (struct reader *)handle;
5839 HRESULT hr;
5841 TRACE( "%p %u %u %p %u %p %p %u %p\n", handle, mapping, type, desc, option, heap, value,
5842 size, error );
5843 if (error) FIXME( "ignoring error parameter\n" );
5845 if (!reader || !value) return E_INVALIDARG;
5847 EnterCriticalSection( &reader->cs );
5849 if (reader->magic != READER_MAGIC)
5851 LeaveCriticalSection( &reader->cs );
5852 return E_INVALIDARG;
5855 if ((hr = read_type( reader, mapping, type, NULL, NULL, desc, option, heap, value, size )) != S_OK)
5857 LeaveCriticalSection( &reader->cs );
5858 return hr;
5861 switch (mapping)
5863 case WS_ELEMENT_TYPE_MAPPING:
5864 hr = read_node( reader );
5865 break;
5867 default:
5868 break;
5871 if (hr == S_OK && !read_end_of_data( reader )) hr = WS_E_INVALID_FORMAT;
5873 LeaveCriticalSection( &reader->cs );
5874 return hr;
5877 HRESULT read_header( WS_XML_READER *handle, const WS_XML_STRING *localname, const WS_XML_STRING *ns,
5878 WS_TYPE type, const void *desc, WS_READ_OPTION option, WS_HEAP *heap, void *value,
5879 ULONG size )
5881 struct reader *reader = (struct reader *)handle;
5882 HRESULT hr;
5884 EnterCriticalSection( &reader->cs );
5886 if (reader->magic != READER_MAGIC)
5888 LeaveCriticalSection( &reader->cs );
5889 return E_INVALIDARG;
5892 hr = read_type( reader, WS_ELEMENT_CONTENT_TYPE_MAPPING, type, localname, ns, desc, option, heap,
5893 value, size );
5895 LeaveCriticalSection( &reader->cs );
5896 return hr;
5899 /**************************************************************************
5900 * WsReadElement [webservices.@]
5902 HRESULT WINAPI WsReadElement( WS_XML_READER *handle, const WS_ELEMENT_DESCRIPTION *desc,
5903 WS_READ_OPTION option, WS_HEAP *heap, void *value, ULONG size,
5904 WS_ERROR *error )
5906 struct reader *reader = (struct reader *)handle;
5907 HRESULT hr;
5909 TRACE( "%p %p %u %p %p %u %p\n", handle, desc, option, heap, value, size, error );
5910 if (error) FIXME( "ignoring error parameter\n" );
5912 if (!reader || !desc || !value) return E_INVALIDARG;
5914 EnterCriticalSection( &reader->cs );
5916 if (reader->magic != READER_MAGIC)
5918 LeaveCriticalSection( &reader->cs );
5919 return E_INVALIDARG;
5922 hr = read_type( reader, WS_ELEMENT_TYPE_MAPPING, desc->type, desc->elementLocalName,
5923 desc->elementNs, desc->typeDescription, option, heap, value, size );
5925 LeaveCriticalSection( &reader->cs );
5926 return hr;
5929 /**************************************************************************
5930 * WsReadValue [webservices.@]
5932 HRESULT WINAPI WsReadValue( WS_XML_READER *handle, WS_VALUE_TYPE value_type, void *value, ULONG size,
5933 WS_ERROR *error )
5935 struct reader *reader = (struct reader *)handle;
5936 WS_TYPE type = map_value_type( value_type );
5937 HRESULT hr;
5939 TRACE( "%p %u %p %u %p\n", handle, type, value, size, error );
5940 if (error) FIXME( "ignoring error parameter\n" );
5942 if (!reader || !value || type == ~0u) return E_INVALIDARG;
5944 EnterCriticalSection( &reader->cs );
5946 if (reader->magic != READER_MAGIC)
5948 LeaveCriticalSection( &reader->cs );
5949 return E_INVALIDARG;
5952 hr = read_type( reader, WS_ELEMENT_TYPE_MAPPING, type, NULL, NULL, NULL, WS_READ_REQUIRED_VALUE,
5953 NULL, value, size );
5955 LeaveCriticalSection( &reader->cs );
5956 return hr;
5959 /**************************************************************************
5960 * WsReadAttribute [webservices.@]
5962 HRESULT WINAPI WsReadAttribute( WS_XML_READER *handle, const WS_ATTRIBUTE_DESCRIPTION *desc,
5963 WS_READ_OPTION option, WS_HEAP *heap, void *value, ULONG size,
5964 WS_ERROR *error )
5966 struct reader *reader = (struct reader *)handle;
5967 HRESULT hr;
5969 TRACE( "%p %p %u %p %p %u %p\n", handle, desc, option, heap, value, size, error );
5970 if (error) FIXME( "ignoring error parameter\n" );
5972 if (!reader || !desc || !value) return E_INVALIDARG;
5974 EnterCriticalSection( &reader->cs );
5976 if (reader->magic != READER_MAGIC)
5978 LeaveCriticalSection( &reader->cs );
5979 return E_INVALIDARG;
5982 if (!reader->input_type)
5984 LeaveCriticalSection( &reader->cs );
5985 return WS_E_INVALID_OPERATION;
5988 hr = read_type( reader, WS_ATTRIBUTE_TYPE_MAPPING, desc->type, desc->attributeLocalName,
5989 desc->attributeNs, desc->typeDescription, option, heap, value, size );
5991 LeaveCriticalSection( &reader->cs );
5992 return hr;
5995 static inline BOOL is_utf8( const unsigned char *data, ULONG size, ULONG *offset )
5997 static const char bom[] = {0xef,0xbb,0xbf};
5998 const unsigned char *p = data;
6000 return (size >= sizeof(bom) && !memcmp( p, bom, sizeof(bom) ) && (*offset = sizeof(bom))) ||
6001 (size > 2 && !(*offset = 0));
6004 static inline BOOL is_utf16le( const unsigned char *data, ULONG size, ULONG *offset )
6006 static const char bom[] = {0xff,0xfe};
6007 const unsigned char *p = data;
6009 return (size >= sizeof(bom) && !memcmp( p, bom, sizeof(bom) ) && (*offset = sizeof(bom))) ||
6010 (size >= 4 && p[0] == '<' && !p[1] && !(*offset = 0));
6013 static WS_CHARSET detect_charset( const unsigned char *data, ULONG size, ULONG *offset )
6015 WS_CHARSET ret = 0;
6017 /* FIXME: parse xml declaration */
6019 if (is_utf16le( data, size, offset )) ret = WS_CHARSET_UTF16LE;
6020 else if (is_utf8( data, size, offset )) ret = WS_CHARSET_UTF8;
6021 else
6023 FIXME( "charset not recognized\n" );
6024 return 0;
6027 TRACE( "detected charset %u\n", ret );
6028 return ret;
6031 static void set_input_buffer( struct reader *reader, struct xmlbuf *buf, const unsigned char *data, ULONG size )
6033 reader->input_type = WS_XML_READER_INPUT_TYPE_BUFFER;
6034 reader->input_buf = buf;
6035 reader->input_data = data;
6036 reader->input_size = size;
6038 reader->read_size = reader->input_size;
6039 reader->read_pos = 0;
6040 reader->read_bufptr = reader->input_data;
6042 reader->text_conv_offset = 0;
6045 /**************************************************************************
6046 * WsSetInput [webservices.@]
6048 HRESULT WINAPI WsSetInput( WS_XML_READER *handle, const WS_XML_READER_ENCODING *encoding,
6049 const WS_XML_READER_INPUT *input, const WS_XML_READER_PROPERTY *properties,
6050 ULONG count, WS_ERROR *error )
6052 struct reader *reader = (struct reader *)handle;
6053 struct node *node;
6054 ULONG i, offset = 0;
6055 HRESULT hr;
6057 TRACE( "%p %p %p %p %u %p\n", handle, encoding, input, properties, count, error );
6058 if (error) FIXME( "ignoring error parameter\n" );
6060 if (!reader) return E_INVALIDARG;
6062 EnterCriticalSection( &reader->cs );
6064 if (reader->magic != READER_MAGIC)
6066 LeaveCriticalSection( &reader->cs );
6067 return E_INVALIDARG;
6070 for (i = 0; i < count; i++)
6072 hr = prop_set( reader->prop, reader->prop_count, properties[i].id, properties[i].value,
6073 properties[i].valueSize );
6074 if (hr != S_OK) goto done;
6077 if ((hr = init_reader( reader )) != S_OK) goto done;
6079 switch (encoding->encodingType)
6081 case WS_XML_READER_ENCODING_TYPE_TEXT:
6083 WS_XML_READER_TEXT_ENCODING *text = (WS_XML_READER_TEXT_ENCODING *)encoding;
6084 WS_XML_READER_BUFFER_INPUT *buf = (WS_XML_READER_BUFFER_INPUT *)input;
6086 if (input->inputType != WS_XML_READER_INPUT_TYPE_BUFFER)
6088 FIXME( "charset detection on input type %u not supported\n", input->inputType );
6089 hr = E_NOTIMPL;
6090 goto done;
6093 if (text->charSet != WS_CHARSET_AUTO) reader->input_charset = text->charSet;
6094 else reader->input_charset = detect_charset( buf->encodedData, buf->encodedDataSize, &offset );
6096 reader->input_enc = WS_XML_READER_ENCODING_TYPE_TEXT;
6097 break;
6099 case WS_XML_READER_ENCODING_TYPE_BINARY:
6101 WS_XML_READER_BINARY_ENCODING *bin = (WS_XML_READER_BINARY_ENCODING *)encoding;
6102 reader->input_enc = WS_XML_READER_ENCODING_TYPE_BINARY;
6103 reader->input_charset = 0;
6104 reader->dict_static = bin->staticDictionary ? bin->staticDictionary : &dict_builtin_static.dict;
6105 reader->dict = bin->dynamicDictionary ? bin->dynamicDictionary : &dict_builtin.dict;
6106 break;
6108 default:
6109 FIXME( "encoding type %u not supported\n", encoding->encodingType );
6110 hr = E_NOTIMPL;
6111 goto done;
6114 switch (input->inputType)
6116 case WS_XML_READER_INPUT_TYPE_BUFFER:
6118 WS_XML_READER_BUFFER_INPUT *buf = (WS_XML_READER_BUFFER_INPUT *)input;
6119 set_input_buffer( reader, NULL, (const unsigned char *)buf->encodedData + offset,
6120 buf->encodedDataSize - offset );
6121 break;
6123 default:
6124 FIXME( "input type %u not supported\n", input->inputType );
6125 hr = E_NOTIMPL;
6126 goto done;
6129 if (!(node = alloc_node( WS_XML_NODE_TYPE_BOF ))) hr = E_OUTOFMEMORY;
6130 else read_insert_bof( reader, node );
6132 done:
6133 LeaveCriticalSection( &reader->cs );
6134 return hr;
6137 /**************************************************************************
6138 * WsSetInputToBuffer [webservices.@]
6140 HRESULT WINAPI WsSetInputToBuffer( WS_XML_READER *handle, WS_XML_BUFFER *buffer,
6141 const WS_XML_READER_PROPERTY *properties, ULONG count,
6142 WS_ERROR *error )
6144 struct reader *reader = (struct reader *)handle;
6145 struct xmlbuf *xmlbuf = (struct xmlbuf *)buffer;
6146 struct node *node;
6147 HRESULT hr;
6148 ULONG i;
6150 TRACE( "%p %p %p %u %p\n", handle, buffer, properties, count, error );
6151 if (error) FIXME( "ignoring error parameter\n" );
6153 if (!reader || !xmlbuf) return E_INVALIDARG;
6155 EnterCriticalSection( &reader->cs );
6157 if (reader->magic != READER_MAGIC)
6159 LeaveCriticalSection( &reader->cs );
6160 return E_INVALIDARG;
6163 for (i = 0; i < count; i++)
6165 hr = prop_set( reader->prop, reader->prop_count, properties[i].id, properties[i].value,
6166 properties[i].valueSize );
6167 if (hr != S_OK) goto done;
6170 if ((hr = init_reader( reader )) != S_OK) goto done;
6172 reader->input_enc = xmlbuf->encoding;
6173 reader->input_charset = xmlbuf->charset;
6174 set_input_buffer( reader, xmlbuf, xmlbuf->bytes.bytes, xmlbuf->bytes.length );
6176 if (!(node = alloc_node( WS_XML_NODE_TYPE_BOF ))) hr = E_OUTOFMEMORY;
6177 else read_insert_bof( reader, node );
6179 done:
6180 LeaveCriticalSection( &reader->cs );
6181 return hr;
6184 /**************************************************************************
6185 * WsGetReaderPosition [webservices.@]
6187 HRESULT WINAPI WsGetReaderPosition( WS_XML_READER *handle, WS_XML_NODE_POSITION *pos, WS_ERROR *error )
6189 struct reader *reader = (struct reader *)handle;
6191 TRACE( "%p %p %p\n", handle, pos, error );
6192 if (error) FIXME( "ignoring error parameter\n" );
6194 if (!reader || !pos) return E_INVALIDARG;
6196 EnterCriticalSection( &reader->cs );
6198 if (reader->magic != READER_MAGIC)
6200 LeaveCriticalSection( &reader->cs );
6201 return E_INVALIDARG;
6204 if (!reader->input_buf)
6206 LeaveCriticalSection( &reader->cs );
6207 return WS_E_INVALID_OPERATION;
6210 pos->buffer = (WS_XML_BUFFER *)reader->input_buf;
6211 pos->node = reader->current;
6213 LeaveCriticalSection( &reader->cs );
6214 return S_OK;
6217 /**************************************************************************
6218 * WsSetReaderPosition [webservices.@]
6220 HRESULT WINAPI WsSetReaderPosition( WS_XML_READER *handle, const WS_XML_NODE_POSITION *pos, WS_ERROR *error )
6222 struct reader *reader = (struct reader *)handle;
6224 TRACE( "%p %p %p\n", handle, pos, error );
6225 if (error) FIXME( "ignoring error parameter\n" );
6227 if (!reader || !pos) return E_INVALIDARG;
6229 EnterCriticalSection( &reader->cs );
6231 if (reader->magic != READER_MAGIC || (struct xmlbuf *)pos->buffer != reader->input_buf)
6233 LeaveCriticalSection( &reader->cs );
6234 return E_INVALIDARG;
6237 if (!reader->input_buf)
6239 LeaveCriticalSection( &reader->cs );
6240 return WS_E_INVALID_OPERATION;
6243 reader->current = pos->node;
6245 LeaveCriticalSection( &reader->cs );
6246 return S_OK;
6249 static HRESULT utf8_to_base64( const WS_XML_UTF8_TEXT *utf8, WS_XML_BASE64_TEXT *base64 )
6251 if (utf8->value.length % 4) return WS_E_INVALID_FORMAT;
6252 if (!(base64->bytes = heap_alloc( utf8->value.length * 3 / 4 ))) return E_OUTOFMEMORY;
6253 base64->length = decode_base64( utf8->value.bytes, utf8->value.length, base64->bytes );
6254 return S_OK;
6257 /**************************************************************************
6258 * WsReadBytes [webservices.@]
6260 HRESULT WINAPI WsReadBytes( WS_XML_READER *handle, void *bytes, ULONG max_count, ULONG *count, WS_ERROR *error )
6262 struct reader *reader = (struct reader *)handle;
6263 HRESULT hr;
6265 TRACE( "%p %p %u %p %p\n", handle, bytes, max_count, count, error );
6266 if (error) FIXME( "ignoring error parameter\n" );
6268 if (!reader) return E_INVALIDARG;
6270 EnterCriticalSection( &reader->cs );
6272 if (reader->magic != READER_MAGIC)
6274 LeaveCriticalSection( &reader->cs );
6275 return E_INVALIDARG;
6278 if (!reader->input_type)
6280 LeaveCriticalSection( &reader->cs );
6281 return WS_E_INVALID_OPERATION;
6284 if (!count)
6286 LeaveCriticalSection( &reader->cs );
6287 return E_INVALIDARG;
6290 *count = 0;
6291 if (node_type( reader->current ) == WS_XML_NODE_TYPE_TEXT && bytes)
6293 const WS_XML_TEXT_NODE *text = (const WS_XML_TEXT_NODE *)reader->current;
6294 WS_XML_BASE64_TEXT base64;
6296 if ((hr = utf8_to_base64( (const WS_XML_UTF8_TEXT *)text->text, &base64 )) != S_OK)
6298 LeaveCriticalSection( &reader->cs );
6299 return hr;
6301 if (reader->text_conv_offset == base64.length)
6303 heap_free( base64.bytes );
6304 hr = read_node( reader );
6305 LeaveCriticalSection( &reader->cs );
6306 return hr;
6308 *count = min( base64.length - reader->text_conv_offset, max_count );
6309 memcpy( bytes, base64.bytes + reader->text_conv_offset, *count );
6310 reader->text_conv_offset += *count;
6311 heap_free( base64.bytes );
6314 LeaveCriticalSection( &reader->cs );
6315 return S_OK;
6318 static HRESULT utf8_to_utf16( const WS_XML_UTF8_TEXT *utf8, WS_XML_UTF16_TEXT *utf16 )
6320 int len = MultiByteToWideChar( CP_UTF8, 0, (char *)utf8->value.bytes, utf8->value.length, NULL, 0 );
6321 if (!(utf16->bytes = heap_alloc( len * sizeof(WCHAR) ))) return E_OUTOFMEMORY;
6322 MultiByteToWideChar( CP_UTF8, 0, (char *)utf8->value.bytes, utf8->value.length, (WCHAR *)utf16->bytes, len );
6323 utf16->byteCount = len * sizeof(WCHAR);
6324 return S_OK;
6327 /**************************************************************************
6328 * WsReadChars [webservices.@]
6330 HRESULT WINAPI WsReadChars( WS_XML_READER *handle, WCHAR *chars, ULONG max_count, ULONG *count, WS_ERROR *error )
6332 struct reader *reader = (struct reader *)handle;
6334 TRACE( "%p %p %u %p %p\n", handle, chars, max_count, count, error );
6335 if (error) FIXME( "ignoring error parameter\n" );
6337 if (!reader) return E_INVALIDARG;
6339 EnterCriticalSection( &reader->cs );
6341 if (reader->magic != READER_MAGIC)
6343 LeaveCriticalSection( &reader->cs );
6344 return E_INVALIDARG;
6347 if (!reader->input_type)
6349 LeaveCriticalSection( &reader->cs );
6350 return WS_E_INVALID_OPERATION;
6353 if (!count)
6355 LeaveCriticalSection( &reader->cs );
6356 return E_INVALIDARG;
6359 *count = 0;
6360 if (node_type( reader->current ) == WS_XML_NODE_TYPE_TEXT && chars)
6362 const WS_XML_TEXT_NODE *text = (const WS_XML_TEXT_NODE *)reader->current;
6363 WS_XML_UTF16_TEXT utf16;
6364 HRESULT hr;
6366 if ((hr = utf8_to_utf16( (const WS_XML_UTF8_TEXT *)text->text, &utf16 )) != S_OK)
6368 LeaveCriticalSection( &reader->cs );
6369 return hr;
6371 if (reader->text_conv_offset == utf16.byteCount / sizeof(WCHAR))
6373 heap_free( utf16.bytes );
6374 hr = read_node( reader );
6375 LeaveCriticalSection( &reader->cs );
6376 return hr;
6378 *count = min( utf16.byteCount / sizeof(WCHAR) - reader->text_conv_offset, max_count );
6379 memcpy( chars, utf16.bytes + reader->text_conv_offset * sizeof(WCHAR), *count * sizeof(WCHAR) );
6380 reader->text_conv_offset += *count;
6381 heap_free( utf16.bytes );
6384 LeaveCriticalSection( &reader->cs );
6385 return S_OK;
6388 /**************************************************************************
6389 * WsReadCharsUtf8 [webservices.@]
6391 HRESULT WINAPI WsReadCharsUtf8( WS_XML_READER *handle, BYTE *bytes, ULONG max_count, ULONG *count, WS_ERROR *error )
6393 struct reader *reader = (struct reader *)handle;
6394 HRESULT hr;
6396 TRACE( "%p %p %u %p %p\n", handle, bytes, max_count, count, error );
6397 if (error) FIXME( "ignoring error parameter\n" );
6399 if (!reader) return E_INVALIDARG;
6401 EnterCriticalSection( &reader->cs );
6403 if (reader->magic != READER_MAGIC)
6405 LeaveCriticalSection( &reader->cs );
6406 return E_INVALIDARG;
6409 if (!reader->input_type)
6411 LeaveCriticalSection( &reader->cs );
6412 return WS_E_INVALID_OPERATION;
6415 if (!count)
6417 LeaveCriticalSection( &reader->cs );
6418 return E_INVALIDARG;
6421 *count = 0;
6422 if (node_type( reader->current ) == WS_XML_NODE_TYPE_TEXT && bytes)
6424 const WS_XML_TEXT_NODE *text = (const WS_XML_TEXT_NODE *)reader->current;
6425 const WS_XML_UTF8_TEXT *utf8 = (const WS_XML_UTF8_TEXT *)text->text;
6427 if (reader->text_conv_offset == utf8->value.length)
6429 hr = read_node( reader );
6430 LeaveCriticalSection( &reader->cs );
6431 return hr;
6433 *count = min( utf8->value.length - reader->text_conv_offset, max_count );
6434 memcpy( bytes, utf8->value.bytes + reader->text_conv_offset, *count );
6435 reader->text_conv_offset += *count;
6438 LeaveCriticalSection( &reader->cs );
6439 return S_OK;
6442 static HRESULT move_to_element( struct reader *reader )
6444 HRESULT hr;
6445 if (node_type( reader->current ) == WS_XML_NODE_TYPE_BOF &&
6446 (hr = read_move_to( reader, WS_MOVE_TO_CHILD_NODE, NULL )) != S_OK) return hr;
6447 if (node_type( reader->current ) != WS_XML_NODE_TYPE_ELEMENT) return E_FAIL;
6448 return S_OK;
6451 static HRESULT copy_tree( struct reader *reader, WS_XML_WRITER *writer )
6453 const struct node *node, *parent;
6454 BOOL done = FALSE;
6455 HRESULT hr;
6457 if ((hr = move_to_element( reader )) != S_OK) return hr;
6458 parent = reader->current;
6459 for (;;)
6461 node = reader->current;
6462 if ((hr = WsWriteNode( writer, (const WS_XML_NODE *)node, NULL )) != S_OK) break;
6463 if (node_type( node ) == WS_XML_NODE_TYPE_END_ELEMENT && node->parent == parent) done = TRUE;
6464 if ((hr = read_next_node( reader )) != S_OK || done) break;
6466 return hr;
6469 /**************************************************************************
6470 * WsReadXmlBuffer [webservices.@]
6472 HRESULT WINAPI WsReadXmlBuffer( WS_XML_READER *handle, WS_HEAP *heap, WS_XML_BUFFER **ret, WS_ERROR *error )
6474 struct reader *reader = (struct reader *)handle;
6475 WS_XML_WRITER *writer = NULL;
6476 WS_XML_BUFFER *buffer;
6477 HRESULT hr;
6479 TRACE( "%p %p %p %p\n", handle, heap, ret, error );
6480 if (error) FIXME( "ignoring error parameter\n" );
6482 if (!reader || !heap) return E_INVALIDARG;
6483 if (!ret) return E_FAIL;
6485 EnterCriticalSection( &reader->cs );
6487 if (reader->magic != READER_MAGIC)
6489 LeaveCriticalSection( &reader->cs );
6490 return E_INVALIDARG;
6493 if (!reader->input_type)
6495 LeaveCriticalSection( &reader->cs );
6496 return WS_E_INVALID_OPERATION;
6499 if ((hr = WsCreateWriter( NULL, 0, &writer, NULL )) != S_OK) goto done;
6500 if ((hr = WsCreateXmlBuffer( heap, NULL, 0, &buffer, NULL )) != S_OK) goto done;
6501 if ((hr = WsSetOutputToBuffer( writer, buffer, NULL, 0, NULL )) != S_OK) goto done;
6502 if ((hr = copy_tree( reader, writer )) == S_OK) *ret = buffer;
6504 done:
6505 if (hr != S_OK) free_xmlbuf( (struct xmlbuf *)buffer );
6506 WsFreeWriter( writer );
6507 LeaveCriticalSection( &reader->cs );
6508 return hr;
6511 HRESULT get_param_desc( const WS_STRUCT_DESCRIPTION *desc, USHORT index, const WS_FIELD_DESCRIPTION **ret )
6513 if (index >= desc->fieldCount) return E_INVALIDARG;
6514 *ret = desc->fields[index];
6515 return S_OK;
6518 static ULONG get_field_size( const WS_FIELD_DESCRIPTION *desc )
6520 WS_READ_OPTION option;
6521 ULONG size;
6523 switch ((option = get_field_read_option( desc->type, desc->options )))
6525 case WS_READ_REQUIRED_POINTER:
6526 case WS_READ_OPTIONAL_POINTER:
6527 case WS_READ_NILLABLE_POINTER:
6528 size = sizeof(void *);
6529 break;
6531 case WS_READ_REQUIRED_VALUE:
6532 case WS_READ_NILLABLE_VALUE:
6533 size = get_type_size( desc->type, desc->typeDescription );
6534 break;
6536 default:
6537 WARN( "unhandled option %u\n", option );
6538 return 0;
6541 return size;
6544 static HRESULT read_param( struct reader *reader, const WS_FIELD_DESCRIPTION *desc, WS_HEAP *heap, void *ret )
6546 if (!ret && !(ret = ws_alloc_zero( heap, get_field_size(desc) ))) return WS_E_QUOTA_EXCEEDED;
6547 return read_type_field( reader, desc, heap, ret, 0 );
6550 static HRESULT read_param_array( struct reader *reader, const WS_FIELD_DESCRIPTION *desc, WS_HEAP *heap,
6551 void **ret, ULONG *count )
6553 if (!ret && !(ret = ws_alloc_zero( heap, sizeof(void **) ))) return WS_E_QUOTA_EXCEEDED;
6554 return read_type_repeating_element( reader, desc, heap, ret, count );
6557 static void set_array_len( const WS_PARAMETER_DESCRIPTION *params, ULONG count, ULONG index, ULONG len,
6558 const void **args )
6560 ULONG i, *ptr;
6561 for (i = 0; i < count; i++)
6563 if (params[i].outputMessageIndex != index || params[i].parameterType != WS_PARAMETER_TYPE_ARRAY_COUNT)
6564 continue;
6565 if ((ptr = *(ULONG **)args[i])) *ptr = len;
6566 break;
6570 HRESULT read_output_params( WS_XML_READER *handle, WS_HEAP *heap, const WS_ELEMENT_DESCRIPTION *desc,
6571 const WS_PARAMETER_DESCRIPTION *params, ULONG count, const void **args )
6573 struct reader *reader = (struct reader *)handle;
6574 const WS_STRUCT_DESCRIPTION *desc_struct;
6575 const WS_FIELD_DESCRIPTION *desc_field;
6576 ULONG i, len;
6577 HRESULT hr;
6579 if (desc->type != WS_STRUCT_TYPE || !(desc_struct = desc->typeDescription)) return E_INVALIDARG;
6581 EnterCriticalSection( &reader->cs );
6583 if (reader->magic != READER_MAGIC)
6585 LeaveCriticalSection( &reader->cs );
6586 return E_INVALIDARG;
6589 if ((hr = start_mapping( reader, WS_ELEMENT_TYPE_MAPPING, desc->elementLocalName, desc->elementNs )) != S_OK)
6590 goto done;
6592 for (i = 0; i < count; i++)
6594 if (params[i].outputMessageIndex == INVALID_PARAMETER_INDEX) continue;
6595 if (params[i].parameterType == WS_PARAMETER_TYPE_MESSAGES)
6597 FIXME( "messages type not supported\n" );
6598 hr = E_NOTIMPL;
6599 goto done;
6601 if ((hr = get_param_desc( desc_struct, params[i].outputMessageIndex, &desc_field )) != S_OK) goto done;
6602 if (params[i].parameterType == WS_PARAMETER_TYPE_NORMAL)
6604 void *ptr = *(void **)args[i];
6605 if ((hr = read_param( reader, desc_field, heap, ptr )) != S_OK) goto done;
6607 else if (params[i].parameterType == WS_PARAMETER_TYPE_ARRAY)
6609 void **ptr = *(void ***)args[i];
6610 if ((hr = read_param_array( reader, desc_field, heap, ptr, &len )) != S_OK) goto done;
6611 set_array_len( params, count, params[i].outputMessageIndex, len, args );
6615 if (desc_struct->structOptions & WS_STRUCT_IGNORE_TRAILING_ELEMENT_CONTENT)
6617 struct node *parent = find_parent( reader );
6618 parent->flags |= NODE_FLAG_IGNORE_TRAILING_ELEMENT_CONTENT;
6621 hr = end_mapping( reader, WS_ELEMENT_TYPE_MAPPING );
6623 done:
6624 LeaveCriticalSection( &reader->cs );
6625 return hr;