webservices: Implement WsWriteArray.
[wine.git] / dlls / webservices / reader.c
blobb562c004a7ade71ea6e427b5b209af95bb55bdd2
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>
21 #include "windef.h"
22 #include "winbase.h"
23 #include "winnls.h"
24 #include "webservices.h"
26 #include "wine/debug.h"
27 #include "wine/list.h"
28 #include "webservices_private.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(webservices);
32 const char *debugstr_xmlstr( const WS_XML_STRING *str )
34 if (!str) return "(null)";
35 return debugstr_an( (const char *)str->bytes, str->length );
38 ULONG prop_size( const struct prop_desc *desc, ULONG count )
40 ULONG i, ret = count * sizeof(struct prop);
41 for (i = 0; i < count; i++) ret += desc[i].size;
42 return ret;
45 void prop_init( const struct prop_desc *desc, ULONG count, struct prop *prop, void *data )
47 ULONG i;
48 char *ptr = data;
49 for (i = 0; i < count; i++)
51 prop[i].value = ptr;
52 prop[i].size = desc[i].size;
53 prop[i].readonly = desc[i].readonly;
54 prop[i].writeonly = desc[i].writeonly;
55 ptr += prop[i].size;
59 HRESULT prop_set( const struct prop *prop, ULONG count, ULONG id, const void *value, ULONG size )
61 if (id >= count || size != prop[id].size || prop[id].readonly) return E_INVALIDARG;
62 memcpy( prop[id].value, value, size );
63 return S_OK;
66 HRESULT prop_get( const struct prop *prop, ULONG count, ULONG id, void *buf, ULONG size )
68 if (id >= count || size != prop[id].size || prop[id].writeonly) return E_INVALIDARG;
69 memcpy( buf, prop[id].value, prop[id].size );
70 return S_OK;
73 static const struct prop_desc error_props[] =
75 { sizeof(ULONG), TRUE }, /* WS_ERROR_PROPERTY_STRING_COUNT */
76 { sizeof(ULONG), FALSE }, /* WS_ERROR_PROPERTY_ORIGINAL_ERROR_CODE */
77 { sizeof(LANGID), FALSE } /* WS_ERROR_PROPERTY_LANGID */
80 struct error
82 ULONG prop_count;
83 struct prop prop[sizeof(error_props)/sizeof(error_props[0])];
86 static struct error *alloc_error(void)
88 static const ULONG count = sizeof(error_props)/sizeof(error_props[0]);
89 struct error *ret;
90 ULONG size = sizeof(*ret) + prop_size( error_props, count );
92 if (!(ret = heap_alloc_zero( size ))) return NULL;
93 prop_init( error_props, count, ret->prop, &ret[1] );
94 ret->prop_count = count;
95 return ret;
98 /**************************************************************************
99 * WsCreateError [webservices.@]
101 HRESULT WINAPI WsCreateError( const WS_ERROR_PROPERTY *properties, ULONG count, WS_ERROR **handle )
103 struct error *error;
104 LANGID langid = GetUserDefaultUILanguage();
105 HRESULT hr;
106 ULONG i;
108 TRACE( "%p %u %p\n", properties, count, handle );
110 if (!handle) return E_INVALIDARG;
111 if (!(error = alloc_error())) return E_OUTOFMEMORY;
113 prop_set( error->prop, error->prop_count, WS_ERROR_PROPERTY_LANGID, &langid, sizeof(langid) );
114 for (i = 0; i < count; i++)
116 if (properties[i].id == WS_ERROR_PROPERTY_ORIGINAL_ERROR_CODE)
118 heap_free( error );
119 return E_INVALIDARG;
121 hr = prop_set( error->prop, error->prop_count, properties[i].id, properties[i].value,
122 properties[i].valueSize );
123 if (hr != S_OK)
125 heap_free( error );
126 return hr;
130 *handle = (WS_ERROR *)error;
131 return S_OK;
134 /**************************************************************************
135 * WsFreeError [webservices.@]
137 void WINAPI WsFreeError( WS_ERROR *handle )
139 struct error *error = (struct error *)handle;
141 TRACE( "%p\n", handle );
142 heap_free( error );
145 /**************************************************************************
146 * WsResetError [webservices.@]
148 HRESULT WINAPI WsResetError( WS_ERROR *handle )
150 struct error *error = (struct error *)handle;
151 ULONG code;
153 TRACE( "%p\n", handle );
155 if (!handle) return E_INVALIDARG;
157 /* FIXME: release strings added with WsAddErrorString when it's implemented, reset string count */
158 code = 0;
159 return prop_set( error->prop, error->prop_count, WS_ERROR_PROPERTY_ORIGINAL_ERROR_CODE, &code, sizeof(code) );
162 static const struct prop_desc heap_props[] =
164 { sizeof(SIZE_T), FALSE }, /* WS_HEAP_PROPERTY_MAX_SIZE */
165 { sizeof(SIZE_T), FALSE }, /* WS_HEAP_PROPERTY_TRIM_SIZE */
166 { sizeof(SIZE_T), TRUE }, /* WS_HEAP_PROPERTY_REQUESTED_SIZE */
167 { sizeof(SIZE_T), TRUE } /* WS_HEAP_PROPERTY_ACTUAL_SIZE */
170 struct heap
172 HANDLE handle;
173 ULONG prop_count;
174 struct prop prop[sizeof(heap_props)/sizeof(heap_props[0])];
177 static BOOL ensure_heap( struct heap *heap )
179 SIZE_T size;
180 if (heap->handle) return TRUE;
181 if (prop_get( heap->prop, heap->prop_count, WS_HEAP_PROPERTY_MAX_SIZE, &size, sizeof(size) ) != S_OK)
182 return FALSE;
183 if (!(heap->handle = HeapCreate( 0, 0, size ))) return FALSE;
184 return TRUE;
187 void *ws_alloc( WS_HEAP *handle, SIZE_T size )
189 struct heap *heap = (struct heap *)handle;
190 if (!ensure_heap( heap )) return NULL;
191 return HeapAlloc( heap->handle, 0, size );
194 static void *ws_alloc_zero( WS_HEAP *handle, SIZE_T size )
196 struct heap *heap = (struct heap *)handle;
197 if (!ensure_heap( heap )) return NULL;
198 return HeapAlloc( heap->handle, HEAP_ZERO_MEMORY, size );
201 void *ws_realloc( WS_HEAP *handle, void *ptr, SIZE_T size )
203 struct heap *heap = (struct heap *)handle;
204 if (!ensure_heap( heap )) return NULL;
205 return HeapReAlloc( heap->handle, 0, ptr, size );
208 static void *ws_realloc_zero( WS_HEAP *handle, void *ptr, SIZE_T size )
210 struct heap *heap = (struct heap *)handle;
211 if (!ensure_heap( heap )) return NULL;
212 return HeapReAlloc( heap->handle, HEAP_ZERO_MEMORY, ptr, size );
215 void ws_free( WS_HEAP *handle, void *ptr )
217 struct heap *heap = (struct heap *)handle;
218 if (!heap->handle) return;
219 HeapFree( heap->handle, 0, ptr );
222 /**************************************************************************
223 * WsAlloc [webservices.@]
225 HRESULT WINAPI WsAlloc( WS_HEAP *handle, SIZE_T size, void **ptr, WS_ERROR *error )
227 void *mem;
229 TRACE( "%p %u %p %p\n", handle, (ULONG)size, ptr, error );
230 if (error) FIXME( "ignoring error parameter\n" );
232 if (!handle || !ptr) return E_INVALIDARG;
234 if (!(mem = ws_alloc( handle, size ))) return E_OUTOFMEMORY;
235 *ptr = mem;
236 return S_OK;
239 static struct heap *alloc_heap(void)
241 static const ULONG count = sizeof(heap_props)/sizeof(heap_props[0]);
242 struct heap *ret;
243 ULONG size = sizeof(*ret) + prop_size( heap_props, count );
245 if (!(ret = heap_alloc_zero( size ))) return NULL;
246 prop_init( heap_props, count, ret->prop, &ret[1] );
247 ret->prop_count = count;
248 return ret;
251 /**************************************************************************
252 * WsCreateHeap [webservices.@]
254 HRESULT WINAPI WsCreateHeap( SIZE_T max_size, SIZE_T trim_size, const WS_HEAP_PROPERTY *properties,
255 ULONG count, WS_HEAP **handle, WS_ERROR *error )
257 struct heap *heap;
259 TRACE( "%u %u %p %u %p %p\n", (ULONG)max_size, (ULONG)trim_size, properties, count, handle, error );
260 if (error) FIXME( "ignoring error parameter\n" );
262 if (!handle || count) return E_INVALIDARG;
263 if (!(heap = alloc_heap())) return E_OUTOFMEMORY;
265 prop_set( heap->prop, heap->prop_count, WS_HEAP_PROPERTY_MAX_SIZE, &max_size, sizeof(max_size) );
266 prop_set( heap->prop, heap->prop_count, WS_HEAP_PROPERTY_TRIM_SIZE, &trim_size, sizeof(trim_size) );
268 *handle = (WS_HEAP *)heap;
269 return S_OK;
272 /**************************************************************************
273 * WsFreeHeap [webservices.@]
275 void WINAPI WsFreeHeap( WS_HEAP *handle )
277 struct heap *heap = (struct heap *)handle;
279 TRACE( "%p\n", handle );
281 if (!heap) return;
282 HeapDestroy( heap->handle );
283 heap_free( heap );
286 /**************************************************************************
287 * WsResetHeap [webservices.@]
289 HRESULT WINAPI WsResetHeap( WS_HEAP *handle, WS_ERROR *error )
291 struct heap *heap = (struct heap *)handle;
293 TRACE( "%p %p\n", handle, error );
294 if (error) FIXME( "ignoring error parameter\n" );
296 if (!heap) return E_INVALIDARG;
298 HeapDestroy( heap->handle );
299 heap->handle = NULL;
300 return S_OK;
303 struct node *alloc_node( WS_XML_NODE_TYPE type )
305 struct node *ret;
307 if (!(ret = heap_alloc_zero( sizeof(*ret) ))) return NULL;
308 ret->hdr.node.nodeType = type;
309 list_init( &ret->entry );
310 list_init( &ret->children );
311 return ret;
314 void free_attribute( WS_XML_ATTRIBUTE *attr )
316 if (!attr) return;
317 heap_free( attr->prefix );
318 heap_free( attr->localName );
319 heap_free( attr->ns );
320 heap_free( attr->value );
321 heap_free( attr );
324 void free_node( struct node *node )
326 if (!node) return;
327 switch (node_type( node ))
329 case WS_XML_NODE_TYPE_ELEMENT:
331 WS_XML_ELEMENT_NODE *elem = &node->hdr;
332 ULONG i;
334 for (i = 0; i < elem->attributeCount; i++) free_attribute( elem->attributes[i] );
335 heap_free( elem->attributes );
336 heap_free( elem->prefix );
337 heap_free( elem->localName );
338 heap_free( elem->ns );
339 break;
341 case WS_XML_NODE_TYPE_TEXT:
343 WS_XML_TEXT_NODE *text = (WS_XML_TEXT_NODE *)node;
344 heap_free( text->text );
345 break;
347 case WS_XML_NODE_TYPE_COMMENT:
349 WS_XML_COMMENT_NODE *comment = (WS_XML_COMMENT_NODE *)node;
350 heap_free( comment->value.bytes );
351 break;
353 case WS_XML_NODE_TYPE_CDATA:
354 case WS_XML_NODE_TYPE_END_CDATA:
355 case WS_XML_NODE_TYPE_END_ELEMENT:
356 case WS_XML_NODE_TYPE_EOF:
357 case WS_XML_NODE_TYPE_BOF:
358 break;
360 default:
361 ERR( "unhandled type %u\n", node_type( node ) );
362 break;
364 heap_free( node );
367 void destroy_nodes( struct node *node )
369 struct list *ptr;
371 if (!node) return;
372 while ((ptr = list_head( &node->children )))
374 struct node *child = LIST_ENTRY( ptr, struct node, entry );
375 list_remove( &child->entry );
376 destroy_nodes( child );
378 free_node( node );
381 static WS_XML_ATTRIBUTE *dup_attribute( const WS_XML_ATTRIBUTE *src )
383 WS_XML_ATTRIBUTE *dst;
384 const WS_XML_STRING *prefix = (src->prefix && src->prefix->length) ? src->prefix : NULL;
385 const WS_XML_STRING *localname = src->localName;
386 const WS_XML_STRING *ns = src->localName;
388 if (!(dst = heap_alloc( sizeof(*dst) ))) return NULL;
389 dst->singleQuote = src->singleQuote;
390 dst->isXmlNs = src->isXmlNs;
391 if (prefix && !(dst->prefix = alloc_xml_string( prefix->bytes, prefix->length ))) goto error;
392 if (localname && !(dst->localName = alloc_xml_string( localname->bytes, localname->length ))) goto error;
393 if (ns && !(dst->ns = alloc_xml_string( ns->bytes, ns->length ))) goto error;
394 return dst;
396 error:
397 free_attribute( dst );
398 return NULL;
401 static WS_XML_ATTRIBUTE **dup_attributes( WS_XML_ATTRIBUTE * const *src, ULONG count )
403 WS_XML_ATTRIBUTE **dst;
404 ULONG i;
406 if (!(dst = heap_alloc( sizeof(*dst) * count ))) return NULL;
407 for (i = 0; i < count; i++)
409 if (!(dst[i] = dup_attribute( src[i] )))
411 for (; i > 0; i--) free_attribute( dst[i - 1] );
412 heap_free( dst );
413 return NULL;
416 return dst;
419 static struct node *dup_element_node( const WS_XML_ELEMENT_NODE *src )
421 struct node *node;
422 WS_XML_ELEMENT_NODE *dst;
423 ULONG count = src->attributeCount;
424 WS_XML_ATTRIBUTE **attrs = src->attributes;
425 const WS_XML_STRING *prefix = (src->prefix && src->prefix->length) ? src->prefix : NULL;
426 const WS_XML_STRING *localname = src->localName;
427 const WS_XML_STRING *ns = src->ns;
429 if (!(node = alloc_node( WS_XML_NODE_TYPE_ELEMENT ))) return NULL;
430 dst = &node->hdr;
432 if (count && !(dst->attributes = dup_attributes( attrs, count ))) goto error;
433 dst->attributeCount = count;
435 if (prefix && !(dst->prefix = alloc_xml_string( prefix->bytes, prefix->length ))) goto error;
436 if (localname && !(dst->localName = alloc_xml_string( localname->bytes, localname->length ))) goto error;
437 if (ns && !(dst->ns = alloc_xml_string( ns->bytes, ns->length ))) goto error;
438 return node;
440 error:
441 free_node( node );
442 return NULL;
445 static struct node *dup_text_node( const WS_XML_TEXT_NODE *src )
447 struct node *node;
448 WS_XML_TEXT_NODE *dst;
450 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
451 dst = (WS_XML_TEXT_NODE *)node;
453 if (src->text)
455 WS_XML_UTF8_TEXT *utf8;
456 const WS_XML_UTF8_TEXT *utf8_src = (WS_XML_UTF8_TEXT *)src->text;
457 if (!(utf8 = alloc_utf8_text( utf8_src->value.bytes, utf8_src->value.length )))
459 free_node( node );
460 return NULL;
462 dst->text = &utf8->text;
464 return node;
467 static struct node *dup_comment_node( const WS_XML_COMMENT_NODE *src )
469 struct node *node;
470 WS_XML_COMMENT_NODE *dst;
472 if (!(node = alloc_node( WS_XML_NODE_TYPE_COMMENT ))) return NULL;
473 dst = (WS_XML_COMMENT_NODE *)node;
475 if (src->value.length && !(dst->value.bytes = heap_alloc( src->value.length )))
477 free_node( node );
478 return NULL;
480 memcpy( dst->value.bytes, src->value.bytes, src->value.length );
481 dst->value.length = src->value.length;
482 return node;
485 static struct node *dup_node( const struct node *src )
487 switch (node_type( src ))
489 case WS_XML_NODE_TYPE_ELEMENT:
490 return dup_element_node( &src->hdr );
492 case WS_XML_NODE_TYPE_TEXT:
493 return dup_text_node( (const WS_XML_TEXT_NODE *)src );
495 case WS_XML_NODE_TYPE_COMMENT:
496 return dup_comment_node( (const WS_XML_COMMENT_NODE *)src );
498 case WS_XML_NODE_TYPE_CDATA:
499 case WS_XML_NODE_TYPE_END_CDATA:
500 case WS_XML_NODE_TYPE_END_ELEMENT:
501 case WS_XML_NODE_TYPE_EOF:
502 case WS_XML_NODE_TYPE_BOF:
503 return alloc_node( node_type( src ) );
505 default:
506 ERR( "unhandled type %u\n", node_type( src ) );
507 break;
509 return NULL;
512 static HRESULT dup_tree( struct node **dst, const struct node *src )
514 struct node *parent;
515 const struct node *child;
517 if (!*dst && !(*dst = dup_node( src ))) return E_OUTOFMEMORY;
518 parent = *dst;
520 LIST_FOR_EACH_ENTRY( child, &src->children, struct node, entry )
522 HRESULT hr = E_OUTOFMEMORY;
523 struct node *new_child;
525 if (!(new_child = dup_node( child )) || (hr = dup_tree( &new_child, child )) != S_OK)
527 destroy_nodes( *dst );
528 return hr;
530 new_child->parent = parent;
531 list_add_tail( &parent->children, &new_child->entry );
533 return S_OK;
536 static const struct prop_desc reader_props[] =
538 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_MAX_DEPTH */
539 { sizeof(BOOL), FALSE }, /* WS_XML_READER_PROPERTY_ALLOW_FRAGMENT */
540 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_MAX_ATTRIBUTES */
541 { sizeof(BOOL), FALSE }, /* WS_XML_READER_PROPERTY_READ_DECLARATION */
542 { sizeof(WS_CHARSET), FALSE }, /* WS_XML_READER_PROPERTY_CHARSET */
543 { sizeof(ULONGLONG), TRUE }, /* WS_XML_READER_PROPERTY_ROW */
544 { sizeof(ULONGLONG), TRUE }, /* WS_XML_READER_PROPERTY_COLUMN */
545 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_UTF8_TRIM_SIZE */
546 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_STREAM_BUFFER_SIZE */
547 { sizeof(BOOL), TRUE }, /* WS_XML_READER_PROPERTY_IN_ATTRIBUTE */
548 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_STREAM_MAX_ROOT_MIME_PART_SIZE */
549 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_STREAM_MAX_MIME_HEADERS_SIZE */
550 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_MAX_MIME_PARTS */
551 { sizeof(BOOL), FALSE }, /* WS_XML_READER_PROPERTY_ALLOW_INVALID_CHARACTER_REFERENCES */
552 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_MAX_NAMESPACES */
555 enum reader_state
557 READER_STATE_INITIAL,
558 READER_STATE_BOF,
559 READER_STATE_STARTELEMENT,
560 READER_STATE_STARTATTRIBUTE,
561 READER_STATE_STARTCDATA,
562 READER_STATE_CDATA,
563 READER_STATE_TEXT,
564 READER_STATE_ENDELEMENT,
565 READER_STATE_ENDCDATA,
566 READER_STATE_COMMENT,
567 READER_STATE_EOF
570 struct prefix
572 WS_XML_STRING str;
573 WS_XML_STRING ns;
576 struct reader
578 ULONG read_size;
579 ULONG read_pos;
580 const unsigned char *read_bufptr;
581 enum reader_state state;
582 struct node *root;
583 struct node *current;
584 ULONG current_attr;
585 struct node *last;
586 struct prefix *prefixes;
587 ULONG nb_prefixes;
588 ULONG nb_prefixes_allocated;
589 WS_XML_READER_INPUT_TYPE input_type;
590 struct xmlbuf *input_buf;
591 const unsigned char *input_data;
592 ULONG input_size;
593 ULONG prop_count;
594 struct prop prop[sizeof(reader_props)/sizeof(reader_props[0])];
597 static struct reader *alloc_reader(void)
599 static const ULONG count = sizeof(reader_props)/sizeof(reader_props[0]);
600 struct reader *ret;
601 ULONG size = sizeof(*ret) + prop_size( reader_props, count );
603 if (!(ret = heap_alloc_zero( size ))) return NULL;
604 if (!(ret->prefixes = heap_alloc_zero( sizeof(*ret->prefixes) )))
606 heap_free( ret );
607 return NULL;
609 ret->nb_prefixes = ret->nb_prefixes_allocated = 1;
611 prop_init( reader_props, count, ret->prop, &ret[1] );
612 ret->prop_count = count;
613 return ret;
616 static void clear_prefixes( struct prefix *prefixes, ULONG count )
618 ULONG i;
619 for (i = 0; i < count; i++)
621 heap_free( prefixes[i].str.bytes );
622 prefixes[i].str.bytes = NULL;
623 prefixes[i].str.length = 0;
625 heap_free( prefixes[i].ns.bytes );
626 prefixes[i].ns.bytes = NULL;
627 prefixes[i].ns.length = 0;
631 static void free_reader( struct reader *reader )
633 if (!reader) return;
634 destroy_nodes( reader->root );
635 clear_prefixes( reader->prefixes, reader->nb_prefixes );
636 heap_free( reader->prefixes );
637 heap_free( reader );
640 HRESULT copy_node( WS_XML_READER *handle, struct node **node )
642 struct reader *reader = (struct reader *)handle;
643 return dup_tree( node, reader->current );
646 static HRESULT set_prefix( struct prefix *prefix, const WS_XML_STRING *str, const WS_XML_STRING *ns )
648 if (str)
650 heap_free( prefix->str.bytes );
651 if (!(prefix->str.bytes = heap_alloc( str->length ))) return E_OUTOFMEMORY;
652 memcpy( prefix->str.bytes, str->bytes, str->length );
653 prefix->str.length = str->length;
656 heap_free( prefix->ns.bytes );
657 if (!(prefix->ns.bytes = heap_alloc( ns->length ))) return E_OUTOFMEMORY;
658 memcpy( prefix->ns.bytes, ns->bytes, ns->length );
659 prefix->ns.length = ns->length;
661 return S_OK;
664 static HRESULT bind_prefix( struct reader *reader, const WS_XML_STRING *prefix, const WS_XML_STRING *ns )
666 ULONG i;
667 HRESULT hr;
669 for (i = 0; i < reader->nb_prefixes; i++)
671 if (WsXmlStringEquals( prefix, &reader->prefixes[i].str, NULL ) == S_OK)
672 return set_prefix( &reader->prefixes[i], NULL, ns );
674 if (i >= reader->nb_prefixes_allocated)
676 ULONG new_size = reader->nb_prefixes_allocated * sizeof(*reader->prefixes) * 2;
677 struct prefix *tmp = heap_realloc_zero( reader->prefixes, new_size );
678 if (!tmp) return E_OUTOFMEMORY;
679 reader->prefixes = tmp;
680 reader->nb_prefixes_allocated *= 2;
683 if ((hr = set_prefix( &reader->prefixes[i], prefix, ns )) != S_OK) return hr;
684 reader->nb_prefixes++;
685 return S_OK;
688 static const WS_XML_STRING *get_namespace( struct reader *reader, const WS_XML_STRING *prefix )
690 ULONG i;
691 for (i = 0; i < reader->nb_prefixes; i++)
693 if (WsXmlStringEquals( prefix, &reader->prefixes[i].str, NULL ) == S_OK)
694 return &reader->prefixes[i].ns;
696 return NULL;
699 static void read_insert_eof( struct reader *reader, struct node *eof )
701 if (!reader->root) reader->root = eof;
702 else
704 eof->parent = reader->root;
705 list_add_tail( &reader->root->children, &eof->entry );
707 reader->current = reader->last = eof;
710 static void read_insert_bof( struct reader *reader, struct node *bof )
712 reader->root->parent = bof;
713 list_add_tail( &bof->children, &reader->root->entry );
714 reader->current = reader->last = reader->root = bof;
717 static void read_insert_node( struct reader *reader, struct node *parent, struct node *node )
719 node->parent = parent;
720 list_add_before( list_tail( &parent->children ), &node->entry );
721 reader->current = reader->last = node;
724 static HRESULT read_init_state( struct reader *reader )
726 struct node *node;
728 destroy_nodes( reader->root );
729 reader->root = NULL;
730 reader->input_buf = NULL;
731 clear_prefixes( reader->prefixes, reader->nb_prefixes );
732 reader->nb_prefixes = 1;
733 if (!(node = alloc_node( WS_XML_NODE_TYPE_EOF ))) return E_OUTOFMEMORY;
734 read_insert_eof( reader, node );
735 reader->state = READER_STATE_INITIAL;
736 return S_OK;
739 /**************************************************************************
740 * WsCreateReader [webservices.@]
742 HRESULT WINAPI WsCreateReader( const WS_XML_READER_PROPERTY *properties, ULONG count,
743 WS_XML_READER **handle, WS_ERROR *error )
745 struct reader *reader;
746 ULONG i, max_depth = 32, max_attrs = 128, max_ns = 32;
747 WS_CHARSET charset = WS_CHARSET_UTF8;
748 BOOL read_decl = TRUE;
749 HRESULT hr;
751 TRACE( "%p %u %p %p\n", properties, count, handle, error );
752 if (error) FIXME( "ignoring error parameter\n" );
754 if (!handle) return E_INVALIDARG;
755 if (!(reader = alloc_reader())) return E_OUTOFMEMORY;
757 prop_set( reader->prop, reader->prop_count, WS_XML_READER_PROPERTY_MAX_DEPTH, &max_depth, sizeof(max_depth) );
758 prop_set( reader->prop, reader->prop_count, WS_XML_READER_PROPERTY_MAX_ATTRIBUTES, &max_attrs, sizeof(max_attrs) );
759 prop_set( reader->prop, reader->prop_count, WS_XML_READER_PROPERTY_READ_DECLARATION, &read_decl, sizeof(read_decl) );
760 prop_set( reader->prop, reader->prop_count, WS_XML_READER_PROPERTY_CHARSET, &charset, sizeof(charset) );
761 prop_set( reader->prop, reader->prop_count, WS_XML_READER_PROPERTY_MAX_NAMESPACES, &max_ns, sizeof(max_ns) );
763 for (i = 0; i < count; i++)
765 hr = prop_set( reader->prop, reader->prop_count, properties[i].id, properties[i].value,
766 properties[i].valueSize );
767 if (hr != S_OK)
769 free_reader( reader );
770 return hr;
774 if ((hr = read_init_state( reader )) != S_OK)
776 free_reader( reader );
777 return hr;
780 *handle = (WS_XML_READER *)reader;
781 return S_OK;
784 /**************************************************************************
785 * WsFreeReader [webservices.@]
787 void WINAPI WsFreeReader( WS_XML_READER *handle )
789 struct reader *reader = (struct reader *)handle;
791 TRACE( "%p\n", handle );
792 free_reader( reader );
795 /**************************************************************************
796 * WsFillReader [webservices.@]
798 HRESULT WINAPI WsFillReader( WS_XML_READER *handle, ULONG min_size, const WS_ASYNC_CONTEXT *ctx,
799 WS_ERROR *error )
801 struct reader *reader = (struct reader *)handle;
803 TRACE( "%p %u %p %p\n", handle, min_size, ctx, error );
804 if (error) FIXME( "ignoring error parameter\n" );
806 if (!reader) return E_INVALIDARG;
808 /* FIXME: add support for stream input */
809 reader->read_size = min( min_size, reader->input_size );
810 reader->read_pos = 0;
812 return S_OK;
815 /**************************************************************************
816 * WsGetErrorProperty [webservices.@]
818 HRESULT WINAPI WsGetErrorProperty( WS_ERROR *handle, WS_ERROR_PROPERTY_ID id, void *buf,
819 ULONG size )
821 struct error *error = (struct error *)handle;
823 TRACE( "%p %u %p %u\n", handle, id, buf, size );
824 return prop_get( error->prop, error->prop_count, id, buf, size );
827 /**************************************************************************
828 * WsGetErrorString [webservices.@]
830 HRESULT WINAPI WsGetErrorString( WS_ERROR *handle, ULONG index, WS_STRING *str )
832 FIXME( "%p %u %p: stub\n", handle, index, str );
833 return E_NOTIMPL;
836 /**************************************************************************
837 * WsGetHeapProperty [webservices.@]
839 HRESULT WINAPI WsGetHeapProperty( WS_HEAP *handle, WS_HEAP_PROPERTY_ID id, void *buf,
840 ULONG size, WS_ERROR *error )
842 struct heap *heap = (struct heap *)handle;
844 TRACE( "%p %u %p %u %p\n", handle, id, buf, size, error );
845 if (error) FIXME( "ignoring error parameter\n" );
847 return prop_get( heap->prop, heap->prop_count, id, buf, size );
850 /**************************************************************************
851 * WsGetNamespaceFromPrefix [webservices.@]
853 HRESULT WINAPI WsGetNamespaceFromPrefix( WS_XML_READER *handle, const WS_XML_STRING *prefix,
854 BOOL required, const WS_XML_STRING **ns, WS_ERROR *error )
856 static const WS_XML_STRING xml = {3, (BYTE *)"xml"};
857 static const WS_XML_STRING xmlns = {5, (BYTE *)"xmlns"};
858 static const WS_XML_STRING empty_ns = {0, NULL};
859 static const WS_XML_STRING xml_ns = {36, (BYTE *)"http://www.w3.org/XML/1998/namespace"};
860 static const WS_XML_STRING xmlns_ns = {29, (BYTE *)"http://www.w3.org/2000/xmlns/"};
861 struct reader *reader = (struct reader *)handle;
862 BOOL found = FALSE;
864 TRACE( "%p %s %d %p %p\n", handle, debugstr_xmlstr(prefix), required, ns, error );
865 if (error) FIXME( "ignoring error parameter\n" );
867 if (!reader || !prefix || !ns) return E_INVALIDARG;
868 if (reader->state != READER_STATE_STARTELEMENT) return WS_E_INVALID_OPERATION;
870 if (!prefix->length)
872 *ns = &empty_ns;
873 found = TRUE;
875 else if (WsXmlStringEquals( prefix, &xml, NULL ) == S_OK)
877 *ns = &xml_ns;
878 found = TRUE;
880 else if (WsXmlStringEquals( prefix, &xmlns, NULL ) == S_OK)
882 *ns = &xmlns_ns;
883 found = TRUE;
885 else
887 WS_XML_ELEMENT_NODE *elem = &reader->current->hdr;
888 ULONG i;
890 for (i = 0; i < elem->attributeCount; i++)
892 if (!elem->attributes[i]->isXmlNs) continue;
893 if (WsXmlStringEquals( prefix, elem->attributes[i]->prefix, NULL ) == S_OK)
895 *ns = elem->attributes[i]->ns;
896 found = TRUE;
897 break;
902 if (!found)
904 if (required) return WS_E_INVALID_FORMAT;
905 *ns = NULL;
906 return S_FALSE;
908 return S_OK;
911 /**************************************************************************
912 * WsGetReaderNode [webservices.@]
914 HRESULT WINAPI WsGetReaderNode( WS_XML_READER *handle, const WS_XML_NODE **node,
915 WS_ERROR *error )
917 struct reader *reader = (struct reader *)handle;
919 TRACE( "%p %p %p\n", handle, node, error );
920 if (error) FIXME( "ignoring error parameter\n" );
922 if (!reader || !node) return E_INVALIDARG;
924 *node = &reader->current->hdr.node;
925 return S_OK;
928 /**************************************************************************
929 * WsGetReaderProperty [webservices.@]
931 HRESULT WINAPI WsGetReaderProperty( WS_XML_READER *handle, WS_XML_READER_PROPERTY_ID id,
932 void *buf, ULONG size, WS_ERROR *error )
934 struct reader *reader = (struct reader *)handle;
936 TRACE( "%p %u %p %u %p\n", handle, id, buf, size, error );
937 if (error) FIXME( "ignoring error parameter\n" );
939 if (!reader->input_type) return WS_E_INVALID_OPERATION;
941 if (id == WS_XML_READER_PROPERTY_CHARSET)
943 WS_CHARSET charset;
944 HRESULT hr;
946 if ((hr = prop_get( reader->prop, reader->prop_count, id, &charset, size )) != S_OK) return hr;
947 if (!charset) return WS_E_INVALID_FORMAT;
948 *(WS_CHARSET *)buf = charset;
949 return S_OK;
951 return prop_get( reader->prop, reader->prop_count, id, buf, size );
954 /**************************************************************************
955 * WsGetXmlAttribute [webservices.@]
957 HRESULT WINAPI WsGetXmlAttribute( WS_XML_READER *handle, const WS_XML_STRING *attr,
958 WS_HEAP *heap, WCHAR **str, ULONG *len, WS_ERROR *error )
960 FIXME( "%p %s %p %p %p %p: stub\n", handle, debugstr_xmlstr(attr), heap, str, len, error );
961 return E_NOTIMPL;
964 WS_XML_STRING *alloc_xml_string( const unsigned char *data, ULONG len )
966 WS_XML_STRING *ret;
968 if (!(ret = heap_alloc( sizeof(*ret) + len ))) return NULL;
969 ret->length = len;
970 ret->bytes = len ? (BYTE *)(ret + 1) : NULL;
971 ret->dictionary = NULL;
972 ret->id = 0;
973 if (data) memcpy( ret->bytes, data, len );
974 return ret;
977 WS_XML_UTF8_TEXT *alloc_utf8_text( const unsigned char *data, ULONG len )
979 WS_XML_UTF8_TEXT *ret;
981 if (!(ret = heap_alloc( sizeof(*ret) + len ))) return NULL;
982 ret->text.textType = WS_XML_TEXT_TYPE_UTF8;
983 ret->value.length = len;
984 ret->value.bytes = len ? (BYTE *)(ret + 1) : NULL;
985 ret->value.dictionary = NULL;
986 ret->value.id = 0;
987 if (data) memcpy( ret->value.bytes, data, len );
988 return ret;
991 static inline BOOL read_end_of_data( struct reader *reader )
993 return reader->read_pos >= reader->read_size;
996 static inline const unsigned char *read_current_ptr( struct reader *reader )
998 return &reader->read_bufptr[reader->read_pos];
1001 /* UTF-8 support based on libs/wine/utf8.c */
1003 /* number of following bytes in sequence based on first byte value (for bytes above 0x7f) */
1004 static const char utf8_length[128] =
1006 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x80-0x8f */
1007 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x90-0x9f */
1008 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xa0-0xaf */
1009 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xb0-0xbf */
1010 0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xc0-0xcf */
1011 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xd0-0xdf */
1012 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, /* 0xe0-0xef */
1013 3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0 /* 0xf0-0xff */
1016 /* first byte mask depending on UTF-8 sequence length */
1017 static const unsigned char utf8_mask[4] = { 0x7f, 0x1f, 0x0f, 0x07 };
1019 /* minimum Unicode value depending on UTF-8 sequence length */
1020 static const unsigned int utf8_minval[4] = { 0x0, 0x80, 0x800, 0x10000 };
1022 static inline unsigned int read_utf8_char( struct reader *reader, unsigned int *skip )
1024 unsigned int len, res;
1025 unsigned char ch = reader->read_bufptr[reader->read_pos];
1026 const unsigned char *end;
1028 if (reader->read_pos >= reader->read_size) return 0;
1030 if (ch < 0x80)
1032 *skip = 1;
1033 return ch;
1035 len = utf8_length[ch - 0x80];
1036 if (reader->read_pos + len >= reader->read_size) return 0;
1037 end = reader->read_bufptr + reader->read_pos + len;
1038 res = ch & utf8_mask[len];
1040 switch (len)
1042 case 3:
1043 if ((ch = end[-3] ^ 0x80) >= 0x40) break;
1044 res = (res << 6) | ch;
1045 case 2:
1046 if ((ch = end[-2] ^ 0x80) >= 0x40) break;
1047 res = (res << 6) | ch;
1048 case 1:
1049 if ((ch = end[-1] ^ 0x80) >= 0x40) break;
1050 res = (res << 6) | ch;
1051 if (res < utf8_minval[len]) break;
1052 *skip = len + 1;
1053 return res;
1056 return 0;
1059 static inline void read_skip( struct reader *reader, unsigned int count )
1061 if (reader->read_pos + count > reader->read_size) return;
1062 reader->read_pos += count;
1065 static inline void read_rewind( struct reader *reader, unsigned int count )
1067 reader->read_pos -= count;
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 while (reader->read_pos < reader->read_size && read_isspace( reader->read_bufptr[reader->read_pos] ))
1087 reader->read_pos++;
1090 static inline int read_cmp( struct reader *reader, const char *str, int len )
1092 const unsigned char *ptr = read_current_ptr( reader );
1094 if (len < 0) len = strlen( str );
1095 if (reader->read_pos + len > reader->read_size) return -1;
1096 while (len--)
1098 if (*str != *ptr) return *ptr - *str;
1099 str++; ptr++;
1101 return 0;
1104 static HRESULT read_xmldecl( struct reader *reader )
1106 if (!reader->read_size) return WS_E_INVALID_FORMAT;
1108 if (read_cmp( reader, "<", 1 ) || read_cmp( reader, "<?", 2 ))
1110 reader->state = READER_STATE_BOF;
1111 return S_OK;
1113 if (read_cmp( reader, "<?xml ", 6 )) return WS_E_INVALID_FORMAT;
1114 read_skip( reader, 6 );
1116 /* FIXME: parse attributes */
1117 while (reader->read_pos < reader->read_size && reader->read_bufptr[reader->read_pos] != '?')
1118 reader->read_pos++;
1120 if (read_cmp( reader, "?>", 2 )) return WS_E_INVALID_FORMAT;
1121 read_skip( reader, 2 );
1123 reader->state = READER_STATE_BOF;
1124 return S_OK;
1127 HRESULT append_attribute( WS_XML_ELEMENT_NODE *elem, WS_XML_ATTRIBUTE *attr )
1129 if (elem->attributeCount)
1131 WS_XML_ATTRIBUTE **tmp;
1132 if (!(tmp = heap_realloc( elem->attributes, (elem->attributeCount + 1) * sizeof(attr) )))
1133 return E_OUTOFMEMORY;
1134 elem->attributes = tmp;
1136 else if (!(elem->attributes = heap_alloc( sizeof(attr) ))) return E_OUTOFMEMORY;
1137 elem->attributes[elem->attributeCount++] = attr;
1138 return S_OK;
1141 static HRESULT parse_name( const unsigned char *str, unsigned int len,
1142 WS_XML_STRING **prefix, WS_XML_STRING **localname )
1144 const unsigned char *name_ptr = str, *prefix_ptr = NULL;
1145 unsigned int i, name_len = len, prefix_len = 0;
1147 for (i = 0; i < len; i++)
1149 if (str[i] == ':')
1151 prefix_ptr = str;
1152 prefix_len = i;
1153 name_ptr = &str[i + 1];
1154 name_len -= i + 1;
1155 break;
1158 if (!(*prefix = alloc_xml_string( prefix_ptr, prefix_len ))) return E_OUTOFMEMORY;
1159 if (!(*localname = alloc_xml_string( name_ptr, name_len )))
1161 heap_free( *prefix );
1162 return E_OUTOFMEMORY;
1164 return S_OK;
1167 static int codepoint_to_utf8( int cp, unsigned char *dst )
1169 if (cp < 0x80)
1171 *dst = cp;
1172 return 1;
1174 if (cp < 0x800)
1176 dst[1] = 0x80 | (cp & 0x3f);
1177 cp >>= 6;
1178 dst[0] = 0xc0 | cp;
1179 return 2;
1181 if ((cp >= 0xd800 && cp <= 0xdfff) || cp == 0xfffe || cp == 0xffff) return -1;
1182 if (cp < 0x10000)
1184 dst[2] = 0x80 | (cp & 0x3f);
1185 cp >>= 6;
1186 dst[1] = 0x80 | (cp & 0x3f);
1187 cp >>= 6;
1188 dst[0] = 0xe0 | cp;
1189 return 3;
1191 dst[3] = 0x80 | (cp & 0x3f);
1192 cp >>= 6;
1193 dst[2] = 0x80 | (cp & 0x3f);
1194 cp >>= 6;
1195 dst[1] = 0x80 | (cp & 0x3f);
1196 cp >>= 6;
1197 dst[0] = 0xf0 | cp;
1198 return 4;
1201 static HRESULT decode_text( const unsigned char *str, ULONG len, unsigned char *ret, ULONG *ret_len )
1203 const unsigned char *p = str;
1204 unsigned char *q = ret;
1206 *ret_len = 0;
1207 while (len)
1209 if (*p == '&')
1211 p++; len--;
1212 if (!len) return WS_E_INVALID_FORMAT;
1214 if (len >= 3 && !memcmp( p, "lt;", 3 ))
1216 *q++ = '<';
1217 p += 3;
1218 len -= 3;
1220 else if (len >= 3 && !memcmp( p, "gt;", 3 ))
1222 *q++ = '>';
1223 p += 3;
1224 len -= 3;
1226 else if (len >= 5 && !memcmp( p, "quot;", 5 ))
1228 *q++ = '"';
1229 p += 5;
1230 len -= 5;
1232 else if (len >= 4 && !memcmp( p, "amp;", 4 ))
1234 *q++ = '&';
1235 p += 4;
1236 len -= 4;
1238 else if (len >= 5 && !memcmp( p, "apos;", 5 ))
1240 *q++ = '\'';
1241 p += 5;
1242 len -= 5;
1244 else if (*p == '#')
1246 ULONG start, nb_digits, i;
1247 int len_utf8, cp = 0;
1249 p++; len--;
1250 if (!len || *p != 'x') return WS_E_INVALID_FORMAT;
1251 p++; len--;
1253 start = len;
1254 while (len && isxdigit( *p )) { p++; len--; };
1255 if (!len) return WS_E_INVALID_FORMAT;
1257 p -= nb_digits = start - len;
1258 if (!nb_digits || nb_digits > 5 || p[nb_digits] != ';') return WS_E_INVALID_FORMAT;
1259 for (i = 0; i < nb_digits; i++)
1261 cp *= 16;
1262 if (*p >= '0' && *p <= '9') cp += *p - '0';
1263 else if (*p >= 'a' && *p <= 'f') cp += *p - 'a' + 10;
1264 else cp += *p - 'A' + 10;
1265 p++;
1267 p++; len--;
1268 if ((len_utf8 = codepoint_to_utf8( cp, q )) < 0) return WS_E_INVALID_FORMAT;
1269 *ret_len += len_utf8;
1270 q += len_utf8;
1271 continue;
1273 else return WS_E_INVALID_FORMAT;
1275 else
1277 *q++ = *p++;
1278 len--;
1280 *ret_len += 1;
1282 return S_OK;
1285 static HRESULT read_attribute( struct reader *reader, WS_XML_ATTRIBUTE **ret )
1287 static const WS_XML_STRING xmlns = {5, (BYTE *)"xmlns"};
1288 WS_XML_ATTRIBUTE *attr;
1289 WS_XML_UTF8_TEXT *text = NULL;
1290 unsigned int len = 0, ch, skip, quote;
1291 const unsigned char *start;
1292 WS_XML_STRING *prefix, *localname;
1293 HRESULT hr = WS_E_INVALID_FORMAT;
1295 if (!(attr = heap_alloc_zero( sizeof(*attr) ))) return E_OUTOFMEMORY;
1297 start = read_current_ptr( reader );
1298 for (;;)
1300 if (!(ch = read_utf8_char( reader, &skip ))) goto error;
1301 if (!read_isnamechar( ch )) break;
1302 read_skip( reader, skip );
1303 len += skip;
1305 if (!len) goto error;
1307 if ((hr = parse_name( start, len, &prefix, &localname )) != S_OK) goto error;
1308 hr = E_OUTOFMEMORY;
1309 if (WsXmlStringEquals( prefix, &xmlns, NULL ) == S_OK)
1311 heap_free( prefix );
1312 attr->isXmlNs = 1;
1313 if (!(attr->prefix = alloc_xml_string( localname->bytes, localname->length )))
1315 heap_free( localname );
1316 goto error;
1318 attr->localName = localname;
1320 else if (!prefix->length && WsXmlStringEquals( localname, &xmlns, NULL ) == S_OK)
1322 attr->isXmlNs = 1;
1323 attr->prefix = prefix;
1324 attr->localName = localname;
1326 else
1328 attr->prefix = prefix;
1329 attr->localName = localname;
1332 hr = WS_E_INVALID_FORMAT;
1333 read_skip_whitespace( reader );
1334 if (read_cmp( reader, "=", 1 )) goto error;
1335 read_skip( reader, 1 );
1337 read_skip_whitespace( reader );
1338 if (read_cmp( reader, "\"", 1 ) && read_cmp( reader, "'", 1 )) goto error;
1339 quote = read_utf8_char( reader, &skip );
1340 read_skip( reader, 1 );
1342 len = 0;
1343 start = read_current_ptr( reader );
1344 for (;;)
1346 if (!(ch = read_utf8_char( reader, &skip ))) goto error;
1347 if (ch == quote) break;
1348 read_skip( reader, skip );
1349 len += skip;
1351 read_skip( reader, 1 );
1353 hr = E_OUTOFMEMORY;
1354 if (attr->isXmlNs)
1356 if (!(attr->ns = alloc_xml_string( start, len ))) goto error;
1357 if ((hr = bind_prefix( reader, attr->prefix, attr->ns )) != S_OK) goto error;
1358 if (!(text = alloc_utf8_text( NULL, 0 ))) goto error;
1360 else
1362 if (!(text = alloc_utf8_text( NULL, len ))) goto error;
1363 if ((hr = decode_text( start, len, text->value.bytes, &text->value.length )) != S_OK) goto error;
1366 attr->value = &text->text;
1367 attr->singleQuote = (quote == '\'');
1369 *ret = attr;
1370 return S_OK;
1372 error:
1373 heap_free( text );
1374 free_attribute( attr );
1375 return hr;
1378 static inline BOOL is_valid_parent( const struct node *node )
1380 if (!node) return FALSE;
1381 return node_type( node ) == WS_XML_NODE_TYPE_ELEMENT || node_type( node ) == WS_XML_NODE_TYPE_BOF;
1384 struct node *find_parent( struct node *node )
1386 if (is_valid_parent( node )) return node;
1387 if (is_valid_parent( node->parent )) return node->parent;
1388 return NULL;
1391 static HRESULT set_namespaces( struct reader *reader, WS_XML_ELEMENT_NODE *elem )
1393 static const WS_XML_STRING xml = {3, (BYTE *)"xml"};
1394 const WS_XML_STRING *ns;
1395 ULONG i;
1397 if (!(ns = get_namespace( reader, elem->prefix ))) return WS_E_INVALID_FORMAT;
1398 if (!(elem->ns = alloc_xml_string( ns->bytes, ns->length ))) return E_OUTOFMEMORY;
1399 if (!elem->ns->length) elem->ns->bytes = (BYTE *)(elem->ns + 1); /* quirk */
1401 for (i = 0; i < elem->attributeCount; i++)
1403 WS_XML_ATTRIBUTE *attr = elem->attributes[i];
1404 if (attr->isXmlNs || WsXmlStringEquals( attr->prefix, &xml, NULL ) == S_OK) continue;
1405 if (!(ns = get_namespace( reader, attr->prefix ))) return WS_E_INVALID_FORMAT;
1406 if (!(attr->ns = alloc_xml_string( ns->bytes, ns->length ))) return E_OUTOFMEMORY;
1408 return S_OK;
1411 static HRESULT read_element( struct reader *reader )
1413 unsigned int len = 0, ch, skip;
1414 const unsigned char *start;
1415 struct node *node = NULL, *endnode, *parent;
1416 WS_XML_ELEMENT_NODE *elem;
1417 WS_XML_ATTRIBUTE *attr = NULL;
1418 HRESULT hr = WS_E_INVALID_FORMAT;
1420 if (read_end_of_data( reader ))
1422 reader->current = LIST_ENTRY( list_tail( &reader->root->children ), struct node, entry );
1423 reader->last = reader->current;
1424 reader->state = READER_STATE_EOF;
1425 return S_OK;
1428 if (read_cmp( reader, "<", 1 )) goto error;
1429 read_skip( reader, 1 );
1430 if (!read_isnamechar( read_utf8_char( reader, &skip )))
1432 read_rewind( reader, 1 );
1433 goto error;
1436 start = read_current_ptr( reader );
1437 for (;;)
1439 if (!(ch = read_utf8_char( reader, &skip ))) goto error;
1440 if (!read_isnamechar( ch )) break;
1441 read_skip( reader, skip );
1442 len += skip;
1444 if (!len) goto error;
1446 if (!(parent = find_parent( reader->current ))) goto error;
1448 hr = E_OUTOFMEMORY;
1449 if (!(node = alloc_node( WS_XML_NODE_TYPE_ELEMENT ))) goto error;
1450 if (!(endnode = alloc_node( WS_XML_NODE_TYPE_END_ELEMENT ))) goto error;
1451 list_add_tail( &node->children, &endnode->entry );
1452 endnode->parent = node;
1454 elem = (WS_XML_ELEMENT_NODE *)node;
1455 if ((hr = parse_name( start, len, &elem->prefix, &elem->localName )) != S_OK) goto error;
1457 reader->current_attr = 0;
1458 for (;;)
1460 read_skip_whitespace( reader );
1461 if (!read_cmp( reader, ">", 1 ) || !read_cmp( reader, "/>", 2 )) break;
1462 if ((hr = read_attribute( reader, &attr )) != S_OK) goto error;
1463 if ((hr = append_attribute( elem, attr )) != S_OK)
1465 free_attribute( attr );
1466 goto error;
1468 reader->current_attr++;
1470 if ((hr = set_namespaces( reader, elem )) != S_OK) goto error;
1472 read_insert_node( reader, parent, node );
1473 reader->state = READER_STATE_STARTELEMENT;
1474 return S_OK;
1476 error:
1477 destroy_nodes( node );
1478 return hr;
1481 static HRESULT read_text( struct reader *reader )
1483 unsigned int len = 0, ch, skip;
1484 const unsigned char *start;
1485 struct node *node, *parent;
1486 WS_XML_TEXT_NODE *text;
1487 WS_XML_UTF8_TEXT *utf8;
1488 HRESULT hr;
1490 start = read_current_ptr( reader );
1491 for (;;)
1493 if (read_end_of_data( reader )) break;
1494 if (!(ch = read_utf8_char( reader, &skip ))) return WS_E_INVALID_FORMAT;
1495 if (ch == '<') break;
1496 read_skip( reader, skip );
1497 len += skip;
1500 if (!(parent = find_parent( reader->current ))) return WS_E_INVALID_FORMAT;
1502 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return E_OUTOFMEMORY;
1503 text = (WS_XML_TEXT_NODE *)node;
1504 if (!(utf8 = alloc_utf8_text( NULL, len )))
1506 heap_free( node );
1507 return E_OUTOFMEMORY;
1509 if ((hr = decode_text( start, len, utf8->value.bytes, &utf8->value.length )) != S_OK)
1511 heap_free( utf8 );
1512 heap_free( node );
1513 return hr;
1515 text->text = &utf8->text;
1517 read_insert_node( reader, parent, node );
1518 reader->state = READER_STATE_TEXT;
1519 return S_OK;
1522 static HRESULT read_node( struct reader * );
1524 static HRESULT read_startelement( struct reader *reader )
1526 read_skip_whitespace( reader );
1527 if (!read_cmp( reader, "/>", 2 ))
1529 read_skip( reader, 2 );
1530 reader->current = LIST_ENTRY( list_tail( &reader->current->children ), struct node, entry );
1531 reader->last = reader->current;
1532 reader->state = READER_STATE_ENDELEMENT;
1533 return S_OK;
1535 else if (!read_cmp( reader, ">", 1 ))
1537 read_skip( reader, 1 );
1538 return read_node( reader );
1540 return WS_E_INVALID_FORMAT;
1543 static HRESULT read_to_startelement( struct reader *reader, BOOL *found )
1545 HRESULT hr;
1547 switch (reader->state)
1549 case READER_STATE_INITIAL:
1550 if ((hr = read_xmldecl( reader )) != S_OK) return hr;
1551 break;
1553 case READER_STATE_STARTELEMENT:
1554 if (found) *found = TRUE;
1555 return S_OK;
1557 default:
1558 break;
1561 read_skip_whitespace( reader );
1562 if ((hr = read_element( reader )) == S_OK && found)
1564 if (reader->state == READER_STATE_STARTELEMENT)
1565 *found = TRUE;
1566 else
1567 *found = FALSE;
1570 return hr;
1573 static int cmp_name( const unsigned char *name1, ULONG len1, const unsigned char *name2, ULONG len2 )
1575 ULONG i;
1576 if (len1 != len2) return 1;
1577 for (i = 0; i < len1; i++) { if (toupper( name1[i] ) != toupper( name2[i] )) return 1; }
1578 return 0;
1581 static struct node *read_find_startelement( struct reader *reader, const WS_XML_STRING *prefix,
1582 const WS_XML_STRING *localname )
1584 struct node *parent;
1585 const WS_XML_STRING *str;
1587 for (parent = reader->current; parent; parent = parent->parent)
1589 if (node_type( parent ) == WS_XML_NODE_TYPE_ELEMENT)
1591 str = parent->hdr.prefix;
1592 if (cmp_name( str->bytes, str->length, prefix->bytes, prefix->length )) continue;
1593 str = parent->hdr.localName;
1594 if (cmp_name( str->bytes, str->length, localname->bytes, localname->length )) continue;
1595 return parent;
1598 return NULL;
1601 static HRESULT read_endelement( struct reader *reader )
1603 struct node *parent;
1604 unsigned int len = 0, ch, skip;
1605 const unsigned char *start;
1606 WS_XML_STRING *prefix, *localname;
1607 HRESULT hr;
1609 if (reader->state == READER_STATE_EOF) return WS_E_INVALID_FORMAT;
1611 if (read_end_of_data( reader ))
1613 reader->current = LIST_ENTRY( list_tail( &reader->root->children ), struct node, entry );
1614 reader->last = reader->current;
1615 reader->state = READER_STATE_EOF;
1616 return S_OK;
1619 if (read_cmp( reader, "</", 2 )) return WS_E_INVALID_FORMAT;
1620 read_skip( reader, 2 );
1622 start = read_current_ptr( reader );
1623 for (;;)
1625 if (!(ch = read_utf8_char( reader, &skip ))) return WS_E_INVALID_FORMAT;
1626 if (ch == '>')
1628 read_skip( reader, 1 );
1629 break;
1631 if (!read_isnamechar( ch )) return WS_E_INVALID_FORMAT;
1632 read_skip( reader, skip );
1633 len += skip;
1636 if ((hr = parse_name( start, len, &prefix, &localname )) != S_OK) return hr;
1637 parent = read_find_startelement( reader, prefix, localname );
1638 heap_free( prefix );
1639 heap_free( localname );
1640 if (!parent) return WS_E_INVALID_FORMAT;
1642 reader->current = LIST_ENTRY( list_tail( &parent->children ), struct node, entry );
1643 reader->last = reader->current;
1644 reader->state = READER_STATE_ENDELEMENT;
1645 return S_OK;
1648 static HRESULT read_comment( struct reader *reader )
1650 unsigned int len = 0, ch, skip;
1651 const unsigned char *start;
1652 struct node *node, *parent;
1653 WS_XML_COMMENT_NODE *comment;
1655 if (read_cmp( reader, "<!--", 4 )) return WS_E_INVALID_FORMAT;
1656 read_skip( reader, 4 );
1658 start = read_current_ptr( reader );
1659 for (;;)
1661 if (!read_cmp( reader, "-->", 3 ))
1663 read_skip( reader, 3 );
1664 break;
1666 if (!(ch = read_utf8_char( reader, &skip ))) return WS_E_INVALID_FORMAT;
1667 read_skip( reader, skip );
1668 len += skip;
1671 if (!(parent = find_parent( reader->current ))) return WS_E_INVALID_FORMAT;
1673 if (!(node = alloc_node( WS_XML_NODE_TYPE_COMMENT ))) return E_OUTOFMEMORY;
1674 comment = (WS_XML_COMMENT_NODE *)node;
1675 if (!(comment->value.bytes = heap_alloc( len )))
1677 heap_free( node );
1678 return E_OUTOFMEMORY;
1680 memcpy( comment->value.bytes, start, len );
1681 comment->value.length = len;
1683 read_insert_node( reader, parent, node );
1684 reader->state = READER_STATE_COMMENT;
1685 return S_OK;
1688 static HRESULT read_startcdata( struct reader *reader )
1690 struct node *node, *endnode, *parent;
1692 if (read_cmp( reader, "<![CDATA[", 9 )) return WS_E_INVALID_FORMAT;
1693 read_skip( reader, 9 );
1695 if (!(parent = find_parent( reader->current ))) return WS_E_INVALID_FORMAT;
1697 if (!(node = alloc_node( WS_XML_NODE_TYPE_CDATA ))) return E_OUTOFMEMORY;
1698 if (!(endnode = alloc_node( WS_XML_NODE_TYPE_END_CDATA )))
1700 heap_free( node );
1701 return E_OUTOFMEMORY;
1703 list_add_tail( &node->children, &endnode->entry );
1704 endnode->parent = node;
1706 read_insert_node( reader, parent, node );
1707 reader->state = READER_STATE_STARTCDATA;
1708 return S_OK;
1711 static HRESULT read_cdata( struct reader *reader )
1713 unsigned int len = 0, ch, skip;
1714 const unsigned char *start;
1715 struct node *node;
1716 WS_XML_TEXT_NODE *text;
1717 WS_XML_UTF8_TEXT *utf8;
1719 start = read_current_ptr( reader );
1720 for (;;)
1722 if (!read_cmp( reader, "]]>", 3 )) break;
1723 if (!(ch = read_utf8_char( reader, &skip ))) return WS_E_INVALID_FORMAT;
1724 read_skip( reader, skip );
1725 len += skip;
1728 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return E_OUTOFMEMORY;
1729 text = (WS_XML_TEXT_NODE *)node;
1730 if (!(utf8 = alloc_utf8_text( start, len )))
1732 heap_free( node );
1733 return E_OUTOFMEMORY;
1735 text->text = &utf8->text;
1737 read_insert_node( reader, reader->current, node );
1738 reader->state = READER_STATE_CDATA;
1739 return S_OK;
1742 static HRESULT read_endcdata( struct reader *reader )
1744 struct node *parent;
1746 if (read_cmp( reader, "]]>", 3 )) return WS_E_INVALID_FORMAT;
1747 read_skip( reader, 3 );
1749 if (node_type( reader->current ) == WS_XML_NODE_TYPE_TEXT) parent = reader->current->parent;
1750 else parent = reader->current;
1752 reader->current = LIST_ENTRY( list_tail( &parent->children ), struct node, entry );
1753 reader->last = reader->current;
1754 reader->state = READER_STATE_ENDCDATA;
1755 return S_OK;
1758 static HRESULT read_node( struct reader *reader )
1760 HRESULT hr;
1762 for (;;)
1764 if (read_end_of_data( reader ))
1766 reader->current = LIST_ENTRY( list_tail( &reader->root->children ), struct node, entry );
1767 reader->last = reader->current;
1768 reader->state = READER_STATE_EOF;
1769 return S_OK;
1771 if (reader->state == READER_STATE_STARTCDATA) return read_cdata( reader );
1772 else if (reader->state == READER_STATE_CDATA) return read_endcdata( reader );
1773 else if (!read_cmp( reader, "<?", 2 ))
1775 hr = read_xmldecl( reader );
1776 if (FAILED( hr )) return hr;
1778 else if (!read_cmp( reader, "</", 2 )) return read_endelement( reader );
1779 else if (!read_cmp( reader, "<![CDATA[", 9 )) return read_startcdata( reader );
1780 else if (!read_cmp( reader, "<!--", 4 )) return read_comment( reader );
1781 else if (!read_cmp( reader, "<", 1 )) return read_element( reader );
1782 else if (!read_cmp( reader, "/>", 2 ) || !read_cmp( reader, ">", 1 )) return read_startelement( reader );
1783 else return read_text( reader );
1787 /**************************************************************************
1788 * WsReadEndElement [webservices.@]
1790 HRESULT WINAPI WsReadEndElement( WS_XML_READER *handle, WS_ERROR *error )
1792 struct reader *reader = (struct reader *)handle;
1794 TRACE( "%p %p\n", handle, error );
1795 if (error) FIXME( "ignoring error parameter\n" );
1797 if (!reader) return E_INVALIDARG;
1798 return read_endelement( reader );
1801 /**************************************************************************
1802 * WsReadNode [webservices.@]
1804 HRESULT WINAPI WsReadNode( WS_XML_READER *handle, WS_ERROR *error )
1806 struct reader *reader = (struct reader *)handle;
1808 TRACE( "%p %p\n", handle, error );
1809 if (error) FIXME( "ignoring error parameter\n" );
1811 if (!reader) return E_INVALIDARG;
1812 return read_node( reader );
1815 /**************************************************************************
1816 * WsReadStartElement [webservices.@]
1818 HRESULT WINAPI WsReadStartElement( WS_XML_READER *handle, WS_ERROR *error )
1820 struct reader *reader = (struct reader *)handle;
1822 TRACE( "%p %p\n", handle, error );
1823 if (error) FIXME( "ignoring error parameter\n" );
1825 if (!reader) return E_INVALIDARG;
1826 return read_startelement( reader );
1829 /**************************************************************************
1830 * WsReadToStartElement [webservices.@]
1832 HRESULT WINAPI WsReadToStartElement( WS_XML_READER *handle, const WS_XML_STRING *localname,
1833 const WS_XML_STRING *ns, BOOL *found, WS_ERROR *error )
1835 struct reader *reader = (struct reader *)handle;
1837 TRACE( "%p %s %s %p %p\n", handle, debugstr_xmlstr(localname), debugstr_xmlstr(ns), found, error );
1838 if (error) FIXME( "ignoring error parameter\n" );
1840 if (!reader) return E_INVALIDARG;
1841 if (localname || ns) FIXME( "name and/or namespace not verified\n" );
1843 return read_to_startelement( reader, found );
1846 BOOL move_to_root_element( struct node *root, struct node **current )
1848 struct list *ptr;
1849 struct node *node;
1851 if (!(ptr = list_head( &root->children ))) return FALSE;
1852 node = LIST_ENTRY( ptr, struct node, entry );
1853 if (node_type( node ) == WS_XML_NODE_TYPE_ELEMENT)
1855 *current = node;
1856 return TRUE;
1858 while ((ptr = list_next( &root->children, &node->entry )))
1860 struct node *next = LIST_ENTRY( ptr, struct node, entry );
1861 if (node_type( next ) == WS_XML_NODE_TYPE_ELEMENT)
1863 *current = next;
1864 return TRUE;
1866 node = next;
1868 return FALSE;
1871 BOOL move_to_next_element( struct node **current )
1873 struct list *ptr;
1874 struct node *node = *current, *parent = (*current)->parent;
1876 if (!parent) return FALSE;
1877 while ((ptr = list_next( &parent->children, &node->entry )))
1879 struct node *next = LIST_ENTRY( ptr, struct node, entry );
1880 if (node_type( next ) == WS_XML_NODE_TYPE_ELEMENT)
1882 *current = next;
1883 return TRUE;
1885 node = next;
1887 return FALSE;
1890 BOOL move_to_prev_element( struct node **current )
1892 struct list *ptr;
1893 struct node *node = *current, *parent = (*current)->parent;
1895 if (!parent) return FALSE;
1896 while ((ptr = list_prev( &parent->children, &node->entry )))
1898 struct node *prev = LIST_ENTRY( ptr, struct node, entry );
1899 if (node_type( prev ) == WS_XML_NODE_TYPE_ELEMENT)
1901 *current = prev;
1902 return TRUE;
1904 node = prev;
1906 return FALSE;
1909 BOOL move_to_child_element( struct node **current )
1911 struct list *ptr;
1912 struct node *child, *node = *current;
1914 if (!(ptr = list_head( &node->children ))) return FALSE;
1915 child = LIST_ENTRY( ptr, struct node, entry );
1916 if (node_type( child ) == WS_XML_NODE_TYPE_ELEMENT)
1918 *current = child;
1919 return TRUE;
1921 while ((ptr = list_next( &node->children, &child->entry )))
1923 struct node *next = LIST_ENTRY( ptr, struct node, entry );
1924 if (node_type( next ) == WS_XML_NODE_TYPE_ELEMENT)
1926 *current = next;
1927 return TRUE;
1929 child = next;
1931 return FALSE;
1934 BOOL move_to_end_element( struct node **current )
1936 struct list *ptr;
1937 struct node *node = *current;
1939 if (node_type( node ) != WS_XML_NODE_TYPE_ELEMENT) return FALSE;
1941 if ((ptr = list_tail( &node->children )))
1943 struct node *tail = LIST_ENTRY( ptr, struct node, entry );
1944 if (node_type( tail ) == WS_XML_NODE_TYPE_END_ELEMENT)
1946 *current = tail;
1947 return TRUE;
1950 return FALSE;
1953 BOOL move_to_parent_element( struct node **current )
1955 struct node *parent = (*current)->parent;
1957 if (parent && (node_type( parent ) == WS_XML_NODE_TYPE_ELEMENT ||
1958 node_type( parent ) == WS_XML_NODE_TYPE_BOF))
1960 *current = parent;
1961 return TRUE;
1963 return FALSE;
1966 BOOL move_to_first_node( struct node **current )
1968 struct list *ptr;
1969 struct node *node = *current;
1971 if ((ptr = list_head( &node->parent->children )))
1973 *current = LIST_ENTRY( ptr, struct node, entry );
1974 return TRUE;
1976 return FALSE;
1979 BOOL move_to_next_node( struct node **current )
1981 struct list *ptr;
1982 struct node *node = *current;
1984 if ((ptr = list_next( &node->parent->children, &node->entry )))
1986 *current = LIST_ENTRY( ptr, struct node, entry );
1987 return TRUE;
1989 return FALSE;
1992 BOOL move_to_prev_node( struct node **current )
1994 struct list *ptr;
1995 struct node *node = *current;
1997 if ((ptr = list_prev( &node->parent->children, &node->entry )))
1999 *current = LIST_ENTRY( ptr, struct node, entry );
2000 return TRUE;
2002 return FALSE;
2005 BOOL move_to_bof( struct node *root, struct node **current )
2007 *current = root;
2008 return TRUE;
2011 BOOL move_to_eof( struct node *root, struct node **current )
2013 struct list *ptr;
2014 if ((ptr = list_tail( &root->children )))
2016 *current = LIST_ENTRY( ptr, struct node, entry );
2017 return TRUE;
2019 return FALSE;
2022 BOOL move_to_child_node( struct node **current )
2024 struct list *ptr;
2025 struct node *node = *current;
2027 if ((ptr = list_head( &node->children )))
2029 *current = LIST_ENTRY( ptr, struct node, entry );
2030 return TRUE;
2032 return FALSE;
2035 BOOL move_to_parent_node( struct node **current )
2037 struct node *parent = (*current)->parent;
2038 if (!parent) return FALSE;
2039 *current = parent;
2040 return TRUE;
2043 static HRESULT read_move_to( struct reader *reader, WS_MOVE_TO move, BOOL *found )
2045 BOOL success = FALSE;
2046 HRESULT hr = S_OK;
2048 if (!read_end_of_data( reader ))
2050 while (reader->state != READER_STATE_EOF && (hr = read_node( reader )) == S_OK) { /* nothing */ };
2051 if (hr != S_OK) return hr;
2053 switch (move)
2055 case WS_MOVE_TO_ROOT_ELEMENT:
2056 success = move_to_root_element( reader->root, &reader->current );
2057 break;
2059 case WS_MOVE_TO_NEXT_ELEMENT:
2060 success = move_to_next_element( &reader->current );
2061 break;
2063 case WS_MOVE_TO_PREVIOUS_ELEMENT:
2064 success = move_to_prev_element( &reader->current );
2065 break;
2067 case WS_MOVE_TO_CHILD_ELEMENT:
2068 success = move_to_child_element( &reader->current );
2069 break;
2071 case WS_MOVE_TO_END_ELEMENT:
2072 success = move_to_end_element( &reader->current );
2073 break;
2075 case WS_MOVE_TO_PARENT_ELEMENT:
2076 success = move_to_parent_element( &reader->current );
2077 break;
2079 case WS_MOVE_TO_FIRST_NODE:
2080 success = move_to_first_node( &reader->current );
2081 break;
2083 case WS_MOVE_TO_NEXT_NODE:
2084 success = move_to_next_node( &reader->current );
2085 break;
2087 case WS_MOVE_TO_PREVIOUS_NODE:
2088 success = move_to_prev_node( &reader->current );
2089 break;
2091 case WS_MOVE_TO_CHILD_NODE:
2092 success = move_to_child_node( &reader->current );
2093 break;
2095 case WS_MOVE_TO_BOF:
2096 success = move_to_bof( reader->root, &reader->current );
2097 break;
2099 case WS_MOVE_TO_EOF:
2100 success = move_to_eof( reader->root, &reader->current );
2101 break;
2103 default:
2104 FIXME( "unhandled move %u\n", move );
2105 return E_NOTIMPL;
2108 if (found)
2110 *found = success;
2111 return S_OK;
2113 return success ? S_OK : WS_E_INVALID_FORMAT;
2116 /**************************************************************************
2117 * WsMoveReader [webservices.@]
2119 HRESULT WINAPI WsMoveReader( WS_XML_READER *handle, WS_MOVE_TO move, BOOL *found, WS_ERROR *error )
2121 struct reader *reader = (struct reader *)handle;
2123 TRACE( "%p %u %p %p\n", handle, move, found, error );
2124 if (error) FIXME( "ignoring error parameter\n" );
2126 if (!reader) return E_INVALIDARG;
2127 if (!reader->input_type) return WS_E_INVALID_OPERATION;
2129 return read_move_to( reader, move, found );
2132 /**************************************************************************
2133 * WsReadStartAttribute [webservices.@]
2135 HRESULT WINAPI WsReadStartAttribute( WS_XML_READER *handle, ULONG index, WS_ERROR *error )
2137 struct reader *reader = (struct reader *)handle;
2138 WS_XML_ELEMENT_NODE *elem;
2140 TRACE( "%p %u %p\n", handle, index, error );
2141 if (error) FIXME( "ignoring error parameter\n" );
2143 if (!reader) return E_INVALIDARG;
2145 elem = &reader->current->hdr;
2146 if (reader->state != READER_STATE_STARTELEMENT || index >= elem->attributeCount)
2147 return WS_E_INVALID_FORMAT;
2149 reader->current_attr = index;
2150 reader->state = READER_STATE_STARTATTRIBUTE;
2151 return S_OK;
2154 /**************************************************************************
2155 * WsReadEndAttribute [webservices.@]
2157 HRESULT WINAPI WsReadEndAttribute( WS_XML_READER *handle, WS_ERROR *error )
2159 struct reader *reader = (struct reader *)handle;
2161 TRACE( "%p %p\n", handle, error );
2162 if (error) FIXME( "ignoring error parameter\n" );
2164 if (!reader) return E_INVALIDARG;
2166 if (reader->state != READER_STATE_STARTATTRIBUTE)
2167 return WS_E_INVALID_FORMAT;
2169 reader->state = READER_STATE_STARTELEMENT;
2170 return S_OK;
2173 static WCHAR *xmltext_to_widechar( WS_HEAP *heap, const WS_XML_TEXT *text )
2175 WCHAR *ret;
2177 switch (text->textType)
2179 case WS_XML_TEXT_TYPE_UTF8:
2181 const WS_XML_UTF8_TEXT *utf8 = (const WS_XML_UTF8_TEXT *)text;
2182 int len = MultiByteToWideChar( CP_UTF8, 0, (char *)utf8->value.bytes, utf8->value.length, NULL, 0 );
2183 if (!(ret = ws_alloc( heap, (len + 1) * sizeof(WCHAR) ))) return NULL;
2184 MultiByteToWideChar( CP_UTF8, 0, (char *)utf8->value.bytes, utf8->value.length, ret, len );
2185 ret[len] = 0;
2186 break;
2188 default:
2189 FIXME( "unhandled type %u\n", text->textType );
2190 return NULL;
2193 return ret;
2196 #define MAX_INT8 0x7f
2197 #define MIN_INT8 (-MAX_INT8 - 1)
2198 #define MAX_INT16 0x7fff
2199 #define MIN_INT16 (-MAX_INT16 - 1)
2200 #define MAX_INT32 0x7fffffff
2201 #define MIN_INT32 (-MAX_INT32 - 1)
2202 #define MAX_INT64 (((INT64)0x7fffffff << 32) | 0xffffffff)
2203 #define MIN_INT64 (-MAX_INT64 - 1)
2204 #define MAX_UINT8 0xff
2205 #define MAX_UINT16 0xffff
2206 #define MAX_UINT32 0xffffffff
2207 #define MAX_UINT64 (((UINT64)0xffffffff << 32) | 0xffffffff)
2209 static HRESULT str_to_int64( const unsigned char *str, ULONG len, INT64 min, INT64 max, INT64 *ret )
2211 BOOL negative = FALSE;
2212 const unsigned char *ptr = str;
2214 *ret = 0;
2215 while (len && read_isspace( *ptr )) { ptr++; len--; }
2216 while (len && read_isspace( ptr[len - 1] )) { len--; }
2217 if (!len) return WS_E_INVALID_FORMAT;
2219 if (*ptr == '-')
2221 negative = TRUE;
2222 ptr++;
2223 len--;
2225 if (!len) return WS_E_INVALID_FORMAT;
2227 while (len--)
2229 int val;
2231 if (!isdigit( *ptr )) return WS_E_INVALID_FORMAT;
2232 val = *ptr - '0';
2233 if (negative) val = -val;
2235 if ((!negative && (*ret > max / 10 || *ret * 10 > max - val)) ||
2236 (negative && (*ret < min / 10 || *ret * 10 < min - val)))
2238 return WS_E_NUMERIC_OVERFLOW;
2240 *ret = *ret * 10 + val;
2241 ptr++;
2244 return S_OK;
2247 static HRESULT str_to_uint64( const unsigned char *str, ULONG len, UINT64 max, UINT64 *ret )
2249 const unsigned char *ptr = str;
2251 *ret = 0;
2252 while (len && read_isspace( *ptr )) { ptr++; len--; }
2253 while (len && read_isspace( ptr[len - 1] )) { len--; }
2254 if (!len) return WS_E_INVALID_FORMAT;
2256 while (len--)
2258 unsigned int val;
2260 if (!isdigit( *ptr )) return WS_E_INVALID_FORMAT;
2261 val = *ptr - '0';
2263 if ((*ret > max / 10 || *ret * 10 > max - val)) return WS_E_NUMERIC_OVERFLOW;
2264 *ret = *ret * 10 + val;
2265 ptr++;
2268 return S_OK;
2271 #if defined(__i386__) || defined(__x86_64__)
2273 #define RC_DOWN 0x100;
2274 BOOL set_fp_rounding( unsigned short *save )
2276 #ifdef __GNUC__
2277 unsigned short fpword;
2279 __asm__ __volatile__( "fstcw %0" : "=m" (fpword) );
2280 *save = fpword;
2281 fpword |= RC_DOWN;
2282 __asm__ __volatile__( "fldcw %0" : : "m" (fpword) );
2283 return TRUE;
2284 #else
2285 FIXME( "not implemented\n" );
2286 return FALSE;
2287 #endif
2289 void restore_fp_rounding( unsigned short fpword )
2291 #ifdef __GNUC__
2292 __asm__ __volatile__( "fldcw %0" : : "m" (fpword) );
2293 #else
2294 FIXME( "not implemented\n" );
2295 #endif
2297 #else
2298 BOOL set_fp_rounding( unsigned short *save )
2300 FIXME( "not implemented\n" );
2301 return FALSE;
2303 void restore_fp_rounding( unsigned short fpword )
2305 FIXME( "not implemented\n" );
2307 #endif
2309 static HRESULT str_to_double( const unsigned char *str, ULONG len, double *ret )
2311 static const unsigned __int64 nan = 0xfff8000000000000;
2312 static const unsigned __int64 inf = 0x7ff0000000000000;
2313 static const unsigned __int64 inf_min = 0xfff0000000000000;
2314 HRESULT hr = WS_E_INVALID_FORMAT;
2315 const unsigned char *p = str, *q;
2316 int sign = 1, exp_sign = 1, exp = 0, exp_tmp = 0, neg_exp, i, nb_digits, have_digits;
2317 unsigned __int64 val = 0, tmp;
2318 long double exp_val = 1.0, exp_mul = 10.0;
2319 unsigned short fpword;
2321 while (len && read_isspace( *p )) { p++; len--; }
2322 while (len && read_isspace( p[len - 1] )) { len--; }
2323 if (!len) return WS_E_INVALID_FORMAT;
2325 if (len == 3 && !memcmp( p, "NaN", 3 ))
2327 *(unsigned __int64 *)ret = nan;
2328 return S_OK;
2330 else if (len == 3 && !memcmp( p, "INF", 3 ))
2332 *(unsigned __int64 *)ret = inf;
2333 return S_OK;
2335 else if (len == 4 && !memcmp( p, "-INF", 4 ))
2337 *(unsigned __int64 *)ret = inf_min;
2338 return S_OK;
2341 *ret = 0.0;
2342 if (*p == '-')
2344 sign = -1;
2345 p++; len--;
2347 else if (*p == '+') { p++; len--; };
2348 if (!len) return S_OK;
2350 if (!set_fp_rounding( &fpword )) return E_NOTIMPL;
2352 q = p;
2353 while (len && isdigit( *q )) { q++; len--; }
2354 have_digits = nb_digits = q - p;
2355 for (i = 0; i < nb_digits; i++)
2357 tmp = val * 10 + p[i] - '0';
2358 if (val > MAX_UINT64 / 10 || tmp < val)
2360 for (; i < nb_digits; i++) exp++;
2361 break;
2363 val = tmp;
2366 if (len)
2368 if (*q == '.')
2370 p = ++q; len--;
2371 while (len && isdigit( *q )) { q++; len--; };
2372 have_digits |= nb_digits = q - p;
2373 for (i = 0; i < nb_digits; i++)
2375 tmp = val * 10 + p[i] - '0';
2376 if (val > MAX_UINT64 / 10 || tmp < val) break;
2377 val = tmp;
2378 exp--;
2381 if (len > 1 && tolower(*q) == 'e')
2383 if (!have_digits) goto done;
2384 p = ++q; len--;
2385 if (*p == '-')
2387 exp_sign = -1;
2388 p++; len--;
2390 else if (*p == '+') { p++; len--; };
2392 q = p;
2393 while (len && isdigit( *q )) { q++; len--; };
2394 nb_digits = q - p;
2395 if (!nb_digits || len) goto done;
2396 for (i = 0; i < nb_digits; i++)
2398 if (exp_tmp > MAX_INT32 / 10 || (exp_tmp = exp_tmp * 10 + p[i] - '0') < 0)
2399 exp_tmp = MAX_INT32;
2401 exp_tmp *= exp_sign;
2403 if (exp < 0 && exp_tmp < 0 && exp + exp_tmp >= 0) exp = MIN_INT32;
2404 else if (exp > 0 && exp_tmp > 0 && exp + exp_tmp < 0) exp = MAX_INT32;
2405 else exp += exp_tmp;
2408 if (!have_digits || len) goto done;
2410 if ((neg_exp = exp < 0)) exp = -exp;
2411 for (; exp; exp >>= 1)
2413 if (exp & 1) exp_val *= exp_mul;
2414 exp_mul *= exp_mul;
2417 *ret = sign * (neg_exp ? val / exp_val : val * exp_val);
2418 hr = S_OK;
2420 done:
2421 restore_fp_rounding( fpword );
2422 return hr;
2425 static HRESULT str_to_guid( const unsigned char *str, ULONG len, GUID *ret )
2427 static const unsigned char hex[] =
2429 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x00 */
2430 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x10 */
2431 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x20 */
2432 0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0, /* 0x30 */
2433 0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0, /* 0x40 */
2434 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x50 */
2435 0,10,11,12,13,14,15 /* 0x60 */
2437 const unsigned char *p = str;
2438 ULONG i;
2440 while (len && read_isspace( *p )) { p++; len--; }
2441 while (len && read_isspace( p[len - 1] )) { len--; }
2442 if (len != 36) return WS_E_INVALID_FORMAT;
2444 if (p[8] != '-' || p[13] != '-' || p[18] != '-' || p[23] != '-')
2445 return WS_E_INVALID_FORMAT;
2447 for (i = 0; i < 36; i++)
2449 if (i == 8 || i == 13 || i == 18 || i == 23) continue;
2450 if (p[i] > 'f' || (!hex[p[i]] && p[i] != '0')) return WS_E_INVALID_FORMAT;
2453 ret->Data1 = hex[p[0]] << 28 | hex[p[1]] << 24 | hex[p[2]] << 20 | hex[p[3]] << 16 |
2454 hex[p[4]] << 12 | hex[p[5]] << 8 | hex[p[6]] << 4 | hex[p[7]];
2456 ret->Data2 = hex[p[9]] << 12 | hex[p[10]] << 8 | hex[p[11]] << 4 | hex[p[12]];
2457 ret->Data3 = hex[p[14]] << 12 | hex[p[15]] << 8 | hex[p[16]] << 4 | hex[p[17]];
2459 ret->Data4[0] = hex[p[19]] << 4 | hex[p[20]];
2460 ret->Data4[1] = hex[p[21]] << 4 | hex[p[22]];
2461 ret->Data4[2] = hex[p[24]] << 4 | hex[p[25]];
2462 ret->Data4[3] = hex[p[26]] << 4 | hex[p[27]];
2463 ret->Data4[4] = hex[p[28]] << 4 | hex[p[29]];
2464 ret->Data4[5] = hex[p[30]] << 4 | hex[p[31]];
2465 ret->Data4[6] = hex[p[32]] << 4 | hex[p[33]];
2466 ret->Data4[7] = hex[p[34]] << 4 | hex[p[35]];
2468 return S_OK;
2471 #define TICKS_PER_SEC 10000000
2472 #define TICKS_PER_MIN (60 * (ULONGLONG)TICKS_PER_SEC)
2473 #define TICKS_PER_HOUR (3600 * (ULONGLONG)TICKS_PER_SEC)
2474 #define TICKS_PER_DAY (86400 * (ULONGLONG)TICKS_PER_SEC)
2475 #define TICKS_MAX 3155378975999999999
2477 static const int month_offsets[2][12] =
2479 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},
2480 {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}
2483 static const int month_days[2][12] =
2485 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
2486 {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
2489 static inline int is_leap_year( int year )
2491 return !(year % 4) && (year % 100 || !(year % 400));
2494 static inline int valid_day( int year, int month, int day )
2496 return day > 0 && day <= month_days[is_leap_year( year )][month - 1];
2499 static inline int leap_days_before( int year )
2501 return (year - 1) / 4 - (year - 1) / 100 + (year - 1) / 400;
2504 static HRESULT str_to_datetime( const unsigned char *bytes, ULONG len, WS_DATETIME *ret )
2506 const unsigned char *p = bytes, *q;
2507 int year, month, day, hour, min, sec, sec_frac = 0, tz_hour, tz_min, tz_neg;
2509 while (len && read_isspace( *p )) { p++; len--; }
2510 while (len && read_isspace( p[len - 1] )) { len--; }
2512 q = p;
2513 while (len && isdigit( *q )) { q++; len--; };
2514 if (q - p != 4 || !len || *q != '-') return WS_E_INVALID_FORMAT;
2515 year = (p[0] - '0') * 1000 + (p[1] - '0') * 100 + (p[2] - '0') * 10 + p[3] - '0';
2516 if (year < 1) return WS_E_INVALID_FORMAT;
2518 p = ++q; len--;
2519 while (len && isdigit( *q )) { q++; len--; };
2520 if (q - p != 2 || !len || *q != '-') return WS_E_INVALID_FORMAT;
2521 month = (p[0] - '0') * 10 + p[1] - '0';
2522 if (month < 1 || month > 12) return WS_E_INVALID_FORMAT;
2524 p = ++q; len--;
2525 while (len && isdigit( *q )) { q++; len--; };
2526 if (q - p != 2 || !len || *q != 'T') return WS_E_INVALID_FORMAT;
2527 day = (p[0] - '0') * 10 + p[1] - '0';
2528 if (!valid_day( year, month, day )) return WS_E_INVALID_FORMAT;
2530 p = ++q; len--;
2531 while (len && isdigit( *q )) { q++; len--; };
2532 if (q - p != 2 || !len || *q != ':') return WS_E_INVALID_FORMAT;
2533 hour = (p[0] - '0') * 10 + p[1] - '0';
2534 if (hour > 24) return WS_E_INVALID_FORMAT;
2536 p = ++q; len--;
2537 while (len && isdigit( *q )) { q++; len--; };
2538 if (q - p != 2 || !len || *q != ':') return WS_E_INVALID_FORMAT;
2539 min = (p[0] - '0') * 10 + p[1] - '0';
2540 if (min > 59 || (min > 0 && hour == 24)) return WS_E_INVALID_FORMAT;
2542 p = ++q; len--;
2543 while (len && isdigit( *q )) { q++; len--; };
2544 if (q - p != 2 || !len) return WS_E_INVALID_FORMAT;
2545 sec = (p[0] - '0') * 10 + p[1] - '0';
2546 if (sec > 59 || (sec > 0 && hour == 24)) return WS_E_INVALID_FORMAT;
2548 if (*q == '.')
2550 unsigned int i, nb_digits, mul = TICKS_PER_SEC / 10;
2551 p = ++q; len--;
2552 while (len && isdigit( *q )) { q++; len--; };
2553 nb_digits = q - p;
2554 if (nb_digits < 1 || nb_digits > 7) return WS_E_INVALID_FORMAT;
2555 for (i = 0; i < nb_digits; i++)
2557 sec_frac += (p[i] - '0') * mul;
2558 mul /= 10;
2561 if (*q == 'Z')
2563 if (--len) return WS_E_INVALID_FORMAT;
2564 tz_hour = tz_min = tz_neg = 0;
2565 ret->format = WS_DATETIME_FORMAT_UTC;
2567 else if (*q == '+' || *q == '-')
2569 tz_neg = (*q == '-') ? 1 : 0;
2571 p = ++q; len--;
2572 while (len && isdigit( *q )) { q++; len--; };
2573 if (q - p != 2 || !len || *q != ':') return WS_E_INVALID_FORMAT;
2574 tz_hour = (p[0] - '0') * 10 + p[1] - '0';
2575 if (tz_hour > 14) return WS_E_INVALID_FORMAT;
2577 p = ++q; len--;
2578 while (len && isdigit( *q )) { q++; len--; };
2579 if (q - p != 2 || len) return WS_E_INVALID_FORMAT;
2580 tz_min = (p[0] - '0') * 10 + p[1] - '0';
2581 if (tz_min > 59 || (tz_min > 0 && tz_hour == 14)) return WS_E_INVALID_FORMAT;
2583 ret->format = WS_DATETIME_FORMAT_LOCAL;
2585 else return WS_E_INVALID_FORMAT;
2587 ret->ticks = ((year - 1) * 365 + leap_days_before( year )) * TICKS_PER_DAY;
2588 ret->ticks += month_offsets[is_leap_year( year )][month - 1] * TICKS_PER_DAY;
2589 ret->ticks += (day - 1) * TICKS_PER_DAY;
2590 ret->ticks += hour * TICKS_PER_HOUR;
2591 ret->ticks += min * TICKS_PER_MIN;
2592 ret->ticks += sec * TICKS_PER_SEC;
2593 ret->ticks += sec_frac;
2595 if (tz_neg)
2597 if (tz_hour * TICKS_PER_HOUR + tz_min * TICKS_PER_MIN + ret->ticks > TICKS_MAX)
2598 return WS_E_INVALID_FORMAT;
2599 ret->ticks += tz_hour * TICKS_PER_HOUR;
2600 ret->ticks += tz_min * TICKS_PER_MIN;
2602 else
2604 if (tz_hour * TICKS_PER_HOUR + tz_min * TICKS_PER_MIN > ret->ticks)
2605 return WS_E_INVALID_FORMAT;
2606 ret->ticks -= tz_hour * TICKS_PER_HOUR;
2607 ret->ticks -= tz_min * TICKS_PER_MIN;
2610 return S_OK;
2613 #define TICKS_1601_01_01 504911232000000000
2615 /**************************************************************************
2616 * WsDateTimeToFileTime [webservices.@]
2618 HRESULT WINAPI WsDateTimeToFileTime( const WS_DATETIME *dt, FILETIME *ft, WS_ERROR *error )
2620 unsigned __int64 ticks;
2622 TRACE( "%p %p %p\n", dt, ft, error );
2623 if (error) FIXME( "ignoring error parameter\n" );
2625 if (!dt || !ft) return E_INVALIDARG;
2627 if (dt->ticks < TICKS_1601_01_01) return WS_E_INVALID_FORMAT;
2628 ticks = dt->ticks - TICKS_1601_01_01;
2629 ft->dwHighDateTime = ticks >> 32;
2630 ft->dwLowDateTime = (DWORD)ticks;
2631 return S_OK;
2634 /**************************************************************************
2635 * WsFileTimeToDateTime [webservices.@]
2637 HRESULT WINAPI WsFileTimeToDateTime( const FILETIME *ft, WS_DATETIME *dt, WS_ERROR *error )
2639 unsigned __int64 ticks;
2641 TRACE( "%p %p %p\n", ft, dt, error );
2642 if (error) FIXME( "ignoring error parameter\n" );
2644 if (!dt || !ft) return E_INVALIDARG;
2646 ticks = ((unsigned __int64)ft->dwHighDateTime << 32) | ft->dwLowDateTime;
2647 if (ticks > MAX_UINT64 - TICKS_1601_01_01) return WS_E_NUMERIC_OVERFLOW;
2648 if (ticks + TICKS_1601_01_01 > TICKS_MAX) return WS_E_INVALID_FORMAT;
2649 dt->ticks = ticks + TICKS_1601_01_01;
2650 dt->format = WS_DATETIME_FORMAT_UTC;
2651 return S_OK;
2654 static HRESULT read_get_node_text( struct reader *reader, WS_XML_UTF8_TEXT **ret )
2656 WS_XML_TEXT_NODE *text;
2658 if (node_type( reader->current ) != WS_XML_NODE_TYPE_TEXT)
2659 return WS_E_INVALID_FORMAT;
2661 text = (WS_XML_TEXT_NODE *)&reader->current->hdr.node;
2662 if (text->text->textType != WS_XML_TEXT_TYPE_UTF8)
2664 FIXME( "text type %u not supported\n", text->text->textType );
2665 return E_NOTIMPL;
2667 *ret = (WS_XML_UTF8_TEXT *)text->text;
2668 return S_OK;
2671 static HRESULT read_get_attribute_text( struct reader *reader, ULONG index, WS_XML_UTF8_TEXT **ret )
2673 WS_XML_ELEMENT_NODE *elem = &reader->current->hdr;
2674 WS_XML_ATTRIBUTE *attr;
2676 if (node_type( reader->current ) != WS_XML_NODE_TYPE_ELEMENT)
2677 return WS_E_INVALID_FORMAT;
2679 attr = elem->attributes[index];
2680 if (attr->value->textType != WS_XML_TEXT_TYPE_UTF8)
2682 FIXME( "text type %u not supported\n", attr->value->textType );
2683 return E_NOTIMPL;
2685 *ret = (WS_XML_UTF8_TEXT *)attr->value;
2686 return S_OK;
2689 static BOOL find_attribute( struct reader *reader, const WS_XML_STRING *localname,
2690 const WS_XML_STRING *ns, ULONG *index )
2692 ULONG i;
2693 WS_XML_ELEMENT_NODE *elem = &reader->current->hdr;
2695 if (!localname)
2697 *index = reader->current_attr;
2698 return TRUE;
2700 for (i = 0; i < elem->attributeCount; i++)
2702 const WS_XML_STRING *localname2 = elem->attributes[i]->localName;
2703 const WS_XML_STRING *ns2 = elem->attributes[i]->ns;
2705 if (!cmp_name( localname->bytes, localname->length, localname2->bytes, localname2->length ) &&
2706 !cmp_name( ns->bytes, ns->length, ns2->bytes, ns2->length ))
2708 *index = i;
2709 return TRUE;
2712 return FALSE;
2715 /**************************************************************************
2716 * WsFindAttribute [webservices.@]
2718 HRESULT WINAPI WsFindAttribute( WS_XML_READER *handle, const WS_XML_STRING *localname,
2719 const WS_XML_STRING *ns, BOOL required, ULONG *index,
2720 WS_ERROR *error )
2722 struct reader *reader = (struct reader *)handle;
2724 TRACE( "%p %s %s %d %p %p\n", handle, debugstr_xmlstr(localname), debugstr_xmlstr(ns),
2725 required, index, error );
2726 if (error) FIXME( "ignoring error parameter\n" );
2728 if (!reader || !localname || !ns || !index) return E_INVALIDARG;
2730 if (node_type( reader->current ) != WS_XML_NODE_TYPE_ELEMENT)
2731 return WS_E_INVALID_OPERATION;
2733 if (!find_attribute( reader, localname, ns, index ))
2735 if (required) return WS_E_INVALID_FORMAT;
2736 *index = ~0u;
2737 return S_FALSE;
2739 return S_OK;
2742 static HRESULT read_get_text( struct reader *reader, WS_TYPE_MAPPING mapping,
2743 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
2744 WS_XML_UTF8_TEXT **ret, BOOL *found )
2746 switch (mapping)
2748 case WS_ATTRIBUTE_TYPE_MAPPING:
2750 ULONG index;
2751 if (!(*found = find_attribute( reader, localname, ns, &index ))) return S_OK;
2752 return read_get_attribute_text( reader, index, ret );
2754 case WS_ELEMENT_TYPE_MAPPING:
2755 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
2756 case WS_ANY_ELEMENT_TYPE_MAPPING:
2758 HRESULT hr;
2759 *found = TRUE;
2760 if (localname)
2762 const WS_XML_ELEMENT_NODE *elem = &reader->current->hdr;
2764 if (WsXmlStringEquals( localname, elem->localName, NULL ) != S_OK ||
2765 WsXmlStringEquals( ns, elem->ns, NULL ) != S_OK)
2767 *found = FALSE;
2768 return S_OK;
2770 if ((hr = read_startelement( reader )) != S_OK) return hr;
2772 return read_get_node_text( reader, ret );
2774 default:
2775 FIXME( "mapping %u not supported\n", mapping );
2776 return E_NOTIMPL;
2780 static HRESULT read_type_bool( struct reader *reader, WS_TYPE_MAPPING mapping,
2781 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
2782 const WS_BOOL_DESCRIPTION *desc, WS_READ_OPTION option,
2783 WS_HEAP *heap, void *ret, ULONG size )
2785 WS_XML_UTF8_TEXT *utf8;
2786 HRESULT hr;
2787 BOOL found, val = FALSE;
2789 if (desc)
2791 FIXME( "description not supported\n" );
2792 return E_NOTIMPL;
2794 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
2795 if (found)
2797 ULONG len = utf8->value.length;
2798 if (len == 4 && !memcmp( utf8->value.bytes, "true", 4 )) val = TRUE;
2799 else if (len == 1 && !memcmp( utf8->value.bytes, "1", 1 )) val = TRUE;
2800 else if (len == 5 && !memcmp( utf8->value.bytes, "false", 5 )) val = FALSE;
2801 else if (len == 1 && !memcmp( utf8->value.bytes, "0", 1 )) val = FALSE;
2802 else return WS_E_INVALID_FORMAT;
2805 switch (option)
2807 case WS_READ_REQUIRED_VALUE:
2808 if (!found) return WS_E_INVALID_FORMAT;
2809 if (size != sizeof(BOOL)) return E_INVALIDARG;
2810 *(BOOL *)ret = val;
2811 break;
2813 case WS_READ_REQUIRED_POINTER:
2814 if (!found) return WS_E_INVALID_FORMAT;
2815 /* fall through */
2817 case WS_READ_OPTIONAL_POINTER:
2819 BOOL *heap_val = NULL;
2820 if (size != sizeof(heap_val)) return E_INVALIDARG;
2821 if (found)
2823 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
2824 *heap_val = val;
2826 *(BOOL **)ret = heap_val;
2827 break;
2829 default:
2830 FIXME( "read option %u not supported\n", option );
2831 return E_NOTIMPL;
2834 return S_OK;
2837 static HRESULT read_type_int8( struct reader *reader, WS_TYPE_MAPPING mapping,
2838 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
2839 const WS_INT8_DESCRIPTION *desc, WS_READ_OPTION option,
2840 WS_HEAP *heap, void *ret, ULONG size )
2842 WS_XML_UTF8_TEXT *utf8;
2843 HRESULT hr;
2844 INT64 val;
2845 BOOL found;
2847 if (desc)
2849 FIXME( "description not supported\n" );
2850 return E_NOTIMPL;
2852 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
2853 if (found && (hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT8, MAX_INT8, &val )) != S_OK)
2854 return hr;
2856 switch (option)
2858 case WS_READ_REQUIRED_VALUE:
2859 if (!found) return WS_E_INVALID_FORMAT;
2860 if (size != sizeof(INT8)) return E_INVALIDARG;
2861 *(INT8 *)ret = val;
2862 break;
2864 case WS_READ_REQUIRED_POINTER:
2865 if (!found) return WS_E_INVALID_FORMAT;
2866 /* fall through */
2868 case WS_READ_OPTIONAL_POINTER:
2870 INT8 *heap_val = NULL;
2871 if (size != sizeof(heap_val)) return E_INVALIDARG;
2872 if (found)
2874 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
2875 *heap_val = val;
2877 *(INT8 **)ret = heap_val;
2878 break;
2880 default:
2881 FIXME( "read option %u not supported\n", option );
2882 return E_NOTIMPL;
2885 return S_OK;
2888 static HRESULT read_type_int16( struct reader *reader, WS_TYPE_MAPPING mapping,
2889 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
2890 const WS_INT16_DESCRIPTION *desc, WS_READ_OPTION option,
2891 WS_HEAP *heap, void *ret, ULONG size )
2893 WS_XML_UTF8_TEXT *utf8;
2894 HRESULT hr;
2895 INT64 val;
2896 BOOL found;
2898 if (desc)
2900 FIXME( "description not supported\n" );
2901 return E_NOTIMPL;
2903 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
2904 if (found && (hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT16, MAX_INT16, &val )) != S_OK)
2905 return hr;
2907 switch (option)
2909 case WS_READ_REQUIRED_VALUE:
2910 if (!found) return WS_E_INVALID_FORMAT;
2911 if (size != sizeof(INT16)) return E_INVALIDARG;
2912 *(INT16 *)ret = val;
2913 break;
2915 case WS_READ_REQUIRED_POINTER:
2916 if (!found) return WS_E_INVALID_FORMAT;
2917 /* fall through */
2919 case WS_READ_OPTIONAL_POINTER:
2921 INT16 *heap_val = NULL;
2922 if (size != sizeof(heap_val)) return E_INVALIDARG;
2923 if (found)
2925 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
2926 *heap_val = val;
2928 *(INT16 **)ret = heap_val;
2929 break;
2931 default:
2932 FIXME( "read option %u not supported\n", option );
2933 return E_NOTIMPL;
2936 return S_OK;
2939 static HRESULT read_type_int32( struct reader *reader, WS_TYPE_MAPPING mapping,
2940 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
2941 const WS_INT32_DESCRIPTION *desc, WS_READ_OPTION option,
2942 WS_HEAP *heap, void *ret, ULONG size )
2944 WS_XML_UTF8_TEXT *utf8;
2945 HRESULT hr;
2946 INT64 val;
2947 BOOL found;
2949 if (desc)
2951 FIXME( "description not supported\n" );
2952 return E_NOTIMPL;
2954 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
2955 if (found && (hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT32, MAX_INT32, &val )) != S_OK)
2956 return hr;
2958 switch (option)
2960 case WS_READ_REQUIRED_VALUE:
2961 if (!found) return WS_E_INVALID_FORMAT;
2962 if (size != sizeof(INT32)) return E_INVALIDARG;
2963 *(INT32 *)ret = val;
2964 break;
2966 case WS_READ_REQUIRED_POINTER:
2967 if (!found) return WS_E_INVALID_FORMAT;
2968 /* fall through */
2970 case WS_READ_OPTIONAL_POINTER:
2972 INT32 *heap_val = NULL;
2973 if (size != sizeof(heap_val)) return E_INVALIDARG;
2974 if (found)
2976 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
2977 *heap_val = val;
2979 *(INT32 **)ret = heap_val;
2980 break;
2982 default:
2983 FIXME( "read option %u not supported\n", option );
2984 return E_NOTIMPL;
2987 return S_OK;
2990 static HRESULT read_type_int64( struct reader *reader, WS_TYPE_MAPPING mapping,
2991 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
2992 const WS_INT64_DESCRIPTION *desc, WS_READ_OPTION option,
2993 WS_HEAP *heap, void *ret, ULONG size )
2995 WS_XML_UTF8_TEXT *utf8;
2996 HRESULT hr;
2997 INT64 val;
2998 BOOL found;
3000 if (desc)
3002 FIXME( "description not supported\n" );
3003 return E_NOTIMPL;
3005 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
3006 if (found && (hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT64, MAX_INT64, &val )) != S_OK)
3007 return hr;
3009 switch (option)
3011 case WS_READ_REQUIRED_VALUE:
3012 if (!found) return WS_E_INVALID_FORMAT;
3013 if (size != sizeof(INT64)) return E_INVALIDARG;
3014 *(INT64 *)ret = val;
3015 break;
3017 case WS_READ_REQUIRED_POINTER:
3018 if (!found) return WS_E_INVALID_FORMAT;
3019 /* fall through */
3021 case WS_READ_OPTIONAL_POINTER:
3023 INT64 *heap_val = NULL;
3024 if (size != sizeof(heap_val)) return E_INVALIDARG;
3025 if (found)
3027 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
3028 *heap_val = val;
3030 *(INT64 **)ret = heap_val;
3031 break;
3033 default:
3034 FIXME( "read option %u not supported\n", option );
3035 return E_NOTIMPL;
3038 return S_OK;
3041 static HRESULT read_type_uint8( struct reader *reader, WS_TYPE_MAPPING mapping,
3042 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
3043 const WS_UINT8_DESCRIPTION *desc, WS_READ_OPTION option,
3044 WS_HEAP *heap, void *ret, ULONG size )
3046 WS_XML_UTF8_TEXT *utf8;
3047 HRESULT hr;
3048 UINT64 val;
3049 BOOL found;
3051 if (desc)
3053 FIXME( "description not supported\n" );
3054 return E_NOTIMPL;
3056 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
3057 if (found && (hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT8, &val )) != S_OK)
3058 return hr;
3060 switch (option)
3062 case WS_READ_REQUIRED_VALUE:
3063 if (!found) return WS_E_INVALID_FORMAT;
3064 if (size != sizeof(UINT8)) return E_INVALIDARG;
3065 *(UINT8 *)ret = val;
3066 break;
3068 case WS_READ_REQUIRED_POINTER:
3069 if (!found) return WS_E_INVALID_FORMAT;
3070 /* fall through */
3072 case WS_READ_OPTIONAL_POINTER:
3074 UINT8 *heap_val = NULL;
3075 if (size != sizeof(heap_val)) return E_INVALIDARG;
3076 if (found)
3078 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
3079 *heap_val = val;
3081 *(UINT8 **)ret = heap_val;
3082 break;
3084 default:
3085 FIXME( "read option %u not supported\n", option );
3086 return E_NOTIMPL;
3089 return S_OK;
3092 static HRESULT read_type_uint16( struct reader *reader, WS_TYPE_MAPPING mapping,
3093 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
3094 const WS_UINT16_DESCRIPTION *desc, WS_READ_OPTION option,
3095 WS_HEAP *heap, void *ret, ULONG size )
3097 WS_XML_UTF8_TEXT *utf8;
3098 HRESULT hr;
3099 UINT64 val;
3100 BOOL found;
3102 if (desc)
3104 FIXME( "description not supported\n" );
3105 return E_NOTIMPL;
3107 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
3108 if (found && (hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT16, &val )) != S_OK)
3109 return hr;
3111 switch (option)
3113 case WS_READ_REQUIRED_VALUE:
3114 if (!found) return WS_E_INVALID_FORMAT;
3115 if (size != sizeof(UINT16)) return E_INVALIDARG;
3116 *(UINT16 *)ret = val;
3117 break;
3119 case WS_READ_REQUIRED_POINTER:
3120 if (!found) return WS_E_INVALID_FORMAT;
3121 /* fall through */
3123 case WS_READ_OPTIONAL_POINTER:
3125 UINT16 *heap_val = NULL;
3126 if (size != sizeof(heap_val)) return E_INVALIDARG;
3127 if (found)
3129 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
3130 *heap_val = val;
3132 *(UINT16 **)ret = heap_val;
3133 break;
3135 default:
3136 FIXME( "read option %u not supported\n", option );
3137 return E_NOTIMPL;
3140 return S_OK;
3143 static HRESULT read_type_uint32( struct reader *reader, WS_TYPE_MAPPING mapping,
3144 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
3145 const WS_UINT32_DESCRIPTION *desc, WS_READ_OPTION option,
3146 WS_HEAP *heap, void *ret, ULONG size )
3148 WS_XML_UTF8_TEXT *utf8;
3149 HRESULT hr;
3150 UINT64 val;
3151 BOOL found;
3153 if (desc)
3155 FIXME( "description not supported\n" );
3156 return E_NOTIMPL;
3158 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
3159 if (found && (hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT32, &val )) != S_OK)
3160 return hr;
3162 switch (option)
3164 case WS_READ_REQUIRED_VALUE:
3165 if (!found) return WS_E_INVALID_FORMAT;
3166 if (size != sizeof(UINT32)) return E_INVALIDARG;
3167 *(UINT32 *)ret = val;
3168 break;
3170 case WS_READ_REQUIRED_POINTER:
3171 if (!found) return WS_E_INVALID_FORMAT;
3172 /* fall through */
3174 case WS_READ_OPTIONAL_POINTER:
3176 UINT32 *heap_val = NULL;
3177 if (size != sizeof(heap_val)) return E_INVALIDARG;
3178 if (found)
3180 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
3181 *heap_val = val;
3183 *(UINT32 **)ret = heap_val;
3184 break;
3186 default:
3187 FIXME( "read option %u not supported\n", option );
3188 return E_NOTIMPL;
3191 return S_OK;
3194 static HRESULT read_type_uint64( struct reader *reader, WS_TYPE_MAPPING mapping,
3195 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
3196 const WS_UINT64_DESCRIPTION *desc, WS_READ_OPTION option,
3197 WS_HEAP *heap, void *ret, ULONG size )
3199 WS_XML_UTF8_TEXT *utf8;
3200 HRESULT hr;
3201 UINT64 val;
3202 BOOL found;
3204 if (desc)
3206 FIXME( "description not supported\n" );
3207 return E_NOTIMPL;
3209 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
3210 if (found && (hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT64, &val )) != S_OK)
3211 return hr;
3213 switch (option)
3215 case WS_READ_REQUIRED_VALUE:
3216 if (!found) return WS_E_INVALID_FORMAT;
3217 if (size != sizeof(UINT64)) return E_INVALIDARG;
3218 *(UINT64 *)ret = val;
3219 break;
3221 case WS_READ_REQUIRED_POINTER:
3222 if (!found) return WS_E_INVALID_FORMAT;
3223 /* fall through */
3225 case WS_READ_OPTIONAL_POINTER:
3227 UINT64 *heap_val = NULL;
3228 if (size != sizeof(heap_val)) return E_INVALIDARG;
3229 if (found)
3231 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
3232 *heap_val = val;
3234 *(UINT64 **)ret = heap_val;
3235 break;
3237 default:
3238 FIXME( "read option %u not supported\n", option );
3239 return E_NOTIMPL;
3242 return S_OK;
3245 static HRESULT read_type_double( struct reader *reader, WS_TYPE_MAPPING mapping,
3246 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
3247 const WS_DOUBLE_DESCRIPTION *desc, WS_READ_OPTION option,
3248 WS_HEAP *heap, void *ret, ULONG size )
3250 WS_XML_UTF8_TEXT *utf8;
3251 HRESULT hr;
3252 double val = 0.0;
3253 BOOL found;
3255 if (desc) FIXME( "ignoring description\n" );
3257 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
3258 if (found && (hr = str_to_double( utf8->value.bytes, utf8->value.length, &val )) != S_OK) return hr;
3260 switch (option)
3262 case WS_READ_REQUIRED_VALUE:
3263 if (!found) return WS_E_INVALID_FORMAT;
3264 if (size != sizeof(double)) return E_INVALIDARG;
3265 *(double *)ret = val;
3266 break;
3268 case WS_READ_REQUIRED_POINTER:
3269 if (!found) return WS_E_INVALID_FORMAT;
3270 /* fall through */
3272 case WS_READ_OPTIONAL_POINTER:
3274 double *heap_val = NULL;
3275 if (size != sizeof(heap_val)) return E_INVALIDARG;
3276 if (found)
3278 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
3279 *heap_val = val;
3281 *(double **)ret = heap_val;
3282 break;
3284 default:
3285 FIXME( "read option %u not supported\n", option );
3286 return E_NOTIMPL;
3289 return S_OK;
3292 static HRESULT read_type_wsz( struct reader *reader, WS_TYPE_MAPPING mapping,
3293 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
3294 const WS_WSZ_DESCRIPTION *desc, WS_READ_OPTION option,
3295 WS_HEAP *heap, WCHAR **ret, ULONG size )
3297 WS_XML_UTF8_TEXT *utf8;
3298 HRESULT hr;
3299 WCHAR *str = NULL;
3300 BOOL found;
3302 if (desc)
3304 FIXME( "description not supported\n" );
3305 return E_NOTIMPL;
3307 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
3308 if (found && !(str = xmltext_to_widechar( heap, &utf8->text ))) return WS_E_QUOTA_EXCEEDED;
3310 switch (option)
3312 case WS_READ_REQUIRED_POINTER:
3313 if (!found) return WS_E_INVALID_FORMAT;
3314 /* fall through */
3316 case WS_READ_OPTIONAL_POINTER:
3317 if (size != sizeof(str)) return E_INVALIDARG;
3318 *ret = str;
3319 break;
3321 default:
3322 FIXME( "read option %u not supported\n", option );
3323 return E_NOTIMPL;
3326 return S_OK;
3329 static HRESULT get_enum_value( const WS_XML_UTF8_TEXT *text, const WS_ENUM_DESCRIPTION *desc, int *ret )
3331 ULONG i;
3332 for (i = 0; i < desc->valueCount; i++)
3334 if (WsXmlStringEquals( &text->value, desc->values[i].name, NULL ) == S_OK)
3336 *ret = desc->values[i].value;
3337 return S_OK;
3340 return WS_E_INVALID_FORMAT;
3343 static HRESULT read_type_enum( struct reader *reader, WS_TYPE_MAPPING mapping,
3344 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
3345 const WS_ENUM_DESCRIPTION *desc, WS_READ_OPTION option,
3346 WS_HEAP *heap, void *ret, ULONG size )
3348 WS_XML_UTF8_TEXT *utf8;
3349 HRESULT hr;
3350 int val = 0;
3351 BOOL found;
3353 if (!desc) return E_INVALIDARG;
3355 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
3356 if (found && (hr = get_enum_value( utf8, desc, &val )) != S_OK) return hr;
3358 switch (option)
3360 case WS_READ_REQUIRED_VALUE:
3361 if (!found) return WS_E_INVALID_FORMAT;
3362 if (size != sizeof(int)) return E_INVALIDARG;
3363 *(int *)ret = val;
3364 break;
3366 case WS_READ_REQUIRED_POINTER:
3367 if (!found) return WS_E_INVALID_FORMAT;
3368 /* fall through */
3370 case WS_READ_OPTIONAL_POINTER:
3372 int *heap_val = NULL;
3373 if (size != sizeof(heap_val)) return E_INVALIDARG;
3374 if (found)
3376 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
3377 *heap_val = val;
3379 *(int **)ret = heap_val;
3380 break;
3382 default:
3383 FIXME( "read option %u not supported\n", option );
3384 return E_NOTIMPL;
3387 return S_OK;
3390 static HRESULT read_type_datetime( struct reader *reader, WS_TYPE_MAPPING mapping,
3391 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
3392 const WS_DATETIME_DESCRIPTION *desc, WS_READ_OPTION option,
3393 WS_HEAP *heap, void *ret, ULONG size )
3395 WS_XML_UTF8_TEXT *utf8;
3396 HRESULT hr;
3397 WS_DATETIME val = {0, WS_DATETIME_FORMAT_UTC};
3398 BOOL found;
3400 if (desc) FIXME( "ignoring description\n" );
3402 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
3403 if (found && (hr = str_to_datetime( utf8->value.bytes, utf8->value.length, &val )) != S_OK) return hr;
3405 switch (option)
3407 case WS_READ_REQUIRED_VALUE:
3408 if (!found) return WS_E_INVALID_FORMAT;
3409 if (size != sizeof(WS_DATETIME)) return E_INVALIDARG;
3410 *(WS_DATETIME *)ret = val;
3411 break;
3413 case WS_READ_REQUIRED_POINTER:
3414 if (!found) return WS_E_INVALID_FORMAT;
3415 /* fall through */
3417 case WS_READ_OPTIONAL_POINTER:
3419 WS_DATETIME *heap_val = NULL;
3420 if (size != sizeof(heap_val)) return E_INVALIDARG;
3421 if (found)
3423 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
3424 *heap_val = val;
3426 *(WS_DATETIME **)ret = heap_val;
3427 break;
3429 default:
3430 FIXME( "read option %u not supported\n", option );
3431 return E_NOTIMPL;
3434 return S_OK;
3437 static HRESULT read_type_guid( struct reader *reader, WS_TYPE_MAPPING mapping,
3438 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
3439 const WS_GUID_DESCRIPTION *desc, WS_READ_OPTION option,
3440 WS_HEAP *heap, void *ret, ULONG size )
3442 WS_XML_UTF8_TEXT *utf8;
3443 GUID val;
3444 HRESULT hr;
3445 BOOL found;
3447 if (desc) FIXME( "ignoring description\n" );
3449 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
3450 if (found && (hr = str_to_guid( utf8->value.bytes, utf8->value.length, &val )) != S_OK) return hr;
3452 switch (option)
3454 case WS_READ_REQUIRED_VALUE:
3455 if (!found) return WS_E_INVALID_FORMAT;
3456 if (size != sizeof(GUID)) return E_INVALIDARG;
3457 *(GUID *)ret = val;
3458 break;
3460 case WS_READ_REQUIRED_POINTER:
3461 if (!found) return WS_E_INVALID_FORMAT;
3462 /* fall through */
3464 case WS_READ_OPTIONAL_POINTER:
3466 GUID *heap_val = NULL;
3467 if (size != sizeof(heap_val)) return E_INVALIDARG;
3468 if (found)
3470 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
3471 *heap_val = val;
3473 *(GUID **)ret = heap_val;
3474 break;
3476 default:
3477 FIXME( "read option %u not supported\n", option );
3478 return E_NOTIMPL;
3481 return S_OK;
3484 static BOOL is_empty_text_node( const struct node *node )
3486 const WS_XML_TEXT_NODE *text = (const WS_XML_TEXT_NODE *)node;
3487 const WS_XML_UTF8_TEXT *utf8;
3488 ULONG i;
3490 if (node_type( node ) != WS_XML_NODE_TYPE_TEXT) return FALSE;
3491 if (text->text->textType != WS_XML_TEXT_TYPE_UTF8)
3493 ERR( "unhandled text type %u\n", text->text->textType );
3494 return FALSE;
3496 utf8 = (const WS_XML_UTF8_TEXT *)text->text;
3497 for (i = 0; i < utf8->value.length; i++) if (!read_isspace( utf8->value.bytes[i] )) return FALSE;
3498 return TRUE;
3501 static HRESULT read_next_node( struct reader *reader )
3503 if (reader->current == reader->last) return read_node( reader );
3504 if (move_to_child_node( &reader->current )) return S_OK;
3505 if (move_to_next_node( &reader->current )) return S_OK;
3506 if (!move_to_parent_node( &reader->current )) return WS_E_INVALID_FORMAT;
3507 if (move_to_next_node( &reader->current )) return S_OK;
3508 return WS_E_INVALID_FORMAT;
3511 /* skips comment and empty text nodes */
3512 static HRESULT read_type_next_node( struct reader *reader )
3514 for (;;)
3516 HRESULT hr;
3517 WS_XML_NODE_TYPE type;
3519 if ((hr = read_next_node( reader )) != S_OK) return hr;
3520 type = node_type( reader->current );
3521 if (type == WS_XML_NODE_TYPE_COMMENT ||
3522 (type == WS_XML_NODE_TYPE_TEXT && is_empty_text_node( reader->current ))) continue;
3523 return S_OK;
3527 static BOOL match_current_element( struct reader *reader, const WS_XML_STRING *localname,
3528 const WS_XML_STRING *ns )
3530 const WS_XML_ELEMENT_NODE *elem = &reader->current->hdr;
3531 if (node_type( reader->current ) != WS_XML_NODE_TYPE_ELEMENT) return FALSE;
3532 return WsXmlStringEquals( localname, elem->localName, NULL ) == S_OK &&
3533 WsXmlStringEquals( ns, elem->ns, NULL ) == S_OK;
3536 static HRESULT read_type_next_element_node( struct reader *reader, const WS_XML_STRING *localname,
3537 const WS_XML_STRING *ns )
3539 struct node *node;
3540 ULONG attr;
3541 HRESULT hr;
3543 if (!localname) return S_OK; /* assume reader is already correctly positioned */
3544 if (reader->current == reader->last)
3546 BOOL found;
3547 if ((hr = read_to_startelement( reader, &found )) != S_OK) return hr;
3548 if (!found) return WS_E_INVALID_FORMAT;
3550 if (match_current_element( reader, localname, ns )) return S_OK;
3552 node = reader->current;
3553 attr = reader->current_attr;
3555 if ((hr = read_type_next_node( reader )) != S_OK) return hr;
3556 if (match_current_element( reader, localname, ns )) return S_OK;
3558 reader->current = node;
3559 reader->current_attr = attr;
3561 return WS_E_INVALID_FORMAT;
3564 ULONG get_type_size( WS_TYPE type, const WS_STRUCT_DESCRIPTION *desc )
3566 switch (type)
3568 case WS_INT8_TYPE:
3569 case WS_UINT8_TYPE:
3570 return sizeof(INT8);
3572 case WS_INT16_TYPE:
3573 case WS_UINT16_TYPE:
3574 return sizeof(INT16);
3576 case WS_BOOL_TYPE:
3577 case WS_INT32_TYPE:
3578 case WS_UINT32_TYPE:
3579 case WS_ENUM_TYPE:
3580 return sizeof(INT32);
3582 case WS_INT64_TYPE:
3583 case WS_UINT64_TYPE:
3584 return sizeof(INT64);
3586 case WS_DOUBLE_TYPE:
3587 return sizeof(double);
3589 case WS_DATETIME_TYPE:
3590 return sizeof(WS_DATETIME);
3592 case WS_GUID_TYPE:
3593 return sizeof(GUID);
3595 case WS_WSZ_TYPE:
3596 return sizeof(WCHAR *);
3598 case WS_STRUCT_TYPE:
3599 return desc->size;
3601 default:
3602 ERR( "unhandled type %u\n", type );
3603 return 0;
3607 static WS_READ_OPTION get_array_read_option( WS_TYPE type )
3609 switch (type)
3611 case WS_BOOL_TYPE:
3612 case WS_INT8_TYPE:
3613 case WS_INT16_TYPE:
3614 case WS_INT32_TYPE:
3615 case WS_INT64_TYPE:
3616 case WS_UINT8_TYPE:
3617 case WS_UINT16_TYPE:
3618 case WS_UINT32_TYPE:
3619 case WS_UINT64_TYPE:
3620 case WS_DOUBLE_TYPE:
3621 case WS_ENUM_TYPE:
3622 case WS_STRUCT_TYPE:
3623 case WS_DATETIME_TYPE:
3624 case WS_GUID_TYPE:
3625 return WS_READ_REQUIRED_VALUE;
3627 case WS_WSZ_TYPE:
3628 return WS_READ_REQUIRED_POINTER;
3630 default:
3631 FIXME( "unhandled type %u\n", type );
3632 return 0;
3636 static HRESULT read_type( struct reader *, WS_TYPE_MAPPING, WS_TYPE, const WS_XML_STRING *,
3637 const WS_XML_STRING *, const void *, WS_READ_OPTION, WS_HEAP *,
3638 void *, ULONG );
3640 static HRESULT read_type_repeating_element( struct reader *reader, const WS_FIELD_DESCRIPTION *desc,
3641 WS_HEAP *heap, void **ret, ULONG size, ULONG *count )
3643 HRESULT hr;
3644 ULONG item_size, nb_items = 0, nb_allocated = 1, offset = 0;
3645 WS_READ_OPTION option;
3646 char *buf;
3648 if (size != sizeof(void *) || !(option = get_array_read_option( desc->type ))) return E_INVALIDARG;
3650 /* wrapper element */
3651 if (desc->localName && ((hr = read_type_next_element_node( reader, desc->localName, desc->ns )) != S_OK))
3652 return hr;
3654 if (option == WS_READ_REQUIRED_VALUE)
3655 item_size = get_type_size( desc->type, desc->typeDescription );
3656 else
3657 item_size = sizeof(void *);
3659 if (!(buf = ws_alloc_zero( heap, item_size ))) return WS_E_QUOTA_EXCEEDED;
3660 for (;;)
3662 if (nb_items >= nb_allocated)
3664 if (!(buf = ws_realloc_zero( heap, buf, nb_allocated * 2 * item_size )))
3665 return WS_E_QUOTA_EXCEEDED;
3666 nb_allocated *= 2;
3668 hr = read_type( reader, WS_ELEMENT_TYPE_MAPPING, desc->type, desc->itemLocalName, desc->itemNs,
3669 desc->typeDescription, option, heap, buf + offset, item_size );
3670 if (hr == WS_E_INVALID_FORMAT) break;
3671 if (hr != S_OK)
3673 ws_free( heap, buf );
3674 return hr;
3676 offset += item_size;
3677 nb_items++;
3680 if (desc->localName && ((hr = read_type_next_node( reader )) != S_OK)) return hr;
3682 if (desc->itemRange && (nb_items < desc->itemRange->minItemCount || nb_items > desc->itemRange->maxItemCount))
3684 TRACE( "number of items %u out of range (%u-%u)\n", nb_items, desc->itemRange->minItemCount,
3685 desc->itemRange->maxItemCount );
3686 ws_free( heap, buf );
3687 return WS_E_INVALID_FORMAT;
3690 *count = nb_items;
3691 *ret = buf;
3693 return S_OK;
3696 static HRESULT read_type_text( struct reader *reader, const WS_FIELD_DESCRIPTION *desc,
3697 WS_READ_OPTION option, WS_HEAP *heap, void *ret, ULONG size )
3699 HRESULT hr;
3700 if (reader->current == reader->last)
3702 BOOL found;
3703 if ((hr = read_to_startelement( reader, &found )) != S_OK) return S_OK;
3704 if (!found) return WS_E_INVALID_FORMAT;
3706 if ((hr = read_next_node( reader )) != S_OK) return hr;
3707 if (node_type( reader->current ) != WS_XML_NODE_TYPE_TEXT) return WS_E_INVALID_FORMAT;
3709 return read_type( reader, WS_ANY_ELEMENT_TYPE_MAPPING, desc->type, NULL, NULL,
3710 desc->typeDescription, option, heap, ret, size );
3713 static WS_READ_OPTION get_field_read_option( WS_TYPE type )
3715 switch (type)
3717 case WS_BOOL_TYPE:
3718 case WS_INT8_TYPE:
3719 case WS_INT16_TYPE:
3720 case WS_INT32_TYPE:
3721 case WS_INT64_TYPE:
3722 case WS_UINT8_TYPE:
3723 case WS_UINT16_TYPE:
3724 case WS_UINT32_TYPE:
3725 case WS_UINT64_TYPE:
3726 case WS_DOUBLE_TYPE:
3727 case WS_ENUM_TYPE:
3728 case WS_DATETIME_TYPE:
3729 case WS_GUID_TYPE:
3730 return WS_READ_REQUIRED_VALUE;
3732 case WS_WSZ_TYPE:
3733 case WS_STRUCT_TYPE:
3734 return WS_READ_REQUIRED_POINTER;
3736 default:
3737 FIXME( "unhandled type %u\n", type );
3738 return 0;
3742 static HRESULT read_type_struct_field( struct reader *reader, const WS_FIELD_DESCRIPTION *desc,
3743 WS_HEAP *heap, char *buf )
3745 char *ptr;
3746 WS_READ_OPTION option;
3747 ULONG size;
3748 HRESULT hr;
3750 if (!desc) return E_INVALIDARG;
3751 if (desc->options & ~(WS_FIELD_POINTER | WS_FIELD_OPTIONAL))
3753 FIXME( "options %08x not supported\n", desc->options );
3754 return E_NOTIMPL;
3756 if (!(option = get_field_read_option( desc->type ))) return E_INVALIDARG;
3758 if (option == WS_READ_REQUIRED_VALUE)
3759 size = get_type_size( desc->type, desc->typeDescription );
3760 else
3761 size = sizeof(void *);
3763 ptr = buf + desc->offset;
3764 switch (desc->mapping)
3766 case WS_ATTRIBUTE_FIELD_MAPPING:
3767 hr = read_type( reader, WS_ATTRIBUTE_TYPE_MAPPING, desc->type, desc->localName, desc->ns,
3768 desc->typeDescription, option, heap, ptr, size );
3769 break;
3771 case WS_ELEMENT_FIELD_MAPPING:
3772 hr = read_type( reader, WS_ELEMENT_TYPE_MAPPING, desc->type, desc->localName, desc->ns,
3773 desc->typeDescription, option, heap, ptr, size );
3774 break;
3776 case WS_REPEATING_ELEMENT_FIELD_MAPPING:
3778 ULONG count;
3779 hr = read_type_repeating_element( reader, desc, heap, (void **)ptr, size, &count );
3780 if (hr == S_OK) *(ULONG *)(buf + desc->countOffset) = count;
3781 break;
3783 case WS_TEXT_FIELD_MAPPING:
3784 hr = read_type_text( reader, desc, option, heap, ptr, size );
3785 break;
3787 default:
3788 FIXME( "unhandled field mapping %u\n", desc->mapping );
3789 return E_NOTIMPL;
3792 if (hr == WS_E_INVALID_FORMAT && desc->options & WS_FIELD_OPTIONAL)
3794 switch (option)
3796 case WS_READ_REQUIRED_VALUE:
3797 if (desc->defaultValue) memcpy( ptr, desc->defaultValue->value, desc->defaultValue->valueSize );
3798 else memset( ptr, 0, size );
3799 return S_OK;
3801 case WS_READ_REQUIRED_POINTER:
3802 *(void **)ptr = NULL;
3803 return S_OK;
3805 default:
3806 ERR( "unhandled option %u\n", option );
3807 return E_NOTIMPL;
3811 return hr;
3814 static HRESULT read_type_struct( struct reader *reader, WS_TYPE_MAPPING mapping,
3815 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
3816 const WS_STRUCT_DESCRIPTION *desc, WS_READ_OPTION option,
3817 WS_HEAP *heap, void *ret, ULONG size )
3819 ULONG i;
3820 HRESULT hr;
3821 char *buf;
3823 if (!desc) return E_INVALIDARG;
3824 if (desc->structOptions) FIXME( "struct options %08x not supported\n", desc->structOptions );
3826 switch (option)
3828 case WS_READ_REQUIRED_POINTER:
3829 case WS_READ_OPTIONAL_POINTER:
3830 if (size != sizeof(void *)) return E_INVALIDARG;
3831 if (!(buf = ws_alloc_zero( heap, desc->size ))) return WS_E_QUOTA_EXCEEDED;
3832 break;
3834 case WS_READ_REQUIRED_VALUE:
3835 if (size != desc->size) return E_INVALIDARG;
3836 buf = ret;
3837 break;
3839 default:
3840 FIXME( "unhandled read option %u\n", option );
3841 return E_NOTIMPL;
3844 for (i = 0; i < desc->fieldCount; i++)
3846 if ((hr = read_type_struct_field( reader, desc->fields[i], heap, buf )) != S_OK)
3847 break;
3850 switch (option)
3852 case WS_READ_REQUIRED_POINTER:
3853 if (hr != S_OK)
3855 ws_free( heap, buf );
3856 return hr;
3858 *(char **)ret = buf;
3859 return S_OK;
3861 case WS_READ_OPTIONAL_POINTER:
3862 if (hr != S_OK)
3864 ws_free( heap, buf );
3865 buf = NULL;
3867 *(char **)ret = buf;
3868 return S_OK;
3870 case WS_READ_REQUIRED_VALUE:
3871 return hr;
3873 default:
3874 ERR( "unhandled read option %u\n", option );
3875 return E_NOTIMPL;
3879 static HRESULT read_type( struct reader *reader, WS_TYPE_MAPPING mapping, WS_TYPE type,
3880 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
3881 const void *desc, WS_READ_OPTION option, WS_HEAP *heap,
3882 void *value, ULONG size )
3884 HRESULT hr;
3886 switch (mapping)
3888 case WS_ELEMENT_TYPE_MAPPING:
3889 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
3890 if ((hr = read_type_next_element_node( reader, localname, ns )) != S_OK) return hr;
3891 break;
3893 case WS_ANY_ELEMENT_TYPE_MAPPING:
3894 case WS_ATTRIBUTE_TYPE_MAPPING:
3895 break;
3897 default:
3898 FIXME( "unhandled mapping %u\n", mapping );
3899 return E_NOTIMPL;
3902 switch (type)
3904 case WS_STRUCT_TYPE:
3905 if ((hr = read_type_struct( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
3906 return hr;
3907 break;
3909 case WS_BOOL_TYPE:
3910 if ((hr = read_type_bool( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
3911 return hr;
3912 break;
3914 case WS_INT8_TYPE:
3915 if ((hr = read_type_int8( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
3916 return hr;
3917 break;
3919 case WS_INT16_TYPE:
3920 if ((hr = read_type_int16( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
3921 return hr;
3922 break;
3924 case WS_INT32_TYPE:
3925 if ((hr = read_type_int32( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
3926 return hr;
3927 break;
3929 case WS_INT64_TYPE:
3930 if ((hr = read_type_int64( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
3931 return hr;
3932 break;
3934 case WS_UINT8_TYPE:
3935 if ((hr = read_type_uint8( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
3936 return hr;
3937 break;
3939 case WS_UINT16_TYPE:
3940 if ((hr = read_type_uint16( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
3941 return hr;
3942 break;
3944 case WS_UINT32_TYPE:
3945 if ((hr = read_type_uint32( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
3946 return hr;
3947 break;
3949 case WS_UINT64_TYPE:
3950 if ((hr = read_type_uint64( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
3951 return hr;
3952 break;
3954 case WS_DOUBLE_TYPE:
3955 if ((hr = read_type_double( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
3956 return hr;
3957 break;
3959 case WS_WSZ_TYPE:
3960 if ((hr = read_type_wsz( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
3961 return hr;
3962 break;
3964 case WS_ENUM_TYPE:
3965 if ((hr = read_type_enum( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
3966 return hr;
3967 break;
3969 case WS_DATETIME_TYPE:
3970 if ((hr = read_type_datetime( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
3971 return hr;
3972 break;
3974 case WS_GUID_TYPE:
3975 if ((hr = read_type_guid( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
3976 return hr;
3977 break;
3979 default:
3980 FIXME( "type %u not supported\n", type );
3981 return E_NOTIMPL;
3984 switch (mapping)
3986 case WS_ELEMENT_TYPE_MAPPING:
3987 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
3988 return read_type_next_node( reader );
3990 case WS_ATTRIBUTE_TYPE_MAPPING:
3991 default:
3992 return S_OK;
3996 /**************************************************************************
3997 * WsReadType [webservices.@]
3999 HRESULT WINAPI WsReadType( WS_XML_READER *handle, WS_TYPE_MAPPING mapping, WS_TYPE type,
4000 const void *desc, WS_READ_OPTION option, WS_HEAP *heap, void *value,
4001 ULONG size, WS_ERROR *error )
4003 struct reader *reader = (struct reader *)handle;
4004 HRESULT hr;
4006 TRACE( "%p %u %u %p %u %p %p %u %p\n", handle, mapping, type, desc, option, heap, value,
4007 size, error );
4008 if (error) FIXME( "ignoring error parameter\n" );
4010 if (!reader || !value) return E_INVALIDARG;
4012 if ((hr = read_type( reader, mapping, type, NULL, NULL, desc, option, heap, value, size )) != S_OK)
4013 return hr;
4015 switch (mapping)
4017 case WS_ELEMENT_TYPE_MAPPING:
4018 if ((hr = read_node( reader )) != S_OK) return hr;
4019 break;
4021 default:
4022 break;
4025 if (!read_end_of_data( reader )) return WS_E_INVALID_FORMAT;
4026 return S_OK;
4029 /**************************************************************************
4030 * WsReadElement [webservices.@]
4032 HRESULT WINAPI WsReadElement( WS_XML_READER *handle, const WS_ELEMENT_DESCRIPTION *desc,
4033 WS_READ_OPTION option, WS_HEAP *heap, void *value, ULONG size,
4034 WS_ERROR *error )
4036 struct reader *reader = (struct reader *)handle;
4038 TRACE( "%p %p %u %p %p %u %p\n", handle, desc, option, heap, value, size, error );
4039 if (error) FIXME( "ignoring error parameter\n" );
4041 if (!reader || !desc || !value) return E_INVALIDARG;
4043 return read_type( reader, WS_ELEMENT_TYPE_MAPPING, desc->type, desc->elementLocalName,
4044 desc->elementNs, desc->typeDescription, option, heap, value, size );
4047 /**************************************************************************
4048 * WsReadValue [webservices.@]
4050 HRESULT WINAPI WsReadValue( WS_XML_READER *handle, WS_VALUE_TYPE value_type, void *value, ULONG size,
4051 WS_ERROR *error )
4053 struct reader *reader = (struct reader *)handle;
4054 WS_TYPE type = map_value_type( value_type );
4056 TRACE( "%p %u %p %u %p\n", handle, type, value, size, error );
4057 if (error) FIXME( "ignoring error parameter\n" );
4059 if (!reader || !value || type == ~0u) return E_INVALIDARG;
4061 return read_type( reader, WS_ELEMENT_TYPE_MAPPING, type, NULL, NULL, NULL, WS_READ_REQUIRED_VALUE,
4062 NULL, value, size );
4065 /**************************************************************************
4066 * WsSetErrorProperty [webservices.@]
4068 HRESULT WINAPI WsSetErrorProperty( WS_ERROR *handle, WS_ERROR_PROPERTY_ID id, const void *value,
4069 ULONG size )
4071 struct error *error = (struct error *)handle;
4073 TRACE( "%p %u %p %u\n", handle, id, value, size );
4075 if (id == WS_ERROR_PROPERTY_LANGID) return WS_E_INVALID_OPERATION;
4076 return prop_set( error->prop, error->prop_count, id, value, size );
4079 static inline BOOL is_utf8( const unsigned char *data, ULONG size, ULONG *offset )
4081 static const char bom[] = {0xef,0xbb,0xbf};
4082 const unsigned char *p = data;
4084 return (size >= sizeof(bom) && !memcmp( p, bom, sizeof(bom) ) && (*offset = sizeof(bom))) ||
4085 (size > 2 && !(*offset = 0));
4088 static inline BOOL is_utf16le( const unsigned char *data, ULONG size, ULONG *offset )
4090 static const char bom[] = {0xff,0xfe};
4091 const unsigned char *p = data;
4093 return (size >= sizeof(bom) && !memcmp( p, bom, sizeof(bom) ) && (*offset = sizeof(bom))) ||
4094 (size >= 4 && p[0] == '<' && !p[1] && !(*offset = 0));
4097 static WS_CHARSET detect_charset( const unsigned char *data, ULONG size, ULONG *offset )
4099 WS_CHARSET ret = 0;
4101 /* FIXME: parse xml declaration */
4103 if (is_utf16le( data, size, offset )) ret = WS_CHARSET_UTF16LE;
4104 else if (is_utf8( data, size, offset )) ret = WS_CHARSET_UTF8;
4105 else
4107 FIXME( "charset not recognized\n" );
4108 return 0;
4111 TRACE( "detected charset %u\n", ret );
4112 return ret;
4115 static void set_input_buffer( struct reader *reader, struct xmlbuf *buf, const unsigned char *data, ULONG size )
4117 reader->input_type = WS_XML_READER_INPUT_TYPE_BUFFER;
4118 reader->input_buf = buf;
4119 reader->input_data = data;
4120 reader->input_size = size;
4122 reader->read_size = reader->input_size;
4123 reader->read_pos = 0;
4124 reader->read_bufptr = reader->input_data;
4127 /**************************************************************************
4128 * WsSetInput [webservices.@]
4130 HRESULT WINAPI WsSetInput( WS_XML_READER *handle, const WS_XML_READER_ENCODING *encoding,
4131 const WS_XML_READER_INPUT *input, const WS_XML_READER_PROPERTY *properties,
4132 ULONG count, WS_ERROR *error )
4134 struct reader *reader = (struct reader *)handle;
4135 struct node *node;
4136 HRESULT hr;
4137 ULONG i, offset = 0;
4139 TRACE( "%p %p %p %p %u %p\n", handle, encoding, input, properties, count, error );
4140 if (error) FIXME( "ignoring error parameter\n" );
4142 if (!reader) return E_INVALIDARG;
4144 for (i = 0; i < count; i++)
4146 hr = prop_set( reader->prop, reader->prop_count, properties[i].id, properties[i].value,
4147 properties[i].valueSize );
4148 if (hr != S_OK) return hr;
4151 if ((hr = read_init_state( reader )) != S_OK) return hr;
4153 switch (encoding->encodingType)
4155 case WS_XML_READER_ENCODING_TYPE_TEXT:
4157 WS_XML_READER_TEXT_ENCODING *text = (WS_XML_READER_TEXT_ENCODING *)encoding;
4158 WS_XML_READER_BUFFER_INPUT *buf = (WS_XML_READER_BUFFER_INPUT *)input;
4159 WS_CHARSET charset = text->charSet;
4161 if (input->inputType != WS_XML_READER_INPUT_TYPE_BUFFER)
4163 FIXME( "charset detection on input type %u not supported\n", input->inputType );
4164 return E_NOTIMPL;
4167 if (charset == WS_CHARSET_AUTO)
4168 charset = detect_charset( buf->encodedData, buf->encodedDataSize, &offset );
4170 hr = prop_set( reader->prop, reader->prop_count, WS_XML_READER_PROPERTY_CHARSET,
4171 &charset, sizeof(charset) );
4172 if (hr != S_OK) return hr;
4173 break;
4175 default:
4176 FIXME( "encoding type %u not supported\n", encoding->encodingType );
4177 return E_NOTIMPL;
4179 switch (input->inputType)
4181 case WS_XML_READER_INPUT_TYPE_BUFFER:
4183 WS_XML_READER_BUFFER_INPUT *buf = (WS_XML_READER_BUFFER_INPUT *)input;
4184 set_input_buffer( reader, NULL, (const unsigned char *)buf->encodedData + offset,
4185 buf->encodedDataSize - offset );
4186 break;
4188 default:
4189 FIXME( "input type %u not supported\n", input->inputType );
4190 return E_NOTIMPL;
4193 if (!(node = alloc_node( WS_XML_NODE_TYPE_BOF ))) return E_OUTOFMEMORY;
4194 read_insert_bof( reader, node );
4195 return S_OK;
4198 /**************************************************************************
4199 * WsSetInputToBuffer [webservices.@]
4201 HRESULT WINAPI WsSetInputToBuffer( WS_XML_READER *handle, WS_XML_BUFFER *buffer,
4202 const WS_XML_READER_PROPERTY *properties, ULONG count,
4203 WS_ERROR *error )
4205 struct reader *reader = (struct reader *)handle;
4206 struct xmlbuf *xmlbuf = (struct xmlbuf *)buffer;
4207 WS_CHARSET charset;
4208 struct node *node;
4209 HRESULT hr;
4210 ULONG i, offset = 0;
4212 TRACE( "%p %p %p %u %p\n", handle, buffer, properties, count, error );
4213 if (error) FIXME( "ignoring error parameter\n" );
4215 if (!reader || !xmlbuf) return E_INVALIDARG;
4217 for (i = 0; i < count; i++)
4219 hr = prop_set( reader->prop, reader->prop_count, properties[i].id, properties[i].value,
4220 properties[i].valueSize );
4221 if (hr != S_OK) return hr;
4224 if ((hr = read_init_state( reader )) != S_OK) return hr;
4226 charset = detect_charset( xmlbuf->ptr, xmlbuf->size, &offset );
4227 hr = prop_set( reader->prop, reader->prop_count, WS_XML_READER_PROPERTY_CHARSET,
4228 &charset, sizeof(charset) );
4229 if (hr != S_OK) return hr;
4231 set_input_buffer( reader, xmlbuf, (const unsigned char *)xmlbuf->ptr + offset, xmlbuf->size - offset );
4232 if (!(node = alloc_node( WS_XML_NODE_TYPE_BOF ))) return E_OUTOFMEMORY;
4233 read_insert_bof( reader, node );
4234 return S_OK;
4237 /**************************************************************************
4238 * WsXmlStringEquals [webservices.@]
4240 HRESULT WINAPI WsXmlStringEquals( const WS_XML_STRING *str1, const WS_XML_STRING *str2, WS_ERROR *error )
4242 TRACE( "%s %s %p\n", debugstr_xmlstr(str1), debugstr_xmlstr(str2), error );
4243 if (error) FIXME( "ignoring error parameter\n" );
4245 if (!str1 || !str2) return E_INVALIDARG;
4247 if (str1->length != str2->length) return S_FALSE;
4248 if (!memcmp( str1->bytes, str2->bytes, str1->length )) return S_OK;
4249 return S_FALSE;
4252 /**************************************************************************
4253 * WsGetReaderPosition [webservices.@]
4255 HRESULT WINAPI WsGetReaderPosition( WS_XML_READER *handle, WS_XML_NODE_POSITION *pos, WS_ERROR *error )
4257 struct reader *reader = (struct reader *)handle;
4259 TRACE( "%p %p %p\n", handle, pos, error );
4260 if (error) FIXME( "ignoring error parameter\n" );
4262 if (!reader || !pos) return E_INVALIDARG;
4263 if (!reader->input_buf) return WS_E_INVALID_OPERATION;
4265 pos->buffer = (WS_XML_BUFFER *)reader->input_buf;
4266 pos->node = reader->current;
4267 return S_OK;
4270 /**************************************************************************
4271 * WsSetReaderPosition [webservices.@]
4273 HRESULT WINAPI WsSetReaderPosition( WS_XML_READER *handle, const WS_XML_NODE_POSITION *pos, WS_ERROR *error )
4275 struct reader *reader = (struct reader *)handle;
4277 TRACE( "%p %p %p\n", handle, pos, error );
4278 if (error) FIXME( "ignoring error parameter\n" );
4280 if (!reader || !pos || (struct xmlbuf *)pos->buffer != reader->input_buf) return E_INVALIDARG;
4281 if (!reader->input_buf) return WS_E_INVALID_OPERATION;
4283 reader->current = pos->node;
4284 return S_OK;