windowscodecs: Silence fixme for IID_CMetaBitmapRenderTarget.
[wine.git] / dlls / webservices / reader.c
blob0cd974c9118de9aced9b420cde50ae4c0d94d068
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 <stdlib.h>
21 #include <assert.h>
22 #include <float.h>
23 #include <locale.h>
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winnls.h"
28 #include "webservices.h"
30 #include "wine/debug.h"
31 #include "wine/list.h"
32 #include "webservices_private.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(webservices);
36 ULONG prop_size( const struct prop_desc *desc, ULONG count )
38 ULONG i, ret = count * sizeof(struct prop);
39 for (i = 0; i < count; i++) ret += desc[i].size;
40 return ret;
43 void prop_init( const struct prop_desc *desc, ULONG count, struct prop *prop, void *data )
45 ULONG i;
46 char *ptr = data;
47 for (i = 0; i < count; i++)
49 prop[i].value = ptr;
50 prop[i].size = desc[i].size;
51 prop[i].readonly = desc[i].readonly;
52 prop[i].writeonly = desc[i].writeonly;
53 ptr += prop[i].size;
57 HRESULT prop_set( const struct prop *prop, ULONG count, ULONG id, const void *value, ULONG size )
59 if (id >= count || size != prop[id].size || prop[id].readonly) return E_INVALIDARG;
60 memcpy( prop[id].value, value, size );
61 return S_OK;
64 HRESULT prop_get( const struct prop *prop, ULONG count, ULONG id, void *buf, ULONG size )
66 if (id >= count || size != prop[id].size || prop[id].writeonly) return E_INVALIDARG;
67 memcpy( buf, prop[id].value, prop[id].size );
68 return S_OK;
71 struct node *alloc_node( WS_XML_NODE_TYPE type )
73 struct node *ret;
75 if (!(ret = calloc( 1, sizeof(*ret) ))) return NULL;
76 ret->hdr.node.nodeType = type;
77 list_init( &ret->entry );
78 list_init( &ret->children );
79 return ret;
82 void free_attribute( WS_XML_ATTRIBUTE *attr )
84 if (!attr) return;
85 free_xml_string( attr->prefix );
86 free_xml_string( attr->localName );
87 free_xml_string( attr->ns );
88 free( attr->value );
89 free( attr );
92 void free_node( struct node *node )
94 if (!node) return;
95 switch (node_type( node ))
97 case WS_XML_NODE_TYPE_ELEMENT:
99 WS_XML_ELEMENT_NODE *elem = &node->hdr;
100 ULONG i;
102 for (i = 0; i < elem->attributeCount; i++) free_attribute( elem->attributes[i] );
103 free( elem->attributes );
104 free_xml_string( elem->prefix );
105 free_xml_string( elem->localName );
106 free_xml_string( elem->ns );
107 break;
109 case WS_XML_NODE_TYPE_TEXT:
111 WS_XML_TEXT_NODE *text = (WS_XML_TEXT_NODE *)node;
112 free( text->text );
113 break;
115 case WS_XML_NODE_TYPE_COMMENT:
117 WS_XML_COMMENT_NODE *comment = (WS_XML_COMMENT_NODE *)node;
118 free( comment->value.bytes );
119 break;
121 case WS_XML_NODE_TYPE_CDATA:
122 case WS_XML_NODE_TYPE_END_CDATA:
123 case WS_XML_NODE_TYPE_END_ELEMENT:
124 case WS_XML_NODE_TYPE_EOF:
125 case WS_XML_NODE_TYPE_BOF:
126 break;
128 default:
129 ERR( "unhandled type %u\n", node_type( node ) );
130 break;
132 free( node );
135 void destroy_nodes( struct node *node )
137 struct list *ptr;
139 if (!node) return;
140 while ((ptr = list_head( &node->children )))
142 struct node *child = LIST_ENTRY( ptr, struct node, entry );
143 list_remove( &child->entry );
144 destroy_nodes( child );
146 free_node( node );
149 static WS_XML_ATTRIBUTE *dup_attribute( const WS_XML_ATTRIBUTE *src, WS_XML_WRITER_ENCODING_TYPE enc )
151 WS_XML_ATTRIBUTE *dst;
152 HRESULT hr;
154 if (!(dst = calloc( 1, sizeof(*dst) ))) return NULL;
155 dst->singleQuote = src->singleQuote;
156 dst->isXmlNs = src->isXmlNs;
158 if (src->prefix && !(dst->prefix = dup_xml_string( src->prefix, FALSE ))) goto error;
159 if (src->localName && !(dst->localName = dup_xml_string( src->localName, FALSE ))) goto error;
160 if (src->ns && !(dst->ns = dup_xml_string( src->ns, FALSE ))) goto error;
162 if (src->value)
164 switch (enc)
166 case WS_XML_WRITER_ENCODING_TYPE_BINARY:
167 if ((hr = text_to_text( src->value, NULL, NULL, &dst->value )) != S_OK) goto error;
168 break;
170 case WS_XML_WRITER_ENCODING_TYPE_TEXT:
171 if ((hr = text_to_utf8text( src->value, NULL, NULL, (WS_XML_UTF8_TEXT **)&dst->value )) != S_OK)
172 goto error;
173 break;
175 default:
176 ERR( "unhandled encoding %u\n", enc );
177 goto error;
181 return dst;
183 error:
184 free_attribute( dst );
185 return NULL;
188 static WS_XML_ATTRIBUTE **dup_attributes( WS_XML_ATTRIBUTE * const *src, ULONG count,
189 WS_XML_WRITER_ENCODING_TYPE enc )
191 WS_XML_ATTRIBUTE **dst;
192 ULONG i;
194 if (!(dst = malloc( sizeof(*dst) * count ))) return NULL;
195 for (i = 0; i < count; i++)
197 if (!(dst[i] = dup_attribute( src[i], enc )))
199 for (; i > 0; i--) free_attribute( dst[i - 1] );
200 free( dst );
201 return NULL;
204 return dst;
207 static struct node *dup_element_node( const WS_XML_ELEMENT_NODE *src, WS_XML_WRITER_ENCODING_TYPE enc )
209 struct node *node;
210 WS_XML_ELEMENT_NODE *dst;
211 ULONG count = src->attributeCount;
212 WS_XML_ATTRIBUTE **attrs = src->attributes;
213 const WS_XML_STRING *prefix = (src->prefix && src->prefix->length) ? src->prefix : NULL;
214 const WS_XML_STRING *localname = src->localName;
215 const WS_XML_STRING *ns = src->ns;
217 if (!(node = alloc_node( WS_XML_NODE_TYPE_ELEMENT ))) return NULL;
218 dst = &node->hdr;
220 if (count && !(dst->attributes = dup_attributes( attrs, count, enc ))) goto error;
221 dst->attributeCount = count;
223 if (prefix && !(dst->prefix = dup_xml_string( prefix, FALSE ))) goto error;
224 if (localname && !(dst->localName = dup_xml_string( localname, FALSE ))) goto error;
225 if (ns && !(dst->ns = dup_xml_string( ns, FALSE ))) goto error;
226 return node;
228 error:
229 free_node( node );
230 return NULL;
233 static struct node *dup_text_node( const WS_XML_TEXT_NODE *src, WS_XML_WRITER_ENCODING_TYPE enc )
235 struct node *node;
236 WS_XML_TEXT_NODE *dst;
237 HRESULT hr;
239 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
240 dst = (WS_XML_TEXT_NODE *)node;
241 if (!src->text) return node;
243 switch (enc)
245 case WS_XML_WRITER_ENCODING_TYPE_BINARY:
246 hr = text_to_text( src->text, NULL, NULL, &dst->text );
247 break;
249 case WS_XML_WRITER_ENCODING_TYPE_TEXT:
250 hr = text_to_utf8text( src->text, NULL, NULL, (WS_XML_UTF8_TEXT **)&dst->text );
251 break;
253 default:
254 ERR( "unhandled encoding %u\n", enc );
255 free_node( node );
256 return NULL;
259 if (hr != S_OK)
261 free_node( node );
262 return NULL;
265 return node;
268 static struct node *dup_comment_node( const WS_XML_COMMENT_NODE *src )
270 struct node *node;
271 WS_XML_COMMENT_NODE *dst;
273 if (!(node = alloc_node( WS_XML_NODE_TYPE_COMMENT ))) return NULL;
274 dst = (WS_XML_COMMENT_NODE *)node;
276 if (src->value.length && !(dst->value.bytes = malloc( src->value.length )))
278 free_node( node );
279 return NULL;
281 memcpy( dst->value.bytes, src->value.bytes, src->value.length );
282 dst->value.length = src->value.length;
283 return node;
286 static struct node *dup_node( const struct node *src, WS_XML_WRITER_ENCODING_TYPE enc )
288 switch (node_type( src ))
290 case WS_XML_NODE_TYPE_ELEMENT:
291 return dup_element_node( &src->hdr, enc );
293 case WS_XML_NODE_TYPE_TEXT:
294 return dup_text_node( (const WS_XML_TEXT_NODE *)src, enc );
296 case WS_XML_NODE_TYPE_COMMENT:
297 return dup_comment_node( (const WS_XML_COMMENT_NODE *)src );
299 case WS_XML_NODE_TYPE_CDATA:
300 case WS_XML_NODE_TYPE_END_CDATA:
301 case WS_XML_NODE_TYPE_END_ELEMENT:
302 case WS_XML_NODE_TYPE_EOF:
303 case WS_XML_NODE_TYPE_BOF:
304 return alloc_node( node_type( src ) );
306 default:
307 ERR( "unhandled type %u\n", node_type( src ) );
308 break;
310 return NULL;
313 static HRESULT dup_tree( const struct node *src, WS_XML_WRITER_ENCODING_TYPE enc, struct node **dst )
315 struct node *parent;
316 const struct node *child;
318 if (!*dst && !(*dst = dup_node( src, enc ))) return E_OUTOFMEMORY;
319 parent = *dst;
321 LIST_FOR_EACH_ENTRY( child, &src->children, struct node, entry )
323 HRESULT hr = E_OUTOFMEMORY;
324 struct node *new_child;
326 if (!(new_child = dup_node( child, enc )) || (hr = dup_tree( child, enc, &new_child )) != S_OK)
328 destroy_nodes( *dst );
329 return hr;
331 new_child->parent = parent;
332 list_add_tail( &parent->children, &new_child->entry );
334 return S_OK;
337 static const struct prop_desc reader_props[] =
339 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_MAX_DEPTH */
340 { sizeof(BOOL), FALSE }, /* WS_XML_READER_PROPERTY_ALLOW_FRAGMENT */
341 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_MAX_ATTRIBUTES */
342 { sizeof(BOOL), FALSE }, /* WS_XML_READER_PROPERTY_READ_DECLARATION */
343 { sizeof(WS_CHARSET), FALSE }, /* WS_XML_READER_PROPERTY_CHARSET */
344 { sizeof(ULONGLONG), TRUE }, /* WS_XML_READER_PROPERTY_ROW */
345 { sizeof(ULONGLONG), TRUE }, /* WS_XML_READER_PROPERTY_COLUMN */
346 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_UTF8_TRIM_SIZE */
347 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_STREAM_BUFFER_SIZE */
348 { sizeof(BOOL), TRUE }, /* WS_XML_READER_PROPERTY_IN_ATTRIBUTE */
349 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_STREAM_MAX_ROOT_MIME_PART_SIZE */
350 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_STREAM_MAX_MIME_HEADERS_SIZE */
351 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_MAX_MIME_PARTS */
352 { sizeof(BOOL), FALSE }, /* WS_XML_READER_PROPERTY_ALLOW_INVALID_CHARACTER_REFERENCES */
353 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_MAX_NAMESPACES */
356 enum reader_state
358 READER_STATE_INITIAL,
359 READER_STATE_BOF,
360 READER_STATE_STARTELEMENT,
361 READER_STATE_STARTATTRIBUTE,
362 READER_STATE_STARTCDATA,
363 READER_STATE_CDATA,
364 READER_STATE_TEXT,
365 READER_STATE_ENDELEMENT,
366 READER_STATE_ENDCDATA,
367 READER_STATE_COMMENT,
368 READER_STATE_EOF
371 struct prefix
373 WS_XML_STRING *str;
374 WS_XML_STRING *ns;
377 struct reader
379 ULONG magic;
380 CRITICAL_SECTION cs;
381 ULONG read_size;
382 ULONG read_pos;
383 const unsigned char *read_bufptr;
384 enum reader_state state;
385 struct node *root;
386 struct node *current;
387 ULONG current_attr;
388 struct node *last;
389 struct prefix *prefixes;
390 ULONG nb_prefixes;
391 ULONG nb_prefixes_allocated;
392 WS_XML_READER_ENCODING_TYPE input_enc;
393 WS_CHARSET input_charset;
394 WS_XML_READER_INPUT_TYPE input_type;
395 WS_READ_CALLBACK input_cb;
396 void *input_cb_state;
397 struct xmlbuf *input_buf;
398 unsigned char *input_conv;
399 ULONG input_size;
400 ULONG text_conv_offset;
401 unsigned char *stream_buf;
402 const WS_XML_DICTIONARY *dict_static;
403 WS_XML_DICTIONARY *dict;
404 ULONG prop_count;
405 struct prop prop[ARRAY_SIZE( reader_props )];
408 #define READER_MAGIC (('R' << 24) | ('E' << 16) | ('A' << 8) | 'D')
410 static struct reader *alloc_reader(void)
412 static const ULONG count = ARRAY_SIZE( reader_props );
413 struct reader *ret;
414 ULONG size = sizeof(*ret) + prop_size( reader_props, count );
416 if (!(ret = calloc( 1, size ))) return NULL;
417 if (!(ret->prefixes = calloc( 1, sizeof(*ret->prefixes) )))
419 free( ret );
420 return NULL;
422 ret->nb_prefixes = ret->nb_prefixes_allocated = 1;
424 ret->magic = READER_MAGIC;
425 InitializeCriticalSectionEx( &ret->cs, 0, RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO );
426 ret->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": reader.cs");
428 prop_init( reader_props, count, ret->prop, &ret[1] );
429 ret->prop_count = count;
430 return ret;
433 static void clear_prefixes( struct prefix *prefixes, ULONG count )
435 ULONG i;
436 for (i = 0; i < count; i++)
438 free_xml_string( prefixes[i].str );
439 prefixes[i].str = NULL;
440 free_xml_string( prefixes[i].ns );
441 prefixes[i].ns = NULL;
445 static HRESULT set_prefix( struct prefix *prefix, const WS_XML_STRING *str, const WS_XML_STRING *ns )
447 if (str)
449 free_xml_string( prefix->str );
450 if (!(prefix->str = dup_xml_string( str, FALSE ))) return E_OUTOFMEMORY;
452 if (prefix->ns) free_xml_string( prefix->ns );
453 if (!(prefix->ns = dup_xml_string( ns, FALSE ))) return E_OUTOFMEMORY;
454 return S_OK;
457 static HRESULT bind_prefix( struct reader *reader, const WS_XML_STRING *prefix, const WS_XML_STRING *ns )
459 ULONG i;
460 HRESULT hr;
462 for (i = 0; i < reader->nb_prefixes; i++)
464 if (WsXmlStringEquals( prefix, reader->prefixes[i].str, NULL ) == S_OK)
465 return set_prefix( &reader->prefixes[i], NULL, ns );
467 if (i >= reader->nb_prefixes_allocated)
469 ULONG new_size = reader->nb_prefixes_allocated * 2;
470 struct prefix *tmp = realloc( reader->prefixes, new_size * sizeof(*tmp) );
471 if (!tmp) return E_OUTOFMEMORY;
472 memset( tmp + reader->nb_prefixes_allocated, 0, (new_size - reader->nb_prefixes_allocated) * sizeof(*tmp) );
473 reader->prefixes = tmp;
474 reader->nb_prefixes_allocated = new_size;
476 if ((hr = set_prefix( &reader->prefixes[i], prefix, ns )) != S_OK) return hr;
477 reader->nb_prefixes++;
478 return S_OK;
481 static const WS_XML_STRING *get_namespace( struct reader *reader, const WS_XML_STRING *prefix )
483 ULONG i;
484 for (i = 0; i < reader->nb_prefixes; i++)
486 if (WsXmlStringEquals( prefix, reader->prefixes[i].str, NULL ) == S_OK)
487 return reader->prefixes[i].ns;
489 return NULL;
492 static void read_insert_eof( struct reader *reader, struct node *eof )
494 if (!reader->root) reader->root = eof;
495 else
497 eof->parent = reader->root;
498 list_add_tail( &reader->root->children, &eof->entry );
500 reader->current = reader->last = eof;
503 static void read_insert_bof( struct reader *reader, struct node *bof )
505 reader->root->parent = bof;
506 list_add_tail( &bof->children, &reader->root->entry );
507 reader->current = reader->last = reader->root = bof;
510 static void read_insert_node( struct reader *reader, struct node *parent, struct node *node )
512 node->parent = parent;
513 list_add_before( list_tail( &parent->children ), &node->entry );
514 reader->current = reader->last = node;
517 static void free_reader( struct reader *reader )
519 destroy_nodes( reader->root );
520 clear_prefixes( reader->prefixes, reader->nb_prefixes );
521 free( reader->prefixes );
522 free( reader->stream_buf );
523 free( reader->input_conv );
525 reader->cs.DebugInfo->Spare[0] = 0;
526 DeleteCriticalSection( &reader->cs );
527 free( reader );
530 static HRESULT init_reader( struct reader *reader )
532 static const WS_XML_STRING empty = {0, NULL};
533 struct node *node;
534 HRESULT hr;
536 reader->state = READER_STATE_INITIAL;
537 destroy_nodes( reader->root );
538 reader->root = reader->current = NULL;
539 reader->current_attr = 0;
540 clear_prefixes( reader->prefixes, reader->nb_prefixes );
541 reader->nb_prefixes = 1;
542 if ((hr = bind_prefix( reader, &empty, &empty )) != S_OK) return hr;
544 if (!(node = alloc_node( WS_XML_NODE_TYPE_EOF ))) return E_OUTOFMEMORY;
545 read_insert_eof( reader, node );
546 reader->input_enc = WS_XML_READER_ENCODING_TYPE_TEXT;
547 reader->input_charset = WS_CHARSET_UTF8;
548 reader->dict_static = NULL;
549 reader->dict = NULL;
550 return S_OK;
553 /**************************************************************************
554 * WsCreateReader [webservices.@]
556 HRESULT WINAPI WsCreateReader( const WS_XML_READER_PROPERTY *properties, ULONG count,
557 WS_XML_READER **handle, WS_ERROR *error )
559 struct reader *reader;
560 ULONG i, max_depth = 32, max_attrs = 128, max_ns = 32;
561 BOOL read_decl = TRUE;
562 HRESULT hr;
564 TRACE( "%p %lu %p %p\n", properties, count, handle, error );
565 if (error) FIXME( "ignoring error parameter\n" );
567 if (!handle) return E_INVALIDARG;
568 if (!(reader = alloc_reader())) return E_OUTOFMEMORY;
570 prop_set( reader->prop, reader->prop_count, WS_XML_READER_PROPERTY_MAX_DEPTH, &max_depth, sizeof(max_depth) );
571 prop_set( reader->prop, reader->prop_count, WS_XML_READER_PROPERTY_MAX_ATTRIBUTES, &max_attrs, sizeof(max_attrs) );
572 prop_set( reader->prop, reader->prop_count, WS_XML_READER_PROPERTY_READ_DECLARATION, &read_decl, sizeof(read_decl) );
573 prop_set( reader->prop, reader->prop_count, WS_XML_READER_PROPERTY_MAX_NAMESPACES, &max_ns, sizeof(max_ns) );
575 for (i = 0; i < count; i++)
577 hr = prop_set( reader->prop, reader->prop_count, properties[i].id, properties[i].value,
578 properties[i].valueSize );
579 if (hr != S_OK)
581 free_reader( reader );
582 return hr;
586 if ((hr = init_reader( reader )) != S_OK)
588 free_reader( reader );
589 return hr;
592 TRACE( "created %p\n", reader );
593 *handle = (WS_XML_READER *)reader;
594 return S_OK;
597 /**************************************************************************
598 * WsFreeReader [webservices.@]
600 void WINAPI WsFreeReader( WS_XML_READER *handle )
602 struct reader *reader = (struct reader *)handle;
604 TRACE( "%p\n", handle );
606 if (!reader) return;
608 EnterCriticalSection( &reader->cs );
610 if (reader->magic != READER_MAGIC)
612 LeaveCriticalSection( &reader->cs );
613 return;
616 reader->magic = 0;
618 LeaveCriticalSection( &reader->cs );
619 free_reader( reader );
622 static HRESULT read_more_data( struct reader *reader, ULONG min_size, const WS_ASYNC_CONTEXT *ctx,
623 WS_ERROR *error )
625 ULONG size = 0, max_size;
627 if (reader->read_size - reader->read_pos >= min_size) return S_OK;
628 if (reader->input_type != WS_XML_READER_INPUT_TYPE_STREAM) return WS_E_INVALID_FORMAT;
629 if (min_size > reader->input_size) return WS_E_QUOTA_EXCEEDED;
631 if (reader->read_pos)
633 memmove( reader->stream_buf, reader->stream_buf + reader->read_pos, reader->read_size - reader->read_pos );
634 reader->read_size -= reader->read_pos;
635 reader->read_pos = 0;
637 max_size = reader->input_size - reader->read_size;
639 reader->input_cb( reader->input_cb_state, reader->stream_buf + reader->read_size, max_size, &size, ctx, error );
640 if (size < min_size) return WS_E_QUOTA_EXCEEDED;
641 reader->read_size += size;
642 return S_OK;
645 /**************************************************************************
646 * WsFillReader [webservices.@]
648 HRESULT WINAPI WsFillReader( WS_XML_READER *handle, ULONG min_size, const WS_ASYNC_CONTEXT *ctx,
649 WS_ERROR *error )
651 struct reader *reader = (struct reader *)handle;
652 HRESULT hr;
654 TRACE( "%p %lu %p %p\n", handle, min_size, ctx, error );
655 if (error) FIXME( "ignoring error parameter\n" );
656 if (ctx) FIXME( "ignoring ctx parameter\n" );
658 if (!reader) return E_INVALIDARG;
660 EnterCriticalSection( &reader->cs );
662 if (reader->magic != READER_MAGIC)
664 LeaveCriticalSection( &reader->cs );
665 return E_INVALIDARG;
668 if (reader->input_type == WS_XML_READER_INPUT_TYPE_STREAM)
670 hr = read_more_data( reader, min_size, ctx, error );
672 else
674 reader->read_size = min( min_size, reader->input_size );
675 reader->read_pos = 0;
676 hr = S_OK;
679 LeaveCriticalSection( &reader->cs );
680 TRACE( "returning %#lx\n", hr );
681 return hr;
684 /**************************************************************************
685 * WsGetNamespaceFromPrefix [webservices.@]
687 HRESULT WINAPI WsGetNamespaceFromPrefix( WS_XML_READER *handle, const WS_XML_STRING *prefix,
688 BOOL required, const WS_XML_STRING **ns, WS_ERROR *error )
690 static const WS_XML_STRING xml = {3, (BYTE *)"xml"};
691 static const WS_XML_STRING xmlns = {5, (BYTE *)"xmlns"};
692 static const WS_XML_STRING empty_ns = {0, NULL};
693 static const WS_XML_STRING xml_ns = {36, (BYTE *)"http://www.w3.org/XML/1998/namespace"};
694 static const WS_XML_STRING xmlns_ns = {29, (BYTE *)"http://www.w3.org/2000/xmlns/"};
695 struct reader *reader = (struct reader *)handle;
696 BOOL found = FALSE;
697 HRESULT hr = S_OK;
699 TRACE( "%p %s %d %p %p\n", handle, debugstr_xmlstr(prefix), required, ns, error );
700 if (error) FIXME( "ignoring error parameter\n" );
702 if (!reader || !prefix || !ns) return E_INVALIDARG;
704 EnterCriticalSection( &reader->cs );
706 if (reader->magic != READER_MAGIC)
708 LeaveCriticalSection( &reader->cs );
709 return E_INVALIDARG;
712 if (reader->state != READER_STATE_STARTELEMENT) hr = WS_E_INVALID_OPERATION;
713 else if (!prefix->length)
715 *ns = &empty_ns;
716 found = TRUE;
718 else if (WsXmlStringEquals( prefix, &xml, NULL ) == S_OK)
720 *ns = &xml_ns;
721 found = TRUE;
723 else if (WsXmlStringEquals( prefix, &xmlns, NULL ) == S_OK)
725 *ns = &xmlns_ns;
726 found = TRUE;
728 else
730 WS_XML_ELEMENT_NODE *elem = &reader->current->hdr;
731 ULONG i;
733 for (i = 0; i < elem->attributeCount; i++)
735 if (!elem->attributes[i]->isXmlNs) continue;
736 if (WsXmlStringEquals( prefix, elem->attributes[i]->prefix, NULL ) == S_OK)
738 *ns = elem->attributes[i]->ns;
739 found = TRUE;
740 break;
745 LeaveCriticalSection( &reader->cs );
747 if (hr == S_OK && !found)
749 if (required) hr = WS_E_INVALID_FORMAT;
750 else
752 *ns = NULL;
753 hr = S_FALSE;
757 TRACE( "returning %#lx\n", hr );
758 return hr;
761 /**************************************************************************
762 * WsGetReaderNode [webservices.@]
764 HRESULT WINAPI WsGetReaderNode( WS_XML_READER *handle, const WS_XML_NODE **node,
765 WS_ERROR *error )
767 struct reader *reader = (struct reader *)handle;
768 HRESULT hr = S_OK;
770 TRACE( "%p %p %p\n", handle, node, error );
771 if (error) FIXME( "ignoring error parameter\n" );
773 if (!reader || !node) return E_INVALIDARG;
775 EnterCriticalSection( &reader->cs );
777 if (reader->magic != READER_MAGIC)
779 LeaveCriticalSection( &reader->cs );
780 return E_INVALIDARG;
783 *node = &reader->current->hdr.node;
785 LeaveCriticalSection( &reader->cs );
786 TRACE( "returning %#lx\n", hr );
787 return S_OK;
790 static HRESULT get_charset( struct reader *reader, void *buf, ULONG size )
792 if (!buf || size != sizeof(reader->input_charset)) return E_INVALIDARG;
793 if (!reader->input_charset) return WS_E_INVALID_FORMAT;
794 *(WS_CHARSET *)buf = reader->input_charset;
795 return S_OK;
798 /**************************************************************************
799 * WsGetReaderProperty [webservices.@]
801 HRESULT WINAPI WsGetReaderProperty( WS_XML_READER *handle, WS_XML_READER_PROPERTY_ID id,
802 void *buf, ULONG size, WS_ERROR *error )
804 struct reader *reader = (struct reader *)handle;
805 HRESULT hr;
807 TRACE( "%p %u %p %lu %p\n", handle, id, buf, size, error );
808 if (error) FIXME( "ignoring error parameter\n" );
810 if (!reader) return E_INVALIDARG;
812 EnterCriticalSection( &reader->cs );
814 if (reader->magic != READER_MAGIC)
816 LeaveCriticalSection( &reader->cs );
817 return E_INVALIDARG;
820 if (!reader->input_type) hr = WS_E_INVALID_OPERATION;
821 else if (id == WS_XML_READER_PROPERTY_CHARSET) hr = get_charset( reader, buf, size );
822 else hr = prop_get( reader->prop, reader->prop_count, id, buf, size );
824 LeaveCriticalSection( &reader->cs );
825 TRACE( "returning %#lx\n", hr );
826 return hr;
829 /**************************************************************************
830 * WsGetXmlAttribute [webservices.@]
832 HRESULT WINAPI WsGetXmlAttribute( WS_XML_READER *handle, const WS_XML_STRING *attr,
833 WS_HEAP *heap, WCHAR **str, ULONG *len, WS_ERROR *error )
835 FIXME( "%p %s %p %p %p %p: stub\n", handle, debugstr_xmlstr(attr), heap, str, len, error );
836 return E_NOTIMPL;
839 WS_XML_UTF8_TEXT *alloc_utf8_text( const BYTE *data, ULONG len )
841 WS_XML_UTF8_TEXT *ret;
843 if (!(ret = malloc( sizeof(*ret) + len ))) return NULL;
844 ret->text.textType = WS_XML_TEXT_TYPE_UTF8;
845 ret->value.length = len;
846 ret->value.bytes = len ? (BYTE *)(ret + 1) : NULL;
847 ret->value.dictionary = NULL;
848 ret->value.id = 0;
849 if (data) memcpy( ret->value.bytes, data, len );
850 return ret;
853 WS_XML_UTF16_TEXT *alloc_utf16_text( const BYTE *data, ULONG len )
855 WS_XML_UTF16_TEXT *ret;
857 if (!(ret = malloc( sizeof(*ret) + len ))) return NULL;
858 ret->text.textType = WS_XML_TEXT_TYPE_UTF16;
859 ret->byteCount = len;
860 ret->bytes = len ? (BYTE *)(ret + 1) : NULL;
861 if (data) memcpy( ret->bytes, data, len );
862 return ret;
865 WS_XML_BASE64_TEXT *alloc_base64_text( const BYTE *data, ULONG len )
867 WS_XML_BASE64_TEXT *ret;
869 if (!(ret = malloc( sizeof(*ret) + len ))) return NULL;
870 ret->text.textType = WS_XML_TEXT_TYPE_BASE64;
871 ret->length = len;
872 ret->bytes = len ? (BYTE *)(ret + 1) : NULL;
873 if (data) memcpy( ret->bytes, data, len );
874 return ret;
877 WS_XML_BOOL_TEXT *alloc_bool_text( BOOL value )
879 WS_XML_BOOL_TEXT *ret;
881 if (!(ret = malloc( sizeof(*ret) ))) return NULL;
882 ret->text.textType = WS_XML_TEXT_TYPE_BOOL;
883 ret->value = value;
884 return ret;
887 WS_XML_INT32_TEXT *alloc_int32_text( INT32 value )
889 WS_XML_INT32_TEXT *ret;
891 if (!(ret = malloc( sizeof(*ret) ))) return NULL;
892 ret->text.textType = WS_XML_TEXT_TYPE_INT32;
893 ret->value = value;
894 return ret;
897 WS_XML_INT64_TEXT *alloc_int64_text( INT64 value )
899 WS_XML_INT64_TEXT *ret;
901 if (!(ret = malloc( sizeof(*ret) ))) return NULL;
902 ret->text.textType = WS_XML_TEXT_TYPE_INT64;
903 ret->value = value;
904 return ret;
907 WS_XML_UINT64_TEXT *alloc_uint64_text( UINT64 value )
909 WS_XML_UINT64_TEXT *ret;
911 if (!(ret = malloc( sizeof(*ret) ))) return NULL;
912 ret->text.textType = WS_XML_TEXT_TYPE_UINT64;
913 ret->value = value;
914 return ret;
917 static WS_XML_FLOAT_TEXT *alloc_float_text( float value )
919 WS_XML_FLOAT_TEXT *ret;
921 if (!(ret = malloc( sizeof(*ret) ))) return NULL;
922 ret->text.textType = WS_XML_TEXT_TYPE_FLOAT;
923 ret->value = value;
924 return ret;
927 WS_XML_DOUBLE_TEXT *alloc_double_text( double value )
929 WS_XML_DOUBLE_TEXT *ret;
931 if (!(ret = malloc( sizeof(*ret) ))) return NULL;
932 ret->text.textType = WS_XML_TEXT_TYPE_DOUBLE;
933 ret->value = value;
934 return ret;
937 WS_XML_GUID_TEXT *alloc_guid_text( const GUID *value )
939 WS_XML_GUID_TEXT *ret;
941 if (!(ret = malloc( sizeof(*ret) ))) return NULL;
942 ret->text.textType = WS_XML_TEXT_TYPE_GUID;
943 ret->value = *value;
944 return ret;
947 WS_XML_UNIQUE_ID_TEXT *alloc_unique_id_text( const GUID *value )
949 WS_XML_UNIQUE_ID_TEXT *ret;
951 if (!(ret = malloc( sizeof(*ret) ))) return NULL;
952 ret->text.textType = WS_XML_TEXT_TYPE_UNIQUE_ID;
953 ret->value = *value;
954 return ret;
957 WS_XML_DATETIME_TEXT *alloc_datetime_text( const WS_DATETIME *value )
959 WS_XML_DATETIME_TEXT *ret;
961 if (!(ret = malloc( sizeof(*ret) ))) return NULL;
962 ret->text.textType = WS_XML_TEXT_TYPE_DATETIME;
963 ret->value = *value;
964 return ret;
967 static inline BOOL read_end_of_data( struct reader *reader )
969 return (read_more_data( reader, 1, NULL, NULL ) != S_OK);
972 static inline const unsigned char *read_current_ptr( struct reader *reader )
974 return &reader->read_bufptr[reader->read_pos];
977 static inline void read_skip( struct reader *reader, unsigned int count )
979 assert( reader->read_pos + count <= reader->read_size );
980 reader->read_pos += count;
983 static inline HRESULT read_peek( struct reader *reader, unsigned char *bytes, unsigned int len )
985 HRESULT hr;
986 if ((hr = read_more_data( reader, len, NULL, NULL )) != S_OK) return hr;
987 memcpy( bytes, read_current_ptr( reader ), len );
988 return S_OK;
991 static inline HRESULT read_byte( struct reader *reader, unsigned char *byte )
993 HRESULT hr;
994 if ((hr = read_more_data( reader, 1, NULL, NULL )) != S_OK) return hr;
995 *byte = *read_current_ptr( reader );
996 read_skip( reader, 1 );
997 return S_OK;
1000 static inline HRESULT read_bytes( struct reader *reader, unsigned char *bytes, unsigned int len )
1002 HRESULT hr;
1003 if ((hr = read_more_data( reader, len, NULL, NULL )) != S_OK) return hr;
1004 memcpy( bytes, read_current_ptr( reader ), len );
1005 read_skip( reader, len );
1006 return S_OK;
1009 /* UTF-8 support based on libs/wine/utf8.c */
1011 /* number of following bytes in sequence based on first byte value (for bytes above 0x7f) */
1012 static const char utf8_length[128] =
1014 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x80-0x8f */
1015 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x90-0x9f */
1016 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xa0-0xaf */
1017 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xb0-0xbf */
1018 0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xc0-0xcf */
1019 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xd0-0xdf */
1020 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, /* 0xe0-0xef */
1021 3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0 /* 0xf0-0xff */
1024 /* first byte mask depending on UTF-8 sequence length */
1025 static const unsigned char utf8_mask[4] = { 0x7f, 0x1f, 0x0f, 0x07 };
1027 /* minimum Unicode value depending on UTF-8 sequence length */
1028 static const unsigned int utf8_minval[4] = { 0x0, 0x80, 0x800, 0x10000 };
1030 static inline HRESULT read_utf8_char( struct reader *reader, unsigned int *ret, unsigned int *skip )
1032 unsigned int len;
1033 unsigned char ch;
1034 const unsigned char *end;
1035 HRESULT hr;
1037 if ((hr = read_more_data( reader, 1, NULL, NULL )) != S_OK) return hr;
1038 ch = *read_current_ptr( reader );
1039 if (ch < 0x80)
1041 *ret = ch;
1042 *skip = 1;
1043 return S_OK;
1046 len = utf8_length[ch - 0x80];
1047 if ((hr = read_more_data( reader, len, NULL, NULL )) != S_OK) return hr;
1048 end = read_current_ptr( reader ) + len + 1;
1049 *ret = ch & utf8_mask[len];
1051 switch (len)
1053 case 3:
1054 if ((ch = end[-3] ^ 0x80) >= 0x40) break;
1055 *ret = (*ret << 6) | ch;
1056 case 2:
1057 if ((ch = end[-2] ^ 0x80) >= 0x40) break;
1058 *ret = (*ret << 6) | ch;
1059 case 1:
1060 if ((ch = end[-1] ^ 0x80) >= 0x40) break;
1061 *ret = (*ret << 6) | ch;
1062 if (*ret < utf8_minval[len]) break;
1063 *skip = len + 1;
1064 return S_OK;
1067 return WS_E_INVALID_FORMAT;
1070 static inline BOOL read_isnamechar( unsigned int ch )
1072 /* FIXME: incomplete */
1073 return (ch >= 'A' && ch <= 'Z') ||
1074 (ch >= 'a' && ch <= 'z') ||
1075 (ch >= '0' && ch <= '9') ||
1076 ch == '_' || ch == '-' || ch == '.' || ch == ':';
1079 static inline BOOL read_isspace( unsigned int ch )
1081 return ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n';
1084 static inline void read_skip_whitespace( struct reader *reader )
1086 for (;;)
1088 if (read_more_data( reader, 1, NULL, NULL ) != S_OK || !read_isspace( *read_current_ptr( reader ) )) break;
1089 read_skip( reader, 1 );
1093 static inline HRESULT read_cmp( struct reader *reader, const char *str, int len )
1095 const unsigned char *ptr;
1096 HRESULT hr;
1098 if (len < 0) len = strlen( str );
1099 if ((hr = read_more_data( reader, len, NULL, NULL )) != S_OK) return hr;
1101 ptr = read_current_ptr( reader );
1102 while (len--)
1104 if (*str != *ptr) return WS_E_INVALID_FORMAT;
1105 str++; ptr++;
1107 return S_OK;
1110 static HRESULT read_xmldecl( struct reader *reader )
1112 HRESULT hr;
1114 if ((hr = read_more_data( reader, 1, NULL, NULL )) != S_OK) return hr;
1115 if (*read_current_ptr( reader ) != '<' || (hr = read_cmp( reader, "<?", 2 )) != S_OK)
1117 reader->state = READER_STATE_BOF;
1118 return S_OK;
1120 if ((hr = read_cmp( reader, "<?xml ", 6 )) != S_OK) return hr;
1121 read_skip( reader, 6 );
1123 /* FIXME: parse attributes */
1124 for (;;)
1126 if (read_more_data( reader, 1, NULL, NULL ) != S_OK || *read_current_ptr( reader ) == '?' ) break;
1127 read_skip( reader, 1 );
1130 if ((hr = read_cmp( reader, "?>", 2 )) != S_OK) return hr;
1131 read_skip( reader, 2 );
1133 reader->state = READER_STATE_BOF;
1134 return S_OK;
1137 HRESULT append_attribute( WS_XML_ELEMENT_NODE *elem, WS_XML_ATTRIBUTE *attr )
1139 if (elem->attributeCount)
1141 WS_XML_ATTRIBUTE **tmp;
1142 if (!(tmp = realloc( elem->attributes, (elem->attributeCount + 1) * sizeof(attr) ))) return E_OUTOFMEMORY;
1143 elem->attributes = tmp;
1145 else if (!(elem->attributes = malloc( sizeof(attr) ))) return E_OUTOFMEMORY;
1146 elem->attributes[elem->attributeCount++] = attr;
1147 return S_OK;
1150 static inline void init_xml_string( BYTE *bytes, ULONG len, WS_XML_STRING *str )
1152 str->length = len;
1153 str->bytes = bytes;
1154 str->dictionary = NULL;
1155 str->id = 0;
1158 static HRESULT split_qname( const BYTE *str, ULONG len, WS_XML_STRING *prefix, WS_XML_STRING *localname )
1160 BYTE *prefix_bytes = NULL, *localname_bytes = (BYTE *)str, *ptr = (BYTE *)str;
1161 ULONG prefix_len = 0, localname_len = len;
1163 while (len--)
1165 if (*ptr == ':')
1167 if (ptr == str) return WS_E_INVALID_FORMAT;
1168 prefix_bytes = (BYTE *)str;
1169 prefix_len = ptr - str;
1170 localname_bytes = ptr + 1;
1171 localname_len = len;
1172 break;
1174 ptr++;
1176 if (!localname_len) return WS_E_INVALID_FORMAT;
1178 init_xml_string( prefix_bytes, prefix_len, prefix );
1179 init_xml_string( localname_bytes, localname_len, localname );
1180 return S_OK;
1183 static HRESULT parse_qname( const BYTE *str, ULONG len, WS_XML_STRING **prefix_ret, WS_XML_STRING **localname_ret )
1185 WS_XML_STRING prefix, localname;
1186 HRESULT hr;
1188 if ((hr = split_qname( str, len, &prefix, &localname )) != S_OK) return hr;
1189 if (!(*prefix_ret = alloc_xml_string( NULL, prefix.length ))) return E_OUTOFMEMORY;
1190 if (!(*localname_ret = dup_xml_string( &localname, FALSE )))
1192 free_xml_string( *prefix_ret );
1193 return E_OUTOFMEMORY;
1195 memcpy( (*prefix_ret)->bytes, prefix.bytes, prefix.length );
1196 if (prefix.length && add_xml_string( *prefix_ret ) != S_OK) WARN( "prefix not added to dictionary\n" );
1197 return S_OK;
1200 static int codepoint_to_utf8( int cp, unsigned char *dst )
1202 if (!cp) return -1;
1203 if (cp < 0x80)
1205 *dst = cp;
1206 return 1;
1208 if (cp < 0x800)
1210 dst[1] = 0x80 | (cp & 0x3f);
1211 cp >>= 6;
1212 dst[0] = 0xc0 | cp;
1213 return 2;
1215 if ((cp >= 0xd800 && cp <= 0xdfff) || cp == 0xfffe || cp == 0xffff) return -1;
1216 if (cp < 0x10000)
1218 dst[2] = 0x80 | (cp & 0x3f);
1219 cp >>= 6;
1220 dst[1] = 0x80 | (cp & 0x3f);
1221 cp >>= 6;
1222 dst[0] = 0xe0 | cp;
1223 return 3;
1225 if (cp >= 0x110000) return -1;
1226 dst[3] = 0x80 | (cp & 0x3f);
1227 cp >>= 6;
1228 dst[2] = 0x80 | (cp & 0x3f);
1229 cp >>= 6;
1230 dst[1] = 0x80 | (cp & 0x3f);
1231 cp >>= 6;
1232 dst[0] = 0xf0 | cp;
1233 return 4;
1236 static HRESULT decode_text( const unsigned char *str, ULONG len, unsigned char *ret, ULONG *ret_len )
1238 const unsigned char *p = str;
1239 unsigned char *q = ret;
1241 *ret_len = 0;
1242 while (len)
1244 if (*p == '&')
1246 p++; len--;
1247 if (!len) return WS_E_INVALID_FORMAT;
1249 if (len >= 3 && !memcmp( p, "lt;", 3 ))
1251 *q++ = '<';
1252 p += 3;
1253 len -= 3;
1255 else if (len >= 3 && !memcmp( p, "gt;", 3 ))
1257 *q++ = '>';
1258 p += 3;
1259 len -= 3;
1261 else if (len >= 5 && !memcmp( p, "quot;", 5 ))
1263 *q++ = '"';
1264 p += 5;
1265 len -= 5;
1267 else if (len >= 4 && !memcmp( p, "amp;", 4 ))
1269 *q++ = '&';
1270 p += 4;
1271 len -= 4;
1273 else if (len >= 5 && !memcmp( p, "apos;", 5 ))
1275 *q++ = '\'';
1276 p += 5;
1277 len -= 5;
1279 else if (*p == '#')
1281 ULONG start, nb_digits, i;
1282 int len_utf8, cp = 0;
1284 p++; len--;
1285 if (!len) return WS_E_INVALID_FORMAT;
1286 if (*p == 'x')
1288 p++; len--;
1290 start = len;
1291 while (len && isxdigit( *p )) { p++; len--; };
1292 if (!len) return WS_E_INVALID_FORMAT;
1294 p -= nb_digits = start - len;
1295 if (!nb_digits || nb_digits > 6 || p[nb_digits] != ';') return WS_E_INVALID_FORMAT;
1296 for (i = 0; i < nb_digits; i++)
1298 cp *= 16;
1299 if (*p >= '0' && *p <= '9') cp += *p - '0';
1300 else if (*p >= 'a' && *p <= 'f') cp += *p - 'a' + 10;
1301 else cp += *p - 'A' + 10;
1302 p++;
1305 else if (isdigit( *p ))
1307 while (len && *p == '0') { p++; len--; };
1308 if (!len) return WS_E_INVALID_FORMAT;
1310 start = len;
1311 while (len && isdigit( *p )) { p++; len--; };
1312 if (!len) return WS_E_INVALID_FORMAT;
1314 p -= nb_digits = start - len;
1315 if (!nb_digits || nb_digits > 7 || p[nb_digits] != ';') return WS_E_INVALID_FORMAT;
1316 for (i = 0; i < nb_digits; i++)
1318 cp *= 10;
1319 cp += *p - '0';
1320 p++;
1323 else return WS_E_INVALID_FORMAT;
1324 p++; len--;
1325 if ((len_utf8 = codepoint_to_utf8( cp, q )) < 0) return WS_E_INVALID_FORMAT;
1326 *ret_len += len_utf8;
1327 q += len_utf8;
1328 continue;
1330 else return WS_E_INVALID_FORMAT;
1332 else
1334 *q++ = *p++;
1335 len--;
1337 *ret_len += 1;
1339 return S_OK;
1342 static HRESULT read_attribute_value_text( struct reader *reader, WS_XML_ATTRIBUTE *attr )
1344 WS_XML_UTF8_TEXT *utf8;
1345 unsigned int len, ch, skip, quote;
1346 const unsigned char *start;
1347 HRESULT hr;
1349 read_skip_whitespace( reader );
1350 if ((hr = read_cmp( reader, "=", 1 )) != S_OK) return hr;
1351 read_skip( reader, 1 );
1353 read_skip_whitespace( reader );
1354 if ((hr = read_cmp( reader, "\"", 1 )) != S_OK && (hr = read_cmp( reader, "'", 1 )) != S_OK) return hr;
1355 if ((hr = read_utf8_char( reader, &quote, &skip )) != S_OK) return hr;
1356 read_skip( reader, 1 );
1358 len = 0;
1359 start = read_current_ptr( reader );
1360 for (;;)
1362 if ((hr = read_utf8_char( reader, &ch, &skip )) != S_OK) return hr;
1363 if (ch == quote) break;
1364 read_skip( reader, skip );
1365 len += skip;
1367 read_skip( reader, 1 );
1369 if (attr->isXmlNs)
1371 if (!(attr->ns = alloc_xml_string( start, len ))) return E_OUTOFMEMORY;
1372 if ((hr = bind_prefix( reader, attr->prefix, attr->ns )) != S_OK) return hr;
1373 if (!(utf8 = alloc_utf8_text( NULL, 0 ))) return E_OUTOFMEMORY;
1375 else
1377 if (!(utf8 = alloc_utf8_text( NULL, len ))) return E_OUTOFMEMORY;
1378 if ((hr = decode_text( start, len, utf8->value.bytes, &utf8->value.length )) != S_OK)
1380 free( utf8 );
1381 return hr;
1385 attr->value = &utf8->text;
1386 attr->singleQuote = (quote == '\'');
1387 return S_OK;
1390 static inline BOOL is_text_type( unsigned char type )
1392 return (type >= RECORD_ZERO_TEXT && type <= RECORD_QNAME_DICTIONARY_TEXT_WITH_ENDELEMENT);
1395 static HRESULT read_int31( struct reader *reader, ULONG *len )
1397 unsigned char byte;
1398 HRESULT hr;
1400 if ((hr = read_byte( reader, &byte )) != S_OK) return hr;
1401 *len = byte & 0x7f;
1402 if (!(byte & 0x80)) return S_OK;
1404 if ((hr = read_byte( reader, &byte )) != S_OK) return hr;
1405 *len += (byte & 0x7f) << 7;
1406 if (!(byte & 0x80)) return S_OK;
1408 if ((hr = read_byte( reader, &byte )) != S_OK) return hr;
1409 *len += (byte & 0x7f) << 14;
1410 if (!(byte & 0x80)) return S_OK;
1412 if ((hr = read_byte( reader, &byte )) != S_OK) return hr;
1413 *len += (byte & 0x7f) << 21;
1414 if (!(byte & 0x80)) return S_OK;
1416 if ((hr = read_byte( reader, &byte )) != S_OK) return hr;
1417 *len += (byte & 0x07) << 28;
1418 return S_OK;
1421 static HRESULT read_string( struct reader *reader, WS_XML_STRING **str )
1423 ULONG len;
1424 HRESULT hr;
1425 if ((hr = read_int31( reader, &len )) != S_OK) return hr;
1426 if (!(*str = alloc_xml_string( NULL, len ))) return E_OUTOFMEMORY;
1427 if ((hr = read_bytes( reader, (*str)->bytes, len )) == S_OK)
1429 if (add_xml_string( *str ) != S_OK) WARN( "string not added to dictionary\n" );
1430 return S_OK;
1432 free_xml_string( *str );
1433 return hr;
1436 static HRESULT read_dict_string( struct reader *reader, WS_XML_STRING **str )
1438 const WS_XML_DICTIONARY *dict;
1439 HRESULT hr;
1440 ULONG id;
1442 if ((hr = read_int31( reader, &id )) != S_OK) return hr;
1443 dict = (id & 1) ? reader->dict : reader->dict_static;
1444 if (!dict || (id >>= 1) >= dict->stringCount) return WS_E_INVALID_FORMAT;
1445 if (!(*str = alloc_xml_string( NULL, 0 ))) return E_OUTOFMEMORY;
1446 *(*str) = dict->strings[id];
1447 return S_OK;
1450 static HRESULT read_datetime( struct reader *reader, WS_DATETIME *ret )
1452 UINT64 val;
1453 HRESULT hr;
1455 if ((hr = read_bytes( reader, (unsigned char *)&val, sizeof(val) )) != S_OK) return hr;
1457 if ((val & 0x03) == 1) ret->format = WS_DATETIME_FORMAT_UTC;
1458 else if ((val & 0x03) == 2) ret->format = WS_DATETIME_FORMAT_LOCAL;
1459 else ret->format = WS_DATETIME_FORMAT_NONE;
1461 if ((ret->ticks = val >> 2) > TICKS_MAX) return WS_E_INVALID_FORMAT;
1462 return S_OK;
1465 static HRESULT lookup_string( struct reader *reader, ULONG id, const WS_XML_STRING **ret )
1467 const WS_XML_DICTIONARY *dict = (id & 1) ? reader->dict : reader->dict_static;
1468 if (!dict || (id >>= 1) >= dict->stringCount) return WS_E_INVALID_FORMAT;
1469 *ret = &dict->strings[id];
1470 return S_OK;
1473 static HRESULT read_attribute_value_bin( struct reader *reader, WS_XML_ATTRIBUTE *attr )
1475 WS_XML_UTF8_TEXT *text_utf8 = NULL;
1476 WS_XML_BASE64_TEXT *text_base64 = NULL;
1477 WS_XML_INT32_TEXT *text_int32;
1478 WS_XML_INT64_TEXT *text_int64;
1479 WS_XML_BOOL_TEXT *text_bool;
1480 const WS_XML_STRING *str;
1481 unsigned char type;
1482 UINT8 val_uint8;
1483 UINT16 val_uint16;
1484 INT32 val_int32;
1485 ULONG len = 0, id;
1486 GUID guid;
1487 HRESULT hr;
1489 if ((hr = read_peek( reader, &type, 1 )) != S_OK) return hr;
1490 if (!is_text_type( type )) return WS_E_INVALID_FORMAT;
1491 read_skip( reader, 1 );
1493 switch (type)
1495 case RECORD_ZERO_TEXT:
1497 if (!(text_int32 = alloc_int32_text( 0 ))) return E_OUTOFMEMORY;
1498 attr->value = &text_int32->text;
1499 return S_OK;
1501 case RECORD_ONE_TEXT:
1503 if (!(text_int32 = alloc_int32_text( 1 ))) return E_OUTOFMEMORY;
1504 attr->value = &text_int32->text;
1505 return S_OK;
1507 case RECORD_FALSE_TEXT:
1509 if (!(text_bool = alloc_bool_text( FALSE ))) return E_OUTOFMEMORY;
1510 attr->value = &text_bool->text;
1511 return S_OK;
1513 case RECORD_TRUE_TEXT:
1515 if (!(text_bool = alloc_bool_text( TRUE ))) return E_OUTOFMEMORY;
1516 attr->value = &text_bool->text;
1517 return S_OK;
1519 case RECORD_INT8_TEXT:
1521 INT8 val_int8;
1522 if ((hr = read_byte( reader, (unsigned char *)&val_int8 )) != S_OK) return hr;
1523 if (!(text_int64 = alloc_int64_text( val_int8 ))) return E_OUTOFMEMORY;
1524 attr->value = &text_int64->text;
1525 return S_OK;
1527 case RECORD_INT16_TEXT:
1529 INT16 val_int16;
1530 if ((hr = read_bytes( reader, (unsigned char *)&val_int16, sizeof(val_int16) )) != S_OK) return hr;
1531 if (!(text_int64 = alloc_int64_text( val_int16 ))) return E_OUTOFMEMORY;
1532 attr->value = &text_int64->text;
1533 return S_OK;
1535 case RECORD_INT32_TEXT:
1536 if ((hr = read_bytes( reader, (unsigned char *)&val_int32, sizeof(val_int32) )) != S_OK) return hr;
1537 if (!(text_int64 = alloc_int64_text( val_int32 ))) return E_OUTOFMEMORY;
1538 attr->value = &text_int64->text;
1539 return S_OK;
1541 case RECORD_INT64_TEXT:
1543 INT64 val_int64;
1544 if ((hr = read_bytes( reader, (unsigned char *)&val_int64, sizeof(val_int64) )) != S_OK) return hr;
1545 if (!(text_int64 = alloc_int64_text( val_int64 ))) return E_OUTOFMEMORY;
1546 attr->value = &text_int64->text;
1547 return S_OK;
1549 case RECORD_FLOAT_TEXT:
1551 WS_XML_FLOAT_TEXT *text_float;
1552 float val_float;
1554 if ((hr = read_bytes( reader, (unsigned char *)&val_float, sizeof(val_float) )) != S_OK) return hr;
1555 if (!(text_float = alloc_float_text( val_float ))) return E_OUTOFMEMORY;
1556 attr->value = &text_float->text;
1557 return S_OK;
1559 case RECORD_DOUBLE_TEXT:
1561 WS_XML_DOUBLE_TEXT *text_double;
1562 double val_double;
1564 if ((hr = read_bytes( reader, (unsigned char *)&val_double, sizeof(val_double) )) != S_OK) return hr;
1565 if (!(text_double = alloc_double_text( val_double ))) return E_OUTOFMEMORY;
1566 attr->value = &text_double->text;
1567 return S_OK;
1569 case RECORD_DATETIME_TEXT:
1571 WS_XML_DATETIME_TEXT *text_datetime;
1572 WS_DATETIME datetime;
1574 if ((hr = read_datetime( reader, &datetime )) != S_OK) return hr;
1575 if (!(text_datetime = alloc_datetime_text( &datetime ))) return E_OUTOFMEMORY;
1576 attr->value = &text_datetime->text;
1577 return S_OK;
1579 case RECORD_CHARS8_TEXT:
1580 if ((hr = read_byte( reader, (unsigned char *)&val_uint8 )) != S_OK) return hr;
1581 len = val_uint8;
1582 break;
1584 case RECORD_CHARS16_TEXT:
1585 if ((hr = read_bytes( reader, (unsigned char *)&val_uint16, sizeof(val_uint16) )) != S_OK) return hr;
1586 len = val_uint16;
1587 break;
1589 case RECORD_CHARS32_TEXT:
1590 if ((hr = read_bytes( reader, (unsigned char *)&val_int32, sizeof(val_int32) )) != S_OK) return hr;
1591 if (val_int32 < 0) return WS_E_INVALID_FORMAT;
1592 len = val_int32;
1593 break;
1595 case RECORD_BYTES8_TEXT:
1596 if ((hr = read_byte( reader, (unsigned char *)&val_uint8 )) != S_OK) return hr;
1597 if (!(text_base64 = alloc_base64_text( NULL, val_uint8 ))) return E_OUTOFMEMORY;
1598 if ((hr = read_bytes( reader, text_base64->bytes, val_uint8 )) != S_OK)
1600 free( text_base64 );
1601 return hr;
1603 break;
1605 case RECORD_BYTES16_TEXT:
1606 if ((hr = read_bytes( reader, (unsigned char *)&val_uint16, sizeof(val_uint16) )) != S_OK) return hr;
1607 if (!(text_base64 = alloc_base64_text( NULL, val_uint16 ))) return E_OUTOFMEMORY;
1608 if ((hr = read_bytes( reader, text_base64->bytes, val_uint16 )) != S_OK)
1610 free( text_base64 );
1611 return hr;
1613 break;
1615 case RECORD_BYTES32_TEXT:
1616 if ((hr = read_bytes( reader, (unsigned char *)&val_int32, sizeof(val_int32) )) != S_OK) return hr;
1617 if (val_int32 < 0) return WS_E_INVALID_FORMAT;
1618 if (!(text_base64 = alloc_base64_text( NULL, val_int32 ))) return E_OUTOFMEMORY;
1619 if ((hr = read_bytes( reader, text_base64->bytes, val_int32 )) != S_OK)
1621 free( text_base64 );
1622 return hr;
1624 break;
1626 case RECORD_EMPTY_TEXT:
1627 break;
1629 case RECORD_DICTIONARY_TEXT:
1630 if ((hr = read_int31( reader, &id )) != S_OK) return hr;
1631 if ((hr = lookup_string( reader, id, &str )) != S_OK) return hr;
1632 if (!(text_utf8 = alloc_utf8_text( str->bytes, str->length ))) return E_OUTOFMEMORY;
1633 break;
1635 case RECORD_UNIQUE_ID_TEXT:
1637 WS_XML_UNIQUE_ID_TEXT *text_unique_id;
1638 if ((hr = read_bytes( reader, (unsigned char *)&guid, sizeof(guid) )) != S_OK) return hr;
1639 if (!(text_unique_id = alloc_unique_id_text( &guid ))) return E_OUTOFMEMORY;
1640 attr->value = &text_unique_id->text;
1641 return S_OK;
1643 case RECORD_GUID_TEXT:
1645 WS_XML_GUID_TEXT *guid_text;
1646 if ((hr = read_bytes( reader, (unsigned char *)&guid, sizeof(guid) )) != S_OK) return hr;
1647 if (!(guid_text = alloc_guid_text( &guid ))) return E_OUTOFMEMORY;
1648 attr->value = &guid_text->text;
1649 return S_OK;
1651 case RECORD_UINT64_TEXT:
1653 WS_XML_UINT64_TEXT *text_uint64;
1654 UINT64 val_uint64;
1656 if ((hr = read_bytes( reader, (unsigned char *)&val_uint64, sizeof(val_uint64) )) != S_OK) return hr;
1657 if (!(text_uint64 = alloc_uint64_text( val_uint64 ))) return E_OUTOFMEMORY;
1658 attr->value = &text_uint64->text;
1659 return S_OK;
1661 case RECORD_BOOL_TEXT:
1663 WS_XML_BOOL_TEXT *text_bool;
1664 BOOL val_bool;
1666 if ((hr = read_bytes( reader, (unsigned char *)&val_bool, sizeof(val_bool) )) != S_OK) return hr;
1667 if (!(text_bool = alloc_bool_text( !!val_bool ))) return E_OUTOFMEMORY;
1668 attr->value = &text_bool->text;
1669 return S_OK;
1671 default:
1672 ERR( "unhandled record type %02x\n", type );
1673 return WS_E_NOT_SUPPORTED;
1676 if (type >= RECORD_BYTES8_TEXT && type <= RECORD_BYTES32_TEXT)
1678 attr->value = &text_base64->text;
1679 return S_OK;
1682 if (!text_utf8)
1684 if (!(text_utf8 = alloc_utf8_text( NULL, len ))) return E_OUTOFMEMORY;
1685 if (!len) text_utf8->value.bytes = (BYTE *)(text_utf8 + 1); /* quirk */
1686 if ((hr = read_bytes( reader, text_utf8->value.bytes, len )) != S_OK)
1688 free( text_utf8 );
1689 return hr;
1693 attr->value = &text_utf8->text;
1694 return S_OK;
1697 static HRESULT read_attribute_text( struct reader *reader, WS_XML_ATTRIBUTE **ret )
1699 static const WS_XML_STRING xmlns = {5, (BYTE *)"xmlns"};
1700 WS_XML_ATTRIBUTE *attr;
1701 unsigned int len = 0, ch, skip;
1702 const unsigned char *start;
1703 WS_XML_STRING *prefix, *localname;
1704 HRESULT hr;
1706 if (!(attr = calloc( 1, sizeof(*attr) ))) return E_OUTOFMEMORY;
1708 start = read_current_ptr( reader );
1709 for (;;)
1711 if ((hr = read_utf8_char( reader, &ch, &skip )) != S_OK) goto error;
1712 if (!read_isnamechar( ch )) break;
1713 read_skip( reader, skip );
1714 len += skip;
1716 if (!len)
1718 hr = WS_E_INVALID_FORMAT;
1719 goto error;
1722 if ((hr = parse_qname( start, len, &prefix, &localname )) != S_OK) goto error;
1723 if (WsXmlStringEquals( prefix, &xmlns, NULL ) == S_OK)
1725 free_xml_string( prefix );
1726 attr->isXmlNs = 1;
1727 if (!(attr->prefix = alloc_xml_string( localname->bytes, localname->length )))
1729 free_xml_string( localname );
1730 hr = E_OUTOFMEMORY;
1731 goto error;
1733 attr->localName = localname;
1735 else if (!prefix->length && WsXmlStringEquals( localname, &xmlns, NULL ) == S_OK)
1737 attr->isXmlNs = 1;
1738 attr->prefix = prefix;
1739 attr->localName = localname;
1741 else
1743 attr->prefix = prefix;
1744 attr->localName = localname;
1747 if ((hr = read_attribute_value_text( reader, attr )) != S_OK) goto error;
1749 *ret = attr;
1750 return S_OK;
1752 error:
1753 free_attribute( attr );
1754 return hr;
1757 static inline BOOL is_attribute_type( unsigned char type )
1759 return (type >= RECORD_SHORT_ATTRIBUTE && type <= RECORD_PREFIX_ATTRIBUTE_Z);
1762 static WS_XML_STRING *get_xmlns_localname( struct reader *reader, const WS_XML_STRING *prefix )
1764 if (!get_namespace( reader, prefix )) return alloc_xml_string( NULL, 0 );
1765 return alloc_xml_string( prefix->bytes, prefix->length );
1768 static HRESULT read_attribute_bin( struct reader *reader, WS_XML_ATTRIBUTE **ret )
1770 WS_XML_UTF8_TEXT *utf8;
1771 WS_XML_ATTRIBUTE *attr;
1772 unsigned char type = 0;
1773 HRESULT hr;
1775 if ((hr = read_peek( reader, &type, 1 )) != S_OK) return hr;
1776 if (!is_attribute_type( type )) return WS_E_INVALID_FORMAT;
1777 if (!(attr = calloc( 1, sizeof(*attr) ))) return E_OUTOFMEMORY;
1778 read_skip( reader, 1 );
1780 if (type >= RECORD_PREFIX_ATTRIBUTE_A && type <= RECORD_PREFIX_ATTRIBUTE_Z)
1782 unsigned char ch = type - RECORD_PREFIX_ATTRIBUTE_A + 'a';
1783 if (!(attr->prefix = alloc_xml_string( &ch, 1 )))
1785 hr = E_OUTOFMEMORY;
1786 goto error;
1788 if ((hr = read_string( reader, &attr->localName )) != S_OK) goto error;
1789 if ((hr = read_attribute_value_bin( reader, attr )) != S_OK) goto error;
1791 else if (type >= RECORD_PREFIX_DICTIONARY_ATTRIBUTE_A && type <= RECORD_PREFIX_DICTIONARY_ATTRIBUTE_Z)
1793 unsigned char ch = type - RECORD_PREFIX_DICTIONARY_ATTRIBUTE_A + 'a';
1794 if (!(attr->prefix = alloc_xml_string( &ch, 1 )))
1796 hr = E_OUTOFMEMORY;
1797 goto error;
1799 if ((hr = read_dict_string( reader, &attr->localName )) != S_OK) goto error;
1800 if ((hr = read_attribute_value_bin( reader, attr )) != S_OK) goto error;
1802 else
1804 switch (type)
1806 case RECORD_SHORT_ATTRIBUTE:
1807 if (!(attr->prefix = alloc_xml_string( NULL, 0 )))
1809 hr = E_OUTOFMEMORY;
1810 goto error;
1812 if ((hr = read_string( reader, &attr->localName )) != S_OK) goto error;
1813 if ((hr = read_attribute_value_bin( reader, attr )) != S_OK) goto error;
1814 break;
1816 case RECORD_ATTRIBUTE:
1817 if ((hr = read_string( reader, &attr->prefix )) != S_OK) goto error;
1818 if ((hr = read_string( reader, &attr->localName )) != S_OK) goto error;
1819 if ((hr = read_attribute_value_bin( reader, attr )) != S_OK) goto error;
1820 break;
1822 case RECORD_SHORT_DICTIONARY_ATTRIBUTE:
1823 if (!(attr->prefix = alloc_xml_string( NULL, 0 )))
1825 hr = E_OUTOFMEMORY;
1826 goto error;
1828 if ((hr = read_dict_string( reader, &attr->localName )) != S_OK) goto error;
1829 if ((hr = read_attribute_value_bin( reader, attr )) != S_OK) goto error;
1830 break;
1832 case RECORD_DICTIONARY_ATTRIBUTE:
1833 if ((hr = read_string( reader, &attr->prefix )) != S_OK) goto error;
1834 if ((hr = read_dict_string( reader, &attr->localName )) != S_OK) goto error;
1835 if ((hr = read_attribute_value_bin( reader, attr )) != S_OK) goto error;
1836 break;
1838 case RECORD_SHORT_XMLNS_ATTRIBUTE:
1839 if (!(attr->prefix = alloc_xml_string( NULL, 0 )))
1841 hr = E_OUTOFMEMORY;
1842 goto error;
1844 if (!(attr->localName = get_xmlns_localname( reader, attr->prefix )))
1846 hr = E_OUTOFMEMORY;
1847 goto error;
1849 if ((hr = read_string( reader, &attr->ns )) != S_OK) goto error;
1850 if ((hr = bind_prefix( reader, attr->prefix, attr->ns )) != S_OK) goto error;
1851 attr->isXmlNs = 1;
1852 break;
1854 case RECORD_XMLNS_ATTRIBUTE:
1855 if ((hr = read_string( reader, &attr->prefix )) != S_OK) goto error;
1856 if (!(attr->localName = get_xmlns_localname( reader, attr->prefix )))
1858 hr = E_OUTOFMEMORY;
1859 goto error;
1861 if ((hr = read_string( reader, &attr->ns )) != S_OK) goto error;
1862 if ((hr = bind_prefix( reader, attr->prefix, attr->ns )) != S_OK) goto error;
1863 attr->isXmlNs = 1;
1864 break;
1866 case RECORD_SHORT_DICTIONARY_XMLNS_ATTRIBUTE:
1867 if (!(attr->prefix = alloc_xml_string( NULL, 0 )))
1869 hr = E_OUTOFMEMORY;
1870 goto error;
1872 if (!(attr->localName = get_xmlns_localname( reader, attr->prefix )))
1874 hr = E_OUTOFMEMORY;
1875 goto error;
1877 if ((hr = read_dict_string( reader, &attr->ns )) != S_OK) goto error;
1878 if (!(utf8 = alloc_utf8_text( NULL, 0 )))
1880 hr = E_OUTOFMEMORY;
1881 goto error;
1883 attr->value = &utf8->text;
1884 if ((hr = bind_prefix( reader, attr->prefix, attr->ns )) != S_OK) goto error;
1885 attr->isXmlNs = 1;
1886 break;
1888 case RECORD_DICTIONARY_XMLNS_ATTRIBUTE:
1889 if ((hr = read_string( reader, &attr->prefix )) != S_OK) goto error;
1890 if (!(attr->localName = get_xmlns_localname( reader, attr->prefix )))
1892 hr = E_OUTOFMEMORY;
1893 goto error;
1895 if ((hr = read_dict_string( reader, &attr->ns )) != S_OK) goto error;
1896 if (!(utf8 = alloc_utf8_text( NULL, 0 )))
1898 hr = E_OUTOFMEMORY;
1899 goto error;
1901 attr->value = &utf8->text;
1902 if ((hr = bind_prefix( reader, attr->prefix, attr->ns )) != S_OK) goto error;
1903 attr->isXmlNs = 1;
1904 break;
1906 default:
1907 ERR( "unhandled record type %02x\n", type );
1908 return WS_E_NOT_SUPPORTED;
1912 *ret = attr;
1913 return S_OK;
1915 error:
1916 free_attribute( attr );
1917 return hr;
1920 static inline struct node *find_parent( struct reader *reader )
1922 if (node_type( reader->current ) == WS_XML_NODE_TYPE_END_ELEMENT)
1924 if (is_valid_parent( reader->current->parent->parent )) return reader->current->parent->parent;
1925 return NULL;
1927 if (is_valid_parent( reader->current )) return reader->current;
1928 if (is_valid_parent( reader->current->parent )) return reader->current->parent;
1929 return NULL;
1932 static HRESULT set_namespaces( struct reader *reader, WS_XML_ELEMENT_NODE *elem )
1934 static const WS_XML_STRING xml = {3, (BYTE *)"xml"};
1935 const WS_XML_STRING *ns;
1936 ULONG i;
1938 if (!(ns = get_namespace( reader, elem->prefix ))) return WS_E_INVALID_FORMAT;
1939 if (!(elem->ns = dup_xml_string( ns, FALSE ))) return E_OUTOFMEMORY;
1941 for (i = 0; i < elem->attributeCount; i++)
1943 WS_XML_ATTRIBUTE *attr = elem->attributes[i];
1944 if (attr->isXmlNs || WsXmlStringEquals( attr->prefix, &xml, NULL ) == S_OK) continue;
1945 if (!(ns = get_namespace( reader, attr->prefix ))) return WS_E_INVALID_FORMAT;
1946 if (!(attr->ns = alloc_xml_string( NULL, ns->length ))) return E_OUTOFMEMORY;
1947 if (attr->ns->length) memcpy( attr->ns->bytes, ns->bytes, ns->length );
1949 return S_OK;
1952 static WS_XML_ELEMENT_NODE *alloc_element_pair(void)
1954 struct node *node, *end;
1955 if (!(node = alloc_node( WS_XML_NODE_TYPE_ELEMENT ))) return NULL;
1956 if (!(end = alloc_node( WS_XML_NODE_TYPE_END_ELEMENT )))
1958 free_node( node );
1959 return NULL;
1961 list_add_tail( &node->children, &end->entry );
1962 end->parent = node;
1963 return &node->hdr;
1966 static HRESULT read_attributes_text( struct reader *reader, WS_XML_ELEMENT_NODE *elem )
1968 WS_XML_ATTRIBUTE *attr;
1969 HRESULT hr;
1971 reader->current_attr = 0;
1972 for (;;)
1974 read_skip_whitespace( reader );
1975 if (read_cmp( reader, ">", 1 ) == S_OK || read_cmp( reader, "/>", 2 ) == S_OK) break;
1976 if ((hr = read_attribute_text( reader, &attr )) != S_OK) return hr;
1977 if ((hr = append_attribute( elem, attr )) != S_OK)
1979 free_attribute( attr );
1980 return hr;
1982 reader->current_attr++;
1984 return S_OK;
1987 static HRESULT read_element_text( struct reader *reader )
1989 unsigned int len = 0, ch, skip;
1990 const unsigned char *start;
1991 unsigned char buf[2];
1992 struct node *node = NULL, *parent;
1993 WS_XML_ELEMENT_NODE *elem;
1994 HRESULT hr;
1996 if (read_end_of_data( reader ))
1998 reader->current = LIST_ENTRY( list_tail( &reader->root->children ), struct node, entry );
1999 reader->last = reader->current;
2000 reader->state = READER_STATE_EOF;
2001 return S_OK;
2004 if ((hr = read_peek( reader, buf, 2 )) != S_OK) return hr;
2005 if (buf[0] != '<' || !read_isnamechar( buf[1] )) return WS_E_INVALID_FORMAT;
2006 read_skip( reader, 1 );
2008 if (!(elem = alloc_element_pair())) return E_OUTOFMEMORY;
2009 node = (struct node *)elem;
2011 start = read_current_ptr( reader );
2012 for (;;)
2014 if ((hr = read_utf8_char( reader, &ch, &skip )) != S_OK) goto error;
2015 if (!read_isnamechar( ch )) break;
2016 read_skip( reader, skip );
2017 len += skip;
2019 if (!len)
2021 hr = WS_E_INVALID_FORMAT;
2022 goto error;
2025 if (!(parent = find_parent( reader ))) goto error;
2026 if ((hr = parse_qname( start, len, &elem->prefix, &elem->localName )) != S_OK) goto error;
2027 if ((hr = read_attributes_text( reader, elem )) != S_OK) goto error;
2028 if ((hr = set_namespaces( reader, elem )) != S_OK) goto error;
2030 read_insert_node( reader, parent, node );
2031 reader->state = READER_STATE_STARTELEMENT;
2032 return S_OK;
2034 error:
2035 destroy_nodes( node );
2036 return hr;
2039 static inline BOOL is_element_type( unsigned char type )
2041 return (type >= RECORD_SHORT_ELEMENT && type <= RECORD_PREFIX_ELEMENT_Z);
2044 static HRESULT read_attributes_bin( struct reader *reader, WS_XML_ELEMENT_NODE *elem )
2046 WS_XML_ATTRIBUTE *attr;
2047 unsigned char type;
2048 HRESULT hr;
2050 reader->current_attr = 0;
2051 for (;;)
2053 if ((hr = read_peek( reader, &type, 1 )) != S_OK) return hr;
2054 if (!is_attribute_type( type )) break;
2055 if ((hr = read_attribute_bin( reader, &attr )) != S_OK) return hr;
2056 if ((hr = append_attribute( elem, attr )) != S_OK)
2058 free_attribute( attr );
2059 return hr;
2061 reader->current_attr++;
2063 return S_OK;
2066 static HRESULT read_element_bin( struct reader *reader )
2068 struct node *node = NULL, *parent;
2069 WS_XML_ELEMENT_NODE *elem;
2070 unsigned char type;
2071 HRESULT hr;
2073 if ((hr = read_peek( reader, &type, 1 )) != S_OK) return hr;
2074 if (!is_element_type( type )) return WS_E_INVALID_FORMAT;
2075 read_skip( reader, 1 );
2077 if (!(elem = alloc_element_pair())) return E_OUTOFMEMORY;
2078 node = (struct node *)elem;
2080 if (type >= RECORD_PREFIX_ELEMENT_A && type <= RECORD_PREFIX_ELEMENT_Z)
2082 unsigned char ch = type - RECORD_PREFIX_ELEMENT_A + 'a';
2083 if (!(elem->prefix = alloc_xml_string( &ch, 1 )))
2085 hr = E_OUTOFMEMORY;
2086 goto error;
2088 if ((hr = read_string( reader, &elem->localName )) != S_OK) goto error;
2090 else if (type >= RECORD_PREFIX_DICTIONARY_ELEMENT_A && type <= RECORD_PREFIX_DICTIONARY_ELEMENT_Z)
2092 unsigned char ch = type - RECORD_PREFIX_DICTIONARY_ELEMENT_A + 'a';
2093 if (!(elem->prefix = alloc_xml_string( &ch, 1 )))
2095 hr = E_OUTOFMEMORY;
2096 goto error;
2098 if ((hr = read_dict_string( reader, &elem->localName )) != S_OK) goto error;
2100 else
2102 switch (type)
2104 case RECORD_SHORT_ELEMENT:
2105 if (!(elem->prefix = alloc_xml_string( NULL, 0 )))
2107 hr = E_OUTOFMEMORY;
2108 goto error;
2110 if ((hr = read_string( reader, &elem->localName )) != S_OK) goto error;
2111 break;
2113 case RECORD_ELEMENT:
2114 if ((hr = read_string( reader, &elem->prefix )) != S_OK) goto error;
2115 if ((hr = read_string( reader, &elem->localName )) != S_OK) goto error;
2116 break;
2118 case RECORD_SHORT_DICTIONARY_ELEMENT:
2119 if (!(elem->prefix = alloc_xml_string( NULL, 0 )))
2121 hr = E_OUTOFMEMORY;
2122 goto error;
2124 if ((hr = read_dict_string( reader, &elem->localName )) != S_OK) goto error;
2125 break;
2127 case RECORD_DICTIONARY_ELEMENT:
2128 if ((hr = read_string( reader, &elem->prefix )) != S_OK) goto error;
2129 if ((hr = read_dict_string( reader, &elem->localName )) != S_OK) goto error;
2130 break;
2132 default:
2133 ERR( "unhandled record type %02x\n", type );
2134 return WS_E_NOT_SUPPORTED;
2138 if (!(parent = find_parent( reader )))
2140 hr = WS_E_INVALID_FORMAT;
2141 goto error;
2144 if ((hr = read_attributes_bin( reader, elem )) != S_OK) goto error;
2145 if ((hr = set_namespaces( reader, elem )) != S_OK) goto error;
2147 read_insert_node( reader, parent, node );
2148 reader->state = READER_STATE_STARTELEMENT;
2149 return S_OK;
2151 error:
2152 destroy_nodes( node );
2153 return hr;
2156 static HRESULT read_text_text( struct reader *reader )
2158 unsigned int len = 0, ch, skip;
2159 const unsigned char *start;
2160 struct node *node, *parent;
2161 WS_XML_TEXT_NODE *text;
2162 WS_XML_UTF8_TEXT *utf8;
2163 HRESULT hr;
2165 start = read_current_ptr( reader );
2166 for (;;)
2168 if (read_end_of_data( reader )) break;
2169 if ((hr = read_utf8_char( reader, &ch, &skip )) != S_OK) return hr;
2170 if (ch == '<') break;
2171 read_skip( reader, skip );
2172 len += skip;
2175 if (!(parent = find_parent( reader ))) return WS_E_INVALID_FORMAT;
2177 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return E_OUTOFMEMORY;
2178 text = (WS_XML_TEXT_NODE *)node;
2179 if (!(utf8 = alloc_utf8_text( NULL, len )))
2181 free( node );
2182 return E_OUTOFMEMORY;
2184 if ((hr = decode_text( start, len, utf8->value.bytes, &utf8->value.length )) != S_OK)
2186 free( utf8 );
2187 free( node );
2188 return hr;
2190 text->text = &utf8->text;
2192 read_insert_node( reader, parent, node );
2193 reader->state = READER_STATE_TEXT;
2194 reader->text_conv_offset = 0;
2195 return S_OK;
2198 static struct node *alloc_utf8_text_node( const BYTE *data, ULONG len, WS_XML_UTF8_TEXT **ret )
2200 struct node *node;
2201 WS_XML_UTF8_TEXT *utf8;
2202 WS_XML_TEXT_NODE *text;
2204 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
2205 if (!(utf8 = alloc_utf8_text( data, len )))
2207 free( node );
2208 return NULL;
2210 text = (WS_XML_TEXT_NODE *)node;
2211 text->text = &utf8->text;
2212 if (ret) *ret = utf8;
2213 return node;
2216 static struct node *alloc_base64_text_node( const BYTE *data, ULONG len, WS_XML_BASE64_TEXT **ret )
2218 struct node *node;
2219 WS_XML_BASE64_TEXT *base64;
2220 WS_XML_TEXT_NODE *text;
2222 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
2223 if (!(base64 = alloc_base64_text( data, len )))
2225 free( node );
2226 return NULL;
2228 text = (WS_XML_TEXT_NODE *)node;
2229 text->text = &base64->text;
2230 if (ret) *ret = base64;
2231 return node;
2234 static struct node *alloc_bool_text_node( BOOL value )
2236 struct node *node;
2237 WS_XML_BOOL_TEXT *text_bool;
2238 WS_XML_TEXT_NODE *text;
2240 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
2241 if (!(text_bool = alloc_bool_text( value )))
2243 free( node );
2244 return NULL;
2246 text = (WS_XML_TEXT_NODE *)node;
2247 text->text = &text_bool->text;
2248 return node;
2251 static struct node *alloc_int32_text_node( INT32 value )
2253 struct node *node;
2254 WS_XML_INT32_TEXT *text_int32;
2255 WS_XML_TEXT_NODE *text;
2257 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
2258 if (!(text_int32 = alloc_int32_text( value )))
2260 free( node );
2261 return NULL;
2263 text = (WS_XML_TEXT_NODE *)node;
2264 text->text = &text_int32->text;
2265 return node;
2268 static struct node *alloc_int64_text_node( INT64 value )
2270 struct node *node;
2271 WS_XML_INT64_TEXT *text_int64;
2272 WS_XML_TEXT_NODE *text;
2274 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
2275 if (!(text_int64 = alloc_int64_text( value )))
2277 free( node );
2278 return NULL;
2280 text = (WS_XML_TEXT_NODE *)node;
2281 text->text = &text_int64->text;
2282 return node;
2285 static struct node *alloc_float_text_node( float value )
2287 struct node *node;
2288 WS_XML_FLOAT_TEXT *text_float;
2289 WS_XML_TEXT_NODE *text;
2291 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
2292 if (!(text_float = alloc_float_text( value )))
2294 free( node );
2295 return NULL;
2297 text = (WS_XML_TEXT_NODE *)node;
2298 text->text = &text_float->text;
2299 return node;
2302 static struct node *alloc_double_text_node( double value )
2304 struct node *node;
2305 WS_XML_DOUBLE_TEXT *text_double;
2306 WS_XML_TEXT_NODE *text;
2308 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
2309 if (!(text_double = alloc_double_text( value )))
2311 free( node );
2312 return NULL;
2314 text = (WS_XML_TEXT_NODE *)node;
2315 text->text = &text_double->text;
2316 return node;
2319 static struct node *alloc_datetime_text_node( const WS_DATETIME *value )
2321 struct node *node;
2322 WS_XML_DATETIME_TEXT *text_datetime;
2323 WS_XML_TEXT_NODE *text;
2325 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
2326 if (!(text_datetime = alloc_datetime_text( value )))
2328 free( node );
2329 return NULL;
2331 text = (WS_XML_TEXT_NODE *)node;
2332 text->text = &text_datetime->text;
2333 return node;
2336 static struct node *alloc_unique_id_text_node( const GUID *value )
2338 struct node *node;
2339 WS_XML_UNIQUE_ID_TEXT *text_unique_id;
2340 WS_XML_TEXT_NODE *text;
2342 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
2343 if (!(text_unique_id = alloc_unique_id_text( value )))
2345 free( node );
2346 return NULL;
2348 text = (WS_XML_TEXT_NODE *)node;
2349 text->text = &text_unique_id->text;
2350 return node;
2353 static struct node *alloc_guid_text_node( const GUID *value )
2355 struct node *node;
2356 WS_XML_GUID_TEXT *text_guid;
2357 WS_XML_TEXT_NODE *text;
2359 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
2360 if (!(text_guid = alloc_guid_text( value )))
2362 free( node );
2363 return NULL;
2365 text = (WS_XML_TEXT_NODE *)node;
2366 text->text = &text_guid->text;
2367 return node;
2370 static struct node *alloc_uint64_text_node( UINT64 value )
2372 struct node *node;
2373 WS_XML_UINT64_TEXT *text_uint64;
2374 WS_XML_TEXT_NODE *text;
2376 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
2377 if (!(text_uint64 = alloc_uint64_text( value )))
2379 free( node );
2380 return NULL;
2382 text = (WS_XML_TEXT_NODE *)node;
2383 text->text = &text_uint64->text;
2384 return node;
2387 static HRESULT append_text_bytes( struct reader *reader, WS_XML_TEXT_NODE *node, ULONG len )
2389 WS_XML_BASE64_TEXT *new, *old = (WS_XML_BASE64_TEXT *)node->text;
2390 HRESULT hr;
2392 if (!(new = alloc_base64_text( NULL, old->length + len ))) return E_OUTOFMEMORY;
2393 memcpy( new->bytes, old->bytes, old->length );
2394 if ((hr = read_bytes( reader, new->bytes + old->length, len )) != S_OK) return hr;
2395 free( old );
2396 node->text = &new->text;
2397 return S_OK;
2400 static HRESULT read_text_bytes( struct reader *reader, unsigned char type )
2402 struct node *node = NULL, *parent;
2403 WS_XML_BASE64_TEXT *base64;
2404 HRESULT hr;
2405 ULONG len;
2407 if (!(parent = find_parent( reader ))) return WS_E_INVALID_FORMAT;
2408 for (;;)
2410 switch (type)
2412 case RECORD_BYTES8_TEXT:
2413 case RECORD_BYTES8_TEXT_WITH_ENDELEMENT:
2415 UINT8 len_uint8;
2416 if ((hr = read_byte( reader, (unsigned char *)&len_uint8 )) != S_OK) goto error;
2417 len = len_uint8;
2418 break;
2420 case RECORD_BYTES16_TEXT:
2421 case RECORD_BYTES16_TEXT_WITH_ENDELEMENT:
2423 UINT16 len_uint16;
2424 if ((hr = read_bytes( reader, (unsigned char *)&len_uint16, sizeof(len_uint16) )) != S_OK) goto error;
2425 len = len_uint16;
2426 break;
2428 case RECORD_BYTES32_TEXT:
2429 case RECORD_BYTES32_TEXT_WITH_ENDELEMENT:
2431 INT32 len_int32;
2432 if ((hr = read_bytes( reader, (unsigned char *)&len_int32, sizeof(len_int32) )) != S_OK) goto error;
2433 if (len_int32 < 0)
2435 hr = WS_E_INVALID_FORMAT;
2436 goto error;
2438 len = len_int32;
2439 break;
2441 default:
2442 ERR( "unexpected type %u\n", type );
2443 hr = E_INVALIDARG;
2444 goto error;
2447 if (!node)
2449 if (!(node = alloc_base64_text_node( NULL, len, &base64 ))) return E_OUTOFMEMORY;
2450 if ((hr = read_bytes( reader, base64->bytes, len )) != S_OK) goto error;
2452 else if ((hr = append_text_bytes( reader, (WS_XML_TEXT_NODE *)node, len )) != S_OK) goto error;
2454 if (type & 1)
2456 node->flags |= NODE_FLAG_TEXT_WITH_IMPLICIT_END_ELEMENT;
2457 break;
2459 if ((hr = read_peek( reader, &type, 1 )) != S_OK) goto error;
2460 if (type < RECORD_BYTES8_TEXT || type > RECORD_BYTES32_TEXT_WITH_ENDELEMENT) break;
2461 read_skip( reader, 1 );
2464 read_insert_node( reader, parent, node );
2465 reader->state = READER_STATE_TEXT;
2466 reader->text_conv_offset = 0;
2467 return S_OK;
2469 error:
2470 free_node( node );
2471 return hr;
2474 static HRESULT read_text_bin( struct reader *reader )
2476 struct node *node = NULL, *parent;
2477 unsigned char type;
2478 WS_XML_UTF8_TEXT *utf8;
2479 INT32 val_int32;
2480 UINT8 val_uint8;
2481 UINT16 val_uint16;
2482 ULONG len, id;
2483 GUID uuid;
2484 HRESULT hr;
2486 if ((hr = read_peek( reader, &type, 1 )) != S_OK) return hr;
2487 if (!is_text_type( type ) || !(parent = find_parent( reader ))) return WS_E_INVALID_FORMAT;
2488 read_skip( reader, 1 );
2490 switch (type)
2492 case RECORD_ZERO_TEXT:
2493 case RECORD_ZERO_TEXT_WITH_ENDELEMENT:
2494 if (!(node = alloc_int32_text_node( 0 ))) return E_OUTOFMEMORY;
2495 break;
2497 case RECORD_ONE_TEXT:
2498 case RECORD_ONE_TEXT_WITH_ENDELEMENT:
2499 if (!(node = alloc_int32_text_node( 1 ))) return E_OUTOFMEMORY;
2500 break;
2502 case RECORD_FALSE_TEXT:
2503 case RECORD_FALSE_TEXT_WITH_ENDELEMENT:
2504 if (!(node = alloc_bool_text_node( FALSE ))) return E_OUTOFMEMORY;
2505 break;
2507 case RECORD_TRUE_TEXT:
2508 case RECORD_TRUE_TEXT_WITH_ENDELEMENT:
2509 if (!(node = alloc_bool_text_node( TRUE ))) return E_OUTOFMEMORY;
2510 break;
2512 case RECORD_INT8_TEXT:
2513 case RECORD_INT8_TEXT_WITH_ENDELEMENT:
2515 INT8 val_int8;
2516 if ((hr = read_byte( reader, (unsigned char *)&val_int8 )) != S_OK) return hr;
2517 if (!(node = alloc_int32_text_node( val_int8 ))) return E_OUTOFMEMORY;
2518 break;
2520 case RECORD_INT16_TEXT:
2521 case RECORD_INT16_TEXT_WITH_ENDELEMENT:
2523 INT16 val_int16;
2524 if ((hr = read_bytes( reader, (unsigned char *)&val_int16, sizeof(val_int16) )) != S_OK) return hr;
2525 if (!(node = alloc_int32_text_node( val_int16 ))) return E_OUTOFMEMORY;
2526 break;
2528 case RECORD_INT32_TEXT:
2529 case RECORD_INT32_TEXT_WITH_ENDELEMENT:
2530 if ((hr = read_bytes( reader, (unsigned char *)&val_int32, sizeof(val_int32) )) != S_OK) return hr;
2531 if (!(node = alloc_int32_text_node( val_int32 ))) return E_OUTOFMEMORY;
2532 break;
2534 case RECORD_INT64_TEXT:
2535 case RECORD_INT64_TEXT_WITH_ENDELEMENT:
2537 INT64 val_int64;
2538 if ((hr = read_bytes( reader, (unsigned char *)&val_int64, sizeof(val_int64) )) != S_OK) return hr;
2539 if (!(node = alloc_int64_text_node( val_int64 ))) return E_OUTOFMEMORY;
2540 break;
2542 case RECORD_FLOAT_TEXT:
2543 case RECORD_FLOAT_TEXT_WITH_ENDELEMENT:
2545 float val_float;
2546 if ((hr = read_bytes( reader, (unsigned char *)&val_float, sizeof(val_float) )) != S_OK) return hr;
2547 if (!(node = alloc_float_text_node( val_float ))) return E_OUTOFMEMORY;
2548 break;
2550 case RECORD_DOUBLE_TEXT:
2551 case RECORD_DOUBLE_TEXT_WITH_ENDELEMENT:
2553 double val_double;
2554 if ((hr = read_bytes( reader, (unsigned char *)&val_double, sizeof(val_double) )) != S_OK) return hr;
2555 if (!(node = alloc_double_text_node( val_double ))) return E_OUTOFMEMORY;
2556 break;
2558 case RECORD_DATETIME_TEXT:
2559 case RECORD_DATETIME_TEXT_WITH_ENDELEMENT:
2561 WS_DATETIME datetime;
2562 if ((hr = read_datetime( reader, &datetime )) != S_OK) return hr;
2563 if (!(node = alloc_datetime_text_node( &datetime ))) return E_OUTOFMEMORY;
2564 break;
2566 case RECORD_CHARS8_TEXT:
2567 case RECORD_CHARS8_TEXT_WITH_ENDELEMENT:
2568 if ((hr = read_byte( reader, (unsigned char *)&val_uint8 )) != S_OK) return hr;
2569 len = val_uint8;
2570 break;
2572 case RECORD_CHARS16_TEXT:
2573 case RECORD_CHARS16_TEXT_WITH_ENDELEMENT:
2574 if ((hr = read_bytes( reader, (unsigned char *)&val_uint16, sizeof(val_uint16) )) != S_OK) return hr;
2575 len = val_uint16;
2576 break;
2578 case RECORD_CHARS32_TEXT:
2579 case RECORD_CHARS32_TEXT_WITH_ENDELEMENT:
2580 if ((hr = read_bytes( reader, (unsigned char *)&val_int32, sizeof(val_int32) )) != S_OK) return hr;
2581 if (val_int32 < 0) return WS_E_INVALID_FORMAT;
2582 len = val_int32;
2583 break;
2585 case RECORD_BYTES8_TEXT:
2586 case RECORD_BYTES8_TEXT_WITH_ENDELEMENT:
2587 case RECORD_BYTES16_TEXT:
2588 case RECORD_BYTES16_TEXT_WITH_ENDELEMENT:
2589 case RECORD_BYTES32_TEXT:
2590 case RECORD_BYTES32_TEXT_WITH_ENDELEMENT:
2591 return read_text_bytes( reader, type );
2593 case RECORD_EMPTY_TEXT:
2594 case RECORD_EMPTY_TEXT_WITH_ENDELEMENT:
2595 len = 0;
2596 break;
2598 case RECORD_DICTIONARY_TEXT:
2599 case RECORD_DICTIONARY_TEXT_WITH_ENDELEMENT:
2601 const WS_XML_STRING *str;
2602 if ((hr = read_int31( reader, &id )) != S_OK) return hr;
2603 if ((hr = lookup_string( reader, id, &str )) != S_OK) return hr;
2604 if (!(node = alloc_utf8_text_node( str->bytes, str->length, NULL ))) return E_OUTOFMEMORY;
2605 break;
2607 case RECORD_UNIQUE_ID_TEXT:
2608 case RECORD_UNIQUE_ID_TEXT_WITH_ENDELEMENT:
2609 if ((hr = read_bytes( reader, (unsigned char *)&uuid, sizeof(uuid) )) != S_OK) return hr;
2610 if (!(node = alloc_unique_id_text_node( &uuid ))) return E_OUTOFMEMORY;
2611 break;
2613 case RECORD_GUID_TEXT:
2614 case RECORD_GUID_TEXT_WITH_ENDELEMENT:
2615 if ((hr = read_bytes( reader, (unsigned char *)&uuid, sizeof(uuid) )) != S_OK) return hr;
2616 if (!(node = alloc_guid_text_node( &uuid ))) return E_OUTOFMEMORY;
2617 break;
2619 case RECORD_UINT64_TEXT:
2620 case RECORD_UINT64_TEXT_WITH_ENDELEMENT:
2622 UINT64 val_uint64;
2623 if ((hr = read_bytes( reader, (unsigned char *)&val_uint64, sizeof(val_uint64) )) != S_OK) return hr;
2624 if (!(node = alloc_uint64_text_node( val_uint64 ))) return E_OUTOFMEMORY;
2625 break;
2627 case RECORD_BOOL_TEXT:
2628 case RECORD_BOOL_TEXT_WITH_ENDELEMENT:
2630 BOOL val_bool;
2631 if ((hr = read_bytes( reader, (unsigned char *)&val_bool, sizeof(val_bool) )) != S_OK) return hr;
2632 if (!(node = alloc_bool_text_node( !!val_bool ))) return E_OUTOFMEMORY;
2633 break;
2635 default:
2636 ERR( "unhandled record type %02x\n", type );
2637 return WS_E_NOT_SUPPORTED;
2640 if (!node)
2642 if (!(node = alloc_utf8_text_node( NULL, len, &utf8 ))) return E_OUTOFMEMORY;
2643 if (!len) utf8->value.bytes = (BYTE *)(utf8 + 1); /* quirk */
2644 if ((hr = read_bytes( reader, utf8->value.bytes, len )) != S_OK)
2646 free_node( node );
2647 return hr;
2651 if (type & 1) node->flags |= NODE_FLAG_TEXT_WITH_IMPLICIT_END_ELEMENT;
2652 read_insert_node( reader, parent, node );
2653 reader->state = READER_STATE_TEXT;
2654 reader->text_conv_offset = 0;
2655 return S_OK;
2658 static HRESULT read_node_text( struct reader * );
2660 static HRESULT read_startelement_text( struct reader *reader )
2662 HRESULT hr;
2664 if (read_cmp( reader, "<?", 2 ) == S_OK)
2666 if ((hr = read_xmldecl( reader )) != S_OK) return hr;
2668 read_skip_whitespace( reader );
2669 if (read_cmp( reader, "<", 1 ) == S_OK)
2671 if ((hr = read_element_text( reader )) != S_OK) return hr;
2673 if (read_cmp( reader, "/>", 2 ) == S_OK)
2675 read_skip( reader, 2 );
2676 reader->current = LIST_ENTRY( list_tail( &reader->current->children ), struct node, entry );
2677 reader->last = reader->current;
2678 reader->state = READER_STATE_ENDELEMENT;
2679 return S_OK;
2681 else if (read_cmp( reader, ">", 1 ) == S_OK)
2683 read_skip( reader, 1 );
2684 return read_node_text( reader );
2686 return WS_E_INVALID_FORMAT;
2689 static HRESULT read_node_bin( struct reader * );
2691 static HRESULT read_startelement_bin( struct reader *reader )
2693 if (node_type( reader->current ) != WS_XML_NODE_TYPE_ELEMENT) return WS_E_INVALID_FORMAT;
2694 return read_node_bin( reader );
2697 static HRESULT read_startelement( struct reader *reader )
2699 switch (reader->input_enc)
2701 case WS_XML_READER_ENCODING_TYPE_TEXT: return read_startelement_text( reader );
2702 case WS_XML_READER_ENCODING_TYPE_BINARY: return read_startelement_bin( reader );
2703 default:
2704 ERR( "unhandled encoding %u\n", reader->input_enc );
2705 return WS_E_NOT_SUPPORTED;
2709 static HRESULT read_to_startelement_text( struct reader *reader, BOOL *found )
2711 HRESULT hr;
2713 switch (reader->state)
2715 case READER_STATE_INITIAL:
2716 if ((hr = read_xmldecl( reader )) != S_OK) return hr;
2717 break;
2719 case READER_STATE_STARTELEMENT:
2720 if (found) *found = TRUE;
2721 return S_OK;
2723 default:
2724 break;
2727 read_skip_whitespace( reader );
2728 if ((hr = read_element_text( reader )) == S_OK && found)
2730 if (reader->state == READER_STATE_STARTELEMENT)
2731 *found = TRUE;
2732 else
2733 *found = FALSE;
2736 return hr;
2739 static HRESULT read_to_startelement_bin( struct reader *reader, BOOL *found )
2741 HRESULT hr;
2743 if (reader->state == READER_STATE_STARTELEMENT)
2745 if (found) *found = TRUE;
2746 return S_OK;
2749 if ((hr = read_element_bin( reader )) == S_OK && found)
2751 if (reader->state == READER_STATE_STARTELEMENT)
2752 *found = TRUE;
2753 else
2754 *found = FALSE;
2757 return hr;
2760 static HRESULT read_to_startelement( struct reader *reader, BOOL *found )
2762 switch (reader->input_enc)
2764 case WS_XML_READER_ENCODING_TYPE_TEXT: return read_to_startelement_text( reader, found );
2765 case WS_XML_READER_ENCODING_TYPE_BINARY: return read_to_startelement_bin( reader, found );
2766 default:
2767 ERR( "unhandled encoding %u\n", reader->input_enc );
2768 return WS_E_NOT_SUPPORTED;
2772 static int cmp_name( const unsigned char *name1, ULONG len1, const unsigned char *name2, ULONG len2 )
2774 ULONG i;
2775 if (len1 != len2) return 1;
2776 for (i = 0; i < len1; i++) { if (toupper( name1[i] ) != toupper( name2[i] )) return 1; }
2777 return 0;
2780 static struct node *find_startelement( struct reader *reader, const WS_XML_STRING *prefix,
2781 const WS_XML_STRING *localname )
2783 struct node *parent;
2784 const WS_XML_STRING *str;
2786 for (parent = reader->current; parent; parent = parent->parent)
2788 if (node_type( parent ) == WS_XML_NODE_TYPE_ELEMENT)
2790 str = parent->hdr.prefix;
2791 if (cmp_name( str->bytes, str->length, prefix->bytes, prefix->length )) continue;
2792 str = parent->hdr.localName;
2793 if (cmp_name( str->bytes, str->length, localname->bytes, localname->length )) continue;
2794 return parent;
2797 return NULL;
2800 static HRESULT read_endelement_text( struct reader *reader )
2802 struct node *parent;
2803 unsigned int len = 0, ch, skip;
2804 const unsigned char *start;
2805 WS_XML_STRING prefix, localname;
2806 HRESULT hr;
2808 if ((hr = read_cmp( reader, "</", 2 )) != S_OK) return hr;
2809 read_skip( reader, 2 );
2811 start = read_current_ptr( reader );
2812 for (;;)
2814 if ((hr = read_utf8_char( reader, &ch, &skip )) != S_OK) return hr;
2815 if (ch == '>')
2817 read_skip( reader, 1 );
2818 break;
2820 if (!read_isnamechar( ch )) return WS_E_INVALID_FORMAT;
2821 read_skip( reader, skip );
2822 len += skip;
2825 if ((hr = split_qname( start, len, &prefix, &localname )) != S_OK) return hr;
2826 if (!(parent = find_startelement( reader, &prefix, &localname ))) return WS_E_INVALID_FORMAT;
2828 reader->current = LIST_ENTRY( list_tail( &parent->children ), struct node, entry );
2829 reader->last = reader->current;
2830 reader->state = READER_STATE_ENDELEMENT;
2831 return S_OK;
2834 static HRESULT read_endelement_bin( struct reader *reader )
2836 struct node *parent;
2837 unsigned char type;
2838 HRESULT hr;
2840 if (!(reader->current->flags & NODE_FLAG_TEXT_WITH_IMPLICIT_END_ELEMENT))
2842 if ((hr = read_peek( reader, &type, 1 )) != S_OK) return hr;
2843 if (type != RECORD_ENDELEMENT) return WS_E_INVALID_FORMAT;
2844 read_skip( reader, 1 );
2846 if (!(parent = find_parent( reader ))) return WS_E_INVALID_FORMAT;
2848 reader->current = LIST_ENTRY( list_tail( &parent->children ), struct node, entry );
2849 reader->last = reader->current;
2850 reader->state = READER_STATE_ENDELEMENT;
2851 return S_OK;
2854 static HRESULT read_endelement( struct reader *reader )
2856 if (reader->state == READER_STATE_EOF) return WS_E_INVALID_FORMAT;
2858 if (read_end_of_data( reader ))
2860 reader->current = LIST_ENTRY( list_tail( &reader->root->children ), struct node, entry );
2861 reader->last = reader->current;
2862 reader->state = READER_STATE_EOF;
2863 return S_OK;
2866 switch (reader->input_enc)
2868 case WS_XML_READER_ENCODING_TYPE_TEXT: return read_endelement_text( reader );
2869 case WS_XML_READER_ENCODING_TYPE_BINARY: return read_endelement_bin( reader );
2870 default:
2871 ERR( "unhandled encoding %u\n", reader->input_enc );
2872 return WS_E_NOT_SUPPORTED;
2876 static HRESULT read_comment_text( struct reader *reader )
2878 unsigned int len = 0, ch, skip;
2879 const unsigned char *start;
2880 struct node *node, *parent;
2881 WS_XML_COMMENT_NODE *comment;
2882 HRESULT hr;
2884 if ((hr = read_cmp( reader, "<!--", 4 )) != S_OK) return hr;
2885 read_skip( reader, 4 );
2887 start = read_current_ptr( reader );
2888 for (;;)
2890 if (read_cmp( reader, "-->", 3 ) == S_OK)
2892 read_skip( reader, 3 );
2893 break;
2895 if ((hr = read_utf8_char( reader, &ch, &skip )) != S_OK) return hr;
2896 read_skip( reader, skip );
2897 len += skip;
2900 if (!(parent = find_parent( reader ))) return WS_E_INVALID_FORMAT;
2902 if (!(node = alloc_node( WS_XML_NODE_TYPE_COMMENT ))) return E_OUTOFMEMORY;
2903 comment = (WS_XML_COMMENT_NODE *)node;
2904 if (!(comment->value.bytes = malloc( len )))
2906 free( node );
2907 return E_OUTOFMEMORY;
2909 memcpy( comment->value.bytes, start, len );
2910 comment->value.length = len;
2912 read_insert_node( reader, parent, node );
2913 reader->state = READER_STATE_COMMENT;
2914 return S_OK;
2917 static HRESULT read_comment_bin( struct reader *reader )
2919 struct node *node, *parent;
2920 WS_XML_COMMENT_NODE *comment;
2921 unsigned char type;
2922 ULONG len;
2923 HRESULT hr;
2925 if ((hr = read_peek( reader, &type, 1 )) != S_OK) return hr;
2926 if (type != RECORD_COMMENT) return WS_E_INVALID_FORMAT;
2927 read_skip( reader, 1 );
2928 if ((hr = read_int31( reader, &len )) != S_OK) return hr;
2930 if (!(parent = find_parent( reader ))) return WS_E_INVALID_FORMAT;
2932 if (!(node = alloc_node( WS_XML_NODE_TYPE_COMMENT ))) return E_OUTOFMEMORY;
2933 comment = (WS_XML_COMMENT_NODE *)node;
2934 if (!(comment->value.bytes = malloc( len )))
2936 free( node );
2937 return E_OUTOFMEMORY;
2939 if ((hr = read_bytes( reader, comment->value.bytes, len )) != S_OK)
2941 free_node( node );
2942 return E_OUTOFMEMORY;
2944 comment->value.length = len;
2946 read_insert_node( reader, parent, node );
2947 reader->state = READER_STATE_COMMENT;
2948 return S_OK;
2951 static HRESULT read_startcdata( struct reader *reader )
2953 struct node *node, *endnode, *parent;
2954 HRESULT hr;
2956 if ((hr = read_cmp( reader, "<![CDATA[", 9 )) != S_OK) return hr;
2957 read_skip( reader, 9 );
2959 if (!(parent = find_parent( reader ))) return WS_E_INVALID_FORMAT;
2961 if (!(node = alloc_node( WS_XML_NODE_TYPE_CDATA ))) return E_OUTOFMEMORY;
2962 if (!(endnode = alloc_node( WS_XML_NODE_TYPE_END_CDATA )))
2964 free( node );
2965 return E_OUTOFMEMORY;
2967 list_add_tail( &node->children, &endnode->entry );
2968 endnode->parent = node;
2970 read_insert_node( reader, parent, node );
2971 reader->state = READER_STATE_STARTCDATA;
2972 return S_OK;
2975 static HRESULT read_cdata( struct reader *reader )
2977 unsigned int len = 0, ch, skip;
2978 const unsigned char *start;
2979 struct node *node;
2980 WS_XML_TEXT_NODE *text;
2981 WS_XML_UTF8_TEXT *utf8;
2982 HRESULT hr;
2984 start = read_current_ptr( reader );
2985 for (;;)
2987 if (read_cmp( reader, "]]>", 3 ) == S_OK) break;
2988 if ((hr = read_utf8_char( reader, &ch, &skip )) != S_OK) return hr;
2989 read_skip( reader, skip );
2990 len += skip;
2993 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return E_OUTOFMEMORY;
2994 text = (WS_XML_TEXT_NODE *)node;
2995 if (!(utf8 = alloc_utf8_text( start, len )))
2997 free( node );
2998 return E_OUTOFMEMORY;
3000 text->text = &utf8->text;
3002 read_insert_node( reader, reader->current, node );
3003 reader->state = READER_STATE_CDATA;
3004 return S_OK;
3007 static HRESULT read_endcdata( struct reader *reader )
3009 struct node *parent;
3010 HRESULT hr;
3012 if ((hr = read_cmp( reader, "]]>", 3 )) != S_OK) return hr;
3013 read_skip( reader, 3 );
3015 if (node_type( reader->current ) == WS_XML_NODE_TYPE_TEXT) parent = reader->current->parent;
3016 else parent = reader->current;
3018 reader->current = LIST_ENTRY( list_tail( &parent->children ), struct node, entry );
3019 reader->last = reader->current;
3020 reader->state = READER_STATE_ENDCDATA;
3021 return S_OK;
3024 static HRESULT read_node_text( struct reader *reader )
3026 HRESULT hr;
3028 for (;;)
3030 if (read_end_of_data( reader ))
3032 reader->current = LIST_ENTRY( list_tail( &reader->root->children ), struct node, entry );
3033 reader->last = reader->current;
3034 reader->state = READER_STATE_EOF;
3035 return S_OK;
3037 if (reader->state == READER_STATE_STARTCDATA) return read_cdata( reader );
3038 else if (reader->state == READER_STATE_CDATA) return read_endcdata( reader );
3039 else if (read_cmp( reader, "<?", 2 ) == S_OK)
3041 if ((hr = read_xmldecl( reader )) != S_OK) return hr;
3043 else if (read_cmp( reader, "</", 2 ) == S_OK) return read_endelement_text( reader );
3044 else if (read_cmp( reader, "<![CDATA[", 9 ) == S_OK) return read_startcdata( reader );
3045 else if (read_cmp( reader, "<!--", 4 ) == S_OK) return read_comment_text( reader );
3046 else if (read_cmp( reader, "<", 1 ) == S_OK) return read_element_text( reader );
3047 else if (read_cmp( reader, "/>", 2 ) == S_OK || read_cmp( reader, ">", 1 ) == S_OK)
3049 return read_startelement_text( reader );
3051 else return read_text_text( reader );
3055 static HRESULT read_node_bin( struct reader *reader )
3057 unsigned char type;
3058 HRESULT hr;
3060 if (reader->current->flags & NODE_FLAG_TEXT_WITH_IMPLICIT_END_ELEMENT)
3062 reader->current = LIST_ENTRY( list_tail( &reader->current->parent->children ), struct node, entry );
3063 reader->last = reader->current;
3064 reader->state = READER_STATE_ENDELEMENT;
3065 return S_OK;
3067 if (read_end_of_data( reader ))
3069 reader->current = LIST_ENTRY( list_tail( &reader->root->children ), struct node, entry );
3070 reader->last = reader->current;
3071 reader->state = READER_STATE_EOF;
3072 return S_OK;
3075 if ((hr = read_peek( reader, &type, 1 )) != S_OK) return hr;
3076 if (type == RECORD_ENDELEMENT)
3078 return read_endelement_bin( reader );
3080 else if (type == RECORD_COMMENT)
3082 return read_comment_bin( reader );
3084 else if (type >= RECORD_SHORT_ELEMENT && type <= RECORD_PREFIX_ELEMENT_Z)
3086 return read_element_bin( reader );
3088 else if (type >= RECORD_ZERO_TEXT && type <= RECORD_QNAME_DICTIONARY_TEXT_WITH_ENDELEMENT)
3090 return read_text_bin( reader );
3092 FIXME( "unhandled record type %02x\n", type );
3093 return WS_E_NOT_SUPPORTED;
3096 static HRESULT read_node( struct reader *reader )
3098 switch (reader->input_enc)
3100 case WS_XML_READER_ENCODING_TYPE_TEXT: return read_node_text( reader );
3101 case WS_XML_READER_ENCODING_TYPE_BINARY: return read_node_bin( reader );
3102 default:
3103 ERR( "unhandled encoding %u\n", reader->input_enc );
3104 return WS_E_NOT_SUPPORTED;
3108 HRESULT copy_node( WS_XML_READER *handle, WS_XML_WRITER_ENCODING_TYPE enc, struct node **node )
3110 struct reader *reader = (struct reader *)handle;
3111 const struct list *ptr;
3112 const struct node *start;
3113 HRESULT hr;
3115 EnterCriticalSection( &reader->cs );
3117 if (reader->magic != READER_MAGIC)
3119 LeaveCriticalSection( &reader->cs );
3120 return E_INVALIDARG;
3123 if (reader->current != reader->root) ptr = &reader->current->entry;
3124 else /* copy whole tree */
3126 if (!read_end_of_data( reader ))
3128 for (;;)
3130 if ((hr = read_node( reader )) != S_OK) goto done;
3131 if (node_type( reader->current ) == WS_XML_NODE_TYPE_EOF) break;
3134 ptr = list_head( &reader->root->children );
3137 start = LIST_ENTRY( ptr, struct node, entry );
3138 if (node_type( start ) == WS_XML_NODE_TYPE_EOF) hr = WS_E_INVALID_OPERATION;
3139 else hr = dup_tree( start, enc, node );
3141 done:
3142 LeaveCriticalSection( &reader->cs );
3143 return hr;
3146 /**************************************************************************
3147 * WsReadEndElement [webservices.@]
3149 HRESULT WINAPI WsReadEndElement( WS_XML_READER *handle, WS_ERROR *error )
3151 struct reader *reader = (struct reader *)handle;
3152 HRESULT hr;
3154 TRACE( "%p %p\n", handle, error );
3155 if (error) FIXME( "ignoring error parameter\n" );
3157 if (!reader) return E_INVALIDARG;
3159 EnterCriticalSection( &reader->cs );
3161 if (reader->magic != READER_MAGIC)
3163 LeaveCriticalSection( &reader->cs );
3164 return E_INVALIDARG;
3167 hr = read_endelement( reader );
3169 LeaveCriticalSection( &reader->cs );
3170 TRACE( "returning %#lx\n", hr );
3171 return hr;
3174 /**************************************************************************
3175 * WsReadNode [webservices.@]
3177 HRESULT WINAPI WsReadNode( WS_XML_READER *handle, WS_ERROR *error )
3179 struct reader *reader = (struct reader *)handle;
3180 HRESULT hr;
3182 TRACE( "%p %p\n", handle, 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 hr = read_node( reader );
3197 LeaveCriticalSection( &reader->cs );
3198 TRACE( "returning %#lx\n", hr );
3199 return hr;
3202 static HRESULT skip_node( struct reader *reader )
3204 const struct node *parent;
3205 HRESULT hr;
3207 if (node_type( reader->current ) == WS_XML_NODE_TYPE_EOF) return WS_E_INVALID_OPERATION;
3208 if (node_type( reader->current ) == WS_XML_NODE_TYPE_ELEMENT) parent = reader->current;
3209 else parent = NULL;
3211 for (;;)
3213 if ((hr = read_node( reader )) != S_OK || !parent) break;
3214 if (node_type( reader->current ) != WS_XML_NODE_TYPE_END_ELEMENT) continue;
3215 if (reader->current->parent == parent) return read_node( reader );
3218 return hr;
3221 /**************************************************************************
3222 * WsSkipNode [webservices.@]
3224 HRESULT WINAPI WsSkipNode( WS_XML_READER *handle, WS_ERROR *error )
3226 struct reader *reader = (struct reader *)handle;
3227 HRESULT hr;
3229 TRACE( "%p %p\n", handle, error );
3230 if (error) FIXME( "ignoring error parameter\n" );
3232 if (!reader) return E_INVALIDARG;
3234 EnterCriticalSection( &reader->cs );
3236 if (reader->magic != READER_MAGIC)
3238 LeaveCriticalSection( &reader->cs );
3239 return E_INVALIDARG;
3242 hr = skip_node( reader );
3244 LeaveCriticalSection( &reader->cs );
3245 TRACE( "returning %#lx\n", hr );
3246 return hr;
3249 /**************************************************************************
3250 * WsReadStartElement [webservices.@]
3252 HRESULT WINAPI WsReadStartElement( WS_XML_READER *handle, WS_ERROR *error )
3254 struct reader *reader = (struct reader *)handle;
3255 HRESULT hr;
3257 TRACE( "%p %p\n", handle, error );
3258 if (error) FIXME( "ignoring error parameter\n" );
3260 if (!reader) return E_INVALIDARG;
3262 EnterCriticalSection( &reader->cs );
3264 if (reader->magic != READER_MAGIC)
3266 LeaveCriticalSection( &reader->cs );
3267 return E_INVALIDARG;
3270 hr = read_startelement( reader );
3272 LeaveCriticalSection( &reader->cs );
3273 TRACE( "returning %#lx\n", hr );
3274 return hr;
3277 /**************************************************************************
3278 * WsReadToStartElement [webservices.@]
3280 HRESULT WINAPI WsReadToStartElement( WS_XML_READER *handle, const WS_XML_STRING *localname,
3281 const WS_XML_STRING *ns, BOOL *found, WS_ERROR *error )
3283 struct reader *reader = (struct reader *)handle;
3284 HRESULT hr;
3286 TRACE( "%p %s %s %p %p\n", handle, debugstr_xmlstr(localname), debugstr_xmlstr(ns), found, error );
3287 if (error) FIXME( "ignoring error parameter\n" );
3289 if (!reader) return E_INVALIDARG;
3290 if (localname || ns) FIXME( "name and/or namespace not verified\n" );
3292 EnterCriticalSection( &reader->cs );
3294 if (reader->magic != READER_MAGIC)
3296 LeaveCriticalSection( &reader->cs );
3297 return E_INVALIDARG;
3300 hr = read_to_startelement( reader, found );
3302 LeaveCriticalSection( &reader->cs );
3303 TRACE( "returning %#lx\n", hr );
3304 return hr;
3307 BOOL move_to_root_element( struct node *root, struct node **current )
3309 struct list *ptr;
3310 struct node *node;
3312 if (!(ptr = list_head( &root->children ))) return FALSE;
3313 node = LIST_ENTRY( ptr, struct node, entry );
3314 if (node_type( node ) == WS_XML_NODE_TYPE_ELEMENT)
3316 *current = node;
3317 return TRUE;
3319 while ((ptr = list_next( &root->children, &node->entry )))
3321 struct node *next = LIST_ENTRY( ptr, struct node, entry );
3322 if (node_type( next ) == WS_XML_NODE_TYPE_ELEMENT)
3324 *current = next;
3325 return TRUE;
3327 node = next;
3329 return FALSE;
3332 BOOL move_to_next_element( struct node **current )
3334 struct list *ptr;
3335 struct node *node = *current, *parent = (*current)->parent;
3337 if (!parent) return FALSE;
3338 while ((ptr = list_next( &parent->children, &node->entry )))
3340 struct node *next = LIST_ENTRY( ptr, struct node, entry );
3341 if (node_type( next ) == WS_XML_NODE_TYPE_ELEMENT)
3343 *current = next;
3344 return TRUE;
3346 node = next;
3348 return FALSE;
3351 BOOL move_to_prev_element( struct node **current )
3353 struct list *ptr;
3354 struct node *node = *current, *parent = (*current)->parent;
3356 if (!parent) return FALSE;
3357 while ((ptr = list_prev( &parent->children, &node->entry )))
3359 struct node *prev = LIST_ENTRY( ptr, struct node, entry );
3360 if (node_type( prev ) == WS_XML_NODE_TYPE_ELEMENT)
3362 *current = prev;
3363 return TRUE;
3365 node = prev;
3367 return FALSE;
3370 BOOL move_to_child_element( struct node **current )
3372 struct list *ptr;
3373 struct node *child, *node = *current;
3375 if (!(ptr = list_head( &node->children ))) return FALSE;
3376 child = LIST_ENTRY( ptr, struct node, entry );
3377 if (node_type( child ) == WS_XML_NODE_TYPE_ELEMENT)
3379 *current = child;
3380 return TRUE;
3382 while ((ptr = list_next( &node->children, &child->entry )))
3384 struct node *next = LIST_ENTRY( ptr, struct node, entry );
3385 if (node_type( next ) == WS_XML_NODE_TYPE_ELEMENT)
3387 *current = next;
3388 return TRUE;
3390 child = next;
3392 return FALSE;
3395 BOOL move_to_end_element( struct node **current )
3397 struct list *ptr;
3398 struct node *node = *current;
3400 if (node_type( node ) != WS_XML_NODE_TYPE_ELEMENT) return FALSE;
3402 if ((ptr = list_tail( &node->children )))
3404 struct node *tail = LIST_ENTRY( ptr, struct node, entry );
3405 if (node_type( tail ) == WS_XML_NODE_TYPE_END_ELEMENT)
3407 *current = tail;
3408 return TRUE;
3411 return FALSE;
3414 BOOL move_to_parent_element( struct node **current )
3416 struct node *parent = (*current)->parent;
3418 if (parent && (node_type( parent ) == WS_XML_NODE_TYPE_ELEMENT ||
3419 node_type( parent ) == WS_XML_NODE_TYPE_BOF))
3421 *current = parent;
3422 return TRUE;
3424 return FALSE;
3427 BOOL move_to_first_node( struct node **current )
3429 struct list *ptr;
3430 struct node *node = *current;
3432 if ((ptr = list_head( &node->parent->children )))
3434 *current = LIST_ENTRY( ptr, struct node, entry );
3435 return TRUE;
3437 return FALSE;
3440 BOOL move_to_next_node( struct node **current )
3442 struct list *ptr;
3443 struct node *node = *current;
3445 if ((ptr = list_next( &node->parent->children, &node->entry )))
3447 *current = LIST_ENTRY( ptr, struct node, entry );
3448 return TRUE;
3450 return FALSE;
3453 BOOL move_to_prev_node( struct node **current )
3455 struct list *ptr;
3456 struct node *node = *current;
3458 if ((ptr = list_prev( &node->parent->children, &node->entry )))
3460 *current = LIST_ENTRY( ptr, struct node, entry );
3461 return TRUE;
3463 return FALSE;
3466 BOOL move_to_bof( struct node *root, struct node **current )
3468 *current = root;
3469 return TRUE;
3472 BOOL move_to_eof( struct node *root, struct node **current )
3474 struct list *ptr;
3475 if ((ptr = list_tail( &root->children )))
3477 *current = LIST_ENTRY( ptr, struct node, entry );
3478 return TRUE;
3480 return FALSE;
3483 BOOL move_to_child_node( struct node **current )
3485 struct list *ptr;
3486 struct node *node = *current;
3488 if ((ptr = list_head( &node->children )))
3490 *current = LIST_ENTRY( ptr, struct node, entry );
3491 return TRUE;
3493 return FALSE;
3496 BOOL move_to_parent_node( struct node **current )
3498 struct node *parent = (*current)->parent;
3499 if (!parent) return FALSE;
3500 *current = parent;
3501 return TRUE;
3504 static HRESULT read_move_to( struct reader *reader, WS_MOVE_TO move, BOOL *found )
3506 BOOL success = FALSE;
3507 HRESULT hr = S_OK;
3509 if (!read_end_of_data( reader ))
3511 struct node *saved_current = reader->current;
3512 while (reader->state != READER_STATE_EOF && (hr = read_node( reader )) == S_OK) { /* nothing */ };
3513 if (hr != S_OK) return hr;
3514 reader->current = saved_current;
3516 switch (move)
3518 case WS_MOVE_TO_ROOT_ELEMENT:
3519 success = move_to_root_element( reader->root, &reader->current );
3520 break;
3522 case WS_MOVE_TO_NEXT_ELEMENT:
3523 success = move_to_next_element( &reader->current );
3524 break;
3526 case WS_MOVE_TO_PREVIOUS_ELEMENT:
3527 success = move_to_prev_element( &reader->current );
3528 break;
3530 case WS_MOVE_TO_CHILD_ELEMENT:
3531 success = move_to_child_element( &reader->current );
3532 break;
3534 case WS_MOVE_TO_END_ELEMENT:
3535 success = move_to_end_element( &reader->current );
3536 break;
3538 case WS_MOVE_TO_PARENT_ELEMENT:
3539 success = move_to_parent_element( &reader->current );
3540 break;
3542 case WS_MOVE_TO_FIRST_NODE:
3543 success = move_to_first_node( &reader->current );
3544 break;
3546 case WS_MOVE_TO_NEXT_NODE:
3547 success = move_to_next_node( &reader->current );
3548 break;
3550 case WS_MOVE_TO_PREVIOUS_NODE:
3551 success = move_to_prev_node( &reader->current );
3552 break;
3554 case WS_MOVE_TO_CHILD_NODE:
3555 success = move_to_child_node( &reader->current );
3556 break;
3558 case WS_MOVE_TO_BOF:
3559 success = move_to_bof( reader->root, &reader->current );
3560 break;
3562 case WS_MOVE_TO_EOF:
3563 success = move_to_eof( reader->root, &reader->current );
3564 break;
3566 default:
3567 FIXME( "unhandled move %u\n", move );
3568 return E_NOTIMPL;
3571 if (found)
3573 *found = success;
3574 return S_OK;
3576 return success ? S_OK : WS_E_INVALID_FORMAT;
3579 /**************************************************************************
3580 * WsMoveReader [webservices.@]
3582 HRESULT WINAPI WsMoveReader( WS_XML_READER *handle, WS_MOVE_TO move, BOOL *found, WS_ERROR *error )
3584 struct reader *reader = (struct reader *)handle;
3585 HRESULT hr;
3587 TRACE( "%p %u %p %p\n", handle, move, found, error );
3588 if (error) FIXME( "ignoring error parameter\n" );
3590 if (!reader) return E_INVALIDARG;
3592 EnterCriticalSection( &reader->cs );
3594 if (reader->magic != READER_MAGIC)
3596 LeaveCriticalSection( &reader->cs );
3597 return E_INVALIDARG;
3600 if (reader->input_type != WS_XML_READER_INPUT_TYPE_BUFFER) hr = WS_E_INVALID_OPERATION;
3601 else hr = read_move_to( reader, move, found );
3603 LeaveCriticalSection( &reader->cs );
3604 TRACE( "returning %#lx\n", hr );
3605 return hr;
3608 /**************************************************************************
3609 * WsReadStartAttribute [webservices.@]
3611 HRESULT WINAPI WsReadStartAttribute( WS_XML_READER *handle, ULONG index, WS_ERROR *error )
3613 struct reader *reader = (struct reader *)handle;
3614 const WS_XML_ELEMENT_NODE *elem;
3615 HRESULT hr = S_OK;
3617 TRACE( "%p %lu %p\n", handle, index, error );
3618 if (error) FIXME( "ignoring error parameter\n" );
3620 if (!reader) return E_INVALIDARG;
3622 EnterCriticalSection( &reader->cs );
3624 if (reader->magic != READER_MAGIC)
3626 LeaveCriticalSection( &reader->cs );
3627 return E_INVALIDARG;
3630 elem = &reader->current->hdr;
3631 if (reader->state != READER_STATE_STARTELEMENT || index >= elem->attributeCount) hr = WS_E_INVALID_FORMAT;
3632 else
3634 reader->current_attr = index;
3635 reader->state = READER_STATE_STARTATTRIBUTE;
3638 LeaveCriticalSection( &reader->cs );
3639 TRACE( "returning %#lx\n", hr );
3640 return S_OK;
3643 /**************************************************************************
3644 * WsReadEndAttribute [webservices.@]
3646 HRESULT WINAPI WsReadEndAttribute( WS_XML_READER *handle, WS_ERROR *error )
3648 struct reader *reader = (struct reader *)handle;
3649 HRESULT hr = S_OK;
3651 TRACE( "%p %p\n", handle, error );
3652 if (error) FIXME( "ignoring error parameter\n" );
3654 if (!reader) return E_INVALIDARG;
3656 EnterCriticalSection( &reader->cs );
3658 if (reader->magic != READER_MAGIC)
3660 LeaveCriticalSection( &reader->cs );
3661 return E_INVALIDARG;
3664 if (reader->state != READER_STATE_STARTATTRIBUTE) hr = WS_E_INVALID_FORMAT;
3665 else reader->state = READER_STATE_STARTELEMENT;
3667 LeaveCriticalSection( &reader->cs );
3668 TRACE( "returning %#lx\n", hr );
3669 return hr;
3672 static HRESULT str_to_bool( const unsigned char *str, ULONG len, BOOL *ret )
3674 if (len == 4 && !memcmp( str, "true", 4 )) *ret = TRUE;
3675 else if (len == 1 && !memcmp( str, "1", 1 )) *ret = TRUE;
3676 else if (len == 5 && !memcmp( str, "false", 5 )) *ret = FALSE;
3677 else if (len == 1 && !memcmp( str, "0", 1 )) *ret = FALSE;
3678 else return WS_E_INVALID_FORMAT;
3679 return S_OK;
3682 static HRESULT str_to_int64( const unsigned char *str, ULONG len, INT64 min, INT64 max, INT64 *ret )
3684 BOOL negative = FALSE;
3685 const unsigned char *ptr = str;
3687 *ret = 0;
3688 while (len && read_isspace( *ptr )) { ptr++; len--; }
3689 while (len && read_isspace( ptr[len - 1] )) { len--; }
3690 if (!len) return WS_E_INVALID_FORMAT;
3692 if (*ptr == '-')
3694 negative = TRUE;
3695 ptr++;
3696 len--;
3698 if (!len) return WS_E_INVALID_FORMAT;
3700 while (len--)
3702 int val;
3704 if (!isdigit( *ptr )) return WS_E_INVALID_FORMAT;
3705 val = *ptr - '0';
3706 if (negative) val = -val;
3708 if ((!negative && (*ret > max / 10 || *ret * 10 > max - val)) ||
3709 (negative && (*ret < min / 10 || *ret * 10 < min - val)))
3711 return WS_E_NUMERIC_OVERFLOW;
3713 *ret = *ret * 10 + val;
3714 ptr++;
3717 return S_OK;
3720 static HRESULT str_to_uint64( const unsigned char *str, ULONG len, UINT64 max, UINT64 *ret )
3722 const unsigned char *ptr = str;
3724 *ret = 0;
3725 while (len && read_isspace( *ptr )) { ptr++; len--; }
3726 while (len && read_isspace( ptr[len - 1] )) { len--; }
3727 if (!len) return WS_E_INVALID_FORMAT;
3729 while (len--)
3731 unsigned int val;
3733 if (!isdigit( *ptr )) return WS_E_INVALID_FORMAT;
3734 val = *ptr - '0';
3736 if ((*ret > max / 10 || *ret * 10 > max - val)) return WS_E_NUMERIC_OVERFLOW;
3737 *ret = *ret * 10 + val;
3738 ptr++;
3741 return S_OK;
3744 static HRESULT str_to_double( const unsigned char *str, ULONG len, double *ret )
3746 BOOL found_sign = FALSE, found_exponent = FALSE, found_digit = FALSE, found_decimal = FALSE;
3747 static const unsigned __int64 nan = 0xfff8000000000000;
3748 static const unsigned __int64 inf = 0x7ff0000000000000;
3749 static const unsigned __int64 inf_min = 0xfff0000000000000;
3750 const char *p = (const char *)str;
3751 double tmp;
3752 ULONG i;
3754 while (len && read_isspace( *p )) { p++; len--; }
3755 while (len && read_isspace( p[len - 1] )) { len--; }
3756 if (!len) return WS_E_INVALID_FORMAT;
3758 if (len == 3 && !memcmp( p, "NaN", 3 ))
3760 *(unsigned __int64 *)ret = nan;
3761 return S_OK;
3763 if (len == 3 && !memcmp( p, "INF", 3 ))
3765 *(unsigned __int64 *)ret = inf;
3766 return S_OK;
3768 if (len == 4 && !memcmp( p, "-INF", 4 ))
3770 *(unsigned __int64 *)ret = inf_min;
3771 return S_OK;
3774 for (i = 0; i < len; i++)
3776 if (p[i] >= '0' && p[i] <= '9')
3778 found_digit = TRUE;
3779 continue;
3781 if (!found_sign && !found_digit && (p[i] == '+' || p[i] == '-'))
3783 found_sign = TRUE;
3784 continue;
3786 if (!found_exponent && found_digit && (p[i] == 'e' || p[i] == 'E'))
3788 found_exponent = found_decimal = TRUE;
3789 found_digit = found_sign = FALSE;
3790 continue;
3792 if (!found_decimal && p[i] == '.')
3794 found_decimal = TRUE;
3795 continue;
3797 return WS_E_INVALID_FORMAT;
3799 if (!found_digit && !found_exponent)
3801 *ret = 0;
3802 return S_OK;
3805 if (_snscanf_l( p, len, "%lf", c_locale, &tmp ) != 1) return WS_E_INVALID_FORMAT;
3806 *ret = tmp;
3807 return S_OK;
3810 static HRESULT str_to_float( const unsigned char *str, ULONG len, float *ret )
3812 static const unsigned int inf = 0x7f800000;
3813 static const unsigned int inf_min = 0xff800000;
3814 const unsigned char *p = str;
3815 double val;
3816 HRESULT hr;
3818 while (len && read_isspace( *p )) { p++; len--; }
3819 while (len && read_isspace( p[len - 1] )) { len--; }
3820 if (!len) return WS_E_INVALID_FORMAT;
3822 if (len == 3 && !memcmp( p, "INF", 3 ))
3824 *(unsigned int *)ret = inf;
3825 return S_OK;
3827 if (len == 4 && !memcmp( p, "-INF", 4 ))
3829 *(unsigned int *)ret = inf_min;
3830 return S_OK;
3833 if ((hr = str_to_double( p, len, &val )) != S_OK) return hr;
3834 *ret = val;
3835 return S_OK;
3838 HRESULT str_to_guid( const unsigned char *str, ULONG len, GUID *ret )
3840 static const unsigned char hex[] =
3842 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x00 */
3843 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x10 */
3844 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x20 */
3845 0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0, /* 0x30 */
3846 0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0, /* 0x40 */
3847 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x50 */
3848 0,10,11,12,13,14,15 /* 0x60 */
3850 const unsigned char *p = str;
3851 ULONG i;
3853 while (len && read_isspace( *p )) { p++; len--; }
3854 while (len && read_isspace( p[len - 1] )) { len--; }
3855 if (len != 36) return WS_E_INVALID_FORMAT;
3857 if (p[8] != '-' || p[13] != '-' || p[18] != '-' || p[23] != '-')
3858 return WS_E_INVALID_FORMAT;
3860 for (i = 0; i < 36; i++)
3862 if (i == 8 || i == 13 || i == 18 || i == 23) continue;
3863 if (p[i] > 'f' || (!hex[p[i]] && p[i] != '0')) return WS_E_INVALID_FORMAT;
3866 ret->Data1 = hex[p[0]] << 28 | hex[p[1]] << 24 | hex[p[2]] << 20 | hex[p[3]] << 16 |
3867 hex[p[4]] << 12 | hex[p[5]] << 8 | hex[p[6]] << 4 | hex[p[7]];
3869 ret->Data2 = hex[p[9]] << 12 | hex[p[10]] << 8 | hex[p[11]] << 4 | hex[p[12]];
3870 ret->Data3 = hex[p[14]] << 12 | hex[p[15]] << 8 | hex[p[16]] << 4 | hex[p[17]];
3872 ret->Data4[0] = hex[p[19]] << 4 | hex[p[20]];
3873 ret->Data4[1] = hex[p[21]] << 4 | hex[p[22]];
3874 ret->Data4[2] = hex[p[24]] << 4 | hex[p[25]];
3875 ret->Data4[3] = hex[p[26]] << 4 | hex[p[27]];
3876 ret->Data4[4] = hex[p[28]] << 4 | hex[p[29]];
3877 ret->Data4[5] = hex[p[30]] << 4 | hex[p[31]];
3878 ret->Data4[6] = hex[p[32]] << 4 | hex[p[33]];
3879 ret->Data4[7] = hex[p[34]] << 4 | hex[p[35]];
3881 return S_OK;
3884 static HRESULT str_to_string( const unsigned char *str, ULONG len, WS_HEAP *heap, WS_STRING *ret )
3886 int len_utf16 = MultiByteToWideChar( CP_UTF8, 0, (const char *)str, len, NULL, 0 );
3887 if (!(ret->chars = ws_alloc( heap, len_utf16 * sizeof(WCHAR) ))) return WS_E_QUOTA_EXCEEDED;
3888 MultiByteToWideChar( CP_UTF8, 0, (const char *)str, len, ret->chars, len_utf16 );
3889 ret->length = len_utf16;
3890 return S_OK;
3893 static HRESULT str_to_unique_id( const unsigned char *str, ULONG len, WS_HEAP *heap, WS_UNIQUE_ID *ret )
3895 if (len == 45 && !memcmp( str, "urn:uuid:", 9 ))
3897 ret->uri.length = 0;
3898 ret->uri.chars = NULL;
3899 return str_to_guid( str + 9, len - 9, &ret->guid );
3902 memset( &ret->guid, 0, sizeof(ret->guid) );
3903 return str_to_string( str, len, heap, &ret->uri );
3906 static inline unsigned char decode_char( unsigned char c )
3908 if (c >= 'A' && c <= 'Z') return c - 'A';
3909 if (c >= 'a' && c <= 'z') return c - 'a' + 26;
3910 if (c >= '0' && c <= '9') return c - '0' + 52;
3911 if (c == '+') return 62;
3912 if (c == '/') return 63;
3913 return 64;
3916 static ULONG decode_base64( const unsigned char *base64, ULONG len, unsigned char *buf )
3918 ULONG i = 0;
3919 unsigned char c0, c1, c2, c3;
3920 const unsigned char *p = base64;
3922 while (len > 4)
3924 if ((c0 = decode_char( p[0] )) > 63) return 0;
3925 if ((c1 = decode_char( p[1] )) > 63) return 0;
3926 if ((c2 = decode_char( p[2] )) > 63) return 0;
3927 if ((c3 = decode_char( p[3] )) > 63) return 0;
3928 buf[i + 0] = (c0 << 2) | (c1 >> 4);
3929 buf[i + 1] = (c1 << 4) | (c2 >> 2);
3930 buf[i + 2] = (c2 << 6) | c3;
3931 len -= 4;
3932 i += 3;
3933 p += 4;
3935 if (p[2] == '=')
3937 if ((c0 = decode_char( p[0] )) > 63) return 0;
3938 if ((c1 = decode_char( p[1] )) > 63) return 0;
3939 buf[i] = (c0 << 2) | (c1 >> 4);
3940 i++;
3942 else if (p[3] == '=')
3944 if ((c0 = decode_char( p[0] )) > 63) return 0;
3945 if ((c1 = decode_char( p[1] )) > 63) return 0;
3946 if ((c2 = decode_char( p[2] )) > 63) return 0;
3947 buf[i + 0] = (c0 << 2) | (c1 >> 4);
3948 buf[i + 1] = (c1 << 4) | (c2 >> 2);
3949 i += 2;
3951 else
3953 if ((c0 = decode_char( p[0] )) > 63) return 0;
3954 if ((c1 = decode_char( p[1] )) > 63) return 0;
3955 if ((c2 = decode_char( p[2] )) > 63) return 0;
3956 if ((c3 = decode_char( p[3] )) > 63) return 0;
3957 buf[i + 0] = (c0 << 2) | (c1 >> 4);
3958 buf[i + 1] = (c1 << 4) | (c2 >> 2);
3959 buf[i + 2] = (c2 << 6) | c3;
3960 i += 3;
3962 return i;
3965 static HRESULT str_to_bytes( const unsigned char *str, ULONG len, WS_HEAP *heap, WS_BYTES *ret )
3967 const unsigned char *p = str;
3969 while (len && read_isspace( *p )) { p++; len--; }
3970 while (len && read_isspace( p[len - 1] )) { len--; }
3972 if (len % 4) return WS_E_INVALID_FORMAT;
3973 if (!(ret->bytes = ws_alloc( heap, len * 3 / 4 ))) return WS_E_QUOTA_EXCEEDED;
3974 ret->length = decode_base64( p, len, ret->bytes );
3975 return S_OK;
3978 static HRESULT str_to_xml_string( const unsigned char *str, ULONG len, WS_HEAP *heap, WS_XML_STRING *ret )
3980 if (!(ret->bytes = ws_alloc( heap, len ))) return WS_E_QUOTA_EXCEEDED;
3981 memcpy( ret->bytes, str, len );
3982 ret->length = len;
3983 ret->dictionary = NULL;
3984 ret->id = 0;
3985 return S_OK;
3988 static HRESULT copy_xml_string( WS_HEAP *heap, const WS_XML_STRING *src, WS_XML_STRING *dst )
3990 if (!(dst->bytes = ws_alloc( heap, src->length ))) return WS_E_QUOTA_EXCEEDED;
3991 memcpy( dst->bytes, src->bytes, src->length );
3992 dst->length = src->length;
3993 return S_OK;
3996 static HRESULT str_to_qname( struct reader *reader, const unsigned char *str, ULONG len, WS_HEAP *heap,
3997 WS_XML_STRING *prefix_ret, WS_XML_STRING *localname_ret, WS_XML_STRING *ns_ret )
3999 const unsigned char *p = str;
4000 WS_XML_STRING prefix, localname;
4001 const WS_XML_STRING *ns;
4002 HRESULT hr;
4004 while (len && read_isspace( *p )) { p++; len--; }
4005 while (len && read_isspace( p[len - 1] )) { len--; }
4007 if ((hr = split_qname( p, len, &prefix, &localname )) != S_OK) return hr;
4008 if (!(ns = get_namespace( reader, &prefix ))) return WS_E_INVALID_FORMAT;
4010 if (prefix_ret && (hr = copy_xml_string( heap, &prefix, prefix_ret )) != S_OK) return hr;
4011 if ((hr = copy_xml_string( heap, &localname, localname_ret )) != S_OK)
4013 ws_free( heap, prefix_ret->bytes, prefix_ret->length );
4014 return hr;
4016 if ((hr = copy_xml_string( heap, ns, ns_ret )) != S_OK)
4018 ws_free( heap, prefix_ret->bytes, prefix_ret->length );
4019 ws_free( heap, localname_ret->bytes, localname_ret->length );
4020 return hr;
4022 return S_OK;
4025 static HRESULT read_qualified_name( struct reader *reader, WS_HEAP *heap, WS_XML_STRING *prefix,
4026 WS_XML_STRING *localname, WS_XML_STRING *ns )
4028 const WS_XML_TEXT_NODE *node = (const WS_XML_TEXT_NODE *)reader->current;
4029 const WS_XML_UTF8_TEXT *utf8 = (const WS_XML_UTF8_TEXT *)node->text;
4030 return str_to_qname( reader, utf8->value.bytes, utf8->value.length, heap, prefix, localname, ns );
4033 /**************************************************************************
4034 * WsReadQualifiedName [webservices.@]
4036 HRESULT WINAPI WsReadQualifiedName( WS_XML_READER *handle, WS_HEAP *heap, WS_XML_STRING *prefix,
4037 WS_XML_STRING *localname, WS_XML_STRING *ns,
4038 WS_ERROR *error )
4040 struct reader *reader = (struct reader *)handle;
4041 HRESULT hr;
4043 TRACE( "%p %p %p %p %p %p\n", handle, heap, prefix, localname, ns, error );
4044 if (error) FIXME( "ignoring error parameter\n" );
4046 if (!reader || !heap) return E_INVALIDARG;
4048 EnterCriticalSection( &reader->cs );
4050 if (reader->magic != READER_MAGIC)
4052 LeaveCriticalSection( &reader->cs );
4053 return E_INVALIDARG;
4056 if (!reader->input_type) hr = WS_E_INVALID_OPERATION;
4057 else if (!localname) hr = E_INVALIDARG;
4058 else if (reader->state != READER_STATE_TEXT) hr = WS_E_INVALID_FORMAT;
4059 else hr = read_qualified_name( reader, heap, prefix, localname, ns );
4061 LeaveCriticalSection( &reader->cs );
4062 TRACE( "returning %#lx\n", hr );
4063 return hr;
4066 static const int month_offsets[2][12] =
4068 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},
4069 {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}
4072 static inline int valid_day( int year, int month, int day )
4074 return day > 0 && day <= month_days[leap_year( year )][month - 1];
4077 static inline int leap_days_before( int year )
4079 return (year - 1) / 4 - (year - 1) / 100 + (year - 1) / 400;
4082 static HRESULT str_to_datetime( const unsigned char *bytes, ULONG len, WS_DATETIME *ret )
4084 const unsigned char *p = bytes, *q;
4085 int year, month, day, hour, min, sec, sec_frac = 0, tz_hour, tz_min, tz_neg;
4087 while (len && read_isspace( *p )) { p++; len--; }
4088 while (len && read_isspace( p[len - 1] )) { len--; }
4090 q = p;
4091 while (len && isdigit( *q )) { q++; len--; };
4092 if (q - p != 4 || !len || *q != '-') return WS_E_INVALID_FORMAT;
4093 year = (p[0] - '0') * 1000 + (p[1] - '0') * 100 + (p[2] - '0') * 10 + p[3] - '0';
4094 if (year < 1) return WS_E_INVALID_FORMAT;
4096 p = ++q; len--;
4097 while (len && isdigit( *q )) { q++; len--; };
4098 if (q - p != 2 || !len || *q != '-') return WS_E_INVALID_FORMAT;
4099 month = (p[0] - '0') * 10 + p[1] - '0';
4100 if (month < 1 || month > 12) return WS_E_INVALID_FORMAT;
4102 p = ++q; len--;
4103 while (len && isdigit( *q )) { q++; len--; };
4104 if (q - p != 2 || !len || *q != 'T') return WS_E_INVALID_FORMAT;
4105 day = (p[0] - '0') * 10 + p[1] - '0';
4106 if (!valid_day( year, month, day )) return WS_E_INVALID_FORMAT;
4108 p = ++q; len--;
4109 while (len && isdigit( *q )) { q++; len--; };
4110 if (q - p != 2 || !len || *q != ':') return WS_E_INVALID_FORMAT;
4111 hour = (p[0] - '0') * 10 + p[1] - '0';
4112 if (hour > 24) return WS_E_INVALID_FORMAT;
4114 p = ++q; len--;
4115 while (len && isdigit( *q )) { q++; len--; };
4116 if (q - p != 2 || !len || *q != ':') return WS_E_INVALID_FORMAT;
4117 min = (p[0] - '0') * 10 + p[1] - '0';
4118 if (min > 59 || (min > 0 && hour == 24)) return WS_E_INVALID_FORMAT;
4120 p = ++q; len--;
4121 while (len && isdigit( *q )) { q++; len--; };
4122 if (q - p != 2 || !len) return WS_E_INVALID_FORMAT;
4123 sec = (p[0] - '0') * 10 + p[1] - '0';
4124 if (sec > 59 || (sec > 0 && hour == 24)) return WS_E_INVALID_FORMAT;
4126 if (*q == '.')
4128 unsigned int i, nb_digits, mul = TICKS_PER_SEC / 10;
4129 p = ++q; len--;
4130 while (len && isdigit( *q )) { q++; len--; };
4131 nb_digits = q - p;
4132 if (nb_digits < 1 || nb_digits > 7) return WS_E_INVALID_FORMAT;
4133 for (i = 0; i < nb_digits; i++)
4135 sec_frac += (p[i] - '0') * mul;
4136 mul /= 10;
4139 if (*q == 'Z')
4141 if (--len) return WS_E_INVALID_FORMAT;
4142 tz_hour = tz_min = tz_neg = 0;
4143 ret->format = WS_DATETIME_FORMAT_UTC;
4145 else if (*q == '+' || *q == '-')
4147 tz_neg = (*q == '-') ? 1 : 0;
4149 p = ++q; len--;
4150 while (len && isdigit( *q )) { q++; len--; };
4151 if (q - p != 2 || !len || *q != ':') return WS_E_INVALID_FORMAT;
4152 tz_hour = (p[0] - '0') * 10 + p[1] - '0';
4153 if (tz_hour > 14) return WS_E_INVALID_FORMAT;
4155 p = ++q; len--;
4156 while (len && isdigit( *q )) { q++; len--; };
4157 if (q - p != 2 || len) return WS_E_INVALID_FORMAT;
4158 tz_min = (p[0] - '0') * 10 + p[1] - '0';
4159 if (tz_min > 59 || (tz_min > 0 && tz_hour == 14)) return WS_E_INVALID_FORMAT;
4161 ret->format = WS_DATETIME_FORMAT_LOCAL;
4163 else return WS_E_INVALID_FORMAT;
4165 ret->ticks = ((year - 1) * 365 + leap_days_before( year )) * TICKS_PER_DAY;
4166 ret->ticks += month_offsets[leap_year( year )][month - 1] * TICKS_PER_DAY;
4167 ret->ticks += (day - 1) * TICKS_PER_DAY;
4168 ret->ticks += hour * TICKS_PER_HOUR;
4169 ret->ticks += min * TICKS_PER_MIN;
4170 ret->ticks += sec * TICKS_PER_SEC;
4171 ret->ticks += sec_frac;
4173 if (tz_neg)
4175 if (tz_hour * TICKS_PER_HOUR + tz_min * TICKS_PER_MIN + ret->ticks > TICKS_MAX)
4176 return WS_E_INVALID_FORMAT;
4177 ret->ticks += tz_hour * TICKS_PER_HOUR;
4178 ret->ticks += tz_min * TICKS_PER_MIN;
4180 else
4182 if (tz_hour * TICKS_PER_HOUR + tz_min * TICKS_PER_MIN > ret->ticks)
4183 return WS_E_INVALID_FORMAT;
4184 ret->ticks -= tz_hour * TICKS_PER_HOUR;
4185 ret->ticks -= tz_min * TICKS_PER_MIN;
4188 return S_OK;
4191 /**************************************************************************
4192 * WsDateTimeToFileTime [webservices.@]
4194 HRESULT WINAPI WsDateTimeToFileTime( const WS_DATETIME *dt, FILETIME *ft, WS_ERROR *error )
4196 unsigned __int64 ticks;
4198 TRACE( "%p %p %p\n", dt, ft, error );
4199 if (error) FIXME( "ignoring error parameter\n" );
4201 if (!dt || !ft) return E_INVALIDARG;
4203 if (dt->ticks < TICKS_1601_01_01) return WS_E_INVALID_FORMAT;
4204 ticks = dt->ticks - TICKS_1601_01_01;
4205 ft->dwHighDateTime = ticks >> 32;
4206 ft->dwLowDateTime = (DWORD)ticks;
4207 return S_OK;
4210 /**************************************************************************
4211 * WsFileTimeToDateTime [webservices.@]
4213 HRESULT WINAPI WsFileTimeToDateTime( const FILETIME *ft, WS_DATETIME *dt, WS_ERROR *error )
4215 unsigned __int64 ticks;
4217 TRACE( "%p %p %p\n", ft, dt, error );
4218 if (error) FIXME( "ignoring error parameter\n" );
4220 if (!dt || !ft) return E_INVALIDARG;
4222 ticks = ((unsigned __int64)ft->dwHighDateTime << 32) | ft->dwLowDateTime;
4223 if (ticks > MAX_UINT64 - TICKS_1601_01_01) return WS_E_NUMERIC_OVERFLOW;
4224 if (ticks + TICKS_1601_01_01 > TICKS_MAX) return WS_E_INVALID_FORMAT;
4225 dt->ticks = ticks + TICKS_1601_01_01;
4226 dt->format = WS_DATETIME_FORMAT_UTC;
4227 return S_OK;
4230 static BOOL find_attribute( struct reader *reader, const WS_XML_STRING *localname,
4231 const WS_XML_STRING *ns, ULONG *index )
4233 ULONG i;
4234 WS_XML_ELEMENT_NODE *elem = &reader->current->hdr;
4236 if (!localname)
4238 *index = reader->current_attr;
4239 return TRUE;
4241 for (i = 0; i < elem->attributeCount; i++)
4243 const WS_XML_STRING *localname2 = elem->attributes[i]->localName;
4244 const WS_XML_STRING *ns2 = elem->attributes[i]->ns;
4246 if (!cmp_name( localname->bytes, localname->length, localname2->bytes, localname2->length ) &&
4247 !cmp_name( ns->bytes, ns->length, ns2->bytes, ns2->length ))
4249 *index = i;
4250 return TRUE;
4253 return FALSE;
4256 /**************************************************************************
4257 * WsFindAttribute [webservices.@]
4259 HRESULT WINAPI WsFindAttribute( WS_XML_READER *handle, const WS_XML_STRING *localname,
4260 const WS_XML_STRING *ns, BOOL required, ULONG *index,
4261 WS_ERROR *error )
4263 struct reader *reader = (struct reader *)handle;
4264 HRESULT hr = S_OK;
4266 TRACE( "%p %s %s %d %p %p\n", handle, debugstr_xmlstr(localname), debugstr_xmlstr(ns),
4267 required, index, error );
4268 if (error) FIXME( "ignoring error parameter\n" );
4270 if (!reader || !localname || !ns || !index) return E_INVALIDARG;
4272 EnterCriticalSection( &reader->cs );
4274 if (reader->magic != READER_MAGIC)
4276 LeaveCriticalSection( &reader->cs );
4277 return E_INVALIDARG;
4280 if (node_type( reader->current ) != WS_XML_NODE_TYPE_ELEMENT) hr = WS_E_INVALID_OPERATION;
4281 else if (!find_attribute( reader, localname, ns, index ))
4283 if (required) hr = WS_E_INVALID_FORMAT;
4284 else
4286 *index = ~0u;
4287 hr = S_FALSE;
4291 LeaveCriticalSection( &reader->cs );
4292 TRACE( "returning %#lx\n", hr );
4293 return hr;
4296 static HRESULT get_node_text( struct reader *reader, const WS_XML_TEXT **ret )
4298 WS_XML_TEXT_NODE *node = (WS_XML_TEXT_NODE *)&reader->current->hdr.node;
4299 *ret = node->text;
4300 return S_OK;
4303 static HRESULT get_attribute_text( struct reader *reader, ULONG index, const WS_XML_TEXT **ret )
4305 WS_XML_ELEMENT_NODE *elem = &reader->current->hdr;
4306 *ret = elem->attributes[index]->value;
4307 return S_OK;
4310 static BOOL match_element( const struct node *node, const WS_XML_STRING *localname, const WS_XML_STRING *ns )
4312 const WS_XML_ELEMENT_NODE *elem = (const WS_XML_ELEMENT_NODE *)node;
4313 if (node_type( node ) != WS_XML_NODE_TYPE_ELEMENT) return FALSE;
4314 return WsXmlStringEquals( localname, elem->localName, NULL ) == S_OK &&
4315 (!ns || WsXmlStringEquals( ns, elem->ns, NULL ) == S_OK);
4318 static HRESULT read_next_node( struct reader *reader )
4320 if (reader->current == reader->last) return read_node( reader );
4321 if (move_to_child_node( &reader->current )) return S_OK;
4322 if (move_to_next_node( &reader->current )) return S_OK;
4323 if (!move_to_parent_node( &reader->current )) return WS_E_INVALID_FORMAT;
4324 if (move_to_next_node( &reader->current )) return S_OK;
4325 return WS_E_INVALID_FORMAT;
4328 struct reader_pos
4330 struct node *node;
4331 ULONG attr;
4334 static void save_reader_position( const struct reader *reader, struct reader_pos *pos )
4336 pos->node = reader->current;
4337 pos->attr = reader->current_attr;
4340 static void restore_reader_position( struct reader *reader, const struct reader_pos *pos )
4342 reader->current = pos->node;
4343 reader->current_attr = pos->attr;
4346 static HRESULT get_text( struct reader *reader, WS_TYPE_MAPPING mapping, const WS_XML_STRING *localname,
4347 const WS_XML_STRING *ns, const WS_XML_TEXT **ret, BOOL *found )
4349 switch (mapping)
4351 case WS_ATTRIBUTE_TYPE_MAPPING:
4353 ULONG i;
4354 WS_XML_ELEMENT_NODE *elem = &reader->current->hdr;
4356 *found = FALSE;
4357 for (i = 0; i < elem->attributeCount; i++)
4359 const WS_XML_STRING *localname2 = elem->attributes[i]->localName;
4360 const WS_XML_STRING *ns2 = elem->attributes[i]->ns;
4362 if (cmp_name( localname->bytes, localname->length, localname2->bytes, localname2->length )) continue;
4363 if (!ns->length || !cmp_name( ns->bytes, ns->length, ns2->bytes, ns2->length ))
4365 *found = TRUE;
4366 break;
4369 if (!*found) return S_OK;
4370 return get_attribute_text( reader, i, ret );
4372 case WS_ELEMENT_TYPE_MAPPING:
4373 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
4374 case WS_ANY_ELEMENT_TYPE_MAPPING:
4376 *found = TRUE;
4377 if (localname)
4379 struct reader_pos pos;
4380 HRESULT hr;
4382 if (!match_element( reader->current, localname, ns ))
4384 *found = FALSE;
4385 return S_OK;
4387 save_reader_position( reader, &pos );
4388 if ((hr = read_next_node( reader )) != S_OK) return hr;
4389 if (node_type( reader->current ) != WS_XML_NODE_TYPE_TEXT)
4391 restore_reader_position( reader, &pos );
4392 *found = FALSE;
4393 return S_OK;
4396 if (node_type( reader->current ) != WS_XML_NODE_TYPE_TEXT)
4398 *found = FALSE;
4399 return S_OK;
4401 return get_node_text( reader, ret );
4403 default:
4404 FIXME( "mapping %u not supported\n", mapping );
4405 return E_NOTIMPL;
4409 static HRESULT text_to_bool( const WS_XML_TEXT *text, BOOL *val )
4411 HRESULT hr;
4413 switch (text->textType)
4415 case WS_XML_TEXT_TYPE_UTF8:
4417 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
4418 hr = str_to_bool( text_utf8->value.bytes, text_utf8->value.length, val );
4419 break;
4421 case WS_XML_TEXT_TYPE_BOOL:
4423 const WS_XML_BOOL_TEXT *text_bool = (const WS_XML_BOOL_TEXT *)text;
4424 *val = text_bool->value;
4425 hr = S_OK;
4426 break;
4428 default:
4429 FIXME( "unhandled text type %u\n", text->textType );
4430 return E_NOTIMPL;
4433 return hr;
4436 static HRESULT read_type_bool( struct reader *reader, WS_TYPE_MAPPING mapping,
4437 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4438 const WS_BOOL_DESCRIPTION *desc, WS_READ_OPTION option,
4439 WS_HEAP *heap, void *ret, ULONG size, BOOL *found )
4441 const WS_XML_TEXT *text;
4442 HRESULT hr;
4443 BOOL val = FALSE;
4445 if (desc)
4447 FIXME( "description not supported\n" );
4448 return E_NOTIMPL;
4450 if ((hr = get_text( reader, mapping, localname, ns, &text, found )) != S_OK) return hr;
4451 if (*found && (hr = text_to_bool( text, &val )) != S_OK) return hr;
4453 switch (option)
4455 case WS_READ_REQUIRED_VALUE:
4456 if (!*found) return WS_E_INVALID_FORMAT;
4457 /* fall through */
4459 case WS_READ_NILLABLE_VALUE:
4460 if (size != sizeof(val)) return E_INVALIDARG;
4461 *(BOOL *)ret = val;
4462 break;
4464 case WS_READ_REQUIRED_POINTER:
4465 if (!*found) return WS_E_INVALID_FORMAT;
4466 /* fall through */
4468 case WS_READ_OPTIONAL_POINTER:
4469 case WS_READ_NILLABLE_POINTER:
4471 BOOL *heap_val = NULL;
4472 if (size != sizeof(heap_val)) return E_INVALIDARG;
4473 if (*found)
4475 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4476 *heap_val = val;
4478 *(BOOL **)ret = heap_val;
4479 break;
4481 default:
4482 FIXME( "read option %u not supported\n", option );
4483 return E_NOTIMPL;
4486 return S_OK;
4489 static HRESULT text_to_int8( const WS_XML_TEXT *text, INT64 *val )
4491 HRESULT hr;
4493 switch (text->textType)
4495 case WS_XML_TEXT_TYPE_UTF8:
4497 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
4498 hr = str_to_int64( text_utf8->value.bytes, text_utf8->value.length, MIN_INT8, MAX_INT8, val );
4499 break;
4501 case WS_XML_TEXT_TYPE_INT32:
4503 const WS_XML_INT32_TEXT *text_int32 = (const WS_XML_INT32_TEXT *)text;
4504 if (text_int32->value < MIN_INT8 || text_int32->value > MAX_INT8) return WS_E_NUMERIC_OVERFLOW;
4505 *val = text_int32->value;
4506 hr = S_OK;
4507 break;
4509 default:
4510 FIXME( "unhandled text type %u\n", text->textType );
4511 return E_NOTIMPL;
4514 return hr;
4517 static HRESULT read_type_int8( struct reader *reader, WS_TYPE_MAPPING mapping,
4518 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4519 const WS_INT8_DESCRIPTION *desc, WS_READ_OPTION option,
4520 WS_HEAP *heap, void *ret, ULONG size, BOOL *found )
4522 const WS_XML_TEXT *text;
4523 HRESULT hr;
4524 INT64 val = 0;
4526 if (desc)
4528 FIXME( "description not supported\n" );
4529 return E_NOTIMPL;
4531 if ((hr = get_text( reader, mapping, localname, ns, &text, found )) != S_OK) return hr;
4532 if (*found && (hr = text_to_int8( text, &val )) != S_OK) return hr;
4534 switch (option)
4536 case WS_READ_REQUIRED_VALUE:
4537 if (!*found) return WS_E_INVALID_FORMAT;
4538 /* fall through */
4540 case WS_READ_NILLABLE_VALUE:
4541 if (size != sizeof(INT8)) return E_INVALIDARG;
4542 *(INT8 *)ret = val;
4543 break;
4545 case WS_READ_REQUIRED_POINTER:
4546 if (!*found) return WS_E_INVALID_FORMAT;
4547 /* fall through */
4549 case WS_READ_OPTIONAL_POINTER:
4550 case WS_READ_NILLABLE_POINTER:
4552 INT8 *heap_val = NULL;
4553 if (size != sizeof(heap_val)) return E_INVALIDARG;
4554 if (*found)
4556 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4557 *heap_val = val;
4559 *(INT8 **)ret = heap_val;
4560 break;
4562 default:
4563 FIXME( "read option %u not supported\n", option );
4564 return E_NOTIMPL;
4567 return S_OK;
4570 static HRESULT text_to_int16( const WS_XML_TEXT *text, INT64 *val )
4572 HRESULT hr;
4574 switch (text->textType)
4576 case WS_XML_TEXT_TYPE_UTF8:
4578 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
4579 hr = str_to_int64( text_utf8->value.bytes, text_utf8->value.length, MIN_INT16, MAX_INT16, val );
4580 break;
4582 case WS_XML_TEXT_TYPE_INT32:
4584 const WS_XML_INT32_TEXT *text_int32 = (const WS_XML_INT32_TEXT *)text;
4585 if (text_int32->value < MIN_INT16 || text_int32->value > MAX_INT16) return WS_E_NUMERIC_OVERFLOW;
4586 *val = text_int32->value;
4587 hr = S_OK;
4588 break;
4590 default:
4591 FIXME( "unhandled text type %u\n", text->textType );
4592 return E_NOTIMPL;
4595 return hr;
4598 static HRESULT read_type_int16( struct reader *reader, WS_TYPE_MAPPING mapping,
4599 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4600 const WS_INT16_DESCRIPTION *desc, WS_READ_OPTION option,
4601 WS_HEAP *heap, void *ret, ULONG size, BOOL *found )
4603 const WS_XML_TEXT *text;
4604 HRESULT hr;
4605 INT64 val = 0;
4607 if (desc)
4609 FIXME( "description not supported\n" );
4610 return E_NOTIMPL;
4612 if ((hr = get_text( reader, mapping, localname, ns, &text, found )) != S_OK) return hr;
4613 if (*found && (hr = text_to_int16( text, &val )) != S_OK) return hr;
4615 switch (option)
4617 case WS_READ_REQUIRED_VALUE:
4618 if (!*found) return WS_E_INVALID_FORMAT;
4619 /* fall through */
4621 case WS_READ_NILLABLE_VALUE:
4622 if (size != sizeof(INT16)) return E_INVALIDARG;
4623 *(INT16 *)ret = val;
4624 break;
4626 case WS_READ_REQUIRED_POINTER:
4627 if (!*found) return WS_E_INVALID_FORMAT;
4628 /* fall through */
4630 case WS_READ_OPTIONAL_POINTER:
4631 case WS_READ_NILLABLE_POINTER:
4633 INT16 *heap_val = NULL;
4634 if (size != sizeof(heap_val)) return E_INVALIDARG;
4635 if (*found)
4637 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4638 *heap_val = val;
4640 *(INT16 **)ret = heap_val;
4641 break;
4643 default:
4644 FIXME( "read option %u not supported\n", option );
4645 return E_NOTIMPL;
4648 return S_OK;
4651 static HRESULT text_to_int32( const WS_XML_TEXT *text, INT64 *val )
4653 HRESULT hr;
4655 switch (text->textType)
4657 case WS_XML_TEXT_TYPE_UTF8:
4659 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
4660 hr = str_to_int64( text_utf8->value.bytes, text_utf8->value.length, MIN_INT32, MAX_INT32, val );
4661 break;
4663 case WS_XML_TEXT_TYPE_INT32:
4665 const WS_XML_INT32_TEXT *text_int32 = (const WS_XML_INT32_TEXT *)text;
4666 *val = text_int32->value;
4667 hr = S_OK;
4668 break;
4670 default:
4671 FIXME( "unhandled text type %u\n", text->textType );
4672 return E_NOTIMPL;
4675 return hr;
4678 static HRESULT read_type_int32( struct reader *reader, WS_TYPE_MAPPING mapping,
4679 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4680 const WS_INT32_DESCRIPTION *desc, WS_READ_OPTION option,
4681 WS_HEAP *heap, void *ret, ULONG size, BOOL *found )
4683 const WS_XML_TEXT *text;
4684 HRESULT hr;
4685 INT64 val = 0;
4687 if (desc)
4689 FIXME( "description not supported\n" );
4690 return E_NOTIMPL;
4692 if ((hr = get_text( reader, mapping, localname, ns, &text, found )) != S_OK) return hr;
4693 if (*found && (hr = text_to_int32( text, &val )) != S_OK) return hr;
4695 switch (option)
4697 case WS_READ_REQUIRED_VALUE:
4698 if (!*found) return WS_E_INVALID_FORMAT;
4699 /* fall through */
4701 case WS_READ_NILLABLE_VALUE:
4702 if (size != sizeof(INT32)) return E_INVALIDARG;
4703 *(INT32 *)ret = val;
4704 break;
4706 case WS_READ_REQUIRED_POINTER:
4707 if (!*found) return WS_E_INVALID_FORMAT;
4708 /* fall through */
4710 case WS_READ_OPTIONAL_POINTER:
4711 case WS_READ_NILLABLE_POINTER:
4713 INT32 *heap_val = NULL;
4714 if (size != sizeof(heap_val)) return E_INVALIDARG;
4715 if (*found)
4717 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4718 *heap_val = val;
4720 *(INT32 **)ret = heap_val;
4721 break;
4723 default:
4724 FIXME( "read option %u not supported\n", option );
4725 return E_NOTIMPL;
4728 return S_OK;
4731 static HRESULT text_to_int64( const WS_XML_TEXT *text, INT64 *val )
4733 HRESULT hr;
4735 switch (text->textType)
4737 case WS_XML_TEXT_TYPE_UTF8:
4739 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
4740 hr = str_to_int64( text_utf8->value.bytes, text_utf8->value.length, MIN_INT64, MAX_INT64, val );
4741 break;
4743 case WS_XML_TEXT_TYPE_INT64:
4745 const WS_XML_INT64_TEXT *text_int64 = (const WS_XML_INT64_TEXT *)text;
4746 *val = text_int64->value;
4747 hr = S_OK;
4748 break;
4750 default:
4751 FIXME( "unhandled text type %u\n", text->textType );
4752 return E_NOTIMPL;
4755 return hr;
4758 static HRESULT read_type_int64( struct reader *reader, WS_TYPE_MAPPING mapping,
4759 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4760 const WS_INT64_DESCRIPTION *desc, WS_READ_OPTION option,
4761 WS_HEAP *heap, void *ret, ULONG size, BOOL *found )
4763 const WS_XML_TEXT *text;
4764 HRESULT hr;
4765 INT64 val = 0;
4767 if (desc)
4769 FIXME( "description not supported\n" );
4770 return E_NOTIMPL;
4772 if ((hr = get_text( reader, mapping, localname, ns, &text, found )) != S_OK) return hr;
4773 if (*found && (hr = text_to_int64( text, &val )) != S_OK) return hr;
4775 switch (option)
4777 case WS_READ_REQUIRED_VALUE:
4778 if (!*found) return WS_E_INVALID_FORMAT;
4779 /* fall through */
4781 case WS_READ_NILLABLE_VALUE:
4782 if (size != sizeof(val)) return E_INVALIDARG;
4783 *(INT64 *)ret = val;
4784 break;
4786 case WS_READ_REQUIRED_POINTER:
4787 if (!*found) return WS_E_INVALID_FORMAT;
4788 /* fall through */
4790 case WS_READ_OPTIONAL_POINTER:
4791 case WS_READ_NILLABLE_POINTER:
4793 INT64 *heap_val = NULL;
4794 if (size != sizeof(heap_val)) return E_INVALIDARG;
4795 if (*found)
4797 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4798 *heap_val = val;
4800 *(INT64 **)ret = heap_val;
4801 break;
4803 default:
4804 FIXME( "read option %u not supported\n", option );
4805 return E_NOTIMPL;
4808 return S_OK;
4811 static HRESULT text_to_uint8( const WS_XML_TEXT *text, UINT64 *val )
4813 HRESULT hr;
4815 switch (text->textType)
4817 case WS_XML_TEXT_TYPE_UTF8:
4819 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
4820 hr = str_to_uint64( text_utf8->value.bytes, text_utf8->value.length, MAX_UINT8, val );
4821 break;
4823 case WS_XML_TEXT_TYPE_UINT64:
4825 const WS_XML_UINT64_TEXT *text_uint64 = (const WS_XML_UINT64_TEXT *)text;
4826 if (text_uint64->value > MAX_UINT8) return WS_E_NUMERIC_OVERFLOW;
4827 *val = text_uint64->value;
4828 hr = S_OK;
4829 break;
4831 default:
4832 FIXME( "unhandled text type %u\n", text->textType );
4833 return E_NOTIMPL;
4836 return hr;
4839 static HRESULT read_type_uint8( struct reader *reader, WS_TYPE_MAPPING mapping,
4840 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4841 const WS_UINT8_DESCRIPTION *desc, WS_READ_OPTION option,
4842 WS_HEAP *heap, void *ret, ULONG size, BOOL *found )
4844 const WS_XML_TEXT *text;
4845 HRESULT hr;
4846 UINT64 val = 0;
4848 if (desc)
4850 FIXME( "description not supported\n" );
4851 return E_NOTIMPL;
4853 if ((hr = get_text( reader, mapping, localname, ns, &text, found )) != S_OK) return hr;
4854 if (*found && (hr = text_to_uint8( text, &val )) != S_OK) return hr;
4856 switch (option)
4858 case WS_READ_REQUIRED_VALUE:
4859 if (!*found) return WS_E_INVALID_FORMAT;
4860 /* fall through */
4862 case WS_READ_NILLABLE_VALUE:
4863 if (size != sizeof(UINT8)) return E_INVALIDARG;
4864 *(UINT8 *)ret = val;
4865 break;
4867 case WS_READ_REQUIRED_POINTER:
4868 if (!*found) return WS_E_INVALID_FORMAT;
4869 /* fall through */
4871 case WS_READ_OPTIONAL_POINTER:
4872 case WS_READ_NILLABLE_POINTER:
4874 UINT8 *heap_val = NULL;
4875 if (size != sizeof(heap_val)) return E_INVALIDARG;
4876 if (*found)
4878 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4879 *heap_val = val;
4881 *(UINT8 **)ret = heap_val;
4882 break;
4884 default:
4885 FIXME( "read option %u not supported\n", option );
4886 return E_NOTIMPL;
4889 return S_OK;
4892 static HRESULT text_to_uint16( const WS_XML_TEXT *text, UINT64 *val )
4894 HRESULT hr;
4896 switch (text->textType)
4898 case WS_XML_TEXT_TYPE_UTF8:
4900 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
4901 hr = str_to_uint64( text_utf8->value.bytes, text_utf8->value.length, MAX_UINT16, val );
4902 break;
4904 case WS_XML_TEXT_TYPE_INT32:
4906 const WS_XML_INT32_TEXT *text_int32 = (const WS_XML_INT32_TEXT *)text;
4907 if (text_int32->value < 0 || text_int32->value > MAX_UINT16) return WS_E_NUMERIC_OVERFLOW;
4908 *val = text_int32->value;
4909 hr = S_OK;
4910 break;
4912 case WS_XML_TEXT_TYPE_UINT64:
4914 const WS_XML_UINT64_TEXT *text_uint64 = (const WS_XML_UINT64_TEXT *)text;
4915 if (text_uint64->value > MAX_UINT16) return WS_E_NUMERIC_OVERFLOW;
4916 *val = text_uint64->value;
4917 hr = S_OK;
4918 break;
4920 default:
4921 FIXME( "unhandled text type %u\n", text->textType );
4922 return E_NOTIMPL;
4925 return hr;
4928 static HRESULT read_type_uint16( struct reader *reader, WS_TYPE_MAPPING mapping,
4929 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4930 const WS_UINT16_DESCRIPTION *desc, WS_READ_OPTION option,
4931 WS_HEAP *heap, void *ret, ULONG size, BOOL *found )
4933 const WS_XML_TEXT *text;
4934 HRESULT hr;
4935 UINT64 val = 0;
4937 if (desc)
4939 FIXME( "description not supported\n" );
4940 return E_NOTIMPL;
4942 if ((hr = get_text( reader, mapping, localname, ns, &text, found )) != S_OK) return hr;
4943 if (*found && (hr = text_to_uint16( text, &val )) != S_OK) return hr;
4945 switch (option)
4947 case WS_READ_REQUIRED_VALUE:
4948 if (!*found) return WS_E_INVALID_FORMAT;
4949 /* fall through */
4951 case WS_READ_NILLABLE_VALUE:
4952 if (size != sizeof(UINT16)) return E_INVALIDARG;
4953 *(UINT16 *)ret = val;
4954 break;
4956 case WS_READ_REQUIRED_POINTER:
4957 if (!*found) return WS_E_INVALID_FORMAT;
4958 /* fall through */
4960 case WS_READ_OPTIONAL_POINTER:
4961 case WS_READ_NILLABLE_POINTER:
4963 UINT16 *heap_val = NULL;
4964 if (size != sizeof(heap_val)) return E_INVALIDARG;
4965 if (*found)
4967 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4968 *heap_val = val;
4970 *(UINT16 **)ret = heap_val;
4971 break;
4973 default:
4974 FIXME( "read option %u not supported\n", option );
4975 return E_NOTIMPL;
4978 return S_OK;
4981 static HRESULT text_to_uint32( const WS_XML_TEXT *text, UINT64 *val )
4983 HRESULT hr;
4985 switch (text->textType)
4987 case WS_XML_TEXT_TYPE_UTF8:
4989 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
4990 hr = str_to_uint64( text_utf8->value.bytes, text_utf8->value.length, MAX_UINT32, val );
4991 break;
4993 case WS_XML_TEXT_TYPE_INT32:
4995 const WS_XML_INT32_TEXT *text_int32 = (const WS_XML_INT32_TEXT *)text;
4996 if (text_int32->value < 0) return WS_E_NUMERIC_OVERFLOW;
4997 *val = text_int32->value;
4998 hr = S_OK;
4999 break;
5001 case WS_XML_TEXT_TYPE_INT64:
5003 const WS_XML_INT64_TEXT *text_int64 = (const WS_XML_INT64_TEXT *)text;
5004 if (text_int64->value < 0 || text_int64->value > MAX_UINT32) return WS_E_NUMERIC_OVERFLOW;
5005 *val = text_int64->value;
5006 hr = S_OK;
5007 break;
5009 case WS_XML_TEXT_TYPE_UINT64:
5011 const WS_XML_UINT64_TEXT *text_uint64 = (const WS_XML_UINT64_TEXT *)text;
5012 if (text_uint64->value > MAX_UINT32) return WS_E_NUMERIC_OVERFLOW;
5013 *val = text_uint64->value;
5014 hr = S_OK;
5015 break;
5017 default:
5018 FIXME( "unhandled text type %u\n", text->textType );
5019 return E_NOTIMPL;
5022 return hr;
5025 static HRESULT read_type_uint32( struct reader *reader, WS_TYPE_MAPPING mapping,
5026 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
5027 const WS_UINT32_DESCRIPTION *desc, WS_READ_OPTION option,
5028 WS_HEAP *heap, void *ret, ULONG size, BOOL *found )
5030 const WS_XML_TEXT *text;
5031 HRESULT hr;
5032 UINT64 val = 0;
5034 if (desc)
5036 FIXME( "description not supported\n" );
5037 return E_NOTIMPL;
5039 if ((hr = get_text( reader, mapping, localname, ns, &text, found )) != S_OK) return hr;
5040 if (*found && (hr = text_to_uint32( text, &val )) != S_OK) return hr;
5042 switch (option)
5044 case WS_READ_REQUIRED_VALUE:
5045 if (!*found) return WS_E_INVALID_FORMAT;
5046 /* fall through */
5048 case WS_READ_NILLABLE_VALUE:
5049 if (size != sizeof(UINT32)) return E_INVALIDARG;
5050 *(UINT32 *)ret = val;
5051 break;
5053 case WS_READ_REQUIRED_POINTER:
5054 if (!*found) return WS_E_INVALID_FORMAT;
5055 /* fall through */
5057 case WS_READ_OPTIONAL_POINTER:
5058 case WS_READ_NILLABLE_POINTER:
5060 UINT32 *heap_val = NULL;
5061 if (size != sizeof(heap_val)) return E_INVALIDARG;
5062 if (*found)
5064 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5065 *heap_val = val;
5067 *(UINT32 **)ret = heap_val;
5068 break;
5070 default:
5071 FIXME( "read option %u not supported\n", option );
5072 return E_NOTIMPL;
5075 return S_OK;
5078 static HRESULT text_to_uint64( const WS_XML_TEXT *text, UINT64 *val )
5080 HRESULT hr;
5082 switch (text->textType)
5084 case WS_XML_TEXT_TYPE_UTF8:
5086 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
5087 hr = str_to_uint64( text_utf8->value.bytes, text_utf8->value.length, MAX_UINT64, val );
5088 break;
5090 case WS_XML_TEXT_TYPE_INT32:
5092 const WS_XML_INT32_TEXT *text_int32 = (const WS_XML_INT32_TEXT *)text;
5093 if (text_int32->value < 0) return WS_E_NUMERIC_OVERFLOW;
5094 *val = text_int32->value;
5095 hr = S_OK;
5096 break;
5098 case WS_XML_TEXT_TYPE_INT64:
5100 const WS_XML_INT64_TEXT *text_int64 = (const WS_XML_INT64_TEXT *)text;
5101 if (text_int64->value < 0) return WS_E_NUMERIC_OVERFLOW;
5102 *val = text_int64->value;
5103 hr = S_OK;
5104 break;
5106 case WS_XML_TEXT_TYPE_UINT64:
5108 const WS_XML_UINT64_TEXT *text_uint64 = (const WS_XML_UINT64_TEXT *)text;
5109 *val = text_uint64->value;
5110 hr = S_OK;
5111 break;
5113 default:
5114 FIXME( "unhandled text type %u\n", text->textType );
5115 return E_NOTIMPL;
5118 return hr;
5121 static HRESULT read_type_uint64( struct reader *reader, WS_TYPE_MAPPING mapping,
5122 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
5123 const WS_UINT64_DESCRIPTION *desc, WS_READ_OPTION option,
5124 WS_HEAP *heap, void *ret, ULONG size, BOOL *found )
5126 const WS_XML_TEXT *text;
5127 HRESULT hr;
5128 UINT64 val = 0;
5130 if (desc)
5132 FIXME( "description not supported\n" );
5133 return E_NOTIMPL;
5135 if ((hr = get_text( reader, mapping, localname, ns, &text, found )) != S_OK) return hr;
5136 if (*found && (hr = text_to_uint64( text, &val )) != S_OK) return hr;
5138 switch (option)
5140 case WS_READ_REQUIRED_VALUE:
5141 if (!*found) return WS_E_INVALID_FORMAT;
5142 /* fall through */
5144 case WS_READ_NILLABLE_VALUE:
5145 if (size != sizeof(val)) return E_INVALIDARG;
5146 *(UINT64 *)ret = val;
5147 break;
5149 case WS_READ_REQUIRED_POINTER:
5150 if (!*found) return WS_E_INVALID_FORMAT;
5151 /* fall through */
5153 case WS_READ_OPTIONAL_POINTER:
5154 case WS_READ_NILLABLE_POINTER:
5156 UINT64 *heap_val = NULL;
5157 if (size != sizeof(heap_val)) return E_INVALIDARG;
5158 if (*found)
5160 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5161 *heap_val = val;
5163 *(UINT64 **)ret = heap_val;
5164 break;
5166 default:
5167 FIXME( "read option %u not supported\n", option );
5168 return E_NOTIMPL;
5171 return S_OK;
5174 static HRESULT text_to_float( const WS_XML_TEXT *text, float *val )
5176 HRESULT hr;
5178 switch (text->textType)
5180 case WS_XML_TEXT_TYPE_UTF8:
5182 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
5183 hr = str_to_float( text_utf8->value.bytes, text_utf8->value.length, val );
5184 break;
5186 case WS_XML_TEXT_TYPE_FLOAT:
5188 const WS_XML_FLOAT_TEXT *text_float = (const WS_XML_FLOAT_TEXT *)text;
5189 *val = text_float->value;
5190 hr = S_OK;
5191 break;
5193 default:
5194 FIXME( "unhandled text type %u\n", text->textType );
5195 return E_NOTIMPL;
5198 return hr;
5201 static HRESULT read_type_float( struct reader *reader, WS_TYPE_MAPPING mapping,
5202 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
5203 const WS_FLOAT_DESCRIPTION *desc, WS_READ_OPTION option,
5204 WS_HEAP *heap, void *ret, ULONG size, BOOL *found )
5206 const WS_XML_TEXT *text;
5207 HRESULT hr;
5208 float val = 0.0;
5210 if (desc) FIXME( "ignoring description\n" );
5212 if ((hr = get_text( reader, mapping, localname, ns, &text, found )) != S_OK) return hr;
5213 if (*found && (hr = text_to_float( text, &val )) != S_OK) return hr;
5215 switch (option)
5217 case WS_READ_REQUIRED_VALUE:
5218 if (!*found) return WS_E_INVALID_FORMAT;
5219 /* fall through */
5221 case WS_READ_NILLABLE_VALUE:
5222 if (size != sizeof(val)) return E_INVALIDARG;
5223 *(float *)ret = val;
5224 break;
5226 case WS_READ_REQUIRED_POINTER:
5227 if (!*found) return WS_E_INVALID_FORMAT;
5228 /* fall through */
5230 case WS_READ_OPTIONAL_POINTER:
5231 case WS_READ_NILLABLE_POINTER:
5233 float *heap_val = NULL;
5234 if (size != sizeof(heap_val)) return E_INVALIDARG;
5235 if (*found)
5237 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5238 *heap_val = val;
5240 *(float **)ret = heap_val;
5241 break;
5243 default:
5244 FIXME( "read option %u not supported\n", option );
5245 return E_NOTIMPL;
5248 return S_OK;
5251 static HRESULT text_to_double( const WS_XML_TEXT *text, double *val )
5253 HRESULT hr;
5255 switch (text->textType)
5257 case WS_XML_TEXT_TYPE_UTF8:
5259 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
5260 hr = str_to_double( text_utf8->value.bytes, text_utf8->value.length, val );
5261 break;
5263 case WS_XML_TEXT_TYPE_DOUBLE:
5265 const WS_XML_DOUBLE_TEXT *text_double = (const WS_XML_DOUBLE_TEXT *)text;
5266 *val = text_double->value;
5267 hr = S_OK;
5268 break;
5270 default:
5271 FIXME( "unhandled text type %u\n", text->textType );
5272 return E_NOTIMPL;
5275 return hr;
5278 static HRESULT read_type_double( struct reader *reader, WS_TYPE_MAPPING mapping,
5279 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
5280 const WS_DOUBLE_DESCRIPTION *desc, WS_READ_OPTION option,
5281 WS_HEAP *heap, void *ret, ULONG size, BOOL *found )
5283 const WS_XML_TEXT *text;
5284 HRESULT hr;
5285 double val = 0.0;
5287 if (desc) FIXME( "ignoring description\n" );
5289 if ((hr = get_text( reader, mapping, localname, ns, &text, found )) != S_OK) return hr;
5290 if (*found && (hr = text_to_double( text, &val )) != S_OK) return hr;
5292 switch (option)
5294 case WS_READ_REQUIRED_VALUE:
5295 if (!*found) return WS_E_INVALID_FORMAT;
5296 /* fall through */
5298 case WS_READ_NILLABLE_VALUE:
5299 if (size != sizeof(val)) return E_INVALIDARG;
5300 *(double *)ret = val;
5301 break;
5303 case WS_READ_REQUIRED_POINTER:
5304 if (!*found) return WS_E_INVALID_FORMAT;
5305 /* fall through */
5307 case WS_READ_OPTIONAL_POINTER:
5308 case WS_READ_NILLABLE_POINTER:
5310 double *heap_val = NULL;
5311 if (size != sizeof(heap_val)) return E_INVALIDARG;
5312 if (*found)
5314 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5315 *heap_val = val;
5317 *(double **)ret = heap_val;
5318 break;
5320 default:
5321 FIXME( "read option %u not supported\n", option );
5322 return E_NOTIMPL;
5325 return S_OK;
5328 static HRESULT text_to_wsz( const WS_XML_TEXT *text, WS_HEAP *heap, WCHAR **ret )
5330 const WS_XML_UTF8_TEXT *utf8 = (const WS_XML_UTF8_TEXT *)text;
5331 int len;
5333 assert( text->textType == WS_XML_TEXT_TYPE_UTF8 );
5334 len = MultiByteToWideChar( CP_UTF8, 0, (char *)utf8->value.bytes, utf8->value.length, NULL, 0 );
5335 if (!(*ret = ws_alloc( heap, (len + 1) * sizeof(WCHAR) ))) return E_OUTOFMEMORY;
5336 MultiByteToWideChar( CP_UTF8, 0, (char *)utf8->value.bytes, utf8->value.length, *ret, len );
5337 (*ret)[len] = 0;
5338 return S_OK;
5341 static HRESULT read_type_wsz( struct reader *reader, WS_TYPE_MAPPING mapping,
5342 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
5343 const WS_WSZ_DESCRIPTION *desc, WS_READ_OPTION option,
5344 WS_HEAP *heap, WCHAR **ret, ULONG size, BOOL *found )
5346 const WS_XML_TEXT *text;
5347 HRESULT hr;
5348 WCHAR *str = NULL;
5350 if (desc)
5352 FIXME( "description not supported\n" );
5353 return E_NOTIMPL;
5355 if ((hr = get_text( reader, mapping, localname, ns, &text, found )) != S_OK) return hr;
5356 if (*found && (hr = text_to_wsz( text, heap, &str )) != S_OK) return hr;
5358 switch (option)
5360 case WS_READ_REQUIRED_POINTER:
5361 if (!str && !(str = ws_alloc_zero( heap, sizeof(*str) ))) return WS_E_QUOTA_EXCEEDED;
5362 /* fall through */
5364 case WS_READ_OPTIONAL_POINTER:
5365 case WS_READ_NILLABLE_POINTER:
5366 if (size != sizeof(str)) return E_INVALIDARG;
5367 *ret = str;
5368 break;
5370 default:
5371 FIXME( "read option %u not supported\n", option );
5372 return E_NOTIMPL;
5375 return S_OK;
5378 static HRESULT get_enum_value( const WS_XML_TEXT *text, const WS_ENUM_DESCRIPTION *desc, int *ret )
5380 const WS_XML_UTF8_TEXT *utf8 = (const WS_XML_UTF8_TEXT *)text;
5381 ULONG i;
5383 assert( text->textType == WS_XML_TEXT_TYPE_UTF8 );
5384 for (i = 0; i < desc->valueCount; i++)
5386 if (WsXmlStringEquals( &utf8->value, desc->values[i].name, NULL ) == S_OK)
5388 *ret = desc->values[i].value;
5389 return S_OK;
5392 return WS_E_INVALID_FORMAT;
5395 static HRESULT read_type_enum( struct reader *reader, WS_TYPE_MAPPING mapping,
5396 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
5397 const WS_ENUM_DESCRIPTION *desc, WS_READ_OPTION option,
5398 WS_HEAP *heap, void *ret, ULONG size, BOOL *found )
5400 const WS_XML_TEXT *text;
5401 HRESULT hr;
5402 int val = 0;
5404 if (!desc) return E_INVALIDARG;
5406 if ((hr = get_text( reader, mapping, localname, ns, &text, found )) != S_OK) return hr;
5407 if (*found && (hr = get_enum_value( text, desc, &val )) != S_OK) return hr;
5409 switch (option)
5411 case WS_READ_REQUIRED_VALUE:
5412 if (!*found) return WS_E_INVALID_FORMAT;
5413 /* fall through */
5415 case WS_READ_NILLABLE_VALUE:
5416 if (size != sizeof(val)) return E_INVALIDARG;
5417 *(int *)ret = val;
5418 break;
5420 case WS_READ_REQUIRED_POINTER:
5421 if (!*found) return WS_E_INVALID_FORMAT;
5422 /* fall through */
5424 case WS_READ_OPTIONAL_POINTER:
5425 case WS_READ_NILLABLE_POINTER:
5427 int *heap_val = NULL;
5428 if (size != sizeof(heap_val)) return E_INVALIDARG;
5429 if (*found)
5431 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5432 *heap_val = val;
5434 *(int **)ret = heap_val;
5435 break;
5437 default:
5438 FIXME( "read option %u not supported\n", option );
5439 return E_NOTIMPL;
5442 return S_OK;
5445 static HRESULT text_to_datetime( const WS_XML_TEXT *text, WS_DATETIME *val )
5447 HRESULT hr;
5449 switch (text->textType)
5451 case WS_XML_TEXT_TYPE_UTF8:
5453 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
5454 hr = str_to_datetime( text_utf8->value.bytes, text_utf8->value.length, val );
5455 break;
5457 case WS_XML_TEXT_TYPE_DATETIME:
5459 const WS_XML_DATETIME_TEXT *text_datetime = (const WS_XML_DATETIME_TEXT *)text;
5460 *val = text_datetime->value;
5461 hr = S_OK;
5462 break;
5464 default:
5465 FIXME( "unhandled text type %u\n", text->textType );
5466 return E_NOTIMPL;
5469 return hr;
5472 static HRESULT read_type_datetime( struct reader *reader, WS_TYPE_MAPPING mapping,
5473 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
5474 const WS_DATETIME_DESCRIPTION *desc, WS_READ_OPTION option,
5475 WS_HEAP *heap, void *ret, ULONG size, BOOL *found )
5477 const WS_XML_TEXT *text;
5478 HRESULT hr;
5479 WS_DATETIME val = {0, WS_DATETIME_FORMAT_UTC};
5481 if (desc) FIXME( "ignoring description\n" );
5483 if ((hr = get_text( reader, mapping, localname, ns, &text, found )) != S_OK) return hr;
5484 if (*found && (hr = text_to_datetime( text, &val )) != S_OK) return hr;
5486 switch (option)
5488 case WS_READ_REQUIRED_VALUE:
5489 if (!*found) return WS_E_INVALID_FORMAT;
5490 /* fall through */
5492 case WS_READ_NILLABLE_VALUE:
5493 if (size != sizeof(val)) return E_INVALIDARG;
5494 *(WS_DATETIME *)ret = val;
5495 break;
5497 case WS_READ_REQUIRED_POINTER:
5498 if (!*found) return WS_E_INVALID_FORMAT;
5499 /* fall through */
5501 case WS_READ_OPTIONAL_POINTER:
5502 case WS_READ_NILLABLE_POINTER:
5504 WS_DATETIME *heap_val = NULL;
5505 if (size != sizeof(heap_val)) return E_INVALIDARG;
5506 if (*found)
5508 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5509 *heap_val = val;
5511 *(WS_DATETIME **)ret = heap_val;
5512 break;
5514 default:
5515 FIXME( "read option %u not supported\n", option );
5516 return E_NOTIMPL;
5519 return S_OK;
5522 static HRESULT text_to_guid( const WS_XML_TEXT *text, GUID *val )
5524 HRESULT hr;
5526 switch (text->textType)
5528 case WS_XML_TEXT_TYPE_UTF8:
5530 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
5531 hr = str_to_guid( text_utf8->value.bytes, text_utf8->value.length, val );
5532 break;
5534 case WS_XML_TEXT_TYPE_GUID:
5536 const WS_XML_GUID_TEXT *text_guid = (const WS_XML_GUID_TEXT *)text;
5537 *val = text_guid->value;
5538 hr = S_OK;
5539 break;
5541 default:
5542 FIXME( "unhandled text type %u\n", text->textType );
5543 return E_NOTIMPL;
5546 return hr;
5549 static HRESULT read_type_guid( struct reader *reader, WS_TYPE_MAPPING mapping,
5550 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
5551 const WS_GUID_DESCRIPTION *desc, WS_READ_OPTION option,
5552 WS_HEAP *heap, void *ret, ULONG size, BOOL *found )
5554 const WS_XML_TEXT *text;
5555 GUID val = {0};
5556 HRESULT hr;
5558 if (desc) FIXME( "ignoring description\n" );
5560 if ((hr = get_text( reader, mapping, localname, ns, &text, found )) != S_OK) return hr;
5561 if (*found && (hr = text_to_guid( text, &val )) != S_OK) return hr;
5563 switch (option)
5565 case WS_READ_REQUIRED_VALUE:
5566 if (!*found) return WS_E_INVALID_FORMAT;
5567 /* fall through */
5569 case WS_READ_NILLABLE_VALUE:
5570 if (size != sizeof(val)) return E_INVALIDARG;
5571 *(GUID *)ret = val;
5572 break;
5574 case WS_READ_REQUIRED_POINTER:
5575 if (!*found) return WS_E_INVALID_FORMAT;
5576 /* fall through */
5578 case WS_READ_OPTIONAL_POINTER:
5579 case WS_READ_NILLABLE_POINTER:
5581 GUID *heap_val = NULL;
5582 if (size != sizeof(heap_val)) return E_INVALIDARG;
5583 if (*found)
5585 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5586 *heap_val = val;
5588 *(GUID **)ret = heap_val;
5589 break;
5591 default:
5592 FIXME( "read option %u not supported\n", option );
5593 return E_NOTIMPL;
5596 return S_OK;
5599 static HRESULT text_to_unique_id( const WS_XML_TEXT *text, WS_HEAP *heap, WS_UNIQUE_ID *val )
5601 HRESULT hr;
5603 switch (text->textType)
5605 case WS_XML_TEXT_TYPE_UTF8:
5607 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
5608 hr = str_to_unique_id( text_utf8->value.bytes, text_utf8->value.length, heap, val );
5609 break;
5611 case WS_XML_TEXT_TYPE_UNIQUE_ID:
5613 const WS_XML_UNIQUE_ID_TEXT *text_unique_id = (const WS_XML_UNIQUE_ID_TEXT *)text;
5614 val->guid = text_unique_id->value;
5615 val->uri.length = 0;
5616 val->uri.chars = NULL;
5617 hr = S_OK;
5618 break;
5620 default:
5621 FIXME( "unhandled text type %u\n", text->textType );
5622 return E_NOTIMPL;
5625 return hr;
5628 static HRESULT read_type_unique_id( struct reader *reader, WS_TYPE_MAPPING mapping,
5629 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
5630 const WS_UNIQUE_ID_DESCRIPTION *desc, WS_READ_OPTION option,
5631 WS_HEAP *heap, void *ret, ULONG size, BOOL *found )
5633 const WS_XML_TEXT *text;
5634 WS_UNIQUE_ID val = {{0}};
5635 HRESULT hr;
5637 if (desc) FIXME( "ignoring description\n" );
5639 if ((hr = get_text( reader, mapping, localname, ns, &text, found )) != S_OK) return hr;
5640 if (*found && (hr = text_to_unique_id( text, heap, &val )) != S_OK) return hr;
5642 switch (option)
5644 case WS_READ_REQUIRED_VALUE:
5645 if (!*found) return WS_E_INVALID_FORMAT;
5646 /* fall through */
5648 case WS_READ_NILLABLE_VALUE:
5649 if (size != sizeof(val)) return E_INVALIDARG;
5650 *(WS_UNIQUE_ID *)ret = val;
5651 break;
5653 case WS_READ_REQUIRED_POINTER:
5654 if (!*found) return WS_E_INVALID_FORMAT;
5655 /* fall through */
5657 case WS_READ_OPTIONAL_POINTER:
5658 case WS_READ_NILLABLE_POINTER:
5660 WS_UNIQUE_ID *heap_val = NULL;
5661 if (size != sizeof(heap_val)) return E_INVALIDARG;
5662 if (*found)
5664 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5665 *heap_val = val;
5667 *(WS_UNIQUE_ID **)ret = heap_val;
5668 break;
5670 default:
5671 FIXME( "read option %u not supported\n", option );
5672 return E_NOTIMPL;
5675 return S_OK;
5678 static HRESULT text_to_string( const WS_XML_TEXT *text, WS_HEAP *heap, WS_STRING *val )
5680 HRESULT hr;
5682 switch (text->textType)
5684 case WS_XML_TEXT_TYPE_UTF8:
5686 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
5687 hr = str_to_string( text_utf8->value.bytes, text_utf8->value.length, heap, val );
5688 break;
5690 case WS_XML_TEXT_TYPE_UTF16:
5692 const WS_XML_UTF16_TEXT *text_utf16 = (const WS_XML_UTF16_TEXT *)text;
5693 if (!(val->chars = ws_alloc( heap, text_utf16->byteCount ))) return WS_E_QUOTA_EXCEEDED;
5694 memcpy( val->chars, text_utf16->bytes, text_utf16->byteCount );
5695 val->length = text_utf16->byteCount / sizeof(WCHAR);
5696 hr = S_OK;
5697 break;
5699 default:
5700 FIXME( "unhandled text type %u\n", text->textType );
5701 return E_NOTIMPL;
5704 return hr;
5707 static HRESULT read_type_string( struct reader *reader, WS_TYPE_MAPPING mapping,
5708 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
5709 const WS_STRING_DESCRIPTION *desc, WS_READ_OPTION option,
5710 WS_HEAP *heap, void *ret, ULONG size, BOOL *found )
5712 const WS_XML_TEXT *text;
5713 WS_STRING val = {0};
5714 HRESULT hr;
5716 if (desc) FIXME( "ignoring description\n" );
5718 if ((hr = get_text( reader, mapping, localname, ns, &text, found )) != S_OK) return hr;
5719 if (*found && (hr = text_to_string( text, heap, &val )) != S_OK) return hr;
5721 switch (option)
5723 case WS_READ_REQUIRED_VALUE:
5724 case WS_READ_NILLABLE_VALUE:
5725 if (size != sizeof(val)) return E_INVALIDARG;
5726 *(WS_STRING *)ret = val;
5727 break;
5729 case WS_READ_REQUIRED_POINTER:
5731 WS_STRING *heap_val;
5732 if (size != sizeof(heap_val)) return E_INVALIDARG;
5733 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5734 *heap_val = val;
5735 *(WS_STRING **)ret = heap_val;
5736 break;
5738 case WS_READ_OPTIONAL_POINTER:
5739 case WS_READ_NILLABLE_POINTER:
5741 WS_STRING *heap_val = NULL;
5742 if (size != sizeof(heap_val)) return E_INVALIDARG;
5743 if (*found)
5745 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5746 *heap_val = val;
5748 *(WS_STRING **)ret = heap_val;
5749 break;
5751 default:
5752 FIXME( "read option %u not supported\n", option );
5753 return E_NOTIMPL;
5756 return S_OK;
5759 static HRESULT text_to_bytes( const WS_XML_TEXT *text, WS_HEAP *heap, WS_BYTES *val )
5761 HRESULT hr;
5763 switch (text->textType)
5765 case WS_XML_TEXT_TYPE_UTF8:
5767 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
5768 hr = str_to_bytes( text_utf8->value.bytes, text_utf8->value.length, heap, val );
5769 break;
5771 case WS_XML_TEXT_TYPE_BASE64:
5773 const WS_XML_BASE64_TEXT *text_base64 = (const WS_XML_BASE64_TEXT *)text;
5774 if (!(val->bytes = ws_alloc( heap, text_base64->length ))) return WS_E_QUOTA_EXCEEDED;
5775 memcpy( val->bytes, text_base64->bytes, text_base64->length );
5776 val->length = text_base64->length;
5777 hr = S_OK;
5778 break;
5780 default:
5781 FIXME( "unhandled text type %u\n", text->textType );
5782 return E_NOTIMPL;
5785 return hr;
5788 static HRESULT read_type_bytes( struct reader *reader, WS_TYPE_MAPPING mapping,
5789 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
5790 const WS_BYTES_DESCRIPTION *desc, WS_READ_OPTION option,
5791 WS_HEAP *heap, void *ret, ULONG size, BOOL *found )
5793 const WS_XML_TEXT *text;
5794 WS_BYTES val = {0};
5795 HRESULT hr;
5797 if (desc) FIXME( "ignoring description\n" );
5799 if ((hr = get_text( reader, mapping, localname, ns, &text, found )) != S_OK) return hr;
5800 if (*found && (hr = text_to_bytes( text, heap, &val )) != S_OK) return hr;
5802 switch (option)
5804 case WS_READ_REQUIRED_VALUE:
5805 case WS_READ_NILLABLE_VALUE:
5806 if (size != sizeof(val)) return E_INVALIDARG;
5807 *(WS_BYTES *)ret = val;
5808 break;
5810 case WS_READ_REQUIRED_POINTER:
5812 WS_BYTES *heap_val;
5813 if (size != sizeof(heap_val)) return E_INVALIDARG;
5814 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5815 *heap_val = val;
5816 *(WS_BYTES **)ret = heap_val;
5817 break;
5819 case WS_READ_OPTIONAL_POINTER:
5820 case WS_READ_NILLABLE_POINTER:
5822 WS_BYTES *heap_val = NULL;
5823 if (size != sizeof(heap_val)) return E_INVALIDARG;
5824 if (*found)
5826 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5827 *heap_val = val;
5829 *(WS_BYTES **)ret = heap_val;
5830 break;
5832 default:
5833 FIXME( "read option %u not supported\n", option );
5834 return E_NOTIMPL;
5837 return S_OK;
5840 static HRESULT text_to_xml_string( const WS_XML_TEXT *text, WS_HEAP *heap, WS_XML_STRING *val )
5842 const WS_XML_UTF8_TEXT *utf8 = (const WS_XML_UTF8_TEXT *)text;
5843 assert( text->textType == WS_XML_TEXT_TYPE_UTF8 );
5844 return str_to_xml_string( utf8->value.bytes, utf8->value.length, heap, val );
5847 static HRESULT read_type_xml_string( struct reader *reader, WS_TYPE_MAPPING mapping,
5848 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
5849 const WS_XML_STRING_DESCRIPTION *desc, WS_READ_OPTION option,
5850 WS_HEAP *heap, void *ret, ULONG size, BOOL *found )
5852 const WS_XML_TEXT *text;
5853 WS_XML_STRING val = {0};
5854 HRESULT hr;
5856 if (desc) FIXME( "ignoring description\n" );
5858 if ((hr = get_text( reader, mapping, localname, ns, &text, found )) != S_OK) return hr;
5859 if (*found && (hr = text_to_xml_string( text, heap, &val )) != S_OK) return hr;
5861 switch (option)
5863 case WS_READ_REQUIRED_VALUE:
5864 case WS_READ_NILLABLE_VALUE:
5865 if (size != sizeof(val)) return E_INVALIDARG;
5866 *(WS_XML_STRING *)ret = val;
5867 break;
5869 case WS_READ_REQUIRED_POINTER:
5871 WS_XML_STRING *heap_val;
5872 if (size != sizeof(heap_val)) return E_INVALIDARG;
5873 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5874 *heap_val = val;
5875 *(WS_XML_STRING **)ret = heap_val;
5876 break;
5878 case WS_READ_OPTIONAL_POINTER:
5879 case WS_READ_NILLABLE_POINTER:
5881 WS_XML_STRING *heap_val = NULL;
5882 if (size != sizeof(heap_val)) return E_INVALIDARG;
5883 if (*found)
5885 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5886 *heap_val = val;
5888 *(WS_XML_STRING **)ret = heap_val;
5889 break;
5891 default:
5892 FIXME( "read option %u not supported\n", option );
5893 return E_NOTIMPL;
5896 return S_OK;
5899 static HRESULT text_to_qname( struct reader *reader, const WS_XML_TEXT *text, WS_HEAP *heap, WS_XML_QNAME *val )
5901 HRESULT hr;
5903 switch (text->textType)
5905 case WS_XML_TEXT_TYPE_UTF8:
5907 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
5908 hr = str_to_qname( reader, text_utf8->value.bytes, text_utf8->value.length, heap, NULL,
5909 &val->localName, &val->ns );
5910 break;
5912 case WS_XML_TEXT_TYPE_QNAME:
5914 const WS_XML_QNAME_TEXT *text_qname = (const WS_XML_QNAME_TEXT *)text;
5915 if ((hr = copy_xml_string( heap, text_qname->localName, &val->localName )) != S_OK) return hr;
5916 if ((hr = copy_xml_string( heap, text_qname->ns, &val->ns )) != S_OK)
5918 ws_free( heap, val->localName.bytes, val->localName.length );
5919 return hr;
5921 break;
5923 default:
5924 FIXME( "unhandled text type %u\n", text->textType );
5925 return E_NOTIMPL;
5928 return hr;
5931 static HRESULT read_type_qname( struct reader *reader, WS_TYPE_MAPPING mapping,
5932 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
5933 const WS_XML_QNAME_DESCRIPTION *desc, WS_READ_OPTION option,
5934 WS_HEAP *heap, void *ret, ULONG size, BOOL *found )
5936 const WS_XML_TEXT *text;
5937 WS_XML_QNAME val = {{0}};
5938 HRESULT hr;
5940 if (desc) FIXME( "ignoring description\n" );
5942 if (node_type( reader->current ) != WS_XML_NODE_TYPE_ELEMENT) return WS_E_INVALID_FORMAT;
5943 if ((hr = read_startelement( reader )) != S_OK) return hr;
5944 if (node_type( reader->current ) != WS_XML_NODE_TYPE_TEXT) return WS_E_INVALID_FORMAT;
5946 if ((hr = get_text( reader, mapping, localname, ns, &text, found )) != S_OK) return hr;
5947 if (*found && (hr = text_to_qname( reader, text, heap, &val )) != S_OK) return hr;
5949 switch (option)
5951 case WS_READ_REQUIRED_VALUE:
5952 if (!*found) return WS_E_INVALID_FORMAT;
5953 /* fall through */
5955 case WS_READ_NILLABLE_VALUE:
5956 if (size != sizeof(val)) return E_INVALIDARG;
5957 *(WS_XML_QNAME *)ret = val;
5958 break;
5960 case WS_READ_REQUIRED_POINTER:
5961 if (!*found) return WS_E_INVALID_FORMAT;
5962 /* fall through */
5964 case WS_READ_OPTIONAL_POINTER:
5965 case WS_READ_NILLABLE_POINTER:
5967 WS_XML_QNAME *heap_val = NULL;
5968 if (size != sizeof(heap_val)) return E_INVALIDARG;
5969 if (*found)
5971 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5972 *heap_val = val;
5974 *(WS_XML_QNAME **)ret = heap_val;
5975 break;
5977 default:
5978 FIXME( "read option %u not supported\n", option );
5979 return E_NOTIMPL;
5982 return S_OK;
5985 static HRESULT read_type_description( struct reader *reader, WS_TYPE_MAPPING mapping,
5986 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
5987 const WS_STRUCT_DESCRIPTION *desc, WS_READ_OPTION option,
5988 WS_HEAP *heap, void *ret, ULONG size, BOOL *found )
5990 switch (option)
5992 case WS_READ_REQUIRED_POINTER:
5993 case WS_READ_OPTIONAL_POINTER:
5995 if (size != sizeof(desc)) return E_INVALIDARG;
5996 *(const WS_STRUCT_DESCRIPTION **)ret = desc;
5997 *found = TRUE;
5998 break;
6000 default:
6001 FIXME( "read option %u not supported\n", option );
6002 return E_NOTIMPL;
6005 return S_OK;
6008 static BOOL is_empty_text_node( const struct node *node )
6010 const WS_XML_TEXT_NODE *text = (const WS_XML_TEXT_NODE *)node;
6012 if (node_type( node ) != WS_XML_NODE_TYPE_TEXT) return FALSE;
6013 switch (text->text->textType)
6015 case WS_XML_TEXT_TYPE_UTF8:
6017 ULONG i;
6018 const WS_XML_UTF8_TEXT *utf8 = (const WS_XML_UTF8_TEXT *)text->text;
6019 for (i = 0; i < utf8->value.length; i++) if (!read_isspace( utf8->value.bytes[i] )) return FALSE;
6020 return TRUE;
6022 case WS_XML_TEXT_TYPE_BASE64:
6024 const WS_XML_BASE64_TEXT *base64 = (const WS_XML_BASE64_TEXT *)text->text;
6025 return !base64->length;
6027 case WS_XML_TEXT_TYPE_BOOL:
6028 case WS_XML_TEXT_TYPE_INT32:
6029 case WS_XML_TEXT_TYPE_INT64:
6030 case WS_XML_TEXT_TYPE_UINT64:
6031 case WS_XML_TEXT_TYPE_FLOAT:
6032 case WS_XML_TEXT_TYPE_DOUBLE:
6033 case WS_XML_TEXT_TYPE_DECIMAL:
6034 case WS_XML_TEXT_TYPE_GUID:
6035 case WS_XML_TEXT_TYPE_UNIQUE_ID:
6036 case WS_XML_TEXT_TYPE_DATETIME:
6037 return FALSE;
6039 default:
6040 ERR( "unhandled text type %u\n", text->text->textType );
6041 return FALSE;
6045 /* skips comment and empty text nodes */
6046 static HRESULT read_type_next_node( struct reader *reader )
6048 for (;;)
6050 HRESULT hr;
6051 WS_XML_NODE_TYPE type;
6053 if ((hr = read_next_node( reader )) != S_OK) return hr;
6054 type = node_type( reader->current );
6055 if (type == WS_XML_NODE_TYPE_COMMENT ||
6056 (type == WS_XML_NODE_TYPE_TEXT && is_empty_text_node( reader->current ))) continue;
6057 return S_OK;
6061 static HRESULT read_type_next_element_node( struct reader *reader, const WS_XML_STRING *localname,
6062 const WS_XML_STRING *ns )
6064 struct reader_pos pos;
6065 HRESULT hr;
6067 if (!localname) return S_OK; /* assume reader is already correctly positioned */
6068 if (reader->current == reader->last)
6070 BOOL found;
6071 if ((hr = read_to_startelement( reader, &found )) != S_OK) return hr;
6072 if (!found) return WS_E_INVALID_FORMAT;
6074 if (match_element( reader->current, localname, ns )) return S_OK;
6076 save_reader_position( reader, &pos );
6077 if ((hr = read_type_next_node( reader )) != S_OK) return hr;
6078 if (match_element( reader->current, localname, ns )) return S_OK;
6079 restore_reader_position( reader, &pos );
6081 return WS_E_INVALID_FORMAT;
6084 ULONG get_type_size( WS_TYPE type, const void *desc )
6086 switch (type)
6088 case WS_INT8_TYPE:
6089 case WS_UINT8_TYPE:
6090 return sizeof(INT8);
6092 case WS_INT16_TYPE:
6093 case WS_UINT16_TYPE:
6094 return sizeof(INT16);
6096 case WS_BOOL_TYPE:
6097 case WS_INT32_TYPE:
6098 case WS_UINT32_TYPE:
6099 case WS_ENUM_TYPE:
6100 return sizeof(INT32);
6102 case WS_INT64_TYPE:
6103 case WS_UINT64_TYPE:
6104 return sizeof(INT64);
6106 case WS_FLOAT_TYPE:
6107 return sizeof(float);
6109 case WS_DOUBLE_TYPE:
6110 return sizeof(double);
6112 case WS_DATETIME_TYPE:
6113 return sizeof(WS_DATETIME);
6115 case WS_GUID_TYPE:
6116 return sizeof(GUID);
6118 case WS_UNIQUE_ID_TYPE:
6119 return sizeof(WS_UNIQUE_ID);
6121 case WS_STRING_TYPE:
6122 return sizeof(WS_STRING);
6124 case WS_WSZ_TYPE:
6125 return sizeof(WCHAR *);
6127 case WS_BYTES_TYPE:
6128 return sizeof(WS_BYTES);
6130 case WS_XML_STRING_TYPE:
6131 return sizeof(WS_XML_STRING);
6133 case WS_XML_QNAME_TYPE:
6134 return sizeof(WS_XML_QNAME);
6136 case WS_DESCRIPTION_TYPE:
6137 return sizeof(WS_STRUCT_DESCRIPTION *);
6139 case WS_STRUCT_TYPE:
6141 const WS_STRUCT_DESCRIPTION *desc_struct = desc;
6142 return desc_struct->size;
6144 case WS_UNION_TYPE:
6146 const WS_UNION_DESCRIPTION *desc_union = desc;
6147 return desc_union->size;
6149 case WS_ANY_ATTRIBUTES_TYPE:
6150 return 0;
6152 default:
6153 ERR( "unhandled type %u\n", type );
6154 return 0;
6158 static WS_READ_OPTION get_field_read_option( WS_TYPE type, ULONG options )
6160 if (options & WS_FIELD_POINTER)
6162 if (options & WS_FIELD_NILLABLE) return WS_READ_NILLABLE_POINTER;
6163 if (options & WS_FIELD_OPTIONAL) return WS_READ_OPTIONAL_POINTER;
6164 return WS_READ_REQUIRED_POINTER;
6167 switch (type)
6169 case WS_BOOL_TYPE:
6170 case WS_INT8_TYPE:
6171 case WS_INT16_TYPE:
6172 case WS_INT32_TYPE:
6173 case WS_INT64_TYPE:
6174 case WS_UINT8_TYPE:
6175 case WS_UINT16_TYPE:
6176 case WS_UINT32_TYPE:
6177 case WS_UINT64_TYPE:
6178 case WS_FLOAT_TYPE:
6179 case WS_DOUBLE_TYPE:
6180 case WS_DATETIME_TYPE:
6181 case WS_GUID_TYPE:
6182 case WS_UNIQUE_ID_TYPE:
6183 case WS_STRING_TYPE:
6184 case WS_BYTES_TYPE:
6185 case WS_XML_STRING_TYPE:
6186 case WS_XML_QNAME_TYPE:
6187 case WS_XML_BUFFER_TYPE:
6188 case WS_STRUCT_TYPE:
6189 case WS_ENUM_TYPE:
6190 case WS_UNION_TYPE:
6191 if (options & (WS_FIELD_OPTIONAL|WS_FIELD_NILLABLE)) return WS_READ_NILLABLE_VALUE;
6192 return WS_READ_REQUIRED_VALUE;
6194 case WS_WSZ_TYPE:
6195 case WS_DESCRIPTION_TYPE:
6196 if (options & WS_FIELD_NILLABLE) return WS_READ_NILLABLE_POINTER;
6197 if (options & WS_FIELD_OPTIONAL) return WS_READ_OPTIONAL_POINTER;
6198 return WS_READ_REQUIRED_POINTER;
6200 default:
6201 FIXME( "unhandled type %u\n", type );
6202 return 0;
6206 static HRESULT read_type_field( struct reader *, const WS_STRUCT_DESCRIPTION *, const WS_FIELD_DESCRIPTION *,
6207 WS_HEAP *, char *, ULONG );
6209 static HRESULT read_type_union( struct reader *reader, const WS_UNION_DESCRIPTION *desc, WS_HEAP *heap, void *ret,
6210 ULONG size, BOOL *found )
6212 struct reader_pos pos;
6213 HRESULT hr;
6214 ULONG i;
6216 if (size != desc->size) return E_INVALIDARG;
6218 save_reader_position( reader, &pos );
6219 if ((hr = read_type_next_node( reader )) != S_OK) return hr;
6221 for (i = 0; i < desc->fieldCount; i++)
6223 if ((*found = match_element( reader->current, desc->fields[i]->field.localName, desc->fields[i]->field.ns )))
6224 break;
6227 if (!*found)
6229 *(int *)((char *)ret + desc->enumOffset) = desc->noneEnumValue;
6230 restore_reader_position( reader, &pos );
6232 else
6234 ULONG offset = desc->fields[i]->field.offset;
6235 if ((hr = read_type_field( reader, NULL, &desc->fields[i]->field, heap, ret, offset )) != S_OK) return hr;
6236 *(int *)((char *)ret + desc->enumOffset) = desc->fields[i]->value;
6239 return S_OK;
6242 static HRESULT read_type( struct reader *, WS_TYPE_MAPPING, WS_TYPE, const WS_XML_STRING *,
6243 const WS_XML_STRING *, const void *, WS_READ_OPTION, WS_HEAP *,
6244 void *, ULONG, BOOL * );
6246 static HRESULT read_type_array( struct reader *reader, const WS_FIELD_DESCRIPTION *desc, WS_HEAP *heap,
6247 void **ret, ULONG *count )
6249 HRESULT hr;
6250 ULONG item_size, nb_items = 0, nb_allocated = 1, offset = 0;
6251 WS_READ_OPTION option;
6252 BOOL found;
6253 char *buf;
6255 if (!(option = get_field_read_option( desc->type, desc->options ))) return E_INVALIDARG;
6257 /* wrapper element */
6258 if (desc->localName && ((hr = read_type_next_element_node( reader, desc->localName, desc->ns )) != S_OK))
6259 return hr;
6261 if (option == WS_READ_REQUIRED_VALUE || option == WS_READ_NILLABLE_VALUE)
6262 item_size = get_type_size( desc->type, desc->typeDescription );
6263 else
6264 item_size = sizeof(void *);
6266 if (!(buf = ws_alloc_zero( heap, item_size ))) return WS_E_QUOTA_EXCEEDED;
6267 for (;;)
6269 if (nb_items >= nb_allocated)
6271 SIZE_T old_size = nb_allocated * item_size, new_size = old_size * 2;
6272 if (!(buf = ws_realloc_zero( heap, buf, old_size, new_size ))) return WS_E_QUOTA_EXCEEDED;
6273 nb_allocated *= 2;
6276 if (desc->type == WS_UNION_TYPE)
6278 hr = read_type_union( reader, desc->typeDescription, heap, buf + offset, item_size, &found );
6279 if (hr != S_OK)
6281 ws_free( heap, buf, nb_allocated * item_size );
6282 return hr;
6284 if (!found) break;
6286 else
6288 hr = read_type( reader, WS_ELEMENT_TYPE_MAPPING, desc->type, desc->itemLocalName, desc->itemNs,
6289 desc->typeDescription, option, heap, buf + offset, item_size, &found );
6290 if (hr == WS_E_INVALID_FORMAT) break;
6291 if (hr != S_OK)
6293 ws_free( heap, buf, nb_allocated * item_size );
6294 return hr;
6298 offset += item_size;
6299 nb_items++;
6302 if (desc->localName && ((hr = read_type_next_node( reader )) != S_OK)) return hr;
6304 if (desc->itemRange && (nb_items < desc->itemRange->minItemCount || nb_items > desc->itemRange->maxItemCount))
6306 TRACE( "number of items %lu out of range (%lu-%lu)\n", nb_items, desc->itemRange->minItemCount,
6307 desc->itemRange->maxItemCount );
6308 ws_free( heap, buf, nb_allocated * item_size );
6309 return WS_E_INVALID_FORMAT;
6312 *count = nb_items;
6313 *ret = buf;
6315 return S_OK;
6318 static HRESULT read_type_text( struct reader *reader, const WS_FIELD_DESCRIPTION *desc,
6319 WS_READ_OPTION option, WS_HEAP *heap, void *ret, ULONG size )
6321 struct reader_pos pos;
6322 BOOL found;
6323 HRESULT hr;
6325 if (reader->current == reader->last)
6327 if ((hr = read_to_startelement( reader, &found )) != S_OK) return hr;
6328 if (!found) return WS_E_INVALID_FORMAT;
6331 save_reader_position( reader, &pos );
6332 if ((hr = read_next_node( reader )) != S_OK) return hr;
6333 hr = read_type( reader, WS_ANY_ELEMENT_TYPE_MAPPING, desc->type, NULL, NULL,
6334 desc->typeDescription, option, heap, ret, size, &found );
6335 if (hr == S_OK && !found) restore_reader_position( reader, &pos );
6336 return hr;
6339 static HRESULT read_type_field( struct reader *reader, const WS_STRUCT_DESCRIPTION *desc_struct,
6340 const WS_FIELD_DESCRIPTION *desc, WS_HEAP *heap, char *buf, ULONG offset )
6342 char *ptr;
6343 WS_READ_OPTION option;
6344 ULONG size;
6345 HRESULT hr;
6346 BOOL found;
6348 if (!desc) return E_INVALIDARG;
6349 if (desc->options & ~(WS_FIELD_POINTER|WS_FIELD_OPTIONAL|WS_FIELD_NILLABLE|WS_FIELD_NILLABLE_ITEM))
6351 FIXME( "options %#lx not supported\n", desc->options );
6352 return E_NOTIMPL;
6354 if (!(option = get_field_read_option( desc->type, desc->options ))) return E_INVALIDARG;
6356 if (option == WS_READ_REQUIRED_VALUE || option == WS_READ_NILLABLE_VALUE)
6357 size = get_type_size( desc->type, desc->typeDescription );
6358 else
6359 size = sizeof(void *);
6361 ptr = buf + offset;
6362 switch (desc->mapping)
6364 case WS_TYPE_ATTRIBUTE_FIELD_MAPPING:
6365 hr = read_type( reader, WS_ATTRIBUTE_TYPE_MAPPING, desc->type, desc->localName, desc->ns,
6366 desc_struct, option, heap, ptr, size, &found );
6367 break;
6369 case WS_ATTRIBUTE_FIELD_MAPPING:
6370 hr = read_type( reader, WS_ATTRIBUTE_TYPE_MAPPING, desc->type, desc->localName, desc->ns,
6371 desc->typeDescription, option, heap, ptr, size, &found );
6372 break;
6374 case WS_ELEMENT_FIELD_MAPPING:
6375 hr = read_type( reader, WS_ELEMENT_TYPE_MAPPING, desc->type, desc->localName, desc->ns,
6376 desc->typeDescription, option, heap, ptr, size, &found );
6377 break;
6379 case WS_ELEMENT_CHOICE_FIELD_MAPPING:
6381 if (desc->type != WS_UNION_TYPE || !desc->typeDescription ||
6382 (desc->options & (WS_FIELD_POINTER|WS_FIELD_NILLABLE))) return E_INVALIDARG;
6383 hr = read_type_union( reader, desc->typeDescription, heap, ptr, size, &found );
6384 break;
6386 case WS_REPEATING_ELEMENT_FIELD_MAPPING:
6387 case WS_REPEATING_ELEMENT_CHOICE_FIELD_MAPPING:
6389 ULONG count;
6390 hr = read_type_array( reader, desc, heap, (void **)ptr, &count );
6391 if (hr == S_OK) *(ULONG *)(buf + desc->countOffset) = count;
6392 break;
6394 case WS_TEXT_FIELD_MAPPING:
6395 hr = read_type_text( reader, desc, option, heap, ptr, size );
6396 break;
6398 default:
6399 FIXME( "unhandled field mapping %u\n", desc->mapping );
6400 return E_NOTIMPL;
6403 if (hr == WS_E_INVALID_FORMAT)
6405 switch (option)
6407 case WS_READ_REQUIRED_VALUE:
6408 case WS_READ_REQUIRED_POINTER:
6409 return WS_E_INVALID_FORMAT;
6411 case WS_READ_NILLABLE_VALUE:
6412 if (desc->defaultValue) memcpy( ptr, desc->defaultValue->value, desc->defaultValue->valueSize );
6413 return S_OK;
6415 case WS_READ_OPTIONAL_POINTER:
6416 case WS_READ_NILLABLE_POINTER:
6417 *(void **)ptr = NULL;
6418 return S_OK;
6420 default:
6421 ERR( "unhandled option %u\n", option );
6422 return E_NOTIMPL;
6426 return hr;
6429 static HRESULT read_type_struct( struct reader *reader, WS_TYPE_MAPPING mapping, const WS_XML_STRING *localname,
6430 const WS_XML_STRING *ns, const WS_STRUCT_DESCRIPTION *desc, WS_READ_OPTION option,
6431 WS_HEAP *heap, void *ret, ULONG size, BOOL *found )
6433 ULONG i, offset;
6434 HRESULT hr;
6435 char *buf;
6437 if (!desc) return E_INVALIDARG;
6438 if (desc->structOptions & ~WS_STRUCT_IGNORE_TRAILING_ELEMENT_CONTENT)
6440 FIXME( "struct options %#lx not supported\n",
6441 desc->structOptions & ~WS_STRUCT_IGNORE_TRAILING_ELEMENT_CONTENT );
6444 switch (option)
6446 case WS_READ_REQUIRED_POINTER:
6447 case WS_READ_OPTIONAL_POINTER:
6448 case WS_READ_NILLABLE_POINTER:
6449 if (size != sizeof(void *)) return E_INVALIDARG;
6450 if (!(buf = ws_alloc_zero( heap, desc->size ))) return WS_E_QUOTA_EXCEEDED;
6451 break;
6453 case WS_READ_REQUIRED_VALUE:
6454 case WS_READ_NILLABLE_VALUE:
6455 if (size != desc->size) return E_INVALIDARG;
6456 buf = ret;
6457 break;
6459 default:
6460 FIXME( "unhandled read option %u\n", option );
6461 return E_NOTIMPL;
6464 for (i = 0; i < desc->fieldCount; i++)
6466 offset = desc->fields[i]->offset;
6467 if ((hr = read_type_field( reader, desc, desc->fields[i], heap, buf, offset )) != S_OK) break;
6470 switch (option)
6472 case WS_READ_REQUIRED_POINTER:
6473 if (hr != S_OK)
6475 ws_free( heap, buf, desc->size );
6476 return hr;
6478 *(char **)ret = buf;
6479 break;
6481 case WS_READ_OPTIONAL_POINTER:
6482 case WS_READ_NILLABLE_POINTER:
6483 if (is_nil_value( buf, desc->size ))
6485 ws_free( heap, buf, desc->size );
6486 buf = NULL;
6488 *(char **)ret = buf;
6489 break;
6491 case WS_READ_REQUIRED_VALUE:
6492 case WS_READ_NILLABLE_VALUE:
6493 if (hr != S_OK) return hr;
6494 break;
6496 default:
6497 ERR( "unhandled read option %u\n", option );
6498 return E_NOTIMPL;
6501 if (desc->structOptions & WS_STRUCT_IGNORE_TRAILING_ELEMENT_CONTENT)
6503 struct node *parent = find_parent( reader );
6504 parent->flags |= NODE_FLAG_IGNORE_TRAILING_ELEMENT_CONTENT;
6507 *found = TRUE;
6508 return S_OK;
6511 static HRESULT read_type_fault( struct reader *reader, WS_TYPE_MAPPING mapping, const WS_XML_STRING *localname,
6512 const WS_XML_STRING *ns, const WS_FAULT_DESCRIPTION *desc, WS_READ_OPTION option,
6513 WS_HEAP *heap, void *ret, ULONG size, BOOL *found )
6515 static const WS_XML_STRING faultcode = {9, (BYTE *)"faultcode"}, faultstring = {11, (BYTE *)"faultstring"};
6516 static const WS_XML_STRING faultactor = {10, (BYTE *)"faultactor"}, detail = {6, (BYTE *)"detail"};
6518 const struct node *root = reader->current;
6519 WS_FAULT *fault;
6520 HRESULT hr = S_OK;
6522 if (mapping != WS_ELEMENT_TYPE_MAPPING || !desc || !ret)
6523 return E_INVALIDARG;
6524 if (desc->envelopeVersion < WS_ENVELOPE_VERSION_SOAP_1_1 || desc->envelopeVersion >= WS_ENVELOPE_VERSION_NONE)
6525 return E_INVALIDARG;
6526 else if (desc->envelopeVersion != WS_ENVELOPE_VERSION_SOAP_1_1)
6528 FIXME( "unhandled envelopeVersion %u\n", desc->envelopeVersion );
6529 return E_NOTIMPL;
6532 switch (option)
6534 case WS_READ_REQUIRED_VALUE:
6535 if (size != sizeof(*fault))
6536 return E_INVALIDARG;
6537 fault = ret;
6538 memset( fault, 0, sizeof(*fault) );
6539 break;
6541 case WS_READ_REQUIRED_POINTER:
6542 case WS_READ_OPTIONAL_POINTER:
6543 case WS_READ_NILLABLE_POINTER:
6544 if (size != sizeof(void *))
6545 return E_INVALIDARG;
6546 if (!(fault = ws_alloc_zero( heap, sizeof(*fault) )))
6547 return WS_E_QUOTA_EXCEEDED;
6548 break;
6550 case WS_READ_NILLABLE_VALUE:
6551 return E_INVALIDARG;
6553 default:
6554 FIXME( "unhandled read option %u\n", option );
6555 return E_NOTIMPL;
6558 if ((hr = read_type_next_node( reader )) != S_OK) goto done;
6559 for (;;)
6561 if (node_type( reader->current ) == WS_XML_NODE_TYPE_END_ELEMENT && reader->current->parent == root)
6562 break;
6564 if (match_element( reader->current, &faultcode, ns ))
6566 if (fault->code)
6568 hr = WS_E_INVALID_FORMAT;
6569 break;
6571 if (!(fault->code = ws_alloc_zero( heap, sizeof(*fault->code) )))
6573 hr = WS_E_QUOTA_EXCEEDED;
6574 break;
6576 if ((hr = read_type( reader, WS_ELEMENT_TYPE_MAPPING, WS_XML_QNAME_TYPE, NULL, NULL,
6577 NULL, WS_READ_REQUIRED_VALUE, heap, &fault->code->value,
6578 sizeof(fault->code->value), found )) != S_OK)
6579 break;
6582 else if (match_element( reader->current, &faultstring, ns ))
6584 if (fault->reasons)
6586 hr = WS_E_INVALID_FORMAT;
6587 break;
6589 if (!(fault->reasons = ws_alloc_zero( heap, sizeof(*fault->reasons) )))
6591 hr = WS_E_QUOTA_EXCEEDED;
6592 break;
6594 fault->reasonCount = 1;
6595 /* FIXME: parse optional xml:lang attribute */
6596 if ((hr = read_next_node( reader )) != S_OK ||
6597 (hr = read_type( reader, WS_ELEMENT_TYPE_MAPPING, WS_STRING_TYPE, NULL, NULL,
6598 NULL, WS_READ_REQUIRED_VALUE, heap, &fault->reasons->text,
6599 sizeof(fault->reasons->text), found )) != S_OK)
6600 break;
6602 else if (match_element( reader->current, &faultactor, ns ))
6604 if (fault->actor.length > 0)
6606 hr = WS_E_INVALID_FORMAT;
6607 break;
6609 if ((hr = read_next_node( reader )) != S_OK ||
6610 (hr = read_type( reader, WS_ELEMENT_TYPE_MAPPING, WS_STRING_TYPE, NULL, NULL,
6611 NULL, WS_READ_REQUIRED_VALUE, heap, &fault->actor,
6612 sizeof(fault->actor), found )) != S_OK)
6613 break;
6615 else if (match_element( reader->current, &detail, ns ))
6617 if (fault->detail)
6619 hr = WS_E_INVALID_FORMAT;
6620 break;
6622 if ((hr = WsReadXmlBuffer( (WS_XML_READER *)reader, heap, &fault->detail, NULL )) != S_OK)
6623 break;
6625 else if ((hr = read_type_next_node( reader )) != S_OK)
6626 break;
6629 done:
6630 if ((!fault->code || !fault->reasons) && hr == S_OK)
6631 hr = WS_E_INVALID_FORMAT;
6633 if (hr != S_OK)
6635 free_fault_fields( heap, fault );
6637 switch (option)
6639 case WS_READ_REQUIRED_VALUE:
6640 case WS_READ_REQUIRED_POINTER:
6641 memset( fault, 0, sizeof(*fault) );
6642 break;
6644 case WS_READ_OPTIONAL_POINTER:
6645 case WS_READ_NILLABLE_POINTER:
6646 if (hr == WS_E_INVALID_FORMAT && is_nil_value( (const char *)fault, sizeof(*fault) ))
6648 ws_free( heap, fault, sizeof(*fault) );
6649 fault = NULL;
6650 hr = S_OK;
6652 else
6653 memset( fault, 0, sizeof(*fault) );
6654 break;
6656 default:
6657 ERR( "unhandled option %u\n", option );
6658 return E_NOTIMPL;
6662 if (option != WS_READ_REQUIRED_VALUE)
6663 *(WS_FAULT **)ret = fault;
6665 *found = TRUE;
6666 return hr;
6669 static HRESULT start_mapping( struct reader *reader, WS_TYPE_MAPPING mapping, const WS_XML_STRING *localname,
6670 const WS_XML_STRING *ns )
6672 switch (mapping)
6674 case WS_ELEMENT_TYPE_MAPPING:
6675 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
6676 return read_type_next_element_node( reader, localname, ns );
6678 case WS_ANY_ELEMENT_TYPE_MAPPING:
6679 case WS_ATTRIBUTE_TYPE_MAPPING:
6680 return S_OK;
6682 default:
6683 FIXME( "unhandled mapping %u\n", mapping );
6684 return E_NOTIMPL;
6688 static HRESULT read_type_endelement_node( struct reader *reader )
6690 const struct node *parent = find_parent( reader );
6691 HRESULT hr;
6693 for (;;)
6695 if ((hr = read_type_next_node( reader )) != S_OK) return hr;
6696 if (node_type( reader->current ) == WS_XML_NODE_TYPE_END_ELEMENT && reader->current->parent == parent)
6698 return S_OK;
6700 if (read_end_of_data( reader ) || !(parent->flags & NODE_FLAG_IGNORE_TRAILING_ELEMENT_CONTENT)) break;
6703 return WS_E_INVALID_FORMAT;
6706 static HRESULT end_mapping( struct reader *reader, WS_TYPE_MAPPING mapping )
6708 switch (mapping)
6710 case WS_ELEMENT_TYPE_MAPPING:
6711 return read_type_endelement_node( reader );
6713 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
6714 return read_type_next_node( reader );
6716 case WS_ATTRIBUTE_TYPE_MAPPING:
6717 default:
6718 return S_OK;
6722 static BOOL is_true_text( const WS_XML_TEXT *text )
6724 switch (text->textType)
6726 case WS_XML_TEXT_TYPE_UTF8:
6728 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
6729 if (text_utf8->value.length == 4 && !memcmp( text_utf8->value.bytes, "true", 4 )) return TRUE;
6730 return FALSE;
6732 case WS_XML_TEXT_TYPE_BOOL:
6734 const WS_XML_BOOL_TEXT *text_bool = (const WS_XML_BOOL_TEXT *)text;
6735 return text_bool->value;
6737 default:
6738 ERR( "unhandled text type %u\n", text->textType );
6739 return FALSE;
6743 static HRESULT is_nil_element( const WS_XML_ELEMENT_NODE *elem )
6745 static const WS_XML_STRING localname = {3, (BYTE *)"nil"};
6746 static const WS_XML_STRING ns = {41, (BYTE *)"http://www.w3.org/2001/XMLSchema-instance"};
6747 ULONG i;
6749 for (i = 0; i < elem->attributeCount; i++)
6751 if (elem->attributes[i]->isXmlNs) continue;
6752 if (WsXmlStringEquals( elem->attributes[i]->localName, &localname, NULL ) == S_OK &&
6753 WsXmlStringEquals( elem->attributes[i]->ns, &ns, NULL ) == S_OK &&
6754 is_true_text( elem->attributes[i]->value )) return TRUE;
6756 return FALSE;
6759 static HRESULT read_type( struct reader *reader, WS_TYPE_MAPPING mapping, WS_TYPE type,
6760 const WS_XML_STRING *localname, const WS_XML_STRING *ns, const void *desc,
6761 WS_READ_OPTION option, WS_HEAP *heap, void *value, ULONG size, BOOL *found )
6763 HRESULT hr;
6765 if ((hr = start_mapping( reader, mapping, localname, ns )) != S_OK) return hr;
6767 if (mapping == WS_ELEMENT_TYPE_MAPPING && is_nil_element( &reader->current->hdr ))
6769 if (option != WS_READ_NILLABLE_POINTER && option != WS_READ_NILLABLE_VALUE) return WS_E_INVALID_FORMAT;
6770 *found = TRUE;
6771 return end_mapping( reader, mapping );
6774 switch (type)
6776 case WS_BOOL_TYPE:
6777 hr = read_type_bool( reader, mapping, localname, ns, desc, option, heap, value, size, found );
6778 break;
6780 case WS_INT8_TYPE:
6781 hr = read_type_int8( reader, mapping, localname, ns, desc, option, heap, value, size, found );
6782 break;
6784 case WS_INT16_TYPE:
6785 hr = read_type_int16( reader, mapping, localname, ns, desc, option, heap, value, size, found );
6786 break;
6788 case WS_INT32_TYPE:
6789 hr = read_type_int32( reader, mapping, localname, ns, desc, option, heap, value, size, found );
6790 break;
6792 case WS_INT64_TYPE:
6793 hr = read_type_int64( reader, mapping, localname, ns, desc, option, heap, value, size, found );
6794 break;
6796 case WS_UINT8_TYPE:
6797 hr = read_type_uint8( reader, mapping, localname, ns, desc, option, heap, value, size, found );
6798 break;
6800 case WS_UINT16_TYPE:
6801 hr = read_type_uint16( reader, mapping, localname, ns, desc, option, heap, value, size, found );
6802 break;
6804 case WS_UINT32_TYPE:
6805 hr = read_type_uint32( reader, mapping, localname, ns, desc, option, heap, value, size, found );
6806 break;
6808 case WS_UINT64_TYPE:
6809 hr = read_type_uint64( reader, mapping, localname, ns, desc, option, heap, value, size, found );
6810 break;
6812 case WS_FLOAT_TYPE:
6813 hr = read_type_float( reader, mapping, localname, ns, desc, option, heap, value, size, found );
6814 break;
6816 case WS_DOUBLE_TYPE:
6817 hr = read_type_double( reader, mapping, localname, ns, desc, option, heap, value, size, found );
6818 break;
6820 case WS_DATETIME_TYPE:
6821 hr = read_type_datetime( reader, mapping, localname, ns, desc, option, heap, value, size, found );
6822 break;
6824 case WS_GUID_TYPE:
6825 hr = read_type_guid( reader, mapping, localname, ns, desc, option, heap, value, size, found );
6826 break;
6828 case WS_UNIQUE_ID_TYPE:
6829 hr = read_type_unique_id( reader, mapping, localname, ns, desc, option, heap, value, size, found );
6830 break;
6832 case WS_STRING_TYPE:
6833 hr = read_type_string( reader, mapping, localname, ns, desc, option, heap, value, size, found );
6834 break;
6836 case WS_WSZ_TYPE:
6837 hr = read_type_wsz( reader, mapping, localname, ns, desc, option, heap, value, size, found );
6838 break;
6840 case WS_BYTES_TYPE:
6841 hr = read_type_bytes( reader, mapping, localname, ns, desc, option, heap, value, size, found );
6842 break;
6844 case WS_XML_STRING_TYPE:
6845 hr = read_type_xml_string( reader, mapping, localname, ns, desc, option, heap, value, size, found );
6846 break;
6848 case WS_XML_QNAME_TYPE:
6849 hr = read_type_qname( reader, mapping, localname, ns, desc, option, heap, value, size, found );
6850 break;
6852 case WS_DESCRIPTION_TYPE:
6853 hr = read_type_description( reader, mapping, localname, ns, desc, option, heap, value, size, found );
6854 break;
6856 case WS_STRUCT_TYPE:
6857 hr = read_type_struct( reader, mapping, localname, ns, desc, option, heap, value, size, found );
6858 break;
6860 case WS_FAULT_TYPE:
6861 hr = read_type_fault( reader, mapping, localname, ns, desc, option, heap, value, size, found );
6862 break;
6864 case WS_ENUM_TYPE:
6865 hr = read_type_enum( reader, mapping, localname, ns, desc, option, heap, value, size, found );
6866 break;
6868 default:
6869 FIXME( "type %u not supported\n", type );
6870 return E_NOTIMPL;
6873 if (hr != S_OK) return hr;
6874 return end_mapping( reader, mapping );
6877 /**************************************************************************
6878 * WsReadType [webservices.@]
6880 HRESULT WINAPI WsReadType( WS_XML_READER *handle, WS_TYPE_MAPPING mapping, WS_TYPE type,
6881 const void *desc, WS_READ_OPTION option, WS_HEAP *heap, void *value,
6882 ULONG size, WS_ERROR *error )
6884 struct reader *reader = (struct reader *)handle;
6885 BOOL found;
6886 HRESULT hr;
6888 TRACE( "%p %u %u %p %#x %p %p %lu %p\n", handle, mapping, type, desc, option, heap, value,
6889 size, error );
6890 if (error) FIXME( "ignoring error parameter\n" );
6892 if (!reader || !value) return E_INVALIDARG;
6894 EnterCriticalSection( &reader->cs );
6896 if (reader->magic != READER_MAGIC)
6898 LeaveCriticalSection( &reader->cs );
6899 return E_INVALIDARG;
6902 if ((hr = read_type( reader, mapping, type, NULL, NULL, desc, option, heap, value, size, &found )) == S_OK)
6904 switch (mapping)
6906 case WS_ELEMENT_TYPE_MAPPING:
6907 hr = read_node( reader );
6908 break;
6910 default:
6911 break;
6913 if (hr == S_OK && !read_end_of_data( reader )) hr = WS_E_INVALID_FORMAT;
6916 LeaveCriticalSection( &reader->cs );
6917 TRACE( "returning %#lx\n", hr );
6918 return hr;
6921 HRESULT read_header( WS_XML_READER *handle, const WS_XML_STRING *localname, const WS_XML_STRING *ns,
6922 WS_TYPE type, const void *desc, WS_READ_OPTION option, WS_HEAP *heap, void *value,
6923 ULONG size )
6925 struct reader *reader = (struct reader *)handle;
6926 BOOL found;
6927 HRESULT hr;
6929 EnterCriticalSection( &reader->cs );
6931 if (reader->magic != READER_MAGIC)
6933 LeaveCriticalSection( &reader->cs );
6934 return E_INVALIDARG;
6937 hr = read_type( reader, WS_ELEMENT_CONTENT_TYPE_MAPPING, type, localname, ns, desc, option, heap,
6938 value, size, &found );
6940 LeaveCriticalSection( &reader->cs );
6941 return hr;
6944 /**************************************************************************
6945 * WsReadElement [webservices.@]
6947 HRESULT WINAPI WsReadElement( WS_XML_READER *handle, const WS_ELEMENT_DESCRIPTION *desc,
6948 WS_READ_OPTION option, WS_HEAP *heap, void *value, ULONG size,
6949 WS_ERROR *error )
6951 struct reader *reader = (struct reader *)handle;
6952 BOOL found;
6953 HRESULT hr;
6955 TRACE( "%p %p %#x %p %p %lu %p\n", handle, desc, option, heap, value, size, error );
6956 if (error) FIXME( "ignoring error parameter\n" );
6958 if (!reader || !desc || !value) return E_INVALIDARG;
6960 EnterCriticalSection( &reader->cs );
6962 if (reader->magic != READER_MAGIC)
6964 LeaveCriticalSection( &reader->cs );
6965 return E_INVALIDARG;
6968 hr = read_type( reader, WS_ELEMENT_TYPE_MAPPING, desc->type, desc->elementLocalName,
6969 desc->elementNs, desc->typeDescription, option, heap, value, size, &found );
6971 LeaveCriticalSection( &reader->cs );
6972 TRACE( "returning %#lx\n", hr );
6973 return hr;
6976 /**************************************************************************
6977 * WsReadValue [webservices.@]
6979 HRESULT WINAPI WsReadValue( WS_XML_READER *handle, WS_VALUE_TYPE value_type, void *value, ULONG size,
6980 WS_ERROR *error )
6982 struct reader *reader = (struct reader *)handle;
6983 WS_TYPE type = map_value_type( value_type );
6984 BOOL found;
6985 HRESULT hr;
6987 TRACE( "%p %u %p %lu %p\n", handle, type, value, size, error );
6988 if (error) FIXME( "ignoring error parameter\n" );
6990 if (!reader || !value || type == ~0u) return E_INVALIDARG;
6992 EnterCriticalSection( &reader->cs );
6994 if (reader->magic != READER_MAGIC)
6996 LeaveCriticalSection( &reader->cs );
6997 return E_INVALIDARG;
7000 hr = read_type( reader, WS_ELEMENT_TYPE_MAPPING, type, NULL, NULL, NULL, WS_READ_REQUIRED_VALUE,
7001 NULL, value, size, &found );
7003 LeaveCriticalSection( &reader->cs );
7004 TRACE( "returning %#lx\n", hr );
7005 return hr;
7008 /**************************************************************************
7009 * WsReadAttribute [webservices.@]
7011 HRESULT WINAPI WsReadAttribute( WS_XML_READER *handle, const WS_ATTRIBUTE_DESCRIPTION *desc,
7012 WS_READ_OPTION option, WS_HEAP *heap, void *value, ULONG size,
7013 WS_ERROR *error )
7015 struct reader *reader = (struct reader *)handle;
7016 BOOL found;
7017 HRESULT hr;
7019 TRACE( "%p %p %#x %p %p %lu %p\n", handle, desc, option, heap, value, size, error );
7020 if (error) FIXME( "ignoring error parameter\n" );
7022 if (!reader || !desc || !value) return E_INVALIDARG;
7024 EnterCriticalSection( &reader->cs );
7026 if (reader->magic != READER_MAGIC)
7028 LeaveCriticalSection( &reader->cs );
7029 return E_INVALIDARG;
7032 if (!reader->input_type) hr = WS_E_INVALID_OPERATION;
7033 else hr = read_type( reader, WS_ATTRIBUTE_TYPE_MAPPING, desc->type, desc->attributeLocalName,
7034 desc->attributeNs, desc->typeDescription, option, heap, value, size, &found );
7036 LeaveCriticalSection( &reader->cs );
7037 TRACE( "returning %#lx\n", hr );
7038 return hr;
7041 static inline BOOL is_utf8( const unsigned char *data, ULONG size, ULONG *offset )
7043 static const char bom[] = {0xef,0xbb,0xbf};
7044 return (size >= sizeof(bom) && !memcmp( data, bom, sizeof(bom) ) && (*offset = sizeof(bom))) ||
7045 (size > 2 && !(*offset = 0));
7048 static inline BOOL is_utf16le( const unsigned char *data, ULONG size, ULONG *offset )
7050 static const char bom[] = {0xff,0xfe};
7051 return (size >= sizeof(bom) && !memcmp( data, bom, sizeof(bom) ) && (*offset = sizeof(bom))) ||
7052 (size >= 4 && data[0] == '<' && !data[1] && !(*offset = 0));
7055 static WS_CHARSET detect_charset( const unsigned char *data, ULONG size, ULONG *offset )
7057 WS_CHARSET ret = 0;
7059 /* FIXME: parse xml declaration */
7061 if (is_utf16le( data, size, offset )) ret = WS_CHARSET_UTF16LE;
7062 else if (is_utf8( data, size, offset )) ret = WS_CHARSET_UTF8;
7063 else
7065 FIXME( "charset not recognized\n" );
7066 return 0;
7069 TRACE( "detected charset %u\n", ret );
7070 return ret;
7073 static HRESULT utf16le_to_utf8( const unsigned char *data, ULONG size, unsigned char **buf, ULONG *buflen )
7075 if (size % sizeof(WCHAR)) return E_INVALIDARG;
7076 *buflen = WideCharToMultiByte( CP_UTF8, 0, (const WCHAR *)data, size / sizeof(WCHAR), NULL, 0, NULL, NULL );
7077 if (!(*buf = malloc( *buflen ))) return E_OUTOFMEMORY;
7078 WideCharToMultiByte( CP_UTF8, 0, (const WCHAR *)data, size / sizeof(WCHAR), (char *)*buf, *buflen, NULL, NULL );
7079 return S_OK;
7082 static HRESULT set_input_buffer( struct reader *reader, const unsigned char *data, ULONG size )
7084 reader->input_type = WS_XML_READER_INPUT_TYPE_BUFFER;
7085 reader->input_buf = NULL;
7087 if (reader->input_enc == WS_XML_READER_ENCODING_TYPE_TEXT && reader->input_charset == WS_CHARSET_UTF16LE)
7089 unsigned char *buf;
7090 ULONG buflen;
7091 HRESULT hr;
7093 if ((hr = utf16le_to_utf8( data, size, &buf, &buflen )) != S_OK) return hr;
7094 free( reader->input_conv );
7095 reader->read_bufptr = reader->input_conv = buf;
7096 reader->read_size = reader->input_size = buflen;
7098 else
7100 reader->read_bufptr = data;
7101 reader->read_size = reader->input_size = size;
7104 reader->read_pos = 0;
7105 reader->text_conv_offset = 0;
7106 return S_OK;
7109 static void set_input_stream( struct reader *reader, WS_READ_CALLBACK callback, void *state )
7111 reader->input_type = WS_XML_READER_INPUT_TYPE_STREAM;
7112 reader->input_cb = callback;
7113 reader->input_cb_state = state;
7114 reader->input_buf = NULL;
7115 reader->input_size = STREAM_BUFSIZE;
7117 if (reader->read_pos >= reader->read_size) reader->read_size = 0;
7118 else
7120 memmove( reader->stream_buf, reader->stream_buf + reader->read_pos, reader->read_size - reader->read_pos );
7121 reader->read_size -= reader->read_pos;
7123 reader->read_pos = 0;
7124 reader->read_bufptr = reader->stream_buf;
7125 reader->text_conv_offset = 0;
7128 /**************************************************************************
7129 * WsSetInput [webservices.@]
7131 HRESULT WINAPI WsSetInput( WS_XML_READER *handle, const WS_XML_READER_ENCODING *encoding,
7132 const WS_XML_READER_INPUT *input, const WS_XML_READER_PROPERTY *properties,
7133 ULONG count, WS_ERROR *error )
7135 struct reader *reader = (struct reader *)handle;
7136 struct node *node;
7137 ULONG i, offset = 0;
7138 HRESULT hr;
7140 TRACE( "%p %p %p %p %lu %p\n", handle, encoding, input, properties, count, error );
7141 if (error) FIXME( "ignoring error parameter\n" );
7143 if (!reader) return E_INVALIDARG;
7145 EnterCriticalSection( &reader->cs );
7147 if (reader->magic != READER_MAGIC)
7149 LeaveCriticalSection( &reader->cs );
7150 return E_INVALIDARG;
7153 for (i = 0; i < count; i++)
7155 hr = prop_set( reader->prop, reader->prop_count, properties[i].id, properties[i].value,
7156 properties[i].valueSize );
7157 if (hr != S_OK) goto done;
7160 if ((hr = init_reader( reader )) != S_OK) goto done;
7162 switch (encoding->encodingType)
7164 case WS_XML_READER_ENCODING_TYPE_TEXT:
7166 if (input->inputType == WS_XML_READER_INPUT_TYPE_BUFFER)
7168 const WS_XML_READER_TEXT_ENCODING *text = (const WS_XML_READER_TEXT_ENCODING *)encoding;
7169 const WS_XML_READER_BUFFER_INPUT *buf = (const WS_XML_READER_BUFFER_INPUT *)input;
7170 if (text->charSet != WS_CHARSET_AUTO) reader->input_charset = text->charSet;
7171 else reader->input_charset = detect_charset( buf->encodedData, buf->encodedDataSize, &offset );
7174 reader->input_enc = WS_XML_READER_ENCODING_TYPE_TEXT;
7175 break;
7177 case WS_XML_READER_ENCODING_TYPE_BINARY:
7179 const WS_XML_READER_BINARY_ENCODING *bin = (const WS_XML_READER_BINARY_ENCODING *)encoding;
7180 reader->input_enc = WS_XML_READER_ENCODING_TYPE_BINARY;
7181 reader->input_charset = 0;
7182 reader->dict_static = bin->staticDictionary ? bin->staticDictionary : &dict_builtin_static.dict;
7183 reader->dict = bin->dynamicDictionary ? bin->dynamicDictionary : &dict_builtin.dict;
7184 break;
7186 default:
7187 FIXME( "encoding type %u not supported\n", encoding->encodingType );
7188 hr = E_NOTIMPL;
7189 goto done;
7192 switch (input->inputType)
7194 case WS_XML_READER_INPUT_TYPE_BUFFER:
7196 const WS_XML_READER_BUFFER_INPUT *buf = (const WS_XML_READER_BUFFER_INPUT *)input;
7197 hr = set_input_buffer( reader, (const unsigned char *)buf->encodedData + offset, buf->encodedDataSize - offset );
7198 if (hr != S_OK) goto done;
7199 break;
7201 case WS_XML_READER_INPUT_TYPE_STREAM:
7203 const WS_XML_READER_STREAM_INPUT *stream = (const WS_XML_READER_STREAM_INPUT *)input;
7204 if (!reader->stream_buf && !(reader->stream_buf = malloc( STREAM_BUFSIZE )))
7206 hr = E_OUTOFMEMORY;
7207 goto done;
7209 set_input_stream( reader, stream->readCallback, stream->readCallbackState );
7210 break;
7212 default:
7213 FIXME( "input type %u not supported\n", input->inputType );
7214 hr = E_NOTIMPL;
7215 goto done;
7218 if (!(node = alloc_node( WS_XML_NODE_TYPE_BOF ))) hr = E_OUTOFMEMORY;
7219 else read_insert_bof( reader, node );
7221 done:
7222 LeaveCriticalSection( &reader->cs );
7223 TRACE( "returning %#lx\n", hr );
7224 return hr;
7227 static HRESULT set_input_xml_buffer( struct reader *reader, struct xmlbuf *xmlbuf )
7229 reader->input_type = WS_XML_READER_INPUT_TYPE_BUFFER;
7230 reader->input_buf = xmlbuf;
7231 reader->input_enc = xmlbuf->encoding;
7232 reader->input_charset = xmlbuf->charset;
7233 reader->dict_static = xmlbuf->dict_static;
7234 reader->dict = xmlbuf->dict;
7236 if (reader->input_enc == WS_XML_READER_ENCODING_TYPE_TEXT && reader->input_charset == WS_CHARSET_UTF16LE)
7238 unsigned char *buf;
7239 ULONG buflen;
7240 HRESULT hr;
7242 if ((hr = utf16le_to_utf8( xmlbuf->bytes.bytes, xmlbuf->bytes.length, &buf, &buflen )) != S_OK) return hr;
7243 free( reader->input_conv );
7244 reader->read_bufptr = reader->input_conv = buf;
7245 reader->read_size = reader->input_size = buflen;
7247 else
7249 reader->read_bufptr = xmlbuf->bytes.bytes;
7250 reader->read_size = reader->input_size = xmlbuf->bytes.length;
7253 reader->read_pos = 0;
7254 reader->text_conv_offset = 0;
7255 return S_OK;
7258 /**************************************************************************
7259 * WsSetInputToBuffer [webservices.@]
7261 HRESULT WINAPI WsSetInputToBuffer( WS_XML_READER *handle, WS_XML_BUFFER *buffer,
7262 const WS_XML_READER_PROPERTY *properties, ULONG count,
7263 WS_ERROR *error )
7265 struct reader *reader = (struct reader *)handle;
7266 struct xmlbuf *xmlbuf = (struct xmlbuf *)buffer;
7267 struct node *node;
7268 HRESULT hr;
7269 ULONG i;
7271 TRACE( "%p %p %p %lu %p\n", handle, buffer, properties, count, error );
7272 if (error) FIXME( "ignoring error parameter\n" );
7274 if (!reader || !xmlbuf) return E_INVALIDARG;
7276 EnterCriticalSection( &reader->cs );
7278 if (reader->magic != READER_MAGIC)
7280 LeaveCriticalSection( &reader->cs );
7281 return E_INVALIDARG;
7284 for (i = 0; i < count; i++)
7286 hr = prop_set( reader->prop, reader->prop_count, properties[i].id, properties[i].value,
7287 properties[i].valueSize );
7288 if (hr != S_OK) goto done;
7291 if ((hr = init_reader( reader )) != S_OK) goto done;
7292 if ((hr = set_input_xml_buffer( reader, xmlbuf )) != S_OK) goto done;
7294 if (!(node = alloc_node( WS_XML_NODE_TYPE_BOF ))) hr = E_OUTOFMEMORY;
7295 else read_insert_bof( reader, node );
7297 done:
7298 LeaveCriticalSection( &reader->cs );
7299 TRACE( "returning %#lx\n", hr );
7300 return hr;
7303 /**************************************************************************
7304 * WsGetReaderPosition [webservices.@]
7306 HRESULT WINAPI WsGetReaderPosition( WS_XML_READER *handle, WS_XML_NODE_POSITION *pos, WS_ERROR *error )
7308 struct reader *reader = (struct reader *)handle;
7309 HRESULT hr = S_OK;
7311 TRACE( "%p %p %p\n", handle, pos, error );
7312 if (error) FIXME( "ignoring error parameter\n" );
7314 if (!reader || !pos) return E_INVALIDARG;
7316 EnterCriticalSection( &reader->cs );
7318 if (reader->magic != READER_MAGIC)
7320 LeaveCriticalSection( &reader->cs );
7321 return E_INVALIDARG;
7324 if (!reader->input_buf) hr = WS_E_INVALID_OPERATION;
7325 else
7327 pos->buffer = (WS_XML_BUFFER *)reader->input_buf;
7328 pos->node = reader->current;
7331 LeaveCriticalSection( &reader->cs );
7332 TRACE( "returning %#lx\n", hr );
7333 return hr;
7336 /**************************************************************************
7337 * WsSetReaderPosition [webservices.@]
7339 HRESULT WINAPI WsSetReaderPosition( WS_XML_READER *handle, const WS_XML_NODE_POSITION *pos, WS_ERROR *error )
7341 struct reader *reader = (struct reader *)handle;
7342 HRESULT hr = S_OK;
7344 TRACE( "%p %p %p\n", handle, pos, error );
7345 if (error) FIXME( "ignoring error parameter\n" );
7347 if (!reader || !pos) return E_INVALIDARG;
7349 EnterCriticalSection( &reader->cs );
7351 if (reader->magic != READER_MAGIC || (struct xmlbuf *)pos->buffer != reader->input_buf)
7353 LeaveCriticalSection( &reader->cs );
7354 return E_INVALIDARG;
7357 if (!reader->input_buf) hr = WS_E_INVALID_OPERATION;
7358 else reader->current = pos->node;
7360 LeaveCriticalSection( &reader->cs );
7361 TRACE( "returning %#lx\n", hr );
7362 return hr;
7365 static HRESULT utf8_to_base64( const WS_XML_UTF8_TEXT *utf8, WS_XML_BASE64_TEXT *base64 )
7367 if (utf8->value.length % 4) return WS_E_INVALID_FORMAT;
7368 if (!(base64->bytes = malloc( utf8->value.length * 3 / 4 ))) return E_OUTOFMEMORY;
7369 base64->length = decode_base64( utf8->value.bytes, utf8->value.length, base64->bytes );
7370 return S_OK;
7373 /**************************************************************************
7374 * WsReadBytes [webservices.@]
7376 HRESULT WINAPI WsReadBytes( WS_XML_READER *handle, void *bytes, ULONG max_count, ULONG *count, WS_ERROR *error )
7378 struct reader *reader = (struct reader *)handle;
7379 HRESULT hr = S_OK;
7381 TRACE( "%p %p %lu %p %p\n", handle, bytes, max_count, count, error );
7382 if (error) FIXME( "ignoring error parameter\n" );
7384 if (!reader) return E_INVALIDARG;
7386 EnterCriticalSection( &reader->cs );
7388 if (reader->magic != READER_MAGIC)
7390 LeaveCriticalSection( &reader->cs );
7391 return E_INVALIDARG;
7394 if (!reader->input_type)
7396 hr = WS_E_INVALID_OPERATION;
7397 goto done;
7399 if (!count)
7401 hr = E_INVALIDARG;
7402 goto done;
7405 *count = 0;
7406 if (node_type( reader->current ) == WS_XML_NODE_TYPE_TEXT && bytes)
7408 const WS_XML_TEXT_NODE *text = (const WS_XML_TEXT_NODE *)reader->current;
7409 WS_XML_BASE64_TEXT base64;
7411 if ((hr = utf8_to_base64( (const WS_XML_UTF8_TEXT *)text->text, &base64 )) != S_OK) goto done;
7412 if (reader->text_conv_offset == base64.length)
7414 free( base64.bytes );
7415 hr = read_node( reader );
7416 goto done;
7418 *count = min( base64.length - reader->text_conv_offset, max_count );
7419 memcpy( bytes, base64.bytes + reader->text_conv_offset, *count );
7420 reader->text_conv_offset += *count;
7421 free( base64.bytes );
7424 done:
7425 LeaveCriticalSection( &reader->cs );
7426 TRACE( "returning %#lx\n", hr );
7427 return hr;
7430 static HRESULT utf8_to_utf16( const WS_XML_UTF8_TEXT *utf8, WS_XML_UTF16_TEXT *utf16 )
7432 int len = MultiByteToWideChar( CP_UTF8, 0, (char *)utf8->value.bytes, utf8->value.length, NULL, 0 );
7433 if (!(utf16->bytes = malloc( len * sizeof(WCHAR) ))) return E_OUTOFMEMORY;
7434 MultiByteToWideChar( CP_UTF8, 0, (char *)utf8->value.bytes, utf8->value.length, (WCHAR *)utf16->bytes, len );
7435 utf16->byteCount = len * sizeof(WCHAR);
7436 return S_OK;
7439 /**************************************************************************
7440 * WsReadChars [webservices.@]
7442 HRESULT WINAPI WsReadChars( WS_XML_READER *handle, WCHAR *chars, ULONG max_count, ULONG *count, WS_ERROR *error )
7444 struct reader *reader = (struct reader *)handle;
7445 HRESULT hr = S_OK;
7447 TRACE( "%p %p %lu %p %p\n", handle, chars, max_count, count, error );
7448 if (error) FIXME( "ignoring error parameter\n" );
7450 if (!reader) return E_INVALIDARG;
7452 EnterCriticalSection( &reader->cs );
7454 if (reader->magic != READER_MAGIC)
7456 LeaveCriticalSection( &reader->cs );
7457 return E_INVALIDARG;
7460 if (!reader->input_type)
7462 hr = WS_E_INVALID_OPERATION;
7463 goto done;
7465 if (!count)
7467 hr = E_INVALIDARG;
7468 goto done;
7471 *count = 0;
7472 if (node_type( reader->current ) == WS_XML_NODE_TYPE_TEXT && chars)
7474 const WS_XML_TEXT_NODE *text = (const WS_XML_TEXT_NODE *)reader->current;
7475 WS_XML_UTF16_TEXT utf16;
7476 HRESULT hr;
7478 if ((hr = utf8_to_utf16( (const WS_XML_UTF8_TEXT *)text->text, &utf16 )) != S_OK) goto done;
7479 if (reader->text_conv_offset == utf16.byteCount / sizeof(WCHAR))
7481 free( utf16.bytes );
7482 hr = read_node( reader );
7483 goto done;
7485 *count = min( utf16.byteCount / sizeof(WCHAR) - reader->text_conv_offset, max_count );
7486 memcpy( chars, utf16.bytes + reader->text_conv_offset * sizeof(WCHAR), *count * sizeof(WCHAR) );
7487 reader->text_conv_offset += *count;
7488 free( utf16.bytes );
7491 done:
7492 LeaveCriticalSection( &reader->cs );
7493 TRACE( "returning %#lx\n", hr );
7494 return hr;
7497 /**************************************************************************
7498 * WsReadCharsUtf8 [webservices.@]
7500 HRESULT WINAPI WsReadCharsUtf8( WS_XML_READER *handle, BYTE *bytes, ULONG max_count, ULONG *count, WS_ERROR *error )
7502 struct reader *reader = (struct reader *)handle;
7503 HRESULT hr = S_OK;
7505 TRACE( "%p %p %lu %p %p\n", handle, bytes, max_count, count, error );
7506 if (error) FIXME( "ignoring error parameter\n" );
7508 if (!reader) return E_INVALIDARG;
7510 EnterCriticalSection( &reader->cs );
7512 if (reader->magic != READER_MAGIC)
7514 LeaveCriticalSection( &reader->cs );
7515 return E_INVALIDARG;
7518 if (!reader->input_type)
7520 hr = WS_E_INVALID_OPERATION;
7521 goto done;
7523 if (!count)
7525 hr = E_INVALIDARG;
7526 goto done;
7529 *count = 0;
7530 if (node_type( reader->current ) == WS_XML_NODE_TYPE_TEXT && bytes)
7532 const WS_XML_TEXT_NODE *text = (const WS_XML_TEXT_NODE *)reader->current;
7533 const WS_XML_UTF8_TEXT *utf8 = (const WS_XML_UTF8_TEXT *)text->text;
7535 if (reader->text_conv_offset == utf8->value.length)
7537 hr = read_node( reader );
7538 goto done;
7540 *count = min( utf8->value.length - reader->text_conv_offset, max_count );
7541 memcpy( bytes, utf8->value.bytes + reader->text_conv_offset, *count );
7542 reader->text_conv_offset += *count;
7545 done:
7546 LeaveCriticalSection( &reader->cs );
7547 TRACE( "returning %#lx\n", hr );
7548 return hr;
7551 static HRESULT move_to_element( struct reader *reader )
7553 HRESULT hr;
7554 if (node_type( reader->current ) == WS_XML_NODE_TYPE_BOF &&
7555 (hr = read_move_to( reader, WS_MOVE_TO_CHILD_NODE, NULL )) != S_OK) return hr;
7556 if (node_type( reader->current ) != WS_XML_NODE_TYPE_ELEMENT) return E_FAIL;
7557 return S_OK;
7560 static HRESULT copy_tree( struct reader *reader, WS_XML_WRITER *writer )
7562 const struct node *node, *parent;
7563 BOOL done = FALSE;
7564 HRESULT hr;
7566 if ((hr = move_to_element( reader )) != S_OK) return hr;
7567 parent = reader->current;
7568 for (;;)
7570 node = reader->current;
7571 if ((hr = WsWriteNode( writer, (const WS_XML_NODE *)node, NULL )) != S_OK) break;
7572 if (node_type( node ) == WS_XML_NODE_TYPE_END_ELEMENT && node->parent == parent) done = TRUE;
7573 if ((hr = read_next_node( reader )) != S_OK || done) break;
7575 return hr;
7578 /**************************************************************************
7579 * WsReadXmlBuffer [webservices.@]
7581 HRESULT WINAPI WsReadXmlBuffer( WS_XML_READER *handle, WS_HEAP *heap, WS_XML_BUFFER **ret, WS_ERROR *error )
7583 struct reader *reader = (struct reader *)handle;
7584 WS_XML_WRITER *writer = NULL;
7585 WS_XML_BUFFER *buffer = NULL;
7586 HRESULT hr;
7588 TRACE( "%p %p %p %p\n", handle, heap, ret, error );
7589 if (error) FIXME( "ignoring error parameter\n" );
7591 if (!reader || !heap) return E_INVALIDARG;
7592 if (!ret) return E_FAIL;
7594 EnterCriticalSection( &reader->cs );
7596 if (reader->magic != READER_MAGIC)
7598 LeaveCriticalSection( &reader->cs );
7599 return E_INVALIDARG;
7602 if (!reader->input_type) hr = WS_E_INVALID_OPERATION;
7603 else
7605 if ((hr = WsCreateWriter( NULL, 0, &writer, NULL )) != S_OK) goto done;
7606 if ((hr = WsCreateXmlBuffer( heap, NULL, 0, &buffer, NULL )) != S_OK) goto done;
7607 if ((hr = WsSetOutputToBuffer( writer, buffer, NULL, 0, NULL )) != S_OK) goto done;
7608 if ((hr = copy_tree( reader, writer )) == S_OK) *ret = buffer;
7611 done:
7612 if (hr != S_OK) free_xmlbuf( (struct xmlbuf *)buffer );
7613 WsFreeWriter( writer );
7614 LeaveCriticalSection( &reader->cs );
7615 TRACE( "returning %#lx\n", hr );
7616 return hr;
7619 HRESULT create_header_buffer( WS_XML_READER *handle, WS_HEAP *heap, WS_XML_BUFFER **ret )
7621 struct reader *reader = (struct reader *)handle;
7622 HRESULT hr = WS_E_QUOTA_EXCEEDED;
7623 struct xmlbuf *xmlbuf;
7625 EnterCriticalSection( &reader->cs );
7627 if (reader->magic != READER_MAGIC)
7629 LeaveCriticalSection( &reader->cs );
7630 return E_INVALIDARG;
7633 if ((xmlbuf = alloc_xmlbuf( heap, reader->read_pos, reader->input_enc, reader->input_charset,
7634 reader->dict_static, reader->dict )))
7636 memcpy( xmlbuf->bytes.bytes, reader->read_bufptr, reader->read_pos );
7637 xmlbuf->bytes.length = reader->read_pos;
7638 *ret = (WS_XML_BUFFER *)xmlbuf;
7639 hr = S_OK;
7642 LeaveCriticalSection( &reader->cs );
7643 return hr;
7646 HRESULT get_param_desc( const WS_STRUCT_DESCRIPTION *desc, USHORT index, const WS_FIELD_DESCRIPTION **ret )
7648 if (index >= desc->fieldCount) return E_INVALIDARG;
7649 *ret = desc->fields[index];
7650 return S_OK;
7653 static ULONG get_field_size( const WS_FIELD_DESCRIPTION *desc )
7655 if (desc->options & WS_FIELD_POINTER) return sizeof(void *);
7656 return get_type_size( desc->type, desc->typeDescription );
7659 static HRESULT read_param( struct reader *reader, const WS_FIELD_DESCRIPTION *desc, WS_HEAP *heap, void *ret )
7661 if (!ret && !(ret = ws_alloc_zero( heap, get_field_size(desc) ))) return WS_E_QUOTA_EXCEEDED;
7662 return read_type_field( reader, NULL, desc, heap, ret, 0 );
7665 static HRESULT read_param_array( struct reader *reader, const WS_FIELD_DESCRIPTION *desc, WS_HEAP *heap,
7666 void **ret, ULONG *count )
7668 if (!ret && !(ret = ws_alloc_zero( heap, sizeof(void **) ))) return WS_E_QUOTA_EXCEEDED;
7669 return read_type_array( reader, desc, heap, ret, count );
7672 static void set_array_len( const WS_PARAMETER_DESCRIPTION *params, ULONG count, ULONG index, ULONG len,
7673 const void **args )
7675 ULONG i, *ptr;
7676 for (i = 0; i < count; i++)
7678 if (params[i].outputMessageIndex != index || params[i].parameterType != WS_PARAMETER_TYPE_ARRAY_COUNT)
7679 continue;
7680 if ((ptr = *(ULONG **)args[i])) *ptr = len;
7681 break;
7685 HRESULT read_output_params( WS_XML_READER *handle, WS_HEAP *heap, const WS_ELEMENT_DESCRIPTION *desc,
7686 const WS_PARAMETER_DESCRIPTION *params, ULONG count, const void **args )
7688 struct reader *reader = (struct reader *)handle;
7689 const WS_STRUCT_DESCRIPTION *desc_struct;
7690 const WS_FIELD_DESCRIPTION *desc_field;
7691 ULONG i, len;
7692 HRESULT hr;
7694 if (desc->type != WS_STRUCT_TYPE || !(desc_struct = desc->typeDescription)) return E_INVALIDARG;
7696 EnterCriticalSection( &reader->cs );
7698 if (reader->magic != READER_MAGIC)
7700 LeaveCriticalSection( &reader->cs );
7701 return E_INVALIDARG;
7704 if ((hr = start_mapping( reader, WS_ELEMENT_TYPE_MAPPING, desc->elementLocalName, desc->elementNs )) != S_OK)
7705 goto done;
7707 for (i = 0; i < count; i++)
7709 if (params[i].outputMessageIndex == INVALID_PARAMETER_INDEX) continue;
7710 if (params[i].parameterType == WS_PARAMETER_TYPE_MESSAGES)
7712 FIXME( "messages type not supported\n" );
7713 hr = E_NOTIMPL;
7714 goto done;
7716 if ((hr = get_param_desc( desc_struct, params[i].outputMessageIndex, &desc_field )) != S_OK) goto done;
7717 if (params[i].parameterType == WS_PARAMETER_TYPE_NORMAL)
7719 void *ptr = *(void **)args[i];
7720 if ((hr = read_param( reader, desc_field, heap, ptr )) != S_OK) goto done;
7722 else if (params[i].parameterType == WS_PARAMETER_TYPE_ARRAY)
7724 void **ptr = *(void ***)args[i];
7725 if ((hr = read_param_array( reader, desc_field, heap, ptr, &len )) != S_OK) goto done;
7726 set_array_len( params, count, params[i].outputMessageIndex, len, args );
7730 if (desc_struct->structOptions & WS_STRUCT_IGNORE_TRAILING_ELEMENT_CONTENT)
7732 struct node *parent = find_parent( reader );
7733 parent->flags |= NODE_FLAG_IGNORE_TRAILING_ELEMENT_CONTENT;
7736 hr = end_mapping( reader, WS_ELEMENT_TYPE_MAPPING );
7738 done:
7739 LeaveCriticalSection( &reader->cs );
7740 return hr;